From 03f301b25c045941584c62c914987609222dd6a1 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 4 Jan 2019 19:17:54 +0530 Subject: [PATCH 1/6] Add table regions support --- camelot/cli.py | 12 +++++++- camelot/image_processing.py | 34 +++++++++++++++-------- camelot/io.py | 2 +- camelot/parsers/lattice.py | 55 ++++++++++++++++++++++++++----------- camelot/parsers/stream.py | 18 ++++++++---- camelot/utils.py | 4 +-- docs/user/advanced.rst | 14 +++++----- tests/test_common.py | 8 +++--- 8 files changed, 100 insertions(+), 47 deletions(-) diff --git a/camelot/cli.py b/camelot/cli.py index 3f240e0..a2b45a5 100644 --- a/camelot/cli.py +++ b/camelot/cli.py @@ -56,12 +56,15 @@ def cli(ctx, *args, **kwargs): @cli.command('lattice') +@click.option('-R', '--table_regions', default=[], multiple=True, + help='Page regions to analyze. Example: x1,y1,x2,y2' + ' where x1, y1 -> left-top and x2, y2 -> right-bottom.') @click.option('-T', '--table_areas', default=[], multiple=True, help='Table areas to process. Example: x1,y1,x2,y2' ' where x1, y1 -> left-top and x2, y2 -> right-bottom.') @click.option('-back', '--process_background', is_flag=True, help='Process background lines.') -@click.option('-scale', '--line_size_scaling', default=15, +@click.option('-scale', '--line_scale', default=15, help='Line size scaling factor. The larger the value,' ' the smaller the detected lines.') @click.option('-copy', '--copy_text', default=[], type=click.Choice(['h', 'v']), @@ -105,6 +108,8 @@ def lattice(c, *args, **kwargs): filepath = kwargs.pop('filepath') kwargs.update(conf) + table_regions = list(kwargs['table_regions']) + kwargs['table_regions'] = None if not table_regions else table_regions table_areas = list(kwargs['table_areas']) kwargs['table_areas'] = None if not table_areas else table_areas copy_text = list(kwargs['copy_text']) @@ -132,6 +137,9 @@ def lattice(c, *args, **kwargs): @cli.command('stream') +@click.option('-R', '--table_regions', default=[], multiple=True, + help='Page regions to analyze. Example: x1,y1,x2,y2' + ' where x1, y1 -> left-top and x2, y2 -> right-bottom.') @click.option('-T', '--table_areas', default=[], multiple=True, help='Table areas to process. Example: x1,y1,x2,y2' ' where x1, y1 -> left-top and x2, y2 -> right-bottom.') @@ -160,6 +168,8 @@ def stream(c, *args, **kwargs): filepath = kwargs.pop('filepath') kwargs.update(conf) + table_regions = list(kwargs['table_regions']) + kwargs['table_regions'] = None if not table_regions else table_regions table_areas = list(kwargs['table_areas']) kwargs['table_areas'] = None if not table_areas else table_areas columns = list(kwargs['columns']) diff --git a/camelot/image_processing.py b/camelot/image_processing.py index eb23101..8707d48 100644 --- a/camelot/image_processing.py +++ b/camelot/image_processing.py @@ -48,7 +48,8 @@ def adaptive_threshold(imagename, process_background=False, blocksize=15, c=-2): return img, threshold -def find_lines(threshold, direction='horizontal', line_size_scaling=15, iterations=0): +def find_lines(threshold, regions=None, direction='horizontal', + line_scale=15, iterations=0): """Finds horizontal and vertical lines by applying morphological transformations on an image. @@ -56,9 +57,13 @@ def find_lines(threshold, direction='horizontal', line_size_scaling=15, iteratio ---------- threshold : object numpy.ndarray representing the thresholded image. + regions : list, optional (default: None) + List of page regions that may contain tables of the form x1,y1,x2,y2 + where (x1, y1) -> left-top and (x2, y2) -> right-bottom + in image coordinate space. direction : string, optional (default: 'horizontal') Specifies whether to find vertical or horizontal lines. - line_size_scaling : int, optional (default: 15) + line_scale : int, optional (default: 15) Factor by which the page dimensions will be divided to get smallest length of lines that should be detected. @@ -83,10 +88,10 @@ def find_lines(threshold, direction='horizontal', line_size_scaling=15, iteratio lines = [] if direction == 'vertical': - size = threshold.shape[0] // line_size_scaling + size = threshold.shape[0] // line_scale el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) elif direction == 'horizontal': - size = threshold.shape[1] // line_size_scaling + size = threshold.shape[1] // line_scale el = cv2.getStructuringElement(cv2.MORPH_RECT, (size, 1)) elif direction is None: raise ValueError("Specify direction as either 'vertical' or" @@ -112,11 +117,17 @@ def find_lines(threshold, direction='horizontal', line_size_scaling=15, iteratio lines.append(((x1 + x2) // 2, y2, (x1 + x2) // 2, y1)) elif direction == 'horizontal': lines.append((x1, (y1 + y2) // 2, x2, (y1 + y2) // 2)) + if regions is not None: + region_mask = np.zeros(dmask.shape) + for region in regions: + x, y, w, h = region + region_mask[y : y + h, x : x + w] = 1 + dmask = np.multiply(dmask, region_mask) return dmask, lines -def find_table_contours(vertical, horizontal): +def find_contours(vertical, horizontal): """Finds table boundaries using OpenCV's findContours. Parameters @@ -138,11 +149,12 @@ def find_table_contours(vertical, horizontal): try: __, contours, __ = cv2.findContours( - mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) except ValueError: # for opencv backward compatibility contours, __ = cv2.findContours( - mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + # sort in reverse based on contour area and use first 10 contours contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10] cont = [] @@ -153,7 +165,7 @@ def find_table_contours(vertical, horizontal): return cont -def find_table_joints(contours, vertical, horizontal): +def find_joints(contours, vertical, horizontal): """Finds joints/intersections present inside each table boundary. Parameters @@ -176,18 +188,18 @@ def find_table_joints(contours, vertical, horizontal): and (x2, y2) -> rt in image coordinate space. """ - joints = np.bitwise_and(vertical, horizontal) + joints = np.multiply(vertical, horizontal) tables = {} for c in contours: x, y, w, h = c roi = joints[y : y + h, x : x + w] try: __, jc, __ = cv2.findContours( - roi, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) + roi.astype(np.uint8), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) except ValueError: # for opencv backward compatibility jc, __ = cv2.findContours( - roi, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) + roi.astype(np.uint8), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) if len(jc) <= 4: # remove contours with less than 4 joints continue joint_coords = [] diff --git a/camelot/io.py b/camelot/io.py index 44f3354..5162dd2 100644 --- a/camelot/io.py +++ b/camelot/io.py @@ -52,7 +52,7 @@ def read_pdf(filepath, pages='1', password=None, flavor='lattice', to generate columns. process_background* : bool, optional (default: False) Process background lines. - line_size_scaling* : int, optional (default: 15) + line_scale* : int, optional (default: 15) Line size scaling factor. The larger the value the smaller the detected lines. Making it very large will lead to text being detected as lines. diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index f4bc2c0..e061f65 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -16,7 +16,7 @@ from ..utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, merge_close_lines, get_table_index, compute_accuracy, compute_whitespace) from ..image_processing import (adaptive_threshold, find_lines, - find_table_contours, find_table_joints) + find_contours, find_joints) logger = logging.getLogger('camelot') @@ -28,13 +28,17 @@ class Lattice(BaseParser): Parameters ---------- + table_regions : list, optional (default: None) + List of page regions that may contain tables of the form x1,y1,x2,y2 + where (x1, y1) -> left-top and (x2, y2) -> right-bottom + in PDF coordinate space. table_areas : list, optional (default: None) List of table area strings of the form x1,y1,x2,y2 where (x1, y1) -> left-top and (x2, y2) -> right-bottom in PDF coordinate space. process_background : bool, optional (default: False) Process background lines. - line_size_scaling : int, optional (default: 15) + line_scale : int, optional (default: 15) Line size scaling factor. The larger the value the smaller the detected lines. Making it very large will lead to text being detected as lines. @@ -77,14 +81,15 @@ class Lattice(BaseParser): Resolution used for PDF to PNG conversion. """ - def __init__(self, table_areas=None, process_background=False, - line_size_scaling=15, copy_text=None, shift_text=['l', 't'], + def __init__(self, table_regions=None, table_areas=None, process_background=False, + line_scale=15, copy_text=None, shift_text=['l', 't'], split_text=False, flag_size=False, strip_text='', line_tol=2, joint_tol=2, threshold_blocksize=15, threshold_constant=-2, iterations=0, resolution=300, **kwargs): + self.table_regions = table_regions self.table_areas = table_areas self.process_background = process_background - self.line_size_scaling = line_size_scaling + self.line_scale = line_scale self.copy_text = copy_text self.shift_text = shift_text self.split_text = split_text @@ -239,14 +244,35 @@ class Lattice(BaseParser): image_scalers = (image_width_scaler, image_height_scaler, self.pdf_height) pdf_scalers = (pdf_width_scaler, pdf_height_scaler, image_height) - vertical_mask, vertical_segments = find_lines( - self.threshold, direction='vertical', - line_size_scaling=self.line_size_scaling, iterations=self.iterations) - horizontal_mask, horizontal_segments = find_lines( - self.threshold, direction='horizontal', - line_size_scaling=self.line_size_scaling, iterations=self.iterations) + if self.table_areas is None: + regions = None + if self.table_regions is not None: + regions = [] + for region in self.table_regions: + x1, y1, x2, y2 = region.split(",") + x1 = float(x1) + y1 = float(y1) + x2 = float(x2) + y2 = float(y2) + x1, y1, x2, y2 = scale_pdf((x1, y1, x2, y2), image_scalers) + regions.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) + vertical_mask, vertical_segments = find_lines( + self.threshold, regions=regions, direction='vertical', + line_scale=self.line_scale, iterations=self.iterations) + horizontal_mask, horizontal_segments = find_lines( + self.threshold, regions=regions, direction='horizontal', + line_scale=self.line_scale, iterations=self.iterations) + + contours = find_contours(vertical_mask, horizontal_mask) + table_bbox = find_joints(contours, vertical_mask, horizontal_mask) + else: + vertical_mask, vertical_segments = find_lines( + self.threshold, direction='vertical', line_scale=self.line_scale, + iterations=self.iterations) + horizontal_mask, horizontal_segments = find_lines( + self.threshold, direction='horizontal', line_scale=self.line_scale, + iterations=self.iterations) - if self.table_areas is not None: areas = [] for area in self.table_areas: x1, y1, x2, y2 = area.split(",") @@ -256,10 +282,7 @@ class Lattice(BaseParser): y2 = float(y2) x1, y1, x2, y2 = scale_pdf((x1, y1, x2, y2), image_scalers) areas.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) - table_bbox = find_table_joints(areas, vertical_mask, horizontal_mask) - else: - contours = find_table_contours(vertical_mask, horizontal_mask) - table_bbox = find_table_joints(contours, vertical_mask, horizontal_mask) + table_bbox = find_joints(areas, vertical_mask, horizontal_mask) self.table_bbox_unscaled = copy.deepcopy(table_bbox) diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index d36212b..82c5fd1 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -26,6 +26,10 @@ class Stream(BaseParser): Parameters ---------- + table_regions : list, optional (default: None) + List of page regions that may contain tables of the form x1,y1,x2,y2 + where (x1, y1) -> left-top and (x2, y2) -> right-bottom + in PDF coordinate space. table_areas : list, optional (default: None) List of table area strings of the form x1,y1,x2,y2 where (x1, y1) -> left-top and (x2, y2) -> right-bottom @@ -51,9 +55,10 @@ class Stream(BaseParser): to generate columns. """ - def __init__(self, table_areas=None, columns=None, split_text=False, + def __init__(self, table_regions=None, table_areas=None, columns=None, split_text=False, flag_size=False, strip_text='', edge_tol=50, row_tol=2, column_tol=0, **kwargs): + self.table_regions = table_regions self.table_areas = table_areas self.columns = columns self._validate_columns() @@ -275,7 +280,13 @@ class Stream(BaseParser): def _generate_table_bbox(self): self.textedges = [] - if self.table_areas is not None: + if self.table_areas is None: + if self.table_regions is not None: + # filter horizontal text + pass + # find tables based on nurminen's detection algorithm + table_bbox = self._nurminen_table_detection(self.horizontal_text) + else: table_bbox = {} for area in self.table_areas: x1, y1, x2, y2 = area.split(",") @@ -284,9 +295,6 @@ class Stream(BaseParser): x2 = float(x2) y2 = float(y2) table_bbox[(x1, y2, x2, y1)] = None - else: - # find tables based on nurminen's detection algorithm - table_bbox = self._nurminen_table_detection(self.horizontal_text) self.table_bbox = table_bbox def _generate_columns_and_rows(self, table_idx, tk): diff --git a/camelot/utils.py b/camelot/utils.py index 3b78d5e..7b22307 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -101,7 +101,7 @@ stream_kwargs = [ ] lattice_kwargs = [ 'process_background', - 'line_size_scaling', + 'line_scale', 'copy_text', 'shift_text', 'line_tol', @@ -339,7 +339,7 @@ def text_in_bbox(bbox, text): ---------- bbox : tuple Tuple (x1, y1, x2, y2) representing a bounding box where - (x1, y1) -> lb and (x2, y2) -> rt in PDFMiner coordinate + (x1, y1) -> lb and (x2, y2) -> rt in the PDF coordinate space. text : List of PDFMiner text objects. diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index ca40bb8..f454c1e 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -434,11 +434,11 @@ You can pass ``row_tol=<+int>`` to group the rows closer together, as shown belo Detect short lines ------------------ -There might be cases while using :ref:`Lattice ` when smaller lines don't get detected. The size of the smallest line that gets detected is calculated by dividing the PDF page's dimensions with a scaling factor called ``line_size_scaling``. By default, its value is 15. +There might be cases while using :ref:`Lattice ` when smaller lines don't get detected. The size of the smallest line that gets detected is calculated by dividing the PDF page's dimensions with a scaling factor called ``line_scale``. By default, its value is 15. -As you can guess, the larger the ``line_size_scaling``, the smaller the size of lines getting detected. +As you can guess, the larger the ``line_scale``, the smaller the size of lines getting detected. -.. warning:: Making ``line_size_scaling`` very large (>150) will lead to text getting detected as lines. +.. warning:: Making ``line_scale`` very large (>150) will lead to text getting detected as lines. Here's a `PDF <../_static/pdf/short_lines.pdf>`__ where small lines separating the the headers don't get detected with the default value of 15. @@ -458,11 +458,11 @@ Let's plot the table for this PDF. :alt: A plot of the PDF table with short lines :align: left -Clearly, the smaller lines separating the headers, couldn't be detected. Let's try with ``line_size_scaling=40``, and plot the table again. +Clearly, the smaller lines separating the headers, couldn't be detected. Let's try with ``line_scale=40``, and plot the table again. :: - >>> tables = camelot.read_pdf('short_lines.pdf', line_size_scaling=40) + >>> tables = camelot.read_pdf('short_lines.pdf', line_scale=40) >>> camelot.plot(tables[0], kind='grid') >>> plt.show() @@ -511,7 +511,7 @@ We'll use the `PDF <../_static/pdf/short_lines.pdf>`__ from the previous example :: - >>> tables = camelot.read_pdf('short_lines.pdf', line_size_scaling=40, shift_text=['']) + >>> tables = camelot.read_pdf('short_lines.pdf', line_scale=40, shift_text=['']) >>> tables[0].df .. csv-table:: @@ -532,7 +532,7 @@ No surprises there — it did remain in place (observe the strings "2400" and "A :: - >>> tables = camelot.read_pdf('short_lines.pdf', line_size_scaling=40, shift_text=['r', 'b']) + >>> tables = camelot.read_pdf('short_lines.pdf', line_scale=40, shift_text=['r', 'b']) >>> tables[0].df .. tip:: diff --git a/tests/test_common.py b/tests/test_common.py index f9f26bf..3a24c55 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -179,7 +179,7 @@ def test_lattice_copy_text(): df = pd.DataFrame(data_lattice_copy_text) filename = os.path.join(testdir, "row_span_1.pdf") - tables = camelot.read_pdf(filename, line_size_scaling=60, copy_text="v") + tables = camelot.read_pdf(filename, line_scale=60, copy_text="v") assert df.equals(tables[0].df) @@ -189,13 +189,13 @@ def test_lattice_shift_text(): df_rb = pd.DataFrame(data_lattice_shift_text_right_bottom) filename = os.path.join(testdir, "column_span_2.pdf") - tables = camelot.read_pdf(filename, line_size_scaling=40) + tables = camelot.read_pdf(filename, line_scale=40) assert df_lt.equals(tables[0].df) - tables = camelot.read_pdf(filename, line_size_scaling=40, shift_text=['']) + tables = camelot.read_pdf(filename, line_scale=40, shift_text=['']) assert df_disable.equals(tables[0].df) - tables = camelot.read_pdf(filename, line_size_scaling=40, shift_text=['r', 'b']) + tables = camelot.read_pdf(filename, line_scale=40, shift_text=['r', 'b']) assert df_rb.equals(tables[0].df) From eaca147b9dd84e1d44239c689b83736a2c69bd5d Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 4 Jan 2019 20:15:41 +0530 Subject: [PATCH 2/6] Apply mask at threshold level --- camelot/image_processing.py | 17 +++++++++-------- camelot/parsers/lattice.py | 34 ++++++++++++++++------------------ 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/camelot/image_processing.py b/camelot/image_processing.py index 8707d48..3051852 100644 --- a/camelot/image_processing.py +++ b/camelot/image_processing.py @@ -97,17 +97,24 @@ def find_lines(threshold, regions=None, direction='horizontal', raise ValueError("Specify direction as either 'vertical' or" " 'horizontal'") + if regions is not None: + region_mask = np.zeros(threshold.shape) + for region in regions: + x, y, w, h = region + region_mask[y : y + h, x : x + w] = 1 + threshold = np.multiply(threshold, region_mask) + threshold = cv2.erode(threshold, el) threshold = cv2.dilate(threshold, el) dmask = cv2.dilate(threshold, el, iterations=iterations) try: _, contours, _ = cv2.findContours( - threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + threshold.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) except ValueError: # for opencv backward compatibility contours, _ = cv2.findContours( - threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + threshold.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for c in contours: x, y, w, h = cv2.boundingRect(c) @@ -117,12 +124,6 @@ def find_lines(threshold, regions=None, direction='horizontal', lines.append(((x1 + x2) // 2, y2, (x1 + x2) // 2, y1)) elif direction == 'horizontal': lines.append((x1, (y1 + y2) // 2, x2, (y1 + y2) // 2)) - if regions is not None: - region_mask = np.zeros(dmask.shape) - for region in regions: - x, y, w, h = region - region_mask[y : y + h, x : x + w] = 1 - dmask = np.multiply(dmask, region_mask) return dmask, lines diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index e061f65..ab7d3be 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -232,9 +232,22 @@ class Lattice(BaseParser): stderr=subprocess.STDOUT) def _generate_table_bbox(self): + def scale_areas(areas): + scaled_areas = [] + for area in areas: + x1, y1, x2, y2 = area.split(",") + x1 = float(x1) + y1 = float(y1) + x2 = float(x2) + y2 = float(y2) + x1, y1, x2, y2 = scale_pdf((x1, y1, x2, y2), image_scalers) + scaled_areas.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) + return scaled_areas + self.image, self.threshold = adaptive_threshold( self.imagename, process_background=self.process_background, blocksize=self.threshold_blocksize, c=self.threshold_constant) + image_width = self.image.shape[1] image_height = self.image.shape[0] image_width_scaler = image_width / float(self.pdf_width) @@ -247,15 +260,8 @@ class Lattice(BaseParser): if self.table_areas is None: regions = None if self.table_regions is not None: - regions = [] - for region in self.table_regions: - x1, y1, x2, y2 = region.split(",") - x1 = float(x1) - y1 = float(y1) - x2 = float(x2) - y2 = float(y2) - x1, y1, x2, y2 = scale_pdf((x1, y1, x2, y2), image_scalers) - regions.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) + regions = scale_areas(self.table_regions) + vertical_mask, vertical_segments = find_lines( self.threshold, regions=regions, direction='vertical', line_scale=self.line_scale, iterations=self.iterations) @@ -273,15 +279,7 @@ class Lattice(BaseParser): self.threshold, direction='horizontal', line_scale=self.line_scale, iterations=self.iterations) - areas = [] - for area in self.table_areas: - x1, y1, x2, y2 = area.split(",") - x1 = float(x1) - y1 = float(y1) - x2 = float(x2) - y2 = float(y2) - x1, y1, x2, y2 = scale_pdf((x1, y1, x2, y2), image_scalers) - areas.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) + areas = scale_areas(self.table_areas) table_bbox = find_joints(areas, vertical_mask, horizontal_mask) self.table_bbox_unscaled = copy.deepcopy(table_bbox) From d064f716e980dd01f88e2c24a52f54a2ff29bcac Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 4 Jan 2019 20:22:14 +0530 Subject: [PATCH 3/6] Add lattice test --- tests/data.py | 7 +++++++ tests/files/table_region.pdf | Bin 0 -> 262374 bytes tests/test_common.py | 8 ++++++++ 3 files changed, 15 insertions(+) create mode 100644 tests/files/table_region.pdf diff --git a/tests/data.py b/tests/data.py index c223227..99527d5 100755 --- a/tests/data.py +++ b/tests/data.py @@ -427,6 +427,13 @@ data_lattice_two_tables_2 = [ ["Pooled", "23889", "47.7", "1.5", "9.9", "19.9", "17.8", "3.3"] ] +data_lattice_table_regions = [ + ['Età dell’Assicurato \nall’epoca del decesso', 'Misura % di \nmaggiorazione'], + ['18-75', '1,00%'], + ['76-80', '0,50%'], + ['81 in poi', '0,10%'] +] + data_lattice_table_areas = [ ["", "", "", "", "", "", "", "", ""], ["State", "n", "Literacy Status", "", "", "", "", "", ""], diff --git a/tests/files/table_region.pdf b/tests/files/table_region.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f6f053bda2ea473db0301363ddc6d42f14758327 GIT binary patch literal 262374 zcma&tQ*`D+qP}nwr$(C?d-qKKDAq`b*lDR7X$siU%c%Z zeUQlui_$UCvq6*XAIvO3GXV%032pSv3Awo$M9nN6jqC{-L@o6kjf9O1Yz&PE8KjM@ zO&m=Lf3q^P6Y}yBIyl-J=~=-+i-#quY1wRWB6}gk{`986tVaAHd#dts(0Zw+Unj-s z@LF}R(={SLs-|m;&jk5;@(4~e9CKEJ5D`+}zn#RGne^;&e>m}PC^-*rI0|9EY02!O zss46*G7fHO07HqSGj3^=m@U3>?Yom>WOwG~dsL_84*AF)slP(=TGNKg;nMRRnOXv& zfD_h7h60qss$tC>p+NM0tcR;< z{`egku$FRlQ#t&srh)fb5)C&rf!?`%4#UJ*!LYfbA+w=l(XqPMQSsYw*U2Dalx=s(Gb{rC{7%z z^ZT%K5QbALe0Ep}@}=pn*Np=4TZ$Z)MANp2-XCzdC$iCj8cE;unmbcB8VA+Cr&&u- z8I#Nc&pU>^N7m!Vm2?+h8}s697GbEW5La2>Sy5<{ywB&je1B)|KQZRjJo)G07PPKb z-rsG|!8d$=RAT>^PK%n3=*_~$S%@QttR|a=TV~8p*XIN-)n!~K#}wS8Sv3j~7L*vN zWm`A4*RqpVqDDQ7$wE&1D4LW-+njyp=Z(tgYd`br^H>xJ#r5G60JGc&cm;!6~mhr|o3}EAgmgc@a(bvdg%24IZQb!U->xvy`EZd3h>~EC|*e^$( zwbM@@bFTr&;6#@w8}cv|k6KXxv2zsbvGQ2Ce%JC+0WI1_rRIuClDFcUoI~k!j*7}f z)wl$3lU`A^bN#0I!-S>W!&1}QubI-Z$KS{yk|Lv1q* zqm*&_Capp(?{$%lqFO25ScAsdvem@Ym@v1r*$zuv4OT!giY5*c58@_#b28`_Xm+Q>;k*#Q0%LROkSYT{^QxQdv3Y;Z|cCjFVjei%9*bOp#Gh z+B#aAp>d6;x9VF$XI)E}eo@5|Ykx7jB}Go*)P>zCmne}Sd!;=HUwnF(N}Glq!+0Yt zYXE*Lg*b=%ppT|XaZ5-3pdTQ^c@(Z8O_6&7jvivHvYH)-dv(!RJWtVQ%R=&j8ES?9 z<-v+3C)-g#73G{a#j<1^*0|SmDBF*w$DF&5B<5rDUihMJsi|Bodq!O%`GnaR3}6{Vwlrtn1d;3@wVpR{|B+a3u|lZho-ATCL{5BpQ93a zxI;#D>e@O5K}iWQc|wj7{zOW!2A5F0&gS)@c{C%ld?~EEkt@y2r zsEK&fuC0na7aK@fxTFi0acmQ@ha6wnKcR$-jCsF~{A64fC{3>*??F1C{1nuxLEwxm zy^54#<-(FOQtWIjqSD5a)uE#wCs!c!fV4U2Wgv6v`uYUH0BPV;4#9yaV^HsLLtzENra3 zH*Kc8aGZ)Yo7QGsj7yaLLjtUCo1YBf42Bi?DnD4Ai9rUw_$67s|AxsB`eH)Cw{Jx+ zCN!zwoU&06a%a1-VoU&=N1UaC2YXLsH$3JkKmS#c%)>)a>N;ebkfQ*su*|P|y*KX) z$%U*ntyKf_mZvz&+8Wz4q<3)K?P&Q;hl=pw~9-z^NYELVMy#WNL-@aRHph9c_y zS8R-?)Gwjv_0GA*N>t&Na{MyP>jpSW_4!r59KpudiR^RbNtjmB4I7ixwf<5`y;(uv zgVV{TlTehhpKOm;{n^gg-U17p|if10yZp(^!3Q zd1Wz}JtMMsJd&qDHmF{@PY#$K+c!RkoKb`c&~3NfK?vGi22U2OQ6UDnMF+PqGiPB0 zVW#;v@NYVKGH`$%f>PdnuI%DE3YDBw>}F<1_F}q=76-Ix76#Zc=>+o*$4%&I6WRNQ zX^qIVx{x|dgW^pd5o@8hQc@^HB3=8_o)Wu@o>J!H4%ZP}T5=LLDxkt=?&Y_(-C@z8 z%>U*{fcMulmwc&txK<7|NEgA>Mivw$t+)%7aPdO7Zq)sI`G3u-h*XB5^*o)nu>}WEX^kvf7jmVdlI2t|c)`uPj!Gp2fz4 z9xo-b;gWkQXPG1BKK3v0SUM>%iZ32i)wvFPaE}D#Isxhkl`XB~KuZlfnM4jXsf7GDU&D1Eb3)fEOQ84q{yuj^Kru zQ_)~LU7)!n<=Fg0m*;#d4Si9~ zj-&k#hAz??53>bf-YJ)2H zWv}yj&?m<8Q$Qp7N^}+mKrBnvqj5a2qNu!Si4g`UYB_gC zGI9tV4OPDo3J4UM5CjS6w_6oG9TySAZv3!Rt;QzQXGFF(M66jCvGjN^3 z0UC8&;?jJF$4P_(UnnA7Y8UO&P_gdaJioBCkn2LrX2xC`d5F z0Z#3C$OIIx>$}DUh~)M43HlJsaRt5CWc0`vZ%;2IOtxhUe8SjR@tvsgK>NC)*G#>) zG|$rkMb`Z4y+8h&G4TP!c-M{B{W|USTI@!}j_Ih^-Tn0R#A{x(Iiftv{+UCH7{3B|`~RgQ&krM1^Z~KuhDIVhY zE$hzS_UGmd)ccFl9`8bdYE^nfg5i;_eL=Ui_spX@2uLmn`7SVxE<&as7b1ucB1pdg zODMz`A>N@cNGvCTK^Ww=H61KujOht(YyoCseiH zUtMJBfDm19Zm=3cNMZrlP#ARq_*j}lus0!nO62em#XQ`zh_>xL^q!#4K zi(nLAm3R%c4YrM9lyQ|LMSc?oW(rIdrX^HG%n0imtQrIzJQ$Q3>=;x>4l@+FCl-mF zm-rp;w6peM<1Skqhd26t_{*M1UFw<;A^s(nk4%SrhomRJma;mLQIbKp|->R1@2$Y_4C@u-n#{l+wB zq1cq+6t|s1OOPQS=j`H?U_NG{C!bG`5z{)-RFr6-_s_`c6kzBz{cbbT;@E(kRVlS8 zEh-g{t;6y;RYI@*w?V2@n#`oYG10NeF$sFm(QtgNVWsLa<~ zv^DD8js2DTRn%2%f1>_w)rnT|R54dwRJEw*)Oi~YG(fe)Z8&b=Hny3;Y`Cu*ud!`- z>w5G#FHdjN&&is!3|%K~k$7}_HF^bo`F@o=BjC2e$HAM20Ef)reut+SF#SPe3(Oie z#SLL!ll5~;eg7t&*IF42W;6Db4FxMWI|-han7^?S_|76TQ8m3&Lr*7I+8oA zop~TH*HmezbV6%s1Y6o)j00U+O6<*McWw*9-C6VNJPCQ#uo z3;sm{ApJwo$@eM{DkUy4>OsUl$ZZ$gs`lwdNyNg|NcVU!i=o%27hD^l=YxO|tQLF& z)ziaY%ipGJ*|!B*0;xV29XcjXTTgobH9GcB52`PkF0#)}&xN06&AsSz>r?AL4{=97 zMJ$bYqkc#uldF?+;D-#74Lgm<3_9#P9E2S7$l6NElU>TBO2A55%5rB5i%UwZ$2tm` zQzS{bNSVY7#ix+v$mW$8mcW*HCY-00%kdyq)XmD$xDle)ydWGpq48%J~Ri&uXeHEsv)6(!N z3sR0TtSQ|G&}y+!XZ+KG-D;d9DWmKY1l0Lxpy3eXkVZZC+UmmUK5Jeof#wD00&dE0 zx^E;+!aSAV&BSH;9zzY|kK+h5K9%D&oVi36k}P6PxK>5aj{oFvp(nDelxitKrx5H_xb>E}xmak$g zt7P^ZOFK(5n=}pd21_xTMU8d$`l+_61}k^B{d=ve#pm&7KBrfwM;Ff?VxOTp*^cR> zEEhHM>dg(K<)WMRI%?0Q=cQBgr}HpYV2kETx2>wv@BEP(liHIIZMPc?3lWQuLC4 zphDok->I!>q-n8fpXsLQOBsS0HJP}XVVN&khFSC3{MpqxcsUU{@405Vt9fF1&H3c{ z$pzpA&IQMXs)Zv(fTFTu?Ba;xuM+E$-BQKU!7}!;vU1$=m89B&N0rhwsF9C%LLm*^CatJ(-iAe(=^+3^9=h;>nz7?`yBUN_dMTx--7VM z@S?=x#FFgN+_K8@>Wb#d?yBMH>6+!*-MaJo$A<4F*kE}syesb5rI z?cY-0n?F`RKOnF`FM$sq|9!w@W&HO7CJVKoDhc_c* zi|$?%k%6v9eE{>H z(u*IylFb;hZbk*rF6(=|ZWcy9Wy_%78tcIjB|ajiBdP!~A>RkHLp_i&1=6a;q4LFx zga*YDGwc%jpKo{bi+9Z{Y8z1p0i!Rx#1enV|Rkieg(A_}abV~py zILo>3H*A#*mrRUYW$gYv`bg8M-Rbb=IY(?#+A4*bKQwzbU1#z7M*1fErqhUO7WdF7 znX8&xI$y{7hcD}XPXT)a-~2)aUj%!s#r1Hn-!Z&6oKSi!t>9qb<&~3gK6X=&(%j_B z=B&#JcK?Klu)DPY<1UOFkwxc@2n!g8;(S@c-Iv!`*aur?7MhW)LZ?u9?ybvi!gpxZ zWZ(C<#Tay_b*MJ?lp}-jwxZAVHS`YHKFz}N`&HKLwmUK;fWF~T_;S8fP@zf&P-6Z) z&VYcK)>j@@#CY@*WnS6NH#Z8uu%CEGEy7)e4$;RC=cmd>T5T8t-=c#x9{}8Bda7vs zUBqFLqY!0h#Lz!c2A^v*8;NyE49OxyIe1D`jCQ;kOlSbW^ZVp#1;RLII=}|s53tQN>~=FgqM=gy5*%-$-h#;s`YtP zGrHYQtp+|tG;^Ssh4C|9Pt{w68mPPo2uTt@GnltOI62Y8sbVLVF%bXCT0=Af;+Z93 zOfp#4RR5|Ii*k}IZhBdmq2Hbj;2ZBK^0W~KJ9zZMC)H77-{~|uwWbk2O8pCCAhmxH zmEEovCMBJ8jt@eN!sjn^$<2fY6_tfD2d&IcK@Uv)M#=OS*6^Yhrlkvf>kMRACM)jt zTa>r}&$?DII@-YJU8`eHKuS?_@wqUEZo(XIb;51;o`6>e9vqZ(Gd3|PfcKcnevNO( zjOwub0-HzzxMcJ7X5}N>N#GFksjczGhNqrwOAq5@3lrD8%iE=pjDv{C$A|?2-YzTA zN@o>u9JbYr)p`(f@}ie=6ykf2ITil>^d|OihOyR-M6RptEo3LuckqPF@gssx1P^)E z9+1Qt^FAgFgIQ*n0_6Z+Pp=}H>6wA;E>kBRUXkh2YM>U?o_(L+-1zTOXE)*ScuXo_ zW z#k0j>Y=o8{?^qO0$JMYo*+O$8H#3=H40AR^Fh2=1V|9Xy6Qo2%LrY}gCAV5ifQU778ukU!f19zQbxlWwG6&2z)sAW4m4iWf0n*geH zf9+@*059MhA6}_Oi}UG3NmHvy|9V@}6Xgr8Oz@%T1t3Qtxb)IRNxk;td?4KQ`O*DJ z5R+r>Q2O52^T_q0#J)toJU$3-$Ht|AL%TfRa9AV8O1rc4uq!$b%GQ8N;yMDIhnfA{P#V z?m@F3FeymI<62EugtYwj0*-ku-HXj6My%8d`Abc_X=5Bv)Wi%3*N zpg^4e9H9b0-6)n z*mN=#$WpJWwo<8XbKU81vvsoBHN&Ciiw@tPjvt`%vaivD8zxqHtlXz_gA~JZWLh$u zf-7#UQQb_ar(x=-*&3=L`=%e@r^U3Y9jqr^n8|{f_*t<%W?2vmYY=C)|%DVmX5DY{B!;kb?a-8e-CyvzySMu zEW{@+Q5VVp1a?n%PiGcdYt9La2R$4xcqsw}VbNatDJ+mk@w$hNBn3Fyc8pi7^lLOG zsxl~RF%j$Q2Y~4JnevkaGK*mwJB+)AyKOOCnJ#e7;>gRfsTwu}nI5+GA*MrOv=c7q z{uTF@Qg19|&r}F;n?NCMW5LD!4Rz(XY~!)`cG{w?6P|mh`^kyB9nM?+?dPVMRPrNx znBc&2AA+jhKhNI^6L0teC5p1w#;|AROKzDPk0b-u1(cBs6k<1S5T+P(H9*^SkO(ts zvApoYAXR++VzW%rX-<6pyS)7IIrpqy_B2 zshq0qxY?LwzPz+%J@ZHIIXMDZRx&dF(i$F6bUx0fyz3hk^&vGA>(V!;8n1Hmqj7S7 z&n}qdbfYy`+$6pPda_Naw)F5PUZqAR6cJ7GJ?BJQosc!$8U8pvh>($@kwZ`7`016* z?MfRbkhe>Rb?GwV9}@P83t|9Q-|ovzUQD_>_>o-$U}m6pu2GW1N{Hi-+Y*hD6cm>i zC<T|QbV7Ilyp_NB!0;KmpIF_ zyr&0YSl}XI5q#}wlXUzNax;8=Sr8~la6do6Kkq-iC5Yw5Qk1{Ep<}L;S-<9dxc+p@ zGxOmV%adoUwG^lsLs2b`+SN))dT@v24R0XJnAC3AH;HmfFExt zO$WwR%2yxsF8!f|$PS=$qevvM6;C;HwW~`PvEO>7nU+|O`n=< zlDHVeP|_x#PR1CGbwui9tOJu@BxV(0XA-me3+a|KUIhe}qBX#KDY-qFN+h>C{!DFQ zI8=@COUPVssfiNDQGw(AP_pV9eT2)ZR#dALiFyK@eE926Am9Ige_GIt+vy&9L=BbxhmU z+YcGq1HSPe4B08K?qzR=1u(`ix&q`+oI{Z?a5(4UlunG9<@F=N=7_8g#$L!Gc*wYU z_*F9%5qwVQmvXaoKso2CVFAj3F@mJifNZ={ARk*xFCf{G!fAR+r?L68a)mm%4L!?? zwQ#N#)#>dYw#f)DMm-io=oxyKE;oAzaC?I$gH2I7ulYP-k*K9+Le} z5N{D&gfl2*DN)iIb?(LE4rg8Hb$#Vb2OHzYDh6YfW*#DBstM@+8{3ZKr`-l^IrK(W z!@9eFY+W`y*jxKMFB{rI=AH2sT_~TcgRs6UM}TL&_>8)F!oXLcs z$<)P4drqNO#Cx;lI%;`fc-qxu21Zuw64CmLCpab>RAzRCWcD}K7QS|KDC?Tit&;gA z`IG1^rS~}Z97{>Z(zHF>M9_5e;p0>evtg%D;phAm*BR&-`eNJ6x2gd*=M7P2)KhwU zSGMmXAiXuH0I#R z^8fqTFddz50xmR%xl=c1uqk}L3)(TNi~H)X$N@RXFQ;G55PcyC4-$3)ph6Nf#e)*d z!Tg{hy`i(LDZ4tlb$zQ>FR5XH+qbcP)V`6v_1k?*#fa_KjpWQ`#>44=p zzvN`eX%_-Im4rz`A<(@_@$S{JZ--aO*=?MbS;*3-8Y6$7+SOXUOiC_v8WNLBLg4k| z1QPTSq@teI{!3Q9V0t3|92bNi2({CeL$CG|crbb&V!-iaAg)3}!5Fmzb@@1_jz%K) zjc+<9mVBYBrkB`J&^REmgInWiz`f2%>!LZ*_98Tr>TgqdOup>qmh5;jHD{`&EQPyh31WFF2v-M_bw?dQcN!SH(=CzpzM(3Gr=Lia`^ce;1Sro*7?UJl84^{WZP_<4A{I%L6S=K?X!Msq z>{&owOwcb?L{R}kvO?uXD&k*amIo;By2ftT2b&@%vdpZ>5rz3fe>WQdFWn9|Z(lzr z?X_rz$*z`#JykdRT~&~sMNjR)$C3=G6E)X-9VkTOkvaa@?>(@ubW1ROm8qn9oEYF) z?gFc@7fHxqMh)@VqH~kBd|gk?uq^x8OnC#q_SOy8OS3?kumL$C!F*6ziJ$-rp+S3R0Bvz#-(@5^ZT(Hmo!d9+<6MjM_I@Y-DQj%(2xR|&Y{eJ(L3(R1ZW+F z?I`)RXna!>%)Qx&1X|y|NYLnmE;{6Hv0r$teRjYRwB*R}-OIX2;j|1~O+eX5C1dP( zs@K5RM98kDNG6}U%)`Z+UiRJgg z4e?Z1ibC27zktk7Cm6)hEEh^+OFN(^sBf%iX;T}cpo1A93x0J*iht-fiWW+YEfkp| zv~IiXzMnEzHvP$qoxy;vW1ToZuO}|&tYFzrmU{4K^Kp21TUa7bH^!OuEYlK?f|Zds zn!d)|VI#5@Xk;O+PJq4C7rzWF1g66@!ug~WR#(qTA$ljU40(ind(i7HtL2>8LDa_$ zh8PB?Simtdz4xi@^EVGJ*Ae%wImw{}YHml_m{*-GuxK{aSu=44L2QQhkPRz4v+~PPF`HW8&AA!eYgW{7Y+F=Rx8poD(@Sb=R^|+ zLm?wp&?#O%?Zy#7V?IL(EoPpnDJmX3!7H>sOwD?i?+tEmUA&#?pSA?SJ$uOSW0RBi zX6v@$?C+`wI~P)nZta&=JHroKkFF6bo?ZtBOuv+hodl#EtOl$~GZ>e@I1D4yJ?WLelC;K&p8VeW)E`t9`LZP=6h&Pi))ao?qtH-JiD*T>6MC+?ZB#Y^<{6y8*=$K8Cupj%`)z8rq3E!tN-)km04$mz! z+dFF>O2P%is3JoQTJtMFu`*5*{9jI4r7}qe{~4^mzTF zhO26QKZepf*C1$woX_J(chYEjPgdWLTNNb(j+m2k0i&y3An&S)(0IltGNdblMEjAapp4NN-dsqv{m1j^@uv)$&Oa`80rZw21?LC?Q zhK15{J$1`~flHz*9({?4d*1zeqzG7$fLMcDM{O9TvV34ER30lSakyQ_LbyI^-0&Obwgh$6wCOY)OpSjWhBs@U5Fi>M!@Nzwh*4J3{w@ zoD`tl)Vh^A-3$+k44FH5^3%yuT{Ek16)*v5_!0rPM zc*lA5B}cMsrFym|{3XCCqpb2uYF3v?))LZW4+1rs1CsJ2vxxpX=HLKD8o`P`1gJKu zI5ASUIA?MKeVQ*5JWZDeQZCng>UIX7fkqDAv94y*2G%X3##J5eSHol3-QUea>M+Yk zlY6ObKED1LKP7h*-(%m29skNt0Usyjxru~APey@$7&-rqd3gCeLPOnrS$CVg9u zz^yLldyR}CUy7rErChvX-YfZm)H%4z^)MO7BZd`#%b#&alWpGBEu-I*!X6+a036eUdvTi_S&z)&>g4k|YQ)Au~^wDIq~|I8#0w4zH3 zR6s4T>6&wr|B0S;@#O+NyY+{v6k()6@dub}F@mkbKk?0udZP@~A}3#G)WQOgwqr~2 zDU}8kTmzD7rDwfj{2nof{&0wIT;M#ZDRBWUO>L;Ra-OfCFStJCcvt1A;zpsA8B1hW zkUoxRpoeqj0{td(phML~La!PEnH-#ir}ZV4UDR#HyY~gXPOUc-dS;pwg6HU{H*^Rl z&-tu|tc*A6*st<&M7qe0@M(4Z%GB^mt2Wt58ZhB}^7AcZUX&=%%dh)#Z2MI|xTy;s zLh8J862rjVUg_ib_U#nP2%PYW0b9q&KFjR`Z+v-3irvqP|LXvwYa&5`&*&^s6NVYU z;i5P#Yxs088m6k~$F=WG;21t!5HII14Cz6rA~DIz=P>Sr+FS?tYRXd<|1HE4OM}SX zdahwlqE=&|F?uzOz_7(6K&psWI{eyb7`b7kpk0VF{UQ+9_OmC4%yG=wXS>KjaicQs z*LDQq&KH=hUkRnMpeikBd`%Z>T}z3}A5CfELXGG8#~(hdjZO&~$(2FA3~d+xSUeWg z9qGwFNfuJMZdHI8VK*|fstTc)kRqa1w2(K}P*yP~q~nt5UH@;3>jLb0cUq~y)uth= zz|-UmzuF8Gi#;C%C!GG2?wdX4J`wL7(J;ff16s0e$N3NJl*VgDs9ZKzHm$!9OSAYr zz^r1BI|xOFHhwJ!6fS)ObjAo7x$w7fe!797?O2b#Ko7~+@AJu1%HgWg-3sB5?2}#U+`UZlY-(Psw->pVUq_=N#p$2tZs`7zfB#HY2*s- zR5p9it!j2-o~#}}ay=>kB)O+or-0Bn^)cWg?jhvgr7F|()e@)bt$|+rVIf5$Cna?X z0Co(x;`fE^j^u=K;L{EAcGkWa|IX2HK15FW)kk;d#C_`-$`O`<}l`*2RTK%J;I>C{rB6 zI*fD!zZoDxUosQo2VVLCD;3zXQ5lXSX9hEi#uBh0j(7+4lHxZ3AAwpemp&UXb=FeU7u zFI{n|w*fnwayj{d-&$C4t_39lV^FKwT6dH#R#>7EDHpDj$xG$3q(~`FsN3Ug^zb<> zq>s1tr~9C2KPf0^s%<*WOarw?TpEV{t{(`2hAb5hpp;~x3`P(MVA7vbq}#y1h2im} zMhhEkS1k8WEiXI9R4S;9FIk;41*5(L6^SbVPikDxMU>X}Kh3(@vT}Es%Wi%vfS68e zu-W#ydGUVec=^t@)Ha?TPdrYO+qvujH4vZ>8owDT(!7SvO8T%oU`RBClF9Az;+Lnt}?|MIP2(^h7QS1t>!-WXr!gT`>FcNIiBc=XAw$-Qi;J zqJ4fS12b-*d7`BHPc-phc}R-8;rwefSj-fiMvI+lJP2yOM7SM!PIM;LN4a$5rLv#^ z<)ypUh02de4@eQt(>;7$q_5rr=LYx$JTu}*H6bb#qIo1qlNTBj+oV1wV@uV=KSlgV z@7V%5kQuEt0v#Z5eoFJRln3PW1H}DI@csBY5IUHC0%FkY9g2eTKN?=wk{voLpVpDg zdrY!*t^OX@KjwphYh{2@G;`m{rb%8uGjp`3#{8y`3e`GyDYnC1XQ+m`(1ck*=~K}ooK9F&PN$zwSB z>VSc#5sl%UjGn#$YrtZ2%wcGSFCR-Qyu`&q1VB>+H|q6;8o7KSPd2+IMG zNZkA}h*>O>w^e*|d)g4iNS*wSqEyrpj(ch>VqP8R*lvcnICij()+7d0mg>YoqWfw6 zg2C29HvSU+rS5nyq07Y4<@NJ5cH#?8!j$%{Im5v~s`vX5k;Dqtx>beos13TD1M(XZ zf;Kf9DJnnmZyT(#2-v!Bq{(cG6=~gy{HtMoq|Ddo_C!m`?*g0*TSb`=QYIG;*w6)| zv;}AspYom)T~T8Z@|oly!SjlNp|21H54Dx`{%#0_o*$m{uv8E4_Kub398(sBbENAH zSdGor9m37q0!TXfF~0VmM8_F9EmYbA_0KrnonT3L&*(z3%h(F!WtsN_;uz*l$>;B_ z`V1p>H61w5odW-xwFkEi5I$^I;Mr5z_+`yIh(*Q){o82j@U5WW@kwY);fzzKFejbF8rMq^K%)IKJ zKuZOSCJ3ma^l6U!EYU2HDx+vcZMsGrr%AmdEqL}JV;|iGPnl(#EU#!&p&y@M-yXWf z?_Iua|6sEUCe2CkAD_TnpJx|Y_l~B)WE&+PYv$!zI9Tjd`4aGcL8cN!Av^cPx0#gn znPu)$wynzVd-jlM*V>W&h0*{8^1k5rG@E>D6t{tCD-1aoiQTum#mz7y9L8#4^z-}) z|CL=`K3v<2lpW8Fb=x}<6qWEzT<@{yOPHl4G&C+5*3PEGEjlAbRktakwcYO6#C2V3 zzdLB9DCNRjKW;^S>@;|i&=hxH+?})L5Y@wxK zG`~hbL-v@Mqzu%?Ra=E!s=p5Vk~dh`irwXJCPB~5vvKmV6=?JZg%=GN!CUqx5MkD* zFLu9x(>g|vYxW?@97bXzw-0$z|#L-PaO3dm67^$1UCPRDPB zmX=C-C3c)dxFJh&VwjlR78rz2#6JnSra%7 zcuyP=4mt)|Yb2_-g*f)61dkQEG}B>y60Qs+IS5VK!`uwkfc)`r*urSC2XnVm&tUp> zW^8An?|C&4MIXRp`q5RyDDTf|baZ=c$LEB1GrsA4&w7ISIb~!umA^2#%ZM<1k<}~I z>wJij8au9rvtt<)mx{@?gxj)i7-T%{i-+3X0L1N~l`^WW<5V(KmtaC2+J#>4w)SP? z0L_xK0M?t*2LjLC6QJTMsW!9cVGDDw%j*Q&8BK7ph*tffE#~uk!CdV)@#;r;8_JKoV?I_Z7|@aDfwDxtLU}fV;2hHT|LS`f1cT- zno+$i815z$CSl*WE2~kqIez|wmI08vw1o)jxuw4haN!y=+#0dJ^i zp&8LUoe^S^I)Q#}7n8(nxHw3LEFlap51jdzss*`u?yC9-W+a+jYS>!-EU=o)vfqG_ zXvSn2W%b%JXCJ*%vPQz!-Ur(b$$RxyFq$R{_D`$kd)H0ZOV`TF+g)rTvzal|_M);@ zWJH=qrp?8!9@Fjw^JtU+(4OvU!e{+o`o7 z%yv)XlRbPTCI}VnNEr}p#U6aRoY7HG5EV%aZAwZbhqf>hGV5uZ(mR?+Is7OTJHmyr$A6rSKE?T2?G#e5h!I2`Y?BgGB6 z#kkhtw6@4ibXA`a#)Ot7w)X|<%?*^N{b9ftw08DNqkTYu@Sd^C)0pD^;05A8Q$W!j zo3B`|;xf$e!gRTleH=%m`n%{49lbV2EVP@ zX``>PUCi6=N}1b73deNLDaUBea~$>jbe>*Amqw(Co7i{DN>QcR%*UJL6vw+o(el(p z;i*0E#jvwExQl_I72CuK@$2GBK1leRLv@7Y>RBvgc>R@cK-_ZBMJ*q3+KS?^b+uec z88?X(A7LEv-^Zcl*z34b!S$13#qPGuldI7$^INFNoRxpC5;x{Mh`mJOsAZX8BPSvA zU3;VlCA}VUV`C|jaK4EM!d(YINL0WY&`J#b31p&HFPHmPRLNaAtp;rgu#1yHUJ>+c z`=u!_tVMjB?T>P5x=9)Q2>h7)GSKjQ&=AXMLK!W;e2b?0x$u`I#3I*9w_!z%+U2T3 zhmBCQ*7w=j@U!d|mzCA`vvy{C_vrTIJh2{*SEOZvN?kc?S$Xqg@5l-17cc9eMB8O# z?5!sQ@eGKX|$b@74fIp~NRgSexJZyK5L0|Mk5848dn+G}qO^2x-?XJk;L zBH?yO@61Vh|E4_>mX?a*Fq|nK1Ld8kGAIE#1T_W3@(>x)N;XSNX06?eZ{x2o&X__- z)F)+y%Q|wfXUlDk&x#EL6QxmyJAzA?p&uN7WZG}9OmAjl@nYj?9kWdTbNX8M%?me` z-ab}tPQ~<=yF5ZDwXEx5BUvdA0UA@IqeG_M)u)@wURp3Uf7{Csu*71_phItP>qTDH z%87Ot;2ZH3wm^3NMRHoV!!PtyuinB8=^kUSeDC;0H{oC|JF(!TG|}+EK!6FQLAJR?~lwz;LMv#$sEC_{8W8u^fvsB@Qm*Pb8 z;~K%Xec~V08hH+l-4LAf>o)IVRFmv)h)i_~d-AT6nG&BmI)x?C7LUB%hyeZx;fUKL zwQP+>542gk(-fh8l^Vs3?&s0%o!^PwZ=Y3#Ho$B{H~);}_P&La{SSW1{O|cG+i#Bl z5A{dq^Z!HrJaP&X*CG&w)?4Pt2Kxx)^v4tiGoX}-@MEFB?DjU~vN(&muuzVa1?>22 za_^t48!rAg^*12=EA^|JtyiaI7d&og!V4vj41N3u^=th@{SR&bhx(2Fh5EO9(mj3t zU+PCSu4A+U4B>cj!R{cW=-xM8TCMzV>bK~weszWIOElvqDQ;`tW5Z2n#D8}fJr?<- zo%F=vi}-)2zrz1NsDDOp^0|g6QL!8H_Q_TDAtb#-kFY7r8s6U2xS($=YjsN8dWzpeh~RK6y* z6UTQaDX6lOIKIaB#0f|sBnHeuVp1_hAm|uXq5}quDuk#QKqpMv0Rs>NMo8sxvew>f z@Bf^?6(=7RKi{|aS}ULP`tkd|&;9oLKmOZ)mHfZ{BkaHVoB!2+_&@xe-Cy}f|I6;b z|GWR*zw`I@#ozzW_`iAhum9n{{kQ&M_Mh7SdGfdOzyCk|AOHB${^MW&?f>9kD6#+U zZ~gOsWBm{Q<-hlje)m8AgZ~!4MA`qm`nUd->wocI{!9PKU;AI1e|7b5{QLF)x%qeh z;$J99@qhmV6ioj_!J=4CKl}~s2advj!|^}RJpCJjW#IdN6Ar-mGY-PQu^-TNG;|r< zJ?Fl#A6|dMZO*B$$L?_I;V=z2D&wcBbhYlPpR>e2_b+090e=4C@0}+_e8*|u&fg$8 zg8#nKeY;-0%H3f)ry)8`(u!w>Q4oLzqVtN-oq{M}#ukR5;ftB_t} z>qa`I+49ky+=uBM9>sw_{_3y)?l1kx^ku4=3gG=PRpq7sGX3^f5wv`szQE`CGWx3@ zox4#nRFMimrtskViJN-cahWhmZ!{{Ga?l(Bak_7Wte;_cNKrs#_$Y0~+7i|9j zhp#`s`rTiGPk+)KlP`{}etjJL_S;{j10<_t|C{F;e{-lS zbcz}j{|$!zftx(*{Ab@cpw0OY-MrAMf5P2oG^_sL?d$cQ{phOty$|jO|^n-Ky2|@o9pkVm#1(Y4FF1!ALNmUK1T>zKa`GPhu3=X6D zeUmvJe!RaKyYfjW#{+sQPZi9+2Q1>hcR!l%XzXW8fG^-C68({=fM)&#*x`!=N8Z4J zIPm9pK+x>3G3M63Zk5C1y*8~QioU-@oLUq}A} zkQJRz+9j!Pk(DVrKzQ6cq-FM55L;5>{W`4Tsb?MK# zDLrN9bolvQU$6aHw`CP9@OLPmqm&@nZn4*$vmgp*MQ{aC69gG$ZK3xU>GinaAJKxp zY4Unp3j$>qr70ko@ca=47(f3g!oT*HC*iLN_Ixw^*n)^6l%Qa05fgeTEMCI|+ZTj0 zK<9fQ6$C@P9hUHC{@0Mtg)Z5YBMbdX78U;qP!RHye|_?w z{#QnCg5XF$E_vn4f};pR3U^G3h;p`ApXWU|yykAtpI<+)5Lr0yVAl?sWY;U$CP_H2 ze;oJP!*62+O@o!%dOkq40D+RdQAIZOAIS`gC^e zdl4ziCqOk;C5=;E?4&%@YIW0>hQzsnY^oc#?)3b?X}BYuyqaATD()1=wdGRhb9KHI z#zL%=QVAB#$_X*tub%)H*HzAOo=;m&dEA9T6K_@gw8i(AXi>HiF%5CW=f`D09Lbah z>BuEp8a+_1n${;R+qJ7)BQ`l@c%}XX7=|UC?W<-yT=q;-w40)dqDyO3ZOhz;u0>K< z;Te{HUaO*QtK!+#gqu0c`={7zMRT;twgX2YlFfRvF8>Me+a7HEavyCgy^1ROe!Mh@TQhFi zw5Pg_+O9K*v13ra7Gwd)M9>_-wqV`luE$WR?YzQT>Mzza&JEkA=3}(vSeJ~Idq45z z>QGAO{OTnuQB`ZhMJ|?KTy#luqKwDMz2u%ySahpIr{QEO9kD^&M!G&{*qFD+9m(zf zy5rMxWtNg<<|=dT+|4#_jms`^ip^?o8abv>`EGg5N>|zEx-s663oloH92%=XYL$Ng@*!vupHP)^uUUaD;~ z*@&a|*4Q{L7uFMCS?Y9uZtstSmU$$x#3;eU?Q45lxJ?imChcAOwFna|9Id>IW)my* z4qMtsFL&E@pLxr46gJfD?05DHV3jV&smpDn&J42qqqQastm&LgW)~;$w4%hdRG8Wb8>M!Xhz#OSO!Nwlga_Yj%(L)8QZBAG5UPm3< z8z|>=X+@x=XxPE!cDNED_>w7yif|+=6Pj}%R`>quuiKlGxv6+Co&bet*%6WDV)y1d(-PkY+f3aa9sBq=E3)oJ?q=n)8G?_JalG5gu?mjmf*^>n5^^;^mW8r& zyzvPz%8l&qM5JpN#yY<>gS)5Wbks~SC8VW$2)5YnF(6p7RE#FuTn@4vwS`@*BvV@K zSRnMk%N~6>Ow3DSpBFywQK#Fz^*dL{xU4kxbWNJ4W5_JdU3r!i*^J$+6T}oJHlA|M zimEJ}eY-xT%z*m)NbJ)wG`DK3kbqbi$)i>leVRM^`?S8*lJi05D zuqQRJF3i5})Ff`wV7v9G#;~-g$mu0J6(>D%)F;4UpAowSS?_~dV@h;guv}wd#bN8_C3MR|QZdYlHAw2=6EA$aGWxWWbJ-NUY zCP4Og|FF)QVqv-w-!3}RxT&ccpSgT-ZhA}My|SJ%ZFg`C?X=f!;f^(o3$u=%0NujI zB|06K*FtmcOB^*4zrNhgS!LGa>fyBxL37u7Ay9QgWmQ>rr<(M-h2VyFrFJCSy$HB- zmPJ*2%`hQI&ZA`QAjNSQq|VhhlLLj7{t!m|D2g%H?1e~KVaxG^uSH(-*F$e^vc9B~ zxY7{)fzR2aalFAtP{apvh!-742z^H*6TxmW$)H5Mr914C@FHYG;UwK+$?TZpQIaS2sXhYBcc{v$H{4} zk%3H_6Ca+VJs}7S0wG+XuXp<-8mz-O6@|5E>Y7-R@bF34Db0y{BBe9=B5@Bz8%3Vr zXKOAc3&NLU$|-bJ3rwdX)V{)xWP>-vVr@4ziEmt21HoTMU{vcjA}fv!l1Z1B3aF)1 zX9j1%QrP{%$Iklo2FBs~II6)ZzuIMm_V=Y((7RRYZX^L%*)@_h-v#Tz#5TzF-dKyx zI*Ch)eQ}DOD71949akeBi>Y5F9+fx)-fUTK3I9)<9o8(I{n^hBS=R^0thI-IP4YBn zFCC}1Zg(~Vv|`%Hdd+ZkTO!_Y?pqAMEbfP0&g@tYJdEbXxmbw}>G4)%i!kHun%JRc zzST3^FrqL*a{s_5glz=6ulSqo4y>WQnlINfu?c&{ z*%1dGT`SIll8+S=?|?MKSYKiUo2K-^7TwGkgUntT<<=XlrH~zh@;O7jU07_8EJedT z>#5qr1$U9^vuS%ai{2!t>@-d7e7h^6deo?iUc;Ob%iGUwR#a9ISJ;ciK=m5|X2it$46#*yn6(Ro_Oj(MS-o(hHF1oy^? zaF|?8r`27^m+BNaTRJXif3Gy{YY&B+Yw35@^)TT^v~BO(=rxcxmRwuaAvW4Z+FYm6 z$QyLnsg8PS{NZ7zCne!nxdXPkubZ@_uL39w(J(d^uMC`cdoPl%j_<<}k9NbVD$ zP@Qa$u-jexv%fNpqmX^V3FS3G1x>Y(XiaR-Hx`)1;7*5RedUBZc}0b_bV1F9eA^vg zCNby4aB+LuFBp=&FbWWJbV$UMTuo|!+9&H3Td@b!3{bkcA*wuXGo!s$)5GbB1-eWQIPN4m{>eN_cS@Wy}(zbF$_lSu{2q z%d}lT){fpFB-qgQL3QFx$6SHK_i`(!Am+S6yj==~ZAI>3hf^c!M>3cBCSM8{RA~Dy z$<`(1Scg3G_tpmK<%m#%aWhesbG?=;^epDcHpibx+2+Qg<}DX@f6ym++umSDnSYt_ZHHn&#O7Lp0}{`o&f2QyC?is+OiYsEoWSD zPGnW=V};^}eR4yauj7Y=f}tqCUBurF4KI&`E>UJ&ljO_#LMjW00kD82n`H$UH=f`9 zczLic^26c;err4d$*<{*uxDE&G7eX)G(8&ZU;y)+;S8%ZZvAN_ydmpWO3koT69~R{ zTZr4!fEre_F%A5_2XYTi>tNeTlOVKSFRX*T-fW95T=C9oQ}??kKp?D&h%T9iTuJO+ zo$6dIG^M_8Q7Jqx(?yE6+_nuh1sv+X(oSb8^wML`AOQVsL0+um?w)v)`eJ_UUd;D^NJpha>&@>UZT zH$>ijl{QBPDcgQ|CQSG)aq*Dk7E@=E9TR48e2W)7dAc?}?Wy*ul4Ps)4I@WVuQBxCJSY4XutL9`eAKFMi_JdHEDIc?A6 zYssT^w&96(iiXMUA>EnGN4ENq3!=l_kVDOS<(~0@aE+8kS}ox&$PP`5K9u--<`dHW z?vhHrRqw33dCrh-AM2=}kp05|_pKhM&5c;5Y2a-P^|_@+=VdKMwb)^%$e_8k!)CtL zIrE15#@W}TiJ=;Q@zTpXe4|R_HS2aWV@Z9-K|-dxZZ{@<}S-|$@6OG zuV#ws)PQLw(%P!Q#u*(x%~EfphV8N=xI=JQzx?G>ig>7&w2~E=2XI&%Dt5;1B)jH$YOUf`<+Z*xW~}S=8kwGWu?ZB=a7r3)KCh4 ztZvk4dEkiA?{-+r<=#Nv`D`enrrw;HUE3_B8AE`VA5m7G!hN=q4Q+S=#6^mBkbOz6 zN5MRZC~)ff4nk7Eb~sv1^Do6ghtg)?VKeAd#-_wZIw@B@vER zbDy$-e$6nvVm|BNT7JQu5w8e0tL@<1o2_&YeTM|krM(aAg}<=ejdw2BomptdZN1rb zyW8av)7hG}njpiq($rs^qN1^e?v{wVLH41n0x`J7q|n7$oe;?)V>M8yw*MwL{MD1n zzu~=}zXB>xgPU`)UOFWkjrN=we7>C^&fykGZviv(lA7K(cb>33HRv|r?Z@(Xq9?ln z8k^aGSy-Ow(@#RP5;dr19(wL!9bUSu3ym%WLX+Ub0Q^-M!)}&h1ISrd8AjrE3)@jp zRk2@7t%Bi6>NVuXg#ZSXI`@Q8Ss>N!32+@Uyok-*yHA01!3w)f%-$_QF7BEYy~2W} z)ozD-ZgPRVT3Gl5fg+T$uoVi{jfFTESZAttt0U_rzEJy$gbZBNmkxT918Y%6z_VJk zMDL`Ba`_HL+LLLpsI*DJcv>An^R40PO>Qr_J1p;ceL?4|ck?;J9Az3R3Su-}ISCRH z30lNU6!)gaN6shwoaSeD@AhtcUacipRbisriW*QJY0#SuyN&dA!tx$^PG81Smzoky zby}zJf+QV+K*+7WzO|h$we00Ut%8H+9Vpf2`X-@#Ch6|B)EUw`*s#bl%^$(ebt4!U zgw%6}K{Rvy_gi;5-1GZdUm$R_Ad5Fxw?*wHV7T9FKEH7jm`==GU3AzL!UFGbPH(-W09Nm0L$*oC^=owAXdX`$PqB`grQ%@ zjC}mq!%E;1!awgC7V%??;(K<>Vkq+>>|GEd1Kpy`pmxxy!3TX1E0=1@?Z}EQj1Lci z=XH4eIH&ZgQTt|j*qnhDr4w*ZyJ8=0U5{l*p)~WHAsDLLDY)|5>3BuDZ43mfO@Pt% znza+}adaD*%`nPn2d=LfaHbk)Bzajl1HVai6vts^JGNyRlzzpr^Y+SY&LVrMh6Dk5 z$F%!vVqWK11|o0Kc1Zh{C~3M~wMz_940q!|czuH+Y#$p9U6j$S#b;pvuJm(;R*v0E z1El&bJCUgZ8IE`>nx3!WeNtaS$!> zYso68NZt!(KVw18$k?9J7f*MSL)y3hk%m!+=#1}?T7r~-D@`P~~z?7!J zE!MVMQ+TOSqC;kP><&9zTkG(A_Ela2BYh9T_R2Yo3Npfm2Z*~SgmKy+qjX#+h%|xl z1P!q{7FX?hx!+Rh{9N+!h#g?sOBx(A`$nh^WXHP9$1 z;{Fd&>J#9Dphk2h-3upD53YP_ju#v6D3Ju|oNTQXY{R)iDU&mrYkevixr6X1R(3H4 z(bUrhoem>}V^eC^RxgRoRg8$>(TbO6R~4sLF6^6Tb0cj2N`Y&_0o>P__is6UMCo0L zQX3DguJev)$QDGN4)jpKcD#&s&fmO--X!>j6V5ca##{hNF9R(n^V+%vvIGc%-a&%S zrn#O`62x*Gw7<+ixYAvKeGx5A<;$(G5Gg^c4x|EqHIVbv*+f?6Al`uy5vg>7A-2PV zMBx3Une=T|>!wlkke8wFZVS3+`IYN&P$17eoc9<)Zb_lgZrPnZc1LvTzDph)TTFKX zi}>?(aY2E7rXi?@8FQ zGUl-1ElB%QPA^arZI`5j@;(Yn4<`*YR>r#4ANbvR8SU!v7lX3F!p8~U z1a%x=?#^jXue_*ULgdemgC#Y`#k9Vjqw|nbgXn3REi$(@Wwd^g4Qh@v6A7wSkZ9s2 zyoN%^CC<_si7fq!AP`V+08tgG8WmdQ_v%)|NZ|E-be18o1hW{X-ssUuq~T^z{`&Jdgc{A4cJn2e%_B~G14qDO zdIDT>8Omh|5+7o~$t(n313efB@$?#$&;Bbg6ec|b^T@J89GFD$br8v%xFNZ}0K#&A z0{0q;I3Tg%xzxE`VWdCk;F0IODip!V^K&YZeYvww8%+z=hXR6@d$p86BJ9HF4B1n> z@qBFM-Hj@xCX_E1YGCH{06?*tx0d(NLi-vVMThQCrY}?Uwuade{?1=TrwDZKYKMZ% z43bxpYwL6PY)DKq>9>e6D5vOzWCW;kFaX7XGX|f-U_>;JnDuo&cB54l)fszUf}1wX zP@JORrKA*Q1@V8SgQZ`%BOdzP0~M^`(qBgpecl~dYtRGVU1(2xn3uIrp7UBBL%5J2 zowI)~dA=&B+ldU+C|28kcuctE#i1l;-XjmB({`7TIojS*A2-WA%Jm$e8)Tqz1IrON z9)L6o==iLnufTX3kn>e?n!}MOHZ|e3Jzmgj20=U+16K5OvmIqn7n#B;ZM|grVEf`1 ziA+l=SQi(Fv(q>J`Z72V^st3Pp`uHSH3O9S4FI+V&MZq7ZIK6D*IJ03K9_u%O$GXdGS?nOpO-HXnG)#)t`xv>FNjk>))2J- z%O9L!E_*&YaLlyX6j8q3t-Nqg>!&9`J>nP7*|REALf zJm_)EVZms+L`$?nfdb4DF0i1lOZ1LHG!kW3OVD_zw0!{-q@S*mVCEoOBu0VWh!BP? zqAld=*VQRz9=i3|rc+Xzw+QmbyR+ZID!=z0cCXMqS2bLP()fwk&?FC$-`OsMqCnog zg5{QpP#}@k_Xw1_=uTg+fV}hZ721X|NOWD1kqTm4p8qm9k!C+!5l289h{P1nVO@+C zwgvG3Y>8`^_>RXH^pedN+KC){f<>Ab+19(I(A@Kkf{Z5Ab|^;oO2akR$E=9L3%5W! zuvQ1u+d?R|#gjA1L;eFK(9eD!lBSyjzR~p-Lm|e!+cNt()*E)*;)!Ln%l82}Uj%*y ziWjd8MFif`jY+?|;t7^UXmDDBIeeW0`Y>KoduO}t4&2`^J%_MBl0#QU_6(KHTbX@YJOayFBL9xS2zwFSY1j40$R+5u9upg(pvC~|~^QL{7x z%Lq+#A4NL$rI(Wv5UL6`ca4NlhrwJ+oM+)70VICAoZjN5+98*?U*1|2OmG1nkaqL^ z^bu}_$pj!I9Bzn8^cA{4u^mgIOiRr~zu>{DmpXDDdz0~C78RVyz}Qna4+HaLG!5zm zH5H<`=}8@I+Hk%(3M^RAbICv)2cxSg9rEI4gy`%}vQ?)KtJx1z%mlLdc@b%_63D1GO_3~4~i-4HMw7zPtmy2t9V=$=c*hNvOJ&2Zk0#vp#b3e;wC_(zSRZXal zy5H{ELMxR3ronJxQuFhM~m?dR3&wh;Kc0UpD&qoRp|>Ry>!aM>C!p%ZKeB#T-2sBHaA7l15N^m)3dx+0P)B8)GIU< zNe%K+^v2*;O+)R{zM1|0py)ZGBPcYY)%^kwY20w(mB+yrtUD^N+I~k`UX(ks-MZv(y z4SFqLdpc4lw%(OCwcXP1Dm~j6eYSSH*OIXZa|T1XX7h5f_gsigD+-n8ER_9R&`m+` zO~Rb2np6&lIj94+H&@r4h7`A;8XhCCst`nY$89Y3_MBm{C<#x#4>ApsL}`vBl5Kk) zSSIryE3FP9Fo3(|X<^=Ne6p2-jgM(@NXtMmjG?T8^#vlm7pM_}aNZMOc!6leW5ygr zFYzhxx0K%|mowyjfj6G<1mL=T*6KqS;}%(5h|P^V%(ZGzhHD?!=khv7x_YRhdIDVc zSY)IJeAf!bg>3SuYh~b6T+HBux`hzZKtVj{mvUeh0kzcmQ*bnn=e6*B{uAKrMb1gA z7QzbP02L%5A{(J99n_l%1RUkBg#$m85IjGjeDT|#>XTn(#J?;w{uA_7dHqop*~Di> z_D5A@uc01Un`@HiKMGW0L+;g=&zLEL3GgHwC0%>Ur0rBu^Pw2mS5n(wOppahdta9h z7yW)H);U<%p2lt-{f~d33~~mxQ6z1*khHrYDfNrA^H=Hi_k(}>3^l%UCAR$a-``u6 z{ZCPmZO;|iw*R%#8mfuE{oLlN_qn3@$BJxG{ITX+5S}yqI(DwV{Y6DKR9@T9ifmQ9 z?KII|uh+L{DYz_3io3Q0(GL|*gKFgUdFL0=;-v)aY+a~ul+Z3;V~2X>*tbJjl-7+( z)co-9!@4tMy>Pu?;ixwVBAaRA1}DAbx{Y$K{~w|CE3i}xLV8+4_>-CQLcHSqQ?gKmFX z-FwQDF>;%8SmZZah?R%AhTQ#DKppPCuOH72q=O$XM=+WiHd*3GLVl}*{)&_zi=i>* z-gNuZX2WPkHKJNXf)4f0%38km_~}?fMze3K`)x_^x3k?8%QHArMyavU`RLpW>E-Qp zn^ncA8@n0mh*BEA+0YZK=~0*@LB2+?y?nd(kxI<%LX*m@+~|-!7>r-H8=@w{3*v$Z zHHyW;36bXvsRav#Y>U0W>W}G}V{f)yRi-XNeK_lCtKoW+VjBV}$H(=MWPZ86L$$Fy z=(c<7rpXx(OZBlsvf~cYl23qU-8|xTL2Q|2JW!&4USumbAO{gw3PiLuP(OP;Zf}a4 zy0I6~1dAE$ur!N_v0gZw;N+Gdd_|A- zZd^;Wl)}g5@kn~bD&7irxy>5QVa~;3nRC7gwYVpG%m@EfJ*OJUKIF8s5#hNr9QKr$ zDR%SNRLA`o`(kY7HfVYhtBRB8LyMP(ET8HCYRF7y{vG`t?jj{Du>v|TSDn2Nj3g|uxN zHc^j=2PqfOlQ9f2>+Hkht*1EuiIjE-`uKp{@#YvT+d&z38?;i=MG?{_iJ$Mp!PNZo zBu4wPA(C*rIkL8`a|O7#19hKn>+-Q8gDaB9?JFV7Zk)nYg|VO?_lbmh-|fV@vM4U4 z-58wFu$oeNO+#|3xyCh1*X}K^YYzFq|uf{o~MY zk%Fkr2-03OE?#aFi{43P@I-zl|qz#%%EO=+U&i^C9%mUpgPf~QU6rn^w})^^~kyA zGQkUE0WORaKX^nhUs~^hdP#^W-ui(^7v&t3X0qQ&tEH*Nqn;z0W5ddt`#Fj5fjpRN zk-TwOs-=!PTIJD@V-xzRL}<=9y07eLbekLkw>nLa`-5paHxNTtj2OmNy~yLzA&kgz zsm=a^LoQyT$8KdEteo_y>ed^2WrxcVt05kkk`vzYT4U5+2%Y#}{P!|N91e++lYF1%F9=eU#aM-!#b$LXtFYyIVW-J`_6$n(( zDD@EAUNe!2{go7X{mlsF0p3 za&sXaP#{pjM;^g@cPY0eL*J!cx6}>4Xw+iIhwft^>72B2IK_5V1*n%_kJHVa2>Qa3 zheR>L^>c=|ppm_!P36QG8^_4lSrbW`#5Q)lX5cDKJVz+0Cyp}tgrEU%fk2(e-_2kNWMGRqhC;AE7zVo0?-uUu1FN~$qIGa=sH z7#)$^OAlFxxWA|o8)48#qf6ah!@^e*N$)r3rN?XK2cjHs)rBgIx+c+(h`mfI;@6yzz4;hbh zZs)ydnitj#YLADOnlXzfFfgo%SynE&offIvx6PI~I7+p#EEem6uhqn@d1!R^$qCPY z&6UOge;oOpyiCqM=V>+=Zfg_w_--0FnJ`Xzn3b162D;tvDLrhI!_Glcke5%S)R5I` zTM4^C1d)RhHve`P=R?Y1Q%bm=hT+#hi-a3wo@uUs?IZT#4o2z9~`;-W#`*w+6 z7#ae3_e(-|392Xkek9m?FvIZG$g--)Z;24O-GiMOS^ZN~?udG8up?yC`_`iKKA-xsmJVpw#y2 zGth$Qb_;AwTJt)#NACJaO8y=%O=FX~JAt)y-eIXxelWHsDaP-rOd6-4FOua?9Vl+fl(?l_koaQO~>N8NUAt=EauoiXuy*T$CH zXIDKk!{bFb5^YyZ)k->sLE! zqbx5Yv=lwGZ@B%QZ=WnXQ}et7=cbr9;fZCX2P!Z~a)2JhRCHT*WyA|27+1@FJseC) zQnHoLUofwWp;n(?FbjI+v>SnwIr_@k?Fjt|eZLP0q<#^$Ic?hAqu;Lg*C?q+kO}D3 zw02FeS9-5&VzSv>kK%pIwrp%+rF>7^aVc^+wF$^&soZW}wj13>g$CCbVc#PcyUQXR zZ?M2YsOm>Vbo~}IlqialTi|<=J0Mb29`RKUnK{aydE2&kz&#+rUQ~Q84En;G8}@@Pn$U*j2YWBU6ue5A`vQ&n3xJ)B^Mn z>P6vsKs$tj6L7CzBiS1X=~Q+k10ALU89-L1k0Ti%kP2wjq( z>R7(!(AMgdO$^+=S3!W6m5aRex@v6m9_P35FF) zUyZrVoVl4lGV5@IUVhk|9eS)!zPf(dhazT3mE4YOGCG4N!UHAXmhBTVh|sSeo>zdQ zLff^+qAUs9ha#u2eGYS_00UV%zDg%ffT;{q;tD-dAcA`cIU>B4x`F6Es^JK$S}?;6 zU)1n8kaF|-Kr4ygKD<=c6PxNQR8{ojUAh>4i-ReMl?KSQd3~M^c_|x~AEr0bM0U16 z-fsi8soloiDT=G8t6C3Ni;<=|KelhCmrm`AQy>8E%sLU!F|QA_;*1v&bcMDB*}`hZ zp>ez5x#&hTUQ>jzGyQ@lC53r)YYVg1E@FfrZmW5v4uI! z9s@)<+^LHa9c)=>WZgVF;9h;1OYn%tKS(FtYad=zQ-TD`ZB7;4i+N@afTBCFmo63& zsE&SQUr8i{7gE<&U=I4cg&Y6tX7=IJjwc>BBWQyGW=nxo`vt9h-S?-B50vv6Ohsc3}rOxRC+082a_BnS`&?US?obNThlC%_r0FGgUb z;><%uGT>#V@2A|H>8Hyu29_5L^(HS2_aTalY!)Uj-`907+Bcee0{ljJKR$mZL(!$y z3(#DocC|AB<+ci>P6O}_! zIe-GrA2Bh@i|238r&8`qjTT5nK5TyiUGp0I{IEWs!IUgkjlMq?FVdT*y17G+jq#3& zGP_2p7xp)Dz`G6PB90s7wPgRSfq7*oLfyV3%af&7^$SzL(&t9?^c#y95|H^kyFdKI zCsMxp%D2AVN6^-MAsw;t{9(G_Oir4d529Jaf~WkPk@bQJLNI2lo3Hdftm4OKJOTb< zY3uDZ4yOlML9fy(JKZ3_aOo3<Ma{VRy! zowZQb7WV}5@WT-TRn7^6k{i6T&Ccu9)iBl(hq`o3NA(FiDxB?ENWb-0-5g0o~mgz32+NXOlpy@)!@CZc=$ zxX&jES{j^5yky4{v#n_P#d_9qtdM&-+6GAYg(XAhBpfgyoDTZ( z8^~dl5qi(_TeJxb+yIB@K>Tz?!q*ivZHXe1?q8c1PppVPV zB3IV61&hLM-BM<--I6UYBo2Oa6X=j#mLK(ZW1d*PyD*F6MuepGd@B#4KfZWlzk`CC zC61W~tdGYH)mta)u^e5Sk=$?#v3Ol~m+NNZr6k23Lom`?^Y6H7xT#U!*T46Q_;uU{Z;I#Y#7vh)c8e4RX^QT^CwQ>@hl|2u-#lKOJ_fD>TLD)3Q}02$eRB z!w>B^ol1Jt<1oaB|35rHk9T7pF%IjSG3o?jXhTRnZT}rY#z}Wg8w>JII2UkE0Z(Y|2v;rmmB| zyl~*nKVk^4Kp@TUSbdK|!Qh&JGCUDl0}Ny$k~?7hwTBQ85ulgXrEaV@mnPE#R3xq* zni24M4+U;tf7gHC@54{uLm?mX@>2+?f#cv|f=L(Z<^jc(a5#%O9Y=h(u_-8H4}!?O z)WuV&zck4%8+*$}7}*~~HezYj zvZtq+1*1S2K6VgRb&cY*^^WntFL->Jg+s(7uP_VW!FgbZ-RX#u)_}6{T(|}2#gu3d zm!Nch?rk8*0A)OYxn4m{y}Xi0bQpm*t8;1PJH+$3alBv1SF1rL;E&K0tel0TPHY0) zYp}+?Q+;pfNCJSJ-F&w}X7+ED%UcpF-P)Xq%*za!rQ(!k;21j~E<#%Jgfmc~p#c`Ix*stIr zt;8v+$l)~2hz$1){O+F2`&>Oj9bOzW-g*)pha(4oUn5;}_rmsr#2%Kh)j* z=S3&)Jsj|Pw&j=TFwgRLhvzYk$3H=TcJ-%e{d6$kYe4oB*5~cZ06YKW?fX-={$cpH z^mLgIj3nj*BXQEhDLCQr3&nmrF!BZJIqDAs>FZ>;Mcqj_10DVHv_?3l@!M*DKJJ(B z-dh0lv;FO(>*Vay}h@hyFEmK0|jts`ne( zzJ2xoDTGP?zd_ia2XtW=2Mt?)mP+{J_=_OF;6EOM`vUd@O#N7d(fk*R`_y2=H$(4_HaQ6DBN0Y_A-FFTcwRtk>WlU zVHEy_{4_e=$YB^@>}P%$ME-b=ml!zG7Xy3$TS(x$u+%T30zX;MKaVX@9>#ycu`l#L zi`ddnllm6S_;V8Hz~~P|7`zUN=Dy&cfvIePJStvjk24F-8aN zVcZvj{Q|v1pOKEYiA0{kC5{q#jQc7Q-;6K_{^Hmt!rrIDcW@!laKx7(dsk5&Wl>_&zI5Uu|->)*&>7$vd<$&f!5;k?yK1P&v< z5acI^y^q5%;e!zd@!wB`y_3Tr2=$R12Jzp|5`lL{>oMtr5e9zPX9Dw`943D(!btX$ z!`|vRWAJLbj}(a%@rC-d65q&Syd+S9%BeW@0gf{ibbud5f2LR7i7@$t5r%(q*jq&+ zuY54V$S>q)dgYxQrhY8Kpo^0H^uykWFoFJHgh7eGXDsoZ2xC4LVFZ-9efnWR4L z6pdpd{;i?!ow3BZ?3aR$qt964`(lYullZX+n=9Qu5%xZW2_&f!l7QjzNBCj*TuA!Q zG|G@}jzF?nb{Tp?dAbc#s2r%nELsM@=7)Fb{NXZQG?VzEz8XZv30X@#2 zR^mGmCVni!=DNgBKkSVNlQ@#aC6yvR#ONUB5`oWX{W}wwlJda_`-~;NI=jCf$o5Ac z`ydDyoL)zBg!&O?J@gt8pFPfRjn<3U2P2I7f`1wvZ`5HNjWM)Juy9<*s{`|`Rw4;C zZl68QZ{;wK`Cx=W)zoKb>YW_MelWt|6oJp+?>iC3eK^8CyI0<6)^q&FA`H%&`aD4P zod}~DNst9vA&HMMI>=8e@x6W+&3!DwC^*pVGc@%^9j5;Bh-NVB1)AX{P9;T3B>#xB zrnvd6DT@6M$+(yWRxnD~=Od>g``L;wy}`K+yfrw$XP4@MXq()=kB-^pR{ zmctL_u+MWk-fMJ7)W;$WLQ|hc$2&!$!Z9L63fT88v+vYlP$KYon%g@Ors5xoFsPb> zDuK^v{Tp?dz*8K@V%U$TYQNL0$MN|H+0WYgcXF5jFMaz^gaOVz`@`PJVd4iPjQC7o zzBL~vfSLHA90pe6XIBm_ZXK1_!}pprIxGyJOJb7p*7Z zjisLn%(v<=oTo*R;DwJu7!4M%i;mH9m@-<_)cP7b5t?M9yndn3X)R;6T4 zkcjWj>3AQ)pePZ}>G+H#z7b&z&T<^Zvfp=Lz7t`e*m|eMp)jnB(G*809}!3d-hx9q zK1-(F$X+Bv2^hSO>ihP~cd{1=!QanN{TmTRh#bRkqVQn|`wVlu*J~!E4@MXiC4P#; zH*y#Yxn@D7#qaxN-zgH|kPhn8rhg~G_zyNZd~Zb2*f{O-Wt_XU3;w*nP7pV9g^A`GW^I6GFMJ`7>(7xJ_H@{I_C!!0HG z|8DQgcHGFa?H>GAKz)H$9{u2ZK1g{fhkdY}>-7ab$pdoLiGD*hFSh0t*&)#e69^sA>kq$^0N>{id zof0rv7%*^6u?-^xEZNjIN%!dHQ6QF>J2-QJGwC=ixx#=2rokZvOnAiTlQ&{tYZN6y z_g=QCm2e%SeGl%vn7Q}B)4|bt%HVI^HpZo{Ee05Pi`a%y+OXaS^l@&)z9OAm!r<0( zULql2p+_ewW4+kd8c_p=2~5G`FhanR(OSiX81T+Zqy|hQOMn3*1Pm=aO!PfcrwRcE zk`9j669U#Ei&V5uk7S9|5(ZWko^hu165FOQV5msv;4h_wrLurokaVz@NC=p2L|1$K z-3NcERU#5enLn0NCF)cdFr;d;mq;jKqBCf`BD~lKe@P__T>($Z2krDlrxZj8g4#xFhYGOMPIuHyecI^^+*mtn;gy}r4+AF zcR?gy4lqnNb5bIqgas5El>|(4o;GcmBc#HBfuw^&^@I{;8td!YC%JD|O6_r=gR^Co zNC{Xf3>b3jIaE&wn2lC7btj8Sm`4+5<}IS*Epn~3PWDEL0vR}{3ojp?=NqALg(51c6@9l{17<*{@n zfVU`F+19ZWvXXLwAt{FKU>?INcCKICcL3^28x9x1M8(lz_>SfT7zP zl5p5dBm}Itb>BGHuyky^LTAGO7?N<e_VKCBMK08?CnNt)BqBpXynO)(t3<=mdfI4xha7>zfGIA9Ae1m&#}@pSZ7~VsUR1OarklcmMb1kk9XP{; zX|UEyv*()1HY}p>IauAcN_VHGxrIj}@sgx{T9-8E3(~^@I}E>%xGkGtJR@O2ASZ zV`D-w3DYcLqyy)^@iO>eMck{z+O?f+t5kgi3v>3=^&Iaw0bKG zSPmz0ULt8;qI0%R#Uw2AG&5j?fW^KvV9bO=X~R-o7%)(EaI~J#hWRdO+lzL}HAUxi zm@_mu;?NYOgk_Bw+5{i*7@DF347EmR<-yY{gc4SZ!hj((#d(Q@fVFieOzp(j-6-dD zkV+Wx5*aW;!0KA+&b3iZQUoXgLmrOdf<8jPI$Jl=OhQwLCHCMy*RnB<7bnx8$4Am+ zHaB#nvOIxF2$*xRlPPp!BnKk~452CZ5-GjJE_UdbBg`~fPbp!b-{YpGlz;^nLMwG6 zMm9HM3DaoO#{*|Vm1s@ZraskTq!pr0Ap3hyG#IfH8FuEnrP(lF==K zQ^y%+G8>k2+`xpx^I?Q4(IJbp7pgxre4~`G3>Z`*kHaVd(}e*86AnulC1Abmx)fY7 z2}5TH4owjP=0#b+pcT1fmU0~CWpTi`dW94)RTwa|^5DEgLX{XA)i)_(FjmH`mz*+1 ziIz>Z>v~kL6hh1MbTet5cGGpOS5oLnMS4KmZ|FkTpdHJ5r2YDHiG&W#73rja)m^Y& z8#N{Apae`Iv7RHpgetLaY8}uPxENp{OXMt4O2G2eioZYI+*na}Q6$&5r;>C?@kpTS zb}ob9dRbDHXoas^UHe1n3Id6gfEkn0PK?AxX@q8MPXVVr?O2$&B^%RYod z+ArMtUc$189_{Ugd5?iJDj~v|MN%RIMhIBwlx;)Z76Xh~RcOayP17fr!yJSBNyZj(+5Sl2a;H(nG2jMIK;RbuL*iQaiR8HbUnM2wnIeyP~$ zAapu(3pddMg2pAG@dI^H&Vt}EK2Lnb37;24BdEQ4^!b{9-zo6e^zz6|T zB6f|EjU3A_DF@COFifv-@Rty<=zHyaaK!-gAh=}iJv#0^(8LDiV_gt1%V}_Bnr@8fX182-$da!DumHE2hr#WbgbQo=0L;1I_WbuT1ZhZO@1nZInq2yIyHobIA@ z(-Z+Z3B%k95=nU+MhKWoJ|fo96ax%S2a|LV0_LslkRhOo0fyXq_7VvJYdsn&HYmb$ z$Gk*Jl?V=W&itkH5~UHgH?AaLhU>!!B~04FfWhftz$gK8g#m-3$To};Fp*4XYg^2Q zVLptjR|o-9+6xm=3{hkP6D70AOJtQu2w0oY*^kqe=mmlWz(O!I?g!L1IFFnC{wlDPFojRTTsF*dx?Y+*0;5L=+<{8+F+8_x@}H%I^-jP{$WTF zKnpR1rr>&r@lfBrUaX#eG<)mclbt(tyMDF(ZoXO6SBus5X??kVxtKj$wTs*3)oSJ+ z+wm~>xBKzqUA&&Jt`?V1tN&8nEVlE@`F1`YVqEob=O@+X^3~b(@~x|UvRgjOFK_0X z+r{}0Zx+A&%jtHNV&{*Q=+u^KTcIM;;IdWp$c-_>=eYSWJo!vyOe ze;@|gQ9`Om5)u}2XbQpKTnxd0Q32M5Hi6<&9ase5bdUlD`aO7w3>Xz)&Un{|&=vy> zbC@h)gic55V<+25ED;h`*Qv8!=(lDrXEOGBc!W+Cpye-p6+x=lbsH|E9hgur~uPF8bP!VdSFrlh6zk| zItXnT(&xeZAo_cWq?CZcOJtQu2$=1A?Q3m|0ft0Uj&u+LX4*!hD~>r#uOLMrz@{P9 zL;2)RZEcT%vqDY>^dVRTSS1ny)@x;J4K}xNK8zYLI31Y4WT%75>5xuD)UTv_tvtHA zOK2J4ls$x6e|~66A@et!8Kk*^&5Z%00?eYxfNoLKH|4FT1k4XvQw$gtVBmYuCaNg9 z{lFP2u_prz?Wi!lf)oJ;j0&*2b+HSkF9w($h*cOcD!^29NIc%q=Qf;Hqm<- zAZHUs(vVzGG9lpMx>ErIW-hBlqj?-gTH~x6ZA34X8t21uq=OPLRABPJnNY&|*b7XF zp{(y{!$<*x-@(y(Lcl=MkpuQ!F~E?j&9Ov6z`)Vbh&FmPR<97NM2mnuyY+;C^}X-G zt74{JV$(&WB}xmAzdhaQkTJXUAXfQD$?5nI@_yUc*QkSN%&OYc2-7f zY>=bNK@6BtoFG8z)PuIDEMSP$vjroxV0Gwf)A@+TrAKNoLJMYL#L(ED15;Fisk$u; znB-9ysY>j;?oj#wOIAq2(4UVbj8G+Zp)g=b5a9V{O281~C?{bsUC69Q!7SS_DjU|c zAl|EukmGC^sap@6kd??@BB6vu^m|KIXgTIgQ3HlNH;&a40w(%enBF0tSiEvGA|YS~Y#d%nt&2Dv=+761#`Zi8qZ)^KAwf2!V==%$ z`oK;Hp@d1*XsAWxP3>(M5(H}GxH*p=I^LW{Z;1>y{YZ&(`1EMIoyqrD!l)z+H4wE$ zDybZai>LuZk{gGnC?!mQhq-I(Vt^s)6V8KeIliUJB8_Dr6a3TkP2>~<4>ZT3%+P#qimdU2rt*4uDMv+RRx(M%nZ^JNwNeURM!#G8NP{LFY zXp}QiiMcwg>D#EK?!7&^!r45MsBi{aV4C8-5R`z$vVb9ApW6%|X3u>gNcuupkXzc; z$OFA4v4mlIMI+6P0V4}d#k!A8eI$^j1`NCp2u(3yWPmA??)8|3(}4zXB7|6@#q2?k z{VcXbxb?7MeqgQlLn0{yMg^Eeg|j!(>V2wqj3%LAOm)ULcz;@NBLHRxT9r&QHRRSa zU{rv$P2XbJfY~PL z)?vnZEa+>SChE@jA`?HqkOon+Y)uBF&SS2bsOklEvQAwC|@amC* zBhx-wPYoCL~C9H{U9klC90j5!b$>T6Wz`%gh*61-?46sbA%}xj11g6#)Y=LC& zP=QIT615w0I@pF$*|5+#lR%4D5U^Zs#DI|j*0-7P*Q+tNo>ans6WH8%;7n-4ObEJ7 zptmds7|(}M<|Xz+506j|FwBP`&5czenMxFOipF7vrNlT4ECOgVfJ9OTj0!Nc-4?Az zE51^Ip*{=+eGC{GV5u-*exQ9|z^DKdGNAhMeqJKxFhx?yIaEHMN`h{4P6tTP)jy6( z{18acgFtG4`Tqj04}%0f__BcIw0hQtRN4?Du%hCHj@yQ_0|>{=LV)nWdM(Cuj+}o( zXufiJGfNmDU^1DyH^CMJjI#qMgBnn9!x_wDM*Hv>vIUMLL>7WY!`Ej0&(mrQ{8!RmRp~7&Vgu7C6I=v=fz& zuBk)amI4gr&6xq6C5%eK>NaVmknvkc!T^}%SR$d*QFlSq%GJ}*6s1Z;j{(g&q=bNl zl)FM$FGk9GVjGsTv{}Lk0jra2LgPS%b7bD5lrR9s2~(5<=ejKk7^-EF9l!%;LJ70N zhA2>JG$u@uszd-52O>B25~;kzXgekSWZ;}59Y}cVqp`+?{-j99Zs2S(rwS%8StU}c z#L%f=Ozo%4dz65IJ(eqtNCE2$1BP)Jho%T^n5ebz2zDH77^zCcbTe!iyY+;CDc^OW zYuh4#Aw@udP@5%;5U?)gDNKGn#oi(lN!m%j?HDGAr%%x$3HY{1K&_5CM*+&L+vT<0pVaVxVFOd>3 zR~#_K5=ICZ!t^zWEY%@epH*V$8Yl4w6VdMxnu?h!(TX$6j1Po>)xq}YDIkjhhWIbj zOc4TRY|}bvydJApAYq-+U9Ce<=<9rc-ai|Y7u^3=zFu-9BLJ9M!^FnvUBn*Tq ziU(nYfJre_Ue;=CrHGU%N&}`a4r8C55U|#S+Gmwm3NXiMzoa%ycCnZB{T#P|NR>k- za8xI@p+eIzxQH<~$w45|@F0v(!usU%s98*N+(-eFXM$}QAz)3@Sl4tGv~9v+5))0S zOqYDEY}@PReI!hZfyE6(ZtNuz0+!His%xYdZ6Uyrfx`o5LcmbR+;vjLVt{e^C2h)- zb(jYWlPpqFl?VgIp?X@tWY;$hSVs?8r1XF>*Dqyay+iS(>RW}x#GTWD*~=P>Ozpbf z>C<{&4sN|P=h6=O0X%Rfv|-MHQYCe|7+|QEWxxmlv%%M`?qxy1xHybbCAQL|iENZ+ zl z@HeOqwXzc%hDb-0IyfsEV?y)Z66S~EFqSYX32TC|eIHSlevHn(g&1a9=$|T!0egffiodsLUoO{$rl3*?3SoCVwFgx5|J?l37dF{m|khnYqn2K z(4C2=t3)L-GZ-QrnFE~xqXH~|onD*99=t?qz~Y%tP-hIqKZDXK^uwwVPjrm=tQW&kJI$;!Wr4hD=6Fr#It6~oRvsQ`VhLpfT6Jw&xR4&u&85OgZ81Agdvj1pBBm_*L zRMrTorj+%RHq3%UfB~Zf45hL~0YjvNRU#!|raWMrGerrQEex1J%hG?0SpA0)n(DPr zDMvacdB0>fEVo?&U>y7HnES%-mVGI}n*?N&tq;`aBe4l}JbWAR4Vf4yF!$awyZ>aw!B;gVFMlhG0{~ zd{{xics`6Wrz6DTfc>N7{eBp+#Mpb}V=H~=ZA7dRbN4VNeIWD_Yg-sF&47_6;SBSa z5U)e49BK&z=>r&l*{!E?>ro{uq@0jGWNI+mO86p9`TjI&u%UKE+D!VOkgCly&V(va z_~L-E(?RJaiclCZL^@a{5=vO#q}pl3rbdF$7Pq5CYb;!J$>ok+_Ij!Y~fw6ahlOVjbIvj#R}| zB6x5(35O7{(AU}o{EQWtloFN+WEE#kkvbi3MLH0gYS9$9NgevmwuiUfa-u8ofD)#RTgge;_8~F#iZ` z1~Rv$7}^XlU{rt^AJL4jPg5_E6fiRot1w_>fVG7I!}JQOR~RrVz(g1O=#YmKkGb`o z=)IQ7bkaSON4~Ep+6t0`M~A|31gK=r4oB- zO=zJP$E+!+L{h+ZeIXbyGQfOUz>wyac{&&{D!`IZh(NW+rohA!2EY`nL_!;e4EnNw zLADV5WeKB_u#kEgB7DV(4QmxRN)eedE}quNV{kfh_b{D1VDdPOGPgeJ-rKGbVlr^1 z1I*-xin(N#C5%eK9GWSjF-}tqFeKqHV1zadebS2pmXi`$yr{&>x@3hg{ghIhP9K8s z0pj(61QMTAo6A>cFBX5DWcfX*Fsu0a=V!lO-fq{MAEs+|E84|o`R(Ge->h$DdG|N- z&F$j+hc}B~e)4>AyT038EIyg+HJiCH%hmk4eftc(e=vvF zHVydqn}7^3*SKMpJfGnmhj`bSHjCBea=Tow()IlI_UYx~)%@;yn}ewNAP?3a4=}}_5-D>;PX@&6YyVp$)eR*;AYQ4FcZ=cTJyt!Up%=6_{ zZ!TXwsgA2A+hfhySDW?a-Nj<_w7y)wT+F^|``Ks9mz(+Khgp1#_UZSwd9d&K2IpB^ zKJDk%w~O7Td@fe&hD2T!v}7FW-+Yqr}YZ?@a?=~L{EtKDB>KJo4npJD!Qe!IAwX%mO5nQoSs%RQz^St0iJ=<>XuA)$Q`Qpk2OtwSZ51 zvACUmqs6Rxg$sMN%=c@5#&O?!C&;&E{BpM!aQJ7@;vS~?n_n-MSFg7-FAYAvo^M_N z^iQk0s;@TlZx>ZlrK+vEs;_=k{knQqeO7&5eNlZ`eO3Ky^}KpfomXF1zpZ{({l5BR zHLvEoo#wY&40Ue*Qq8y3%j)Ib_4Q&~T~rtAYk0vI>zkW-by+Q{#r)!Ki&2_>?i~grukm()A=YYmU9K;yH`jN!)nBW>-mSNb%a^!FY(0M1?J#`W zz1>u|)$QVDx%(2gi*IoWx6ALVTMRm0SGN$CMYXNAuQv<4ez&gfs=M9wd|Q22eP8{p z`rBf&{so?DxZwHzKT-;hLw`NLx}9l2(XUtArdfYK`{t2!cDGsz=LVpFZeHKdZ1!7I%x!&Sx*Sm$T0ompJ;c)$)3wXWHh6>iKTb7xNoDfuH^B*Ds#^ z=088!8#_Px{BpP53&{8O;`Q;7&&T`S?g>F?U{*cb&M};+S69~y9KCw6UEKV3CZ!vn zzP$Z7$XIV?)$jL@mz92Y?}1du2QokLdB1<}0uMsq2YJa~ZMnJK=7)BcCE>xjeasI% zw)zZ@w$oUgxL0o2O{?$~~ZognQl>37S^?Q4h{My9j;t9(`` zyB{fVOY%=%n18hwGlylv`w(}pkh5{;fA4iX&h9Ar$N@)l&d+of5)H846 z@Hy|5x3%8P0?s;Y=l1*IHSY_)gxx+khLduJRHI=Tw!+b-KlvK-7SmTP?XY(~gEILp zS?z~+0pB<;&DWFn%D*~)V;N^!>)krM_qfKq54PUlv*|g1`hEU>2G^T^^WH!I2tR%N z-P(MY|DNrBe4Bj7?ynv3zP}XT0C#J;EZ@OD-2Wb_>&T4JG+56}i*SdlielvYyh$l*Yyi@N`{d=pmw?~&SQc&#O-oEWE*8XK@#+JKJdn>e4{`d5K zwy-~w9zmc{a!A`Ka%I`ucvhzRxoAv-JIbhvQet4%bfKYbetEyHl=N0cL?6 z)EIGSWK|eM#Ii7~v#@!?HrRJC6HvX*?+nneeOA?b)s3qjRQY(E;Tp01_?p+| zZL=zuE}IzR^zhC{*uuPJUc3LM`CFKPI|8GW*JWj$uYOeAMmXvF-9YJBe^12dl9&qBDpBOd3W?GpPd3GK_U_%=y*TVl%#C za51YE*VoH8w@ZAr#Z4aL;B^@5a7$lq)_+;7Uc$4_;!_<@aj|~$!~S~Lm_x&WEV~*|hzciLUtvsiy;|dzJ;qdiNMs_3@U}yXUh8Ch2f3J5L2Scz=*?dXVn8^RwN*Jn(*sni- zz20QGSRfL!!c&f?e-~@O>wc5@^bm+cWofPE$3x9`w`q>0koG-fyVwInaet7-^dQ)1 ze6n}W-K<*fw_8rPTOPMt*-GGaiinTm&CdN7GT!uSY3aFm@Ld_JoN`?IrG&$B~2Y`I)qUm_%MZ^VW#w~w)X^yJCt9j7_M zC2NH7zM5YlUYBnGuI+hMLk;x^D#GF4Et%ndVdC`?+s};Jxuvt}x68$Mi_KS?#UbK{ z>uZ;r#okJMruNsAL$eqxezZS9etW!#-MOpZEb}$zYuFtg&&DvNjiBVyr;`KZwQnB) z7dWOU+zv5Zgz`2oa?oq|^a8Hx5DFeHXcG0r1^;STnV&V>&tJWOgBr7wvD(zu{)&OXzO|0uR|s-`^8l zal!xxS{gS#`y0=(z(|DW?QHtRP(wf=mw zy!om1&*5A^q{M7;m%j(1AAbbT5P!yh@asW;V`o@_tDUULBai%Vw)*&^9JaROPT)z$ zO&wPaZ-i9=ZuY%pQt15k?=M5-3Qz0(WzOW`z_={m%ke5Cg2RApT$LZtcFC%RI&$50-iR_A>A? zOt#BU;Qkw6yfR4Tc&aS#02m0z*Bh70&`*)X~px66ukJh~I!PQKhA@5gn~ zOxI-%GM?H=k>zPTWPVjH=ViUUEKD8{xNHdiZa#+iS1*=-gI^?b)Ztk>`{vXCG5f!N z`o(|$>OcIi|NY{B{>P{P=f5_;n7wNm#OnDP9u)S(9fQVNvD?#uq;kNzLXv#yx{ literal 0 HcmV?d00001 diff --git a/tests/test_common.py b/tests/test_common.py index 3a24c55..2335060 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -159,6 +159,14 @@ def test_lattice_two_tables(): assert df2.equals(tables[1].df) +def test_lattice_table_regions(): + df = pd.DataFrame(data_lattice_table_regions) + + filename = os.path.join(testdir, "table_region.pdf") + tables = camelot.read_pdf(filename, table_regions=["170,370,560,270"]) + assert df.equals(tables[0].df) + + def test_lattice_table_areas(): df = pd.DataFrame(data_lattice_table_areas) From f94777038ad396c40839f98a10805e4149a341aa Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 4 Jan 2019 20:27:53 +0530 Subject: [PATCH 4/6] Update stream table regions logic --- camelot/parsers/stream.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index 82c5fd1..1efe144 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -281,11 +281,16 @@ class Stream(BaseParser): def _generate_table_bbox(self): self.textedges = [] if self.table_areas is None: + hor_text = self.horizontal_text if self.table_regions is not None: # filter horizontal text - pass + hor_text = [] + for region in self.table_regions: + x1, y1, x2, y2 = region + region_text = text_in_bbox((x1, y2, x2, y1), self.horizontal_text) + hor_text.extend(region_text) # find tables based on nurminen's detection algorithm - table_bbox = self._nurminen_table_detection(self.horizontal_text) + table_bbox = self._nurminen_table_detection(hor_text) else: table_bbox = {} for area in self.table_areas: From 62b358006825b700034355cacd1b13b4738e69a8 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 4 Jan 2019 21:14:55 +0530 Subject: [PATCH 5/6] Update HISTORY.md --- HISTORY.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 6a1e9c4..e4abe83 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,13 @@ Release History master ------ +**Improvements** + +* [#240](https://github.com/socialcopsdev/camelot/issues/209) Add support to analyze only certain page regions to look for tables. [#243](https://github.com/socialcopsdev/camelot/pull/243) by Vinayak Mehta. + * You can use `table_regions` in `read_pdf()` to specify approximate page regions which may contain tables. + * Kwarg `line_size_scaling` is now called `line_scale`. +* [#239](https://github.com/socialcopsdev/camelot/issues/239) Raise warning if PDF is image-based. [#240](https://github.com/socialcopsdev/camelot/pull/240) by Vinayak Mehta. + 0.6.0 (2018-12-24) ------------------ From 302a506e1c1390dc0900d0430b37e2bf15d2bce6 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 4 Jan 2019 21:27:51 +0530 Subject: [PATCH 6/6] Update advanced docs --- docs/_static/csv/table_regions.csv | 4 ++++ docs/_static/pdf/table_regions.pdf | Bin 0 -> 262374 bytes docs/user/advanced.rst | 25 ++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 docs/_static/csv/table_regions.csv create mode 100644 docs/_static/pdf/table_regions.pdf diff --git a/docs/_static/csv/table_regions.csv b/docs/_static/csv/table_regions.csv new file mode 100644 index 0000000..caf534e --- /dev/null +++ b/docs/_static/csv/table_regions.csv @@ -0,0 +1,4 @@ +"Età dell’Assicuratoall’epoca del decesso","Misura % dimaggiorazione" +"18-75","1,00%" +"76-80","0,50%" +"81 in poi","0,10%" diff --git a/docs/_static/pdf/table_regions.pdf b/docs/_static/pdf/table_regions.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f6f053bda2ea473db0301363ddc6d42f14758327 GIT binary patch literal 262374 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 literal 0 HcmV?d00001 diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index f454c1e..e7b4ab7 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -206,12 +206,10 @@ You can also visualize the textedges found on a page by specifying ``kind='texte Specify table areas ------------------- -In cases such as `these <../_static/pdf/table_areas.pdf>`__, it can be useful to specify table boundaries. You can plot the text on this page and note the top left and bottom right coordinates of the table. +In cases such as `these <../_static/pdf/table_areas.pdf>`__, it can be useful to specify exact table boundaries. You can plot the text on this page and note the top left and bottom right coordinates of the table. Table areas that you want Camelot to analyze can be passed as a list of comma-separated strings to :meth:`read_pdf() `, using the ``table_areas`` keyword argument. -.. _for now: https://github.com/socialcopsdev/camelot/issues/102 - :: >>> tables = camelot.read_pdf('table_areas.pdf', flavor='stream', table_areas=['316,499,566,337']) @@ -226,6 +224,27 @@ Table areas that you want Camelot to analyze can be passed as a list of comma-se .. csv-table:: :file: ../_static/csv/table_areas.csv +Specify table regions +--------------------- + +However there may be cases like `[1] <../_static/pdf/table_regions.pdf>`__ and `[2] `__, where the table might not lie at the exact coordinates every time but in an approximate region. + +You can use the ``table_regions`` keyword argument to :meth:`read_pdf() ` to solve for such cases. When ``table_regions`` is specified, Camelot will only analyze the specified regions to look for tables. + +:: + + >>> tables = camelot.read_pdf('table_regions.pdf', table_regions=['170,370,560,270']) + >>> tables[0].df + +.. tip:: + Here's how you can do the same with the :ref:`command-line interface `. + :: + + $ camelot lattice -R 170,370,560,270 table_regions.pdf + +.. csv-table:: + :file: ../_static/csv/table_regions.csv + Specify column separators -------------------------