# Path: kraken/rpred.py
# def rpred(network: TorchSeqRecognizer,
#           im: Image.Image,
#           bounds: dict,
#           pad: int = 16,
#           bidi_reordering: Union[bool, str] = True) -> Generator[ocr_record, None, None]:
#     """
#     Uses a TorchSeqRecognizer and a segmentation to recognize text
# 
#     Args:
#         network (kraken.lib.models.TorchSeqRecognizer): A TorchSegRecognizer
#                                                         object
#         im (PIL.Image.Image): Image to extract text from
#         bounds (dict): A dictionary containing a 'boxes' entry with a list of
#                        coordinates (x0, y0, x1, y1) of a text line in the image
#                        and an entry 'text_direction' containing
#                        'horizontal-lr/rl/vertical-lr/rl'.
#         pad (int): Extra blank padding to the left and right of text line.
#                    Auto-disabled when expected network inputs are incompatible
#                    with padding.
#         bidi_reordering (bool|str): Reorder classes in the ocr_record according to
#                                     the Unicode bidirectional algorithm for correct
#                                     display. Set to L|R to change base text
#                                     direction.
#     Yields:
#         An ocr_record containing the recognized text, absolute character
#         positions, and confidence values for each character.
#     """
#     bounds = copy.deepcopy(bounds)
#     if 'boxes' in bounds:
#         boxes = bounds['boxes']
#         rewrite_boxes = []
#         for box in boxes:
#             rewrite_boxes.append([('default', box)])
#         bounds['boxes'] = rewrite_boxes
#         bounds['script_detection'] = True
#     return mm_rpred(defaultdict(lambda: network), im, bounds, pad, bidi_reordering)
# 
# Path: kraken/serialization.py
# def _rescale(val: Sequence[float], low: float, high: float) -> List[float]:
# def max_bbox(boxes: Iterable[Sequence[int]]) -> Tuple[int, int, int, int]:
# def serialize(records: Sequence[ocr_record],
#               image_name: str = None,
#               image_size: Tuple[int, int] = (0, 0),
#               writing_mode: str = 'horizontal-tb',
#               scripts: Optional[Iterable[str]] = None,
#               regions: Optional[Dict[str, List[List[Tuple[int, int]]]]] = None,
#               template: str = 'hocr') -> str:
# def serialize_segmentation(segresult: Dict[str, Any],
#                            image_name: str = None,
#                            image_size: Tuple[int, int] = (0, 0),
#                            template: str = 'hocr') -> str:
# def render_report(model: str,
#                   chars: int,
#                   errors: int,
#                   char_confusions: Counter,
#                   scripts: Counter,
#                   insertions: Counter,
#                   deletions: int,
#                   substitutions: Counter) -> str:
# 
# Path: kraken/lib/xml.py
# def preparse_xml_data(filenames: Sequence[Union[str, pathlib.Path]],
#                       format_type: str = 'xml',
#                       repolygonize: bool = False) -> Dict[str, Any]:
# def _repolygonize(im: Image.Image, lines: Sequence[Dict[str, Any]]):
# def parse_xml(filename: Union[str, pathlib.Path]) -> Dict[str, Any]:
# def parse_page(filename: Union[str, pathlib.Path]) -> Dict[str, Any]:
#     def _parse_page_custom(s):
#     def _parse_coords(coords):
# def parse_alto(filename: Union[str, pathlib.Path]) -> Dict[str, Any]:


import json
import unittest
import tempfile
import numpy as np
from lxml import etree
from io import StringIO
from pathlib import Path
from hocr_spec import HocrValidator
from collections import Counter
from kraken import rpred, serialization
from kraken.lib import xml
    counts = Counter(ids)
    if len(counts):
        self.assertEqual(counts.most_common(1)[0][1], 1, msg='Duplicate IDs in PageXML output')

    with open(resources / 'pagecontent.xsd') as schema_fp:
        page_schema = etree.XMLSchema(etree.parse(schema_fp))
        page_schema.assertValid(doc)

def validate_alto(self, fp):
    doc = etree.fromstring(fp.getvalue().encode('utf-8'))

    ids = [x.get('ID') for x in doc.findall('.//*[@ID]')]
    counts = Counter(ids)
    self.assertEqual(counts.most_common(1)[0][1], 1, msg='Duplicate IDs in ALTO output')

    with open(resources / 'alto-4-2.xsd') as schema_fp:
        alto_schema = etree.XMLSchema(etree.parse(schema_fp))
        alto_schema.assertValid(doc)


class TestSerializations(unittest.TestCase):
    """
    Tests for output serialization
    """
    def setUp(self):
        with open(resources /'records.json', 'r') as fp:
            self.box_records = [rpred.ocr_record(**x) for x in json.load(fp)]

        with open(resources / 'bl_records.json', 'r') as fp:
            recs = json.load(fp)

# Path: kraken/rpred.py
# def rpred(network: TorchSeqRecognizer,
#           im: Image.Image,
#           bounds: dict,
#           pad: int = 16,
#           bidi_reordering: Union[bool, str] = True) -> Generator[ocr_record, None, None]:
#     """
#     Uses a TorchSeqRecognizer and a segmentation to recognize text
# 
#     Args:
#         network (kraken.lib.models.TorchSeqRecognizer): A TorchSegRecognizer
#                                                         object
#         im (PIL.Image.Image): Image to extract text from
#         bounds (dict): A dictionary containing a 'boxes' entry with a list of
#                        coordinates (x0, y0, x1, y1) of a text line in the image
#                        and an entry 'text_direction' containing
#                        'horizontal-lr/rl/vertical-lr/rl'.
#         pad (int): Extra blank padding to the left and right of text line.
#                    Auto-disabled when expected network inputs are incompatible
#                    with padding.
#         bidi_reordering (bool|str): Reorder classes in the ocr_record according to
#                                     the Unicode bidirectional algorithm for correct
#                                     display. Set to L|R to change base text
#                                     direction.
#     Yields:
#         An ocr_record containing the recognized text, absolute character
#         positions, and confidence values for each character.
#     """
#     bounds = copy.deepcopy(bounds)
#     if 'boxes' in bounds:
#         boxes = bounds['boxes']
#         rewrite_boxes = []
#         for box in boxes:
#             rewrite_boxes.append([('default', box)])
#         bounds['boxes'] = rewrite_boxes
#         bounds['script_detection'] = True
#     return mm_rpred(defaultdict(lambda: network), im, bounds, pad, bidi_reordering)
# 
# Path: kraken/serialization.py
# def _rescale(val: Sequence[float], low: float, high: float) -> List[float]:
# def max_bbox(boxes: Iterable[Sequence[int]]) -> Tuple[int, int, int, int]:
# def serialize(records: Sequence[ocr_record],
#               image_name: str = None,
#               image_size: Tuple[int, int] = (0, 0),
#               writing_mode: str = 'horizontal-tb',
#               scripts: Optional[Iterable[str]] = None,
#               regions: Optional[Dict[str, List[List[Tuple[int, int]]]]] = None,
#               template: str = 'hocr') -> str:
# def serialize_segmentation(segresult: Dict[str, Any],
#                            image_name: str = None,
#                            image_size: Tuple[int, int] = (0, 0),
#                            template: str = 'hocr') -> str:
# def render_report(model: str,
#                   chars: int,
#                   errors: int,
#                   char_confusions: Counter,
#                   scripts: Counter,
#                   insertions: Counter,
#                   deletions: int,
#                   substitutions: Counter) -> str:
# 
# Path: kraken/lib/xml.py
# def preparse_xml_data(filenames: Sequence[Union[str, pathlib.Path]],
#                       format_type: str = 'xml',
#                       repolygonize: bool = False) -> Dict[str, Any]:
# def _repolygonize(im: Image.Image, lines: Sequence[Dict[str, Any]]):
# def parse_xml(filename: Union[str, pathlib.Path]) -> Dict[str, Any]:
# def parse_page(filename: Union[str, pathlib.Path]) -> Dict[str, Any]:
#     def _parse_page_custom(s):
#     def _parse_coords(coords):
# def parse_alto(filename: Union[str, pathlib.Path]) -> Dict[str, Any]:


# Path: tests/test_serialization.py
import json
import unittest
import tempfile
import numpy as np
from lxml import etree
from io import StringIO
from pathlib import Path
from hocr_spec import HocrValidator
from collections import Counter
from kraken import rpred, serialization
from kraken.lib import xml

    counts = Counter(ids)
    if len(counts):
        self.assertEqual(counts.most_common(1)[0][1], 1, msg='Duplicate IDs in PageXML output')

    with open(resources / 'pagecontent.xsd') as schema_fp:
        page_schema = etree.XMLSchema(etree.parse(schema_fp))
        page_schema.assertValid(doc)

def validate_alto(self, fp):
    doc = etree.fromstring(fp.getvalue().encode('utf-8'))

    ids = [x.get('ID') for x in doc.findall('.//*[@ID]')]
    counts = Counter(ids)
    self.assertEqual(counts.most_common(1)[0][1], 1, msg='Duplicate IDs in ALTO output')

    with open(resources / 'alto-4-2.xsd') as schema_fp:
        alto_schema = etree.XMLSchema(etree.parse(schema_fp))
        alto_schema.assertValid(doc)


class TestSerializations(unittest.TestCase):
    """
    Tests for output serialization
    """
    def setUp(self):
        with open(resources /'records.json', 'r') as fp:
            self.box_records = [rpred.ocr_record(**x) for x in json.load(fp)]

        with open(resources / 'bl_records.json', 'r') as fp:
            recs = json.load(fp)

            self.bl_records = [rpred.ocr_record(**bl) for bl in recs['lines']]