From 72c42c74db16e17c8cfcdda6959a54e0d94097f3 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 1 Sep 2018 16:23:54 +0530 Subject: [PATCH 01/39] Remove ocr --- camelot/__init__.py | 2 +- camelot/ocr.py | 331 -------------------------------------------- tools/camelot | 186 ------------------------- 3 files changed, 1 insertion(+), 518 deletions(-) delete mode 100644 camelot/ocr.py diff --git a/camelot/__init__.py b/camelot/__init__.py index 55aee51..b9b5f18 100644 --- a/camelot/__init__.py +++ b/camelot/__init__.py @@ -1,3 +1,3 @@ __version__ = '1.2.0' -__all__ = ['pdf', 'lattice', 'stream', 'ocr'] +__all__ = ['pdf', 'lattice', 'stream'] diff --git a/camelot/ocr.py b/camelot/ocr.py deleted file mode 100644 index 48d1983..0000000 --- a/camelot/ocr.py +++ /dev/null @@ -1,331 +0,0 @@ -import os -import copy -import logging -import subprocess - -import pyocr -from PIL import Image - -from .table import Table -from .imgproc import (adaptive_threshold, find_lines, find_table_contours, - find_table_joints, remove_lines, find_cuts) -from .utils import merge_close_values, encode_list - - -__all__ = ['OCRLattice', 'OCRStream'] -logger = logging.getLogger('app_logger') - - -class OCRLattice: - """Lattice, but for images. - - Parameters - ---------- - table_area : list - List of strings of the form x1,y1,x2,y2 where - (x1, y1) -> left-top and (x2, y2) -> right-bottom in OpenCV's - coordinate space, denoting table areas to analyze. - (optional, default: None) - - mtol : list - List of ints specifying m-tolerance parameters. - (optional, default: [2]) - - blocksize : int - Size of a pixel neighborhood that is used to calculate a - threshold value for the pixel: 3, 5, 7, and so on. - (optional, default: 15) - - threshold_constant : float - Constant subtracted from the mean or weighted mean - (see the details below). Normally, it is positive but may be - zero or negative as well. - (optional, default: -2) - - dpi : int - Dots per inch. - (optional, default: 300) - - layout : int - Tesseract page segmentation mode. - (optional, default: 7) - - lang : string - Language to be used for OCR. - (optional, default: 'eng') - - scale : int - Used to divide the height/width of a pdf to get a structuring - element for image processing. - (optional, default: 15) - - iterations : int - Number of iterations for dilation. - (optional, default: 0) - - debug : string - {'contour', 'line', 'joint', 'table'} - Set to one of the above values to generate a matplotlib plot - of detected contours, lines, joints and the table generated. - (optional, default: None) - """ - def __init__(self, table_area=None, mtol=[2], blocksize=15, threshold_constant=-2, - dpi=300, layout=7, lang="eng", scale=15, iterations=0, debug=None): - - self.method = 'ocrl' - self.table_area = table_area - self.mtol = mtol - self.blocksize = blocksize - self.threshold_constant = threshold_constant - self.tool = pyocr.get_available_tools()[0] # fix this - self.dpi = dpi - self.layout = layout - self.lang = lang - self.scale = scale - self.iterations = iterations - self.debug = debug - - def get_tables(self, pdfname): - if self.tool is None: - return None - - bname, __ = os.path.splitext(pdfname) - imagename = ''.join([bname, '.png']) - logger.info('Processing {0}.'.format(os.path.basename(bname))) - - gs_call = [ - "-q", "-sDEVICE=png16m", "-o", imagename, "-r{0}".format(self.dpi), - pdfname - ] - if "ghostscript" in subprocess.check_output(["gs", "-version"]).lower(): - gs_call.insert(0, "gs") - else: - gs_call.insert(0, "gsc") - subprocess.call(gs_call, stdout=open(os.devnull, 'w'), - stderr=subprocess.STDOUT) - - img, threshold = adaptive_threshold(imagename, blocksize=self.blocksize, - c=self.threshold_constant) - vmask, v_segments = find_lines(threshold, direction='vertical', - scale=self.scale, iterations=self.iterations) - hmask, h_segments = find_lines(threshold, direction='horizontal', - scale=self.scale, iterations=self.iterations) - - if self.table_area is not None: - areas = [] - for area in self.table_area: - x1, y1, x2, y2 = area.split(",") - x1 = int(float(x1)) - y1 = int(float(y1)) - x2 = int(float(x2)) - y2 = int(float(y2)) - areas.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) - table_bbox = find_table_joints(areas, vmask, hmask) - else: - contours = find_table_contours(vmask, hmask) - table_bbox = find_table_joints(contours, vmask, hmask) - - if self.debug: - self.debug_images = (img, table_bbox) - self.debug_segments = (v_segments, h_segments) - self.debug_tables = [] - - if len(self.mtol) == 1 and self.mtol[0] == 2: - mtolerance = copy.deepcopy(self.mtol) * len(table_bbox) - else: - mtolerance = copy.deepcopy(self.mtol) - - page = {} - tables = {} - table_no = 0 - for k in sorted(table_bbox.keys(), key=lambda x: x[1]): - table_data = {} - cols, rows = zip(*table_bbox[k]) - cols, rows = list(cols), list(rows) - cols.extend([k[0], k[2]]) - rows.extend([k[1], k[3]]) - cols = merge_close_values(sorted(cols), mtol=mtolerance[table_no]) - rows = merge_close_values(sorted(rows, reverse=True), mtol=mtolerance[table_no]) - cols = [(cols[i], cols[i + 1]) - for i in range(0, len(cols) - 1)] - rows = [(rows[i], rows[i + 1]) - for i in range(0, len(rows) - 1)] - table = Table(cols, rows) - if self.debug: - self.debug_tables.append(table) - table.image = img[k[3]:k[1],k[0]:k[2]] - for i in range(len(table.cells)): - for j in range(len(table.cells[i])): - x1 = int(table.cells[i][j].x1) - y1 = int(table.cells[i][j].y1) - x2 = int(table.cells[i][j].x2) - y2 = int(table.cells[i][j].y2) - table.cells[i][j].image = img[y1:y2,x1:x2] - text = self.tool.image_to_string( - Image.fromarray(table.cells[i][j].image), - lang=self.lang, - builder=pyocr.builders.TextBuilder(tesseract_layout=self.layout) - ) - table.cells[i][j].add_text(text) - ar = table.get_list() - ar.reverse() - ar = encode_list(ar) - table_data['data'] = ar - tables['table-{0}'.format(table_no + 1)] = table_data - table_no += 1 - page[os.path.basename(bname)] = tables - - if self.debug: - return None - - return page - - -class OCRStream: - """Stream, but for images. - - Parameters - ---------- - table_area : list - List of strings of the form x1,y1,x2,y2 where - (x1, y1) -> left-top and (x2, y2) -> right-bottom in OpenCV's - coordinate space, denoting table areas to analyze. - (optional, default: None) - - columns : list - List of strings where each string is comma-separated values of - x-coordinates in OpenCV's coordinate space. - (optional, default: None) - - blocksize : int - Size of a pixel neighborhood that is used to calculate a - threshold value for the pixel: 3, 5, 7, and so on. - (optional, default: 15) - - threshold_constant : float - Constant subtracted from the mean or weighted mean - (see the details below). Normally, it is positive but may be - zero or negative as well. - (optional, default: -2) - - dpi : int - Dots per inch. - (optional, default: 300) - - layout : int - Tesseract page segmentation mode. - (optional, default: 7) - - lang : string - Language to be used for OCR. - (optional, default: 'eng') - - line_scale : int - Line scaling factor. - (optional, default: 15) - - char_scale : int - Char scaling factor. - (optional, default: 200) - """ - def __init__(self, table_area=None, columns=None, blocksize=15, - threshold_constant=-2, dpi=300, layout=7, lang="eng", - line_scale=15, char_scale=200, debug=False): - - self.method = 'ocrs' - self.table_area = table_area - self.columns = columns - self.blocksize = blocksize - self.threshold_constant = threshold_constant - self.tool = pyocr.get_available_tools()[0] # fix this - self.dpi = dpi - self.layout = layout - self.lang = lang - self.line_scale = line_scale - self.char_scale = char_scale - self.debug = debug - - def get_tables(self, pdfname): - if self.tool is None: - return None - - bname, __ = os.path.splitext(pdfname) - imagename = ''.join([bname, '.png']) - logger.info('Processing {0}.'.format(os.path.basename(bname))) - - gs_call = [ - "-q", "-sDEVICE=png16m", "-o", imagename, "-r{0}".format(self.dpi), - pdfname - ] - if "ghostscript" in subprocess.check_output(["gs", "-version"]).lower(): - gs_call.insert(0, "gs") - else: - gs_call.insert(0, "gsc") - subprocess.call(gs_call, stdout=open(os.devnull, 'w'), - stderr=subprocess.STDOUT) - - img, threshold = adaptive_threshold(imagename, blocksize=self.blocksize, - c=self.threshold_constant) - threshold = remove_lines(threshold, line_scale=self.line_scale) - height, width = threshold.shape - if self.debug: - self.debug_images = img - return None - - if self.table_area is not None: - if self.columns is not None: - if len(self.table_area) != len(self.columns): - raise ValueError("{0}: Length of table area and columns" - " should be equal.".format(os.path.basename(bname))) - - table_bbox = {} - for area in self.table_area: - x1, y1, x2, y2 = area.split(",") - x1 = int(float(x1)) - y1 = int(float(y1)) - x2 = int(float(x2)) - y2 = int(float(y2)) - table_bbox[(x1, y1, x2, y2)] = None - else: - table_bbox = {(0, 0, width, height): None} - - page = {} - tables = {} - table_no = 0 - for k in sorted(table_bbox.keys(), key=lambda x: x[1]): - if self.columns is None: - raise NotImplementedError - else: - table_data = {} - table_image = threshold[k[1]:k[3],k[0]:k[2]] - cols = self.columns[table_no].split(',') - cols = [float(c) for c in cols] - cols.insert(0, k[0]) - cols.append(k[2]) - cols = [(cols[i] - k[0], cols[i + 1] - k[0]) for i in range(0, len(cols) - 1)] - y_cuts = find_cuts(table_image, char_scale=self.char_scale) - rows = [(y_cuts[i], y_cuts[i + 1]) for i in range(0, len(y_cuts) - 1)] - table = Table(cols, rows) - for i in range(len(table.cells)): - for j in range(len(table.cells[i])): - x1 = int(table.cells[i][j].x1) - y1 = int(table.cells[i][j].y1) - x2 = int(table.cells[i][j].x2) - y2 = int(table.cells[i][j].y2) - table.cells[i][j].image = table_image[y1:y2,x1:x2] - cell_image = Image.fromarray(table.cells[i][j].image) - text = self.tool.image_to_string( - cell_image, - lang=self.lang, - builder=pyocr.builders.TextBuilder(tesseract_layout=self.layout) - ) - table.cells[i][j].add_text(text) - ar = table.get_list() - ar.reverse() - ar = encode_list(ar) - table_data['data'] = ar - tables['table-{0}'.format(table_no + 1)] = table_data - table_no += 1 - page[os.path.basename(bname)] = tables - - return page \ No newline at end of file diff --git a/tools/camelot b/tools/camelot index 0918fe1..61a687f 100755 --- a/tools/camelot +++ b/tools/camelot @@ -18,7 +18,6 @@ from PyPDF2 import PdfFileReader from camelot.pdf import Pdf from camelot.lattice import Lattice from camelot.stream import Stream -from camelot.ocr import OCRLattice, OCRStream from camelot import utils @@ -54,8 +53,6 @@ options: camelot methods: lattice Looks for lines between data. stream Looks for spaces between data. - ocrl Lattice, but for images. - ocrs Stream, but for images. See 'camelot -h' for more information on a specific method. """ @@ -107,51 +104,6 @@ options: """ -ocrl_doc = """ -Lattice, but for images. - -usage: - camelot ocrl [-t ...] [-m ...] [options] [--] - -options: - -t, --tarea Specific table areas to analyze. - -m, --mtol Tolerance to account for when merging lines - which are very close. [default: 2] - -b, --blocksize See adaptive threshold doc. [default: 15] - -C, --constant See adaptive threshold doc. [default: -2] - -D, --dpi Dots per inch, specify image quality to be used for OCR. - [default: 300] - -g, --layout Tesseract page segmentation mode. [default: 7] - -l, --lang Specify language to be used for OCR. [default: eng] - -s, --scale Scaling factor. Large scaling factor leads to - smaller lines being detected. [default: 15] - -I, --iterations Number of iterations for dilation. [default: 0] - -d, --debug Debug by visualizing pdf geometry. - (contour,line,joint,table) Example: -d table -""" - -ocrs_doc = """ -Stream, but for images. - -usage: - camelot ocrs [-t ...] [-c ...] [options] [--] - -options: - -t, --tarea Specific table areas to analyze. - -c, --columns Comma-separated list of column x-coordinates. - Example: -c 10.1,20.2,30.3 - -b, --blocksize See adaptive threshold doc. [default: 15] - -C, --constant See adaptive threshold doc. [default: -2] - -D, --dpi Dots per inch, specify image quality to be used for OCR. - [default: 300] - -g, --layout Tesseract page segmentation mode. [default: 7] - -l, --lang Specify language to be used for OCR. [default: eng] - -G, --line-scale Line scaling factor. [default: 15] - -S, --char-scale Char scaling factor. [default: 200] - -d, --debug Debug by visualizing image. -""" - - def plot_table_barchart(r, c, p, pno, tno): row_idx = [i + 1 for i, row in enumerate(r)] col_idx = [i + 1 for i, col in enumerate(c)] @@ -376,10 +328,6 @@ if __name__ == '__main__': args.update(docopt(lattice_doc, argv=argv)) elif args[''] == 'stream': args.update(docopt(stream_doc, argv=argv)) - elif args[''] == 'ocrl': - args.update(docopt(ocrl_doc, argv=argv)) - elif args[''] == 'ocrs': - args.update(docopt(ocrs_doc, argv=argv)) filename = args[''] filedir = os.path.dirname(args['']) @@ -551,140 +499,6 @@ if __name__ == '__main__': except Exception as e: logger.exception(e.message, exc_info=True) sys.exit() - elif args[''] == 'ocrl': - try: - kwargs = { - 'table_area': args['--tarea'] if args['--tarea'] else None, - 'mtol': [int(m) for m in args['--mtol']], - 'blocksize': int(args['--blocksize']), - 'threshold_constant': float(args['--constant']), - 'dpi': int(args['--dpi']), - 'layout': int(args['--layout']), - 'lang': args['--lang'], - 'scale': int(args['--scale']), - 'iterations': int(args['--iterations']), - 'debug': args['--debug'] - } - manager = Pdf(OCRLattice(**kwargs), filename, pagenos=p, clean=True, - parallel=args['--parallel']) - data = manager.extract() - - processing_time = time.time() - start_time - logger.info("Finished processing in " + str(processing_time) + " seconds") - - if args['--plot']: - if args['--output']: - pngname = os.path.join(args['--output'], os.path.basename(pngname)) - plot_type = args['--plot'].split(',') - if 'page' in plot_type: - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - plot_table_barchart(table['r_nempty_cells'], - table['c_nempty_cells'], - table['empty_p'], - page_number, - table_number) - - if 'all' in plot_type: - plot_all_barchart(data, pngname) - - if 'rc' in plot_type: - plot_rc_piechart(data, pngname) - - if args['--print-stats']: - print_stats(data, processing_time) - - if args['--save-stats']: - if args['--output']: - scorename = os.path.join(args['--output'], os.path.basename(scorename)) - with open(scorename, 'w') as score_file: - score_file.write('table,nrows,ncols,empty_p,line_p,text_p,score\n') - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - score_file.write('{0},{1},{2},{3},{4},{5},{6}\n'.format( - ''.join([page_number, '_', table_number]), - table['nrows'], - table['ncols'], - table['empty_p'], - table['line_p'], - table['text_p'], - table['score'])) - if args['--debug']: - manager.debug_plot() - except Exception as e: - logger.exception(e.message, exc_info=True) - sys.exit() - elif args[''] == 'ocrs': - try: - kwargs = { - 'table_area': args['--tarea'] if args['--tarea'] else None, - 'columns': args['--columns'] if args['--columns'] else None, - 'blocksize': int(args['--blocksize']), - 'threshold_constant': float(args['--constant']), - 'dpi': int(args['--dpi']), - 'layout': int(args['--layout']), - 'lang': args['--lang'], - 'line_scale': int(args['--line-scale']), - 'char_scale': int(args['--char-scale']), - 'debug': args['--debug'] - } - manager = Pdf(OCRStream(**kwargs), filename, pagenos=p, clean=True, - parallel=args['--parallel']) - data = manager.extract() - - processing_time = time.time() - start_time - logger.info("Finished processing in " + str(processing_time) + " seconds") - - if args['--plot']: - if args['--output']: - pngname = os.path.join(args['--output'], os.path.basename(pngname)) - plot_type = args['--plot'].split(',') - if 'page' in plot_type: - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - plot_table_barchart(table['r_nempty_cells'], - table['c_nempty_cells'], - table['empty_p'], - page_number, - table_number) - - if 'all' in plot_type: - plot_all_barchart(data, pngname) - - if 'rc' in plot_type: - plot_rc_piechart(data, pngname) - - if args['--print-stats']: - print_stats(data, processing_time) - - if args['--save-stats']: - if args['--output']: - scorename = os.path.join(args['--output'], os.path.basename(scorename)) - with open(scorename, 'w') as score_file: - score_file.write('table,nrows,ncols,empty_p,line_p,text_p,score\n') - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - score_file.write('{0},{1},{2},{3},{4},{5},{6}\n'.format( - ''.join([page_number, '_', table_number]), - table['nrows'], - table['ncols'], - table['empty_p'], - table['line_p'], - table['text_p'], - table['score'])) - if args['--debug']: - manager.debug_plot() - except Exception as e: - logger.exception(e.message, exc_info=True) - sys.exit() if args.get('--debug') is not None and args['--debug']: print("See 'camelot -h' for various parameters you can tweak.") From d65ee180e58bf1453b6475f75acb2f491aade351 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 1 Sep 2018 16:26:15 +0530 Subject: [PATCH 02/39] Update README --- README.md | 2 -- requirements.txt | 1 - 2 files changed, 3 deletions(-) diff --git a/README.md b/README.md index 5cb4fc0..f588557 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,6 @@ options: camelot methods: lattice Looks for lines between data. stream Looks for spaces between data. - ocrl Lattice, but for images. - ocrs Stream, but for images. See 'camelot <method> -h' for more information on a specific method. diff --git a/requirements.txt b/requirements.txt index 826e271..61b0ccd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,5 @@ nose pdfminer pyexcel-xlsx Pillow -pyocr PyPDF2 Sphinx From ae64264d3e8218a13ce024b6043811a77829504b Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sun, 2 Sep 2018 19:04:24 +0530 Subject: [PATCH 03/39] Update README and requirements --- README.md | 14 +++++--------- requirements.txt | 16 ++++++++-------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f588557..c002f09 100644 --- a/README.md +++ b/README.md @@ -55,11 +55,7 @@ See 'camelot <method> -h' for more information on a specific method. Currently, camelot works under Python 2.7. -The required dependencies include [numpy](http://www.numpy.org/), [OpenCV](http://opencv.org/) and [ImageMagick](http://www.imagemagick.org/script/index.php). - -### Optional - -You'll need to install [Tesseract](https://github.com/tesseract-ocr/tesseract) if you want to extract tables from image based pdfs. Also, you'll need a tesseract language pack if your pdf isn't in english. +The required dependencies include [numpy](http://www.numpy.org/), [OpenCV](http://opencv.org/) and [ghostscript](https://www.ghostscript.com/). ## Installation @@ -71,26 +67,26 @@ pip install -U pip setuptools ### Installing dependencies -numpy can be install using `pip`. OpenCV and imagemagick can be installed using your system's default package manager. +numpy can be install using `pip`. OpenCV and ghostscript can be installed using your system's default package manager. #### Linux * Arch Linux
-sudo pacman -S opencv imagemagick
+sudo pacman -S opencv ghostscript
 
* Ubuntu
-sudo apt-get install libopencv-dev python-opencv imagemagick
+sudo apt-get install libopencv-dev python-opencv python-tk ghostscript
 
#### OS X
-brew install homebrew/science/opencv imagemagick
+brew install homebrew/science/opencv ghostscript
 
Finally, `cd` into the project directory and install by diff --git a/requirements.txt b/requirements.txt index 61b0ccd..0535f0c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ -docopt -matplotlib -nose -pdfminer -pyexcel-xlsx -Pillow -PyPDF2 -Sphinx +docopt==0.6.2 +matplotlib==2.2.3 +nose==1.3.7 +pdfminer==20140328 +pyexcel-xlsx==0.5.6 +Pillow==5.2.0 +PyPDF2==1.26.0 +Sphinx==1.8.0b1 \ No newline at end of file From c689735da2cf6cbf3b0626a1179936ae072d6651 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Tue, 4 Sep 2018 03:49:43 +0530 Subject: [PATCH 04/39] Move cell and table to core --- camelot/__init__.py | 7 +- camelot/__version__.py | 1 + camelot/cell.py | 128 ------------------------------- camelot/cli.py | 0 camelot/{table.py => core.py} | 139 +++++++++++++++++++++++++++++++++- camelot/lattice.py | 2 +- camelot/stream.py | 2 +- 7 files changed, 144 insertions(+), 135 deletions(-) create mode 100644 camelot/__version__.py delete mode 100644 camelot/cell.py create mode 100644 camelot/cli.py rename camelot/{table.py => core.py} (73%) diff --git a/camelot/__init__.py b/camelot/__init__.py index b9b5f18..25dd606 100644 --- a/camelot/__init__.py +++ b/camelot/__init__.py @@ -1,3 +1,6 @@ -__version__ = '1.2.0' +from .core import * +from .__version__ import __version__ -__all__ = ['pdf', 'lattice', 'stream'] + +def read_pdf(filepath, pages='1', grid=True): + pass \ No newline at end of file diff --git a/camelot/__version__.py b/camelot/__version__.py new file mode 100644 index 0000000..b794fd4 --- /dev/null +++ b/camelot/__version__.py @@ -0,0 +1 @@ +__version__ = '0.1.0' diff --git a/camelot/cell.py b/camelot/cell.py deleted file mode 100644 index 8dfe8d3..0000000 --- a/camelot/cell.py +++ /dev/null @@ -1,128 +0,0 @@ -class Cell: - """Cell. - Defines a cell object with coordinates relative to a left-bottom - origin, which is also PDFMiner's coordinate space. - - Parameters - ---------- - x1 : float - x-coordinate of left-bottom point. - - y1 : float - y-coordinate of left-bottom point. - - x2 : float - x-coordinate of right-top point. - - y2 : float - y-coordinate of right-top point. - - Attributes - ---------- - lb : tuple - Tuple representing left-bottom coordinates. - - lt : tuple - Tuple representing left-top coordinates. - - rb : tuple - Tuple representing right-bottom coordinates. - - rt : tuple - Tuple representing right-top coordinates. - - bbox : tuple - Tuple representing the cell's bounding box using the - lower-bottom and right-top coordinates. - - left : bool - Whether or not cell is bounded on the left. - - right : bool - Whether or not cell is bounded on the right. - - top : bool - Whether or not cell is bounded on the top. - - bottom : bool - Whether or not cell is bounded on the bottom. - - text_objects : list - List of text objects assigned to cell. - - text : string - Text assigned to cell. - - spanning_h : bool - Whether or not cell spans/extends horizontally. - - spanning_v : bool - Whether or not cell spans/extends vertically. - """ - - def __init__(self, x1, y1, x2, y2): - - self.x1 = x1 - self.y1 = y1 - self.x2 = x2 - self.y2 = y2 - self.lb = (x1, y1) - self.lt = (x1, y2) - self.rb = (x2, y1) - self.rt = (x2, y2) - self.bbox = (x1, y1, x2, y2) - self.left = False - self.right = False - self.top = False - self.bottom = False - self.text_objects = [] - self.text = '' - self.spanning_h = False - self.spanning_v = False - self.image = None - - def add_text(self, text): - """Adds text to cell. - - Parameters - ---------- - text : string - """ - self.text = ''.join([self.text, text]) - - def get_text(self): - """Returns text assigned to cell. - - Returns - ------- - text : string - """ - return self.text - - def add_object(self, t_object): - """Adds PDFMiner text object to cell. - - Parameters - ---------- - t_object : object - """ - self.text_objects.append(t_object) - - def get_objects(self): - """Returns list of text objects assigned to cell. - - Returns - ------- - text_objects : list - """ - return self.text_objects - - def get_bounded_edges(self): - """Returns the number of edges by which a cell is bounded. - - Returns - ------- - bounded_edges : int - """ - self.bounded_edges = self.top + self.bottom + self.left + self.right - return self.bounded_edges diff --git a/camelot/cli.py b/camelot/cli.py new file mode 100644 index 0000000..e69de29 diff --git a/camelot/table.py b/camelot/core.py similarity index 73% rename from camelot/table.py rename to camelot/core.py index fc1a45e..0934961 100644 --- a/camelot/table.py +++ b/camelot/core.py @@ -1,9 +1,138 @@ import numpy as np - -from .cell import Cell +import pandas as pd -class Table: +class Cell(object): + """Cell. + Defines a cell object with coordinates relative to a left-bottom + origin, which is also PDFMiner's coordinate space. + + Parameters + ---------- + x1 : float + x-coordinate of left-bottom point. + + y1 : float + y-coordinate of left-bottom point. + + x2 : float + x-coordinate of right-top point. + + y2 : float + y-coordinate of right-top point. + + Attributes + ---------- + lb : tuple + Tuple representing left-bottom coordinates. + + lt : tuple + Tuple representing left-top coordinates. + + rb : tuple + Tuple representing right-bottom coordinates. + + rt : tuple + Tuple representing right-top coordinates. + + bbox : tuple + Tuple representing the cell's bounding box using the + lower-bottom and right-top coordinates. + + left : bool + Whether or not cell is bounded on the left. + + right : bool + Whether or not cell is bounded on the right. + + top : bool + Whether or not cell is bounded on the top. + + bottom : bool + Whether or not cell is bounded on the bottom. + + text_objects : list + List of text objects assigned to cell. + + text : string + Text assigned to cell. + + spanning_h : bool + Whether or not cell spans/extends horizontally. + + spanning_v : bool + Whether or not cell spans/extends vertically. + """ + + def __init__(self, x1, y1, x2, y2): + + self.x1 = x1 + self.y1 = y1 + self.x2 = x2 + self.y2 = y2 + self.lb = (x1, y1) + self.lt = (x1, y2) + self.rb = (x2, y1) + self.rt = (x2, y2) + self.bbox = (x1, y1, x2, y2) + self.left = False + self.right = False + self.top = False + self.bottom = False + self.text_objects = [] + self.text = '' + self.spanning_h = False + self.spanning_v = False + self.image = None + + def add_text(self, text): + """Adds text to cell. + + Parameters + ---------- + text : string + """ + self.text = ''.join([self.text, text]) + + def get_text(self): + """Returns text assigned to cell. + + Returns + ------- + text : string + """ + return self.text + + def add_object(self, t_object): + """Adds PDFMiner text object to cell. + + Parameters + ---------- + t_object : object + """ + self.text_objects.append(t_object) + + def get_objects(self): + """Returns list of text objects assigned to cell. + + Returns + ------- + text_objects : list + """ + return self.text_objects + + def get_bounded_edges(self): + """Returns the number of edges by which a cell is bounded. + + Returns + ------- + bounded_edges : int + """ + self.bounded_edges = self.top + self.bottom + self.left + self.right + return self.bounded_edges + + +class Table(object): """Table. Defines a table object with coordinates relative to a left-bottom origin, which is also PDFMiner's coordinate space. @@ -234,3 +363,7 @@ class Table: ar.append([self.cells[r][c].get_text().strip() for c in range(len(self.cols))]) return ar + + +class TableSet(object): + pass \ No newline at end of file diff --git a/camelot/lattice.py b/camelot/lattice.py index 40803f6..2dd471d 100644 --- a/camelot/lattice.py +++ b/camelot/lattice.py @@ -8,9 +8,9 @@ import copy_reg import warnings import subprocess +from .core import Table from .imgproc import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) -from .table import Table from .utils import (scale_to_pdf, scale_to_image, segments_bbox, text_in_bbox, merge_close_values, get_table_index, get_score, count_empty, encode_list, get_text_objects, get_page_layout) diff --git a/camelot/stream.py b/camelot/stream.py index e794d6a..ae0ef4a 100644 --- a/camelot/stream.py +++ b/camelot/stream.py @@ -8,7 +8,7 @@ import warnings import numpy as np -from .table import Table +from .core import Table from .utils import (text_in_bbox, get_table_index, get_score, count_empty, encode_list, get_text_objects, get_page_layout) From 0c9e21d8818d8ce90ba3eb5c5c7594e148ea64ee Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Tue, 4 Sep 2018 03:53:30 +0530 Subject: [PATCH 05/39] Update README --- README.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c002f09..7efc6f2 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,22 @@ Camelot is a Python 2.7 library and command-line tool for getting tables out of ## Usage
-from camelot.pdf import Pdf
-from camelot.lattice import Lattice
-
-manager = Pdf(Lattice(), "/path/to/pdf")
-tables = manager.extract()
+>>> import camelot
+>>> tables = camelot.read_pdf("foo.pdf")
+>>> tables
+<TableSet n=2>
+>>> tables.to_csv(zip=True) # to_json, to_excel, to_html
+>>> tables[0]
+<Table shape=(3,4)>
+>>> tables[0].parsing_report
+{
+    "accuracy": 96,
+    "whitespace": 80,
+    "time_taken": 0.5,
+    "page": 1
+}
+>>> tables[0].to_csv("foo.csv") # to_json, to_excel, to_html
+>>> df = tables[0].to_df()
 
Camelot comes with a CLI where you can specify page numbers, output format, output directory etc. By default, the output files are placed in the same directory as the PDF. From 5d29f0c21c0af5bd17e31a86507c8a4fa2d1e844 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Tue, 4 Sep 2018 07:02:30 +0530 Subject: [PATCH 06/39] Move Pdf class to core as FileHandler --- camelot/core.py | 222 ++++++++++++++------------------------- camelot/pdf.py | 268 ------------------------------------------------ 2 files changed, 79 insertions(+), 411 deletions(-) delete mode 100644 camelot/pdf.py diff --git a/camelot/core.py b/camelot/core.py index 0934961..91cb1bd 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -1,69 +1,14 @@ +import os +import tempfile + import numpy as np import pandas as pd +from PyPDF2 import PdfFileReader, PdfFileWriter + +from .utils import get_page_layout, get_text_objects, get_rotation class Cell(object): - """Cell. - Defines a cell object with coordinates relative to a left-bottom - origin, which is also PDFMiner's coordinate space. - - Parameters - ---------- - x1 : float - x-coordinate of left-bottom point. - - y1 : float - y-coordinate of left-bottom point. - - x2 : float - x-coordinate of right-top point. - - y2 : float - y-coordinate of right-top point. - - Attributes - ---------- - lb : tuple - Tuple representing left-bottom coordinates. - - lt : tuple - Tuple representing left-top coordinates. - - rb : tuple - Tuple representing right-bottom coordinates. - - rt : tuple - Tuple representing right-top coordinates. - - bbox : tuple - Tuple representing the cell's bounding box using the - lower-bottom and right-top coordinates. - - left : bool - Whether or not cell is bounded on the left. - - right : bool - Whether or not cell is bounded on the right. - - top : bool - Whether or not cell is bounded on the top. - - bottom : bool - Whether or not cell is bounded on the bottom. - - text_objects : list - List of text objects assigned to cell. - - text : string - Text assigned to cell. - - spanning_h : bool - Whether or not cell spans/extends horizontally. - - spanning_v : bool - Whether or not cell spans/extends vertically. - """ - def __init__(self, x1, y1, x2, y2): self.x1 = x1 @@ -86,76 +31,23 @@ class Cell(object): self.image = None def add_text(self, text): - """Adds text to cell. - - Parameters - ---------- - text : string - """ self.text = ''.join([self.text, text]) def get_text(self): - """Returns text assigned to cell. - - Returns - ------- - text : string - """ return self.text def add_object(self, t_object): - """Adds PDFMiner text object to cell. - - Parameters - ---------- - t_object : object - """ self.text_objects.append(t_object) def get_objects(self): - """Returns list of text objects assigned to cell. - - Returns - ------- - text_objects : list - """ return self.text_objects def get_bounded_edges(self): - """Returns the number of edges by which a cell is bounded. - - Returns - ------- - bounded_edges : int - """ self.bounded_edges = self.top + self.bottom + self.left + self.right return self.bounded_edges class Table(object): - """Table. - Defines a table object with coordinates relative to a left-bottom - origin, which is also PDFMiner's coordinate space. - - Parameters - ---------- - cols : list - List of tuples representing column x-coordinates in increasing - order. - - rows : list - List of tuples representing row y-coordinates in decreasing - order. - - Attributes - ---------- - cells : list - List of cell objects with row-major ordering. - - nocont_ : int - Number of lines that did not contribute to setting cell edges. - """ - def __init__(self, cols, rows): self.cols = cols @@ -166,8 +58,6 @@ class Table(object): self.image = None def set_all_edges(self): - """Sets all table edges to True. - """ for r in range(len(self.rows)): for c in range(len(self.cols)): self.cells[r][c].left = True @@ -177,8 +67,6 @@ class Table(object): return self def set_border_edges(self): - """Sets table border edges to True. - """ for r in range(len(self.rows)): self.cells[r][0].left = True self.cells[r][len(self.cols) - 1].right = True @@ -188,19 +76,6 @@ class Table(object): return self def set_edges(self, vertical, horizontal, jtol=2): - """Sets a cell's edges to True depending on whether they - overlap with lines found by imgproc. - - Parameters - ---------- - vertical : list - List of vertical lines detected by imgproc. Coordinates - scaled and translated to the PDFMiner's coordinate space. - - horizontal : list - List of horizontal lines detected by imgproc. Coordinates - scaled and translated to the PDFMiner's coordinate space. - """ for v in vertical: # find closest x coord # iterate over y coords and find closest points @@ -308,10 +183,6 @@ class Table(object): return self def set_spanning(self): - """Sets a cell's spanning_h or spanning_v attribute to True - depending on whether the cell spans/extends horizontally or - vertically. - """ for r in range(len(self.rows)): for c in range(len(self.cols)): bound = self.cells[r][c].get_bounded_edges() @@ -351,13 +222,6 @@ class Table(object): return self def get_list(self): - """Returns a two-dimensional list of text assigned to each - cell. - - Returns - ------- - ar : list - """ ar = [] for r in range(len(self.rows)): ar.append([self.cells[r][c].get_text().strip() @@ -366,4 +230,76 @@ class Table(object): class TableSet(object): - pass \ No newline at end of file + pass + + +class FileHandler(object): + def __init__(self, filename, pages='1'): + self.filename = filename + if not self.filename.endswith('.pdf'): + raise TypeError("File format not supported.") + self.pages = __get_pages(pages) + self.temp = tempfile.mkdtemp() + + @staticmethod + def __get_pages(filename, pages): + p = {} + if pages == '1': + p.append({'start': 1, 'end': 1}) + else: + infile = PdfFileReader(open(filename, 'rb'), strict=False) + if pages == 'all': + p.append({'start': 1, 'end': infile.getNumPages()}) + else: + for r in pages.split(','): + if '-' in r: + a, b = r.split('-') + if b == 'end': + b = infile.getNumPages() + p.append({'start': int(a), 'end': int(b)}) + else: + p.append({'start': int(r), 'end': int(r)}) + return p + + @staticmethod + def __save_page(filename, page, temp): + with open(filename, 'rb') as fileobj: + infile = PdfFileReader(fileobj, strict=False) + fpath = os.path.join(temp, 'page-{0}.pdf'.format(page)) + fname, fext = os.path.splitext(fpath) + p = infile.getPage(page - 1) + outfile = PdfFileWriter() + outfile.addPage(p) + with open(fpath, 'wb') as f: + outfile.write(f) + layout, dim = get_page_layout(fpath) + # fix rotated pdf + lttextlh = get_text_objects(layout, ltype="lh") + lttextlv = get_text_objects(layout, ltype="lv") + ltchar = get_text_objects(layout, ltype="char") + rotation = get_rotation(lttextlh, lttextlv, ltchar) + if rotation != '': + fpath_new = ''.join([fname.replace('page', 'p'), '_rotated', fext]) + os.rename(fpath, fpath_new) + infile = PdfFileReader(open(fpath_new, 'rb'), strict=False) + outfile = PdfFileWriter() + p = infile.getPage(0) + if rotation == 'left': + p.rotateClockwise(90) + elif rotation == 'right': + p.rotateCounterClockwise(90) + outfile.addPage(p) + with open(fpath, 'wb') as f: + outfile.write(f) + + def parse(self): + for p in self.pages: + __save_page(self.filename, p, self.temp) + pages = [os.path.join(self.temp, 'page-{0}.pdf'.format(p)) + for p in self.pagenos] + tables = {} + for p in pages: + table = self.parser.get_tables(p) + if table is not None: + tables.update(table) + return tables \ No newline at end of file diff --git a/camelot/pdf.py b/camelot/pdf.py deleted file mode 100644 index 08fd26c..0000000 --- a/camelot/pdf.py +++ /dev/null @@ -1,268 +0,0 @@ -import os -import shutil -import tempfile -import itertools -import multiprocessing as mp -from functools import partial - -import cv2 -from PyPDF2 import PdfFileReader, PdfFileWriter - -from .utils import get_page_layout, get_text_objects, get_rotation - - -__all__ = ['Pdf'] - - -def _parse_page_numbers(pagenos): - """Converts list of dicts to list of ints. - - Parameters - ---------- - pagenos : list - List of dicts representing page ranges. A dict must have only - two keys named 'start' and 'end' having int as their value. - - Returns - ------- - page_numbers : list - List of int page numbers. - """ - page_numbers = [] - for p in pagenos: - page_numbers.extend(range(p['start'], p['end'] + 1)) - page_numbers = sorted(set(page_numbers)) - return page_numbers - - -def _save_page(temp, pdfname, pageno): - with open(pdfname, 'rb') as pdffile: - infile = PdfFileReader(pdffile, strict=False) - sp_path = os.path.join(temp, 'page-{0}.pdf'.format(pageno)) - sp_name, sp_ext = os.path.splitext(sp_path) - page = infile.getPage(pageno - 1) - outfile = PdfFileWriter() - outfile.addPage(page) - with open(sp_path, 'wb') as f: - outfile.write(f) - layout, dim = get_page_layout(sp_path) - lttextlh = get_text_objects(layout, ltype="lh") - lttextlv = get_text_objects(layout, ltype="lv") - ltchar = get_text_objects(layout, ltype="char") - rotation = get_rotation(lttextlh, lttextlv, ltchar) - if rotation != '': - sp_new_path = ''.join([sp_name.replace('page', 'p'), '_rotated', sp_ext]) - os.rename(sp_path, sp_new_path) - sp_in = PdfFileReader(open(sp_new_path, 'rb'), - strict=False) - sp_out = PdfFileWriter() - sp_page = sp_in.getPage(0) - if rotation == 'left': - sp_page.rotateClockwise(90) - elif rotation == 'right': - sp_page.rotateCounterClockwise(90) - sp_out.addPage(sp_page) - with open(sp_path, 'wb') as pdf_out: - sp_out.write(pdf_out) - - -class Pdf: - """Pdf manager. - Handles all operations like temp directory creation, splitting file - into single page pdfs, running extraction using multiple processes - and removing the temp directory. - - Parameters - ---------- - extractor : object - camelot.stream.Stream or camelot.lattice.Lattice extractor - object. - - pdfname : string - Path to pdf file. - - pagenos : list - List of dicts representing page ranges. A dict must have only - two keys named 'start' and 'end' having int as their value. - (optional, default: [{'start': 1, 'end': 1}]) - - parallel : bool - Whether or not to run using multiple processes. - (optional, default: False) - - clean : bool - Whether or not to remove the temp directory. - (optional, default: False) - """ - - def __init__(self, extractor, pdfname, pagenos=[{'start': 1, 'end': 1}], - parallel=False, clean=False): - - self.extractor = extractor - self.pdfname = pdfname - if not self.pdfname.endswith('.pdf'): - raise TypeError("File format not supported.") - self.pagenos = _parse_page_numbers(pagenos) - self.parallel = parallel - if self.parallel: - self.cpu_count = mp.cpu_count() - self.pool = mp.Pool(processes=self.cpu_count) - self.clean = clean - self.temp = tempfile.mkdtemp() - - def split(self): - """Splits file into single page pdfs. - """ - if self.parallel: - pfunc = partial(_save_page, self.temp, self.pdfname) - self.pool.map(pfunc, self.pagenos) - else: - for p in self.pagenos: - _save_page(self.temp, self.pdfname, p) - - - def extract(self): - """Runs table extraction by calling extractor.get_tables - on all single page pdfs. - """ - self.split() - pages = [os.path.join(self.temp, 'page-{0}.pdf'.format(p)) - for p in self.pagenos] - if self.parallel: - tables = self.pool.map(self.extractor.get_tables, pages) - tables = {k: v for d in tables if d is not None for k, v in d.items()} - else: - tables = {} - if self.extractor.debug: - if self.extractor.method == 'stream': - self.debug = self.extractor.debug - self.debug_text = [] - elif self.extractor.method in ['lattice', 'ocrl']: - self.debug = self.extractor.debug - self.debug_images = [] - self.debug_segments = [] - self.debug_tables = [] - elif self.extractor.method == 'ocrs': - self.debug = self.extractor.debug - self.debug_images = [] - for p in pages: - table = self.extractor.get_tables(p) - if table is not None: - tables.update(table) - if self.extractor.debug: - if self.extractor.method == 'stream': - self.debug_text.append(self.extractor.debug_text) - elif self.extractor.method in ['lattice', 'ocr']: - self.debug_images.append(self.extractor.debug_images) - self.debug_segments.append(self.extractor.debug_segments) - self.debug_tables.append(self.extractor.debug_tables) - elif self.extractor.method == 'ocrs': - self.debug_images.append(self.extractor.debug_images) - if self.clean: - self.remove_tempdir() - return tables - - def remove_tempdir(self): - """Removes temporary directory that was created to save single - page pdfs and their images. - """ - shutil.rmtree(self.temp) - - def debug_plot(self): - """Generates a matplotlib plot based on the selected extractor - debug option. - """ - import matplotlib.pyplot as plt - import matplotlib.patches as patches - - if self.debug is True: - if hasattr(self, 'debug_text'): - for text in self.debug_text: - fig = plt.figure() - ax = fig.add_subplot(111, aspect='equal') - xs, ys = [], [] - for t in text: - xs.extend([t[0], t[1]]) - ys.extend([t[2], t[3]]) - ax.add_patch( - patches.Rectangle( - (t[0], t[1]), - t[2] - t[0], - t[3] - t[1] - ) - ) - ax.set_xlim(min(xs) - 10, max(xs) + 10) - ax.set_ylim(min(ys) - 10, max(ys) + 10) - plt.show() - elif hasattr(self, 'debug_images'): - for img in self.debug_images: - plt.imshow(img) - plt.show() - elif self.debug == 'contour': - try: - for img, table_bbox in self.debug_images: - for t in table_bbox.keys(): - cv2.rectangle(img, (t[0], t[1]), - (t[2], t[3]), (255, 0, 0), 3) - plt.imshow(img) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") - elif self.debug == 'joint': - try: - for img, table_bbox in self.debug_images: - x_coord = [] - y_coord = [] - for k in table_bbox.keys(): - for coord in table_bbox[k]: - x_coord.append(coord[0]) - y_coord.append(coord[1]) - max_x, max_y = max(x_coord), max(y_coord) - plt.plot(x_coord, y_coord, 'ro') - plt.axis([0, max_x + 100, max_y + 100, 0]) - plt.imshow(img) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") - elif self.debug == 'line': - try: - for v_s, h_s in self.debug_segments: - for v in v_s: - plt.plot([v[0], v[2]], [v[1], v[3]]) - for h in h_s: - plt.plot([h[0], h[2]], [h[1], h[3]]) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") - elif self.debug == 'table': - try: - for tables in self.debug_tables: - for table in tables: - for r in range(len(table.rows)): - for c in range(len(table.cols)): - if table.cells[r][c].left: - plt.plot([table.cells[r][c].lb[0], - table.cells[r][c].lt[0]], - [table.cells[r][c].lb[1], - table.cells[r][c].lt[1]]) - if table.cells[r][c].right: - plt.plot([table.cells[r][c].rb[0], - table.cells[r][c].rt[0]], - [table.cells[r][c].rb[1], - table.cells[r][c].rt[1]]) - if table.cells[r][c].top: - plt.plot([table.cells[r][c].lt[0], - table.cells[r][c].rt[0]], - [table.cells[r][c].lt[1], - table.cells[r][c].rt[1]]) - if table.cells[r][c].bottom: - plt.plot([table.cells[r][c].lb[0], - table.cells[r][c].rb[0]], - [table.cells[r][c].lb[1], - table.cells[r][c].rb[1]]) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") - else: - raise UserWarning("This method can only be called after" - " debug has been specified.") \ No newline at end of file From e3aabb720feee934a450b330139d1a87a471da06 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Tue, 4 Sep 2018 21:28:37 +0530 Subject: [PATCH 07/39] Add stream and lattice to parsers --- camelot/__init__.py | 5 +- camelot/cli.py | 1 + camelot/core.py | 14 +- camelot/{imgproc.py => image_processing.py} | 0 camelot/io.py | 5 + camelot/lattice.py | 382 -------------------- camelot/{stream.py => parsers.py} | 365 ++++++++++++++++++- 7 files changed, 380 insertions(+), 392 deletions(-) rename camelot/{imgproc.py => image_processing.py} (100%) create mode 100644 camelot/io.py delete mode 100644 camelot/lattice.py rename camelot/{stream.py => parsers.py} (51%) diff --git a/camelot/__init__.py b/camelot/__init__.py index 25dd606..24ff0f1 100644 --- a/camelot/__init__.py +++ b/camelot/__init__.py @@ -1,6 +1,3 @@ -from .core import * from .__version__ import __version__ - -def read_pdf(filepath, pages='1', grid=True): - pass \ No newline at end of file +from .io import * \ No newline at end of file diff --git a/camelot/cli.py b/camelot/cli.py index e69de29..302830e 100644 --- a/camelot/cli.py +++ b/camelot/cli.py @@ -0,0 +1 @@ +import click \ No newline at end of file diff --git a/camelot/core.py b/camelot/core.py index 91cb1bd..2cca37d 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -10,7 +10,6 @@ from .utils import get_page_layout, get_text_objects, get_rotation class Cell(object): def __init__(self, x1, y1, x2, y2): - self.x1 = x1 self.y1 = y1 self.x2 = x2 @@ -30,6 +29,9 @@ class Cell(object): self.spanning_v = False self.image = None + def __repr__(self): + pass + def add_text(self, text): self.text = ''.join([self.text, text]) @@ -49,7 +51,6 @@ class Cell(object): class Table(object): def __init__(self, cols, rows): - self.cols = cols self.rows = rows self.cells = [[Cell(c[0], r[1], c[1], r[0]) @@ -57,6 +58,9 @@ class Table(object): self.nocont_ = 0 self.image = None + def __repr__(self): + pass + def set_all_edges(self): for r in range(len(self.rows)): for c in range(len(self.cols)): @@ -230,7 +234,11 @@ class Table(object): class TableSet(object): - pass + def __init__(self): + pass + + def __repr__(self): + pass class FileHandler(object): diff --git a/camelot/imgproc.py b/camelot/image_processing.py similarity index 100% rename from camelot/imgproc.py rename to camelot/image_processing.py diff --git a/camelot/io.py b/camelot/io.py new file mode 100644 index 0000000..a78cf3a --- /dev/null +++ b/camelot/io.py @@ -0,0 +1,5 @@ +from .core import * + + +def read_pdf(filepath, pages='1', grid=True): + pass \ No newline at end of file diff --git a/camelot/lattice.py b/camelot/lattice.py deleted file mode 100644 index 2dd471d..0000000 --- a/camelot/lattice.py +++ /dev/null @@ -1,382 +0,0 @@ -from __future__ import division -import os -import sys -import copy -import types -import logging -import copy_reg -import warnings -import subprocess - -from .core import Table -from .imgproc import (adaptive_threshold, find_lines, find_table_contours, - find_table_joints) -from .utils import (scale_to_pdf, scale_to_image, segments_bbox, text_in_bbox, - merge_close_values, get_table_index, get_score, count_empty, - encode_list, get_text_objects, get_page_layout) - - -__all__ = ['Lattice'] -logger = logging.getLogger('app_logger') - - -def _reduce_method(m): - if m.im_self is None: - return getattr, (m.im_class, m.im_func.func_name) - else: - return getattr, (m.im_self, m.im_func.func_name) -copy_reg.pickle(types.MethodType, _reduce_method) - - -def _reduce_index(t, idx, shift_text): - """Reduces index of a text object if it lies within a spanning - cell. - - Parameters - ---------- - table : object - camelot.table.Table - - idx : list - List of tuples of the form (r_idx, c_idx, text). - - shift_text : list - {'l', 'r', 't', 'b'} - Select one or more from above and pass them as a list to - specify where the text in a spanning cell should flow. - - Returns - ------- - indices : list - List of tuples of the form (idx, text) where idx is the reduced - index of row/column and text is the an lttextline substring. - """ - indices = [] - for r_idx, c_idx, text in idx: - for d in shift_text: - if d == 'l': - if t.cells[r_idx][c_idx].spanning_h: - while not t.cells[r_idx][c_idx].left: - c_idx -= 1 - if d == 'r': - if t.cells[r_idx][c_idx].spanning_h: - while not t.cells[r_idx][c_idx].right: - c_idx += 1 - if d == 't': - if t.cells[r_idx][c_idx].spanning_v: - while not t.cells[r_idx][c_idx].top: - r_idx -= 1 - if d == 'b': - if t.cells[r_idx][c_idx].spanning_v: - while not t.cells[r_idx][c_idx].bottom: - r_idx += 1 - indices.append((r_idx, c_idx, text)) - return indices - - -def _fill_spanning(t, fill=None): - """Fills spanning cells. - - Parameters - ---------- - t : object - camelot.table.Table - - fill : list - {'h', 'v'} - Specify to fill spanning cells in horizontal or vertical - direction. - (optional, default: None) - - Returns - ------- - t : object - camelot.table.Table - """ - for f in fill: - if f == "h": - for i in range(len(t.cells)): - for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_h and not t.cells[i][j].left: - t.cells[i][j].add_text(t.cells[i][j - 1].get_text()) - elif f == "v": - for i in range(len(t.cells)): - for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_v and not t.cells[i][j].top: - t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) - return t - - -class Lattice: - """Lattice looks for lines in the pdf to form a table. - - If you want to give fill and mtol for each table when specifying - multiple table areas, make sure that the length of fill and mtol - is equal to the length of table_area. Mapping between them is based - on index. - - Parameters - ---------- - table_area : list - List of strings of the form x1,y1,x2,y2 where - (x1, y1) -> left-top and (x2, y2) -> right-bottom in PDFMiner's - coordinate space, denoting table areas to analyze. - (optional, default: None) - - fill : list - List of strings specifying directions to fill spanning cells. - {'h', 'v'} to fill spanning cells in horizontal or vertical - direction. - (optional, default: None) - - mtol : list - List of ints specifying m-tolerance parameters. - (optional, default: [2]) - - jtol : list - List of ints specifying j-tolerance parameters. - (optional, default: [2]) - - blocksize : int - Size of a pixel neighborhood that is used to calculate a - threshold value for the pixel: 3, 5, 7, and so on. - (optional, default: 15) - - threshold_constant : float - Constant subtracted from the mean or weighted mean - (see the details below). Normally, it is positive but may be - zero or negative as well. - (optional, default: -2) - - scale : int - Used to divide the height/width of a pdf to get a structuring - element for image processing. - (optional, default: 15) - - iterations : int - Number of iterations for dilation. - (optional, default: 0) - - invert : bool - Whether or not to invert the image. Useful when pdfs have - tables with lines in background. - (optional, default: False) - - margins : tuple - PDFMiner margins. (char_margin, line_margin, word_margin) - (optional, default: (1.0, 0.5, 0.1)) - - split_text : bool - Whether or not to split a text line if it spans across - different cells. - (optional, default: False) - - flag_size : bool - Whether or not to highlight a substring using - if its size is different from rest of the string, useful for - super and subscripts. - (optional, default: True) - - shift_text : list - {'l', 'r', 't', 'b'} - Select one or more from above and pass them as a list to - specify where the text in a spanning cell should flow. - (optional, default: ['l', 't']) - - debug : string - {'contour', 'line', 'joint', 'table'} - Set to one of the above values to generate a matplotlib plot - of detected contours, lines, joints and the table generated. - (optional, default: None) - """ - def __init__(self, table_area=None, fill=None, mtol=[2], jtol=[2], - blocksize=15, threshold_constant=-2, scale=15, iterations=0, - invert=False, margins=(1.0, 0.5, 0.1), split_text=False, - flag_size=True, shift_text=['l', 't'], debug=None): - - self.method = 'lattice' - self.table_area = table_area - self.fill = fill - self.mtol = mtol - self.jtol = jtol - self.blocksize = blocksize - self.threshold_constant = threshold_constant - self.scale = scale - self.iterations = iterations - self.invert = invert - self.char_margin, self.line_margin, self.word_margin = margins - self.split_text = split_text - self.flag_size = flag_size - self.shift_text = shift_text - self.debug = debug - - def get_tables(self, pdfname): - """Expects a single page pdf as input with rotation corrected. - - Parameters - ---------- - pdfname : string - Path to single page pdf file. - - Returns - ------- - page : dict - """ - layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, - line_margin=self.line_margin, word_margin=self.word_margin) - lttextlh = get_text_objects(layout, ltype="lh") - lttextlv = get_text_objects(layout, ltype="lv") - ltchar = get_text_objects(layout, ltype="char") - width, height = dim - bname, __ = os.path.splitext(pdfname) - logger.info('Processing {0}.'.format(os.path.basename(bname))) - if not ltchar: - warnings.warn("{0}: Page contains no text.".format( - os.path.basename(bname))) - return {os.path.basename(bname): None} - - imagename = ''.join([bname, '.png']) - gs_call = [ - "-q", "-sDEVICE=png16m", "-o", imagename, "-r600", pdfname - ] - if "ghostscript" in subprocess.check_output(["gs", "-version"]).lower(): - gs_call.insert(0, "gs") - else: - gs_call.insert(0, "gsc") - subprocess.call(gs_call, stdout=open(os.devnull, 'w'), - stderr=subprocess.STDOUT) - - img, threshold = adaptive_threshold(imagename, invert=self.invert, - blocksize=self.blocksize, c=self.threshold_constant) - pdf_x = width - pdf_y = height - img_x = img.shape[1] - img_y = img.shape[0] - sc_x_image = img_x / float(pdf_x) - sc_y_image = img_y / float(pdf_y) - sc_x_pdf = pdf_x / float(img_x) - sc_y_pdf = pdf_y / float(img_y) - factors_image = (sc_x_image, sc_y_image, pdf_y) - factors_pdf = (sc_x_pdf, sc_y_pdf, img_y) - - vmask, v_segments = find_lines(threshold, direction='vertical', - scale=self.scale, iterations=self.iterations) - hmask, h_segments = find_lines(threshold, direction='horizontal', - scale=self.scale, iterations=self.iterations) - - if self.table_area is not None: - areas = [] - for area in self.table_area: - x1, y1, x2, y2 = area.split(",") - x1 = float(x1) - y1 = float(y1) - x2 = float(x2) - y2 = float(y2) - x1, y1, x2, y2 = scale_to_image((x1, y1, x2, y2), factors_image) - areas.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) - table_bbox = find_table_joints(areas, vmask, hmask) - else: - contours = find_table_contours(vmask, hmask) - table_bbox = find_table_joints(contours, vmask, hmask) - - if len(self.mtol) == 1 and self.mtol[0] == 2: - mtolerance = copy.deepcopy(self.mtol) * len(table_bbox) - else: - mtolerance = copy.deepcopy(self.mtol) - - if len(self.jtol) == 1 and self.jtol[0] == 2: - jtolerance = copy.deepcopy(self.jtol) * len(table_bbox) - else: - jtolerance = copy.deepcopy(self.jtol) - - if self.debug: - self.debug_images = (img, table_bbox) - - table_bbox, v_segments, h_segments = scale_to_pdf(table_bbox, v_segments, - h_segments, factors_pdf) - - if self.debug: - self.debug_segments = (v_segments, h_segments) - self.debug_tables = [] - - page = {} - tables = {} - # sort tables based on y-coord - for table_no, k in enumerate(sorted(table_bbox.keys(), key=lambda x: x[1], reverse=True)): - # select elements which lie within table_bbox - table_data = {} - t_bbox = {} - v_s, h_s = segments_bbox(k, v_segments, h_segments) - t_bbox['horizontal'] = text_in_bbox(k, lttextlh) - t_bbox['vertical'] = text_in_bbox(k, lttextlv) - char_bbox = text_in_bbox(k, ltchar) - table_data['text_p'] = 100 * (1 - (len(char_bbox) / len(ltchar))) - for direction in t_bbox: - t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) - cols, rows = zip(*table_bbox[k]) - cols, rows = list(cols), list(rows) - cols.extend([k[0], k[2]]) - rows.extend([k[1], k[3]]) - # sort horizontal and vertical segments - cols = merge_close_values(sorted(cols), mtol=mtolerance[table_no]) - rows = merge_close_values( - sorted(rows, reverse=True), mtol=mtolerance[table_no]) - # make grid using x and y coord of shortlisted rows and cols - cols = [(cols[i], cols[i + 1]) - for i in range(0, len(cols) - 1)] - rows = [(rows[i], rows[i + 1]) - for i in range(0, len(rows) - 1)] - - table = Table(cols, rows) - # set table edges to True using ver+hor lines - table = table.set_edges(v_s, h_s, jtol=jtolerance[table_no]) - nouse = table.nocont_ / (len(v_s) + len(h_s)) - table_data['line_p'] = 100 * (1 - nouse) - # set spanning cells to True - table = table.set_spanning() - # set table border edges to True - table = table.set_border_edges() - - if self.debug: - self.debug_tables.append(table) - - assignment_errors = [] - table_data['split_text'] = [] - table_data['superscript'] = [] - for direction in ['vertical', 'horizontal']: - for t in t_bbox[direction]: - indices, error = get_table_index( - table, t, direction, split_text=self.split_text, - flag_size=self.flag_size) - if indices[:2] != (-1, -1): - assignment_errors.append(error) - indices = _reduce_index(table, indices, shift_text=self.shift_text) - if len(indices) > 1: - table_data['split_text'].append(indices) - for r_idx, c_idx, text in indices: - if all(s in text for s in ['', '']): - table_data['superscript'].append((r_idx, c_idx, text)) - table.cells[r_idx][c_idx].add_text(text) - score = get_score([[100, assignment_errors]]) - table_data['score'] = score - - if self.fill is not None: - table = _fill_spanning(table, fill=self.fill) - ar = table.get_list() - ar = encode_list(ar) - table_data['data'] = ar - empty_p, r_nempty_cells, c_nempty_cells = count_empty(ar) - table_data['empty_p'] = empty_p - table_data['r_nempty_cells'] = r_nempty_cells - table_data['c_nempty_cells'] = c_nempty_cells - table_data['nrows'] = len(ar) - table_data['ncols'] = len(ar[0]) - tables['table-{0}'.format(table_no + 1)] = table_data - page[os.path.basename(bname)] = tables - - if self.debug: - return None - - return page \ No newline at end of file diff --git a/camelot/stream.py b/camelot/parsers.py similarity index 51% rename from camelot/stream.py rename to camelot/parsers.py index ae0ef4a..f47f51a 100644 --- a/camelot/stream.py +++ b/camelot/parsers.py @@ -1,19 +1,24 @@ from __future__ import division import os +import sys import copy import types import logging import copy_reg import warnings +import subprocess import numpy as np -from .core import Table -from .utils import (text_in_bbox, get_table_index, get_score, count_empty, +from .core import TableSet +from .image_processing import (adaptive_threshold, find_lines, find_table_contours, + find_table_joints) +from .utils import (scale_to_pdf, scale_to_image, segments_bbox, text_in_bbox, + merge_close_values, get_table_index, get_score, count_empty, encode_list, get_text_objects, get_page_layout) -__all__ = ['Stream'] +__all__ = ['Stream', 'Lattice'] logger = logging.getLogger('app_logger') @@ -425,4 +430,358 @@ class Stream: tables['table-{0}'.format(table_no + 1)] = table_data page[os.path.basename(bname)] = tables + return page + + +def _reduce_index(t, idx, shift_text): + """Reduces index of a text object if it lies within a spanning + cell. + + Parameters + ---------- + table : object + camelot.table.Table + + idx : list + List of tuples of the form (r_idx, c_idx, text). + + shift_text : list + {'l', 'r', 't', 'b'} + Select one or more from above and pass them as a list to + specify where the text in a spanning cell should flow. + + Returns + ------- + indices : list + List of tuples of the form (idx, text) where idx is the reduced + index of row/column and text is the an lttextline substring. + """ + indices = [] + for r_idx, c_idx, text in idx: + for d in shift_text: + if d == 'l': + if t.cells[r_idx][c_idx].spanning_h: + while not t.cells[r_idx][c_idx].left: + c_idx -= 1 + if d == 'r': + if t.cells[r_idx][c_idx].spanning_h: + while not t.cells[r_idx][c_idx].right: + c_idx += 1 + if d == 't': + if t.cells[r_idx][c_idx].spanning_v: + while not t.cells[r_idx][c_idx].top: + r_idx -= 1 + if d == 'b': + if t.cells[r_idx][c_idx].spanning_v: + while not t.cells[r_idx][c_idx].bottom: + r_idx += 1 + indices.append((r_idx, c_idx, text)) + return indices + + +def _fill_spanning(t, fill=None): + """Fills spanning cells. + + Parameters + ---------- + t : object + camelot.table.Table + + fill : list + {'h', 'v'} + Specify to fill spanning cells in horizontal or vertical + direction. + (optional, default: None) + + Returns + ------- + t : object + camelot.table.Table + """ + for f in fill: + if f == "h": + for i in range(len(t.cells)): + for j in range(len(t.cells[i])): + if t.cells[i][j].get_text().strip() == '': + if t.cells[i][j].spanning_h and not t.cells[i][j].left: + t.cells[i][j].add_text(t.cells[i][j - 1].get_text()) + elif f == "v": + for i in range(len(t.cells)): + for j in range(len(t.cells[i])): + if t.cells[i][j].get_text().strip() == '': + if t.cells[i][j].spanning_v and not t.cells[i][j].top: + t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) + return t + + +class Lattice: + """Lattice looks for lines in the pdf to form a table. + + If you want to give fill and mtol for each table when specifying + multiple table areas, make sure that the length of fill and mtol + is equal to the length of table_area. Mapping between them is based + on index. + + Parameters + ---------- + table_area : list + List of strings of the form x1,y1,x2,y2 where + (x1, y1) -> left-top and (x2, y2) -> right-bottom in PDFMiner's + coordinate space, denoting table areas to analyze. + (optional, default: None) + + fill : list + List of strings specifying directions to fill spanning cells. + {'h', 'v'} to fill spanning cells in horizontal or vertical + direction. + (optional, default: None) + + mtol : list + List of ints specifying m-tolerance parameters. + (optional, default: [2]) + + jtol : list + List of ints specifying j-tolerance parameters. + (optional, default: [2]) + + blocksize : int + Size of a pixel neighborhood that is used to calculate a + threshold value for the pixel: 3, 5, 7, and so on. + (optional, default: 15) + + threshold_constant : float + Constant subtracted from the mean or weighted mean + (see the details below). Normally, it is positive but may be + zero or negative as well. + (optional, default: -2) + + scale : int + Used to divide the height/width of a pdf to get a structuring + element for image processing. + (optional, default: 15) + + iterations : int + Number of iterations for dilation. + (optional, default: 0) + + invert : bool + Whether or not to invert the image. Useful when pdfs have + tables with lines in background. + (optional, default: False) + + margins : tuple + PDFMiner margins. (char_margin, line_margin, word_margin) + (optional, default: (1.0, 0.5, 0.1)) + + split_text : bool + Whether or not to split a text line if it spans across + different cells. + (optional, default: False) + + flag_size : bool + Whether or not to highlight a substring using + if its size is different from rest of the string, useful for + super and subscripts. + (optional, default: True) + + shift_text : list + {'l', 'r', 't', 'b'} + Select one or more from above and pass them as a list to + specify where the text in a spanning cell should flow. + (optional, default: ['l', 't']) + + debug : string + {'contour', 'line', 'joint', 'table'} + Set to one of the above values to generate a matplotlib plot + of detected contours, lines, joints and the table generated. + (optional, default: None) + """ + def __init__(self, table_area=None, fill=None, mtol=[2], jtol=[2], + blocksize=15, threshold_constant=-2, scale=15, iterations=0, + invert=False, margins=(1.0, 0.5, 0.1), split_text=False, + flag_size=True, shift_text=['l', 't'], debug=None): + + self.method = 'lattice' + self.table_area = table_area + self.fill = fill + self.mtol = mtol + self.jtol = jtol + self.blocksize = blocksize + self.threshold_constant = threshold_constant + self.scale = scale + self.iterations = iterations + self.invert = invert + self.char_margin, self.line_margin, self.word_margin = margins + self.split_text = split_text + self.flag_size = flag_size + self.shift_text = shift_text + self.debug = debug + + def get_tables(self, pdfname): + """Expects a single page pdf as input with rotation corrected. + + Parameters + ---------- + pdfname : string + Path to single page pdf file. + + Returns + ------- + page : dict + """ + layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, + line_margin=self.line_margin, word_margin=self.word_margin) + lttextlh = get_text_objects(layout, ltype="lh") + lttextlv = get_text_objects(layout, ltype="lv") + ltchar = get_text_objects(layout, ltype="char") + width, height = dim + bname, __ = os.path.splitext(pdfname) + logger.info('Processing {0}.'.format(os.path.basename(bname))) + if not ltchar: + warnings.warn("{0}: Page contains no text.".format( + os.path.basename(bname))) + return {os.path.basename(bname): None} + + imagename = ''.join([bname, '.png']) + gs_call = [ + "-q", "-sDEVICE=png16m", "-o", imagename, "-r600", pdfname + ] + if "ghostscript" in subprocess.check_output(["gs", "-version"]).lower(): + gs_call.insert(0, "gs") + else: + gs_call.insert(0, "gsc") + subprocess.call(gs_call, stdout=open(os.devnull, 'w'), + stderr=subprocess.STDOUT) + + img, threshold = adaptive_threshold(imagename, invert=self.invert, + blocksize=self.blocksize, c=self.threshold_constant) + pdf_x = width + pdf_y = height + img_x = img.shape[1] + img_y = img.shape[0] + sc_x_image = img_x / float(pdf_x) + sc_y_image = img_y / float(pdf_y) + sc_x_pdf = pdf_x / float(img_x) + sc_y_pdf = pdf_y / float(img_y) + factors_image = (sc_x_image, sc_y_image, pdf_y) + factors_pdf = (sc_x_pdf, sc_y_pdf, img_y) + + vmask, v_segments = find_lines(threshold, direction='vertical', + scale=self.scale, iterations=self.iterations) + hmask, h_segments = find_lines(threshold, direction='horizontal', + scale=self.scale, iterations=self.iterations) + + if self.table_area is not None: + areas = [] + for area in self.table_area: + x1, y1, x2, y2 = area.split(",") + x1 = float(x1) + y1 = float(y1) + x2 = float(x2) + y2 = float(y2) + x1, y1, x2, y2 = scale_to_image((x1, y1, x2, y2), factors_image) + areas.append((x1, y1, abs(x2 - x1), abs(y2 - y1))) + table_bbox = find_table_joints(areas, vmask, hmask) + else: + contours = find_table_contours(vmask, hmask) + table_bbox = find_table_joints(contours, vmask, hmask) + + if len(self.mtol) == 1 and self.mtol[0] == 2: + mtolerance = copy.deepcopy(self.mtol) * len(table_bbox) + else: + mtolerance = copy.deepcopy(self.mtol) + + if len(self.jtol) == 1 and self.jtol[0] == 2: + jtolerance = copy.deepcopy(self.jtol) * len(table_bbox) + else: + jtolerance = copy.deepcopy(self.jtol) + + if self.debug: + self.debug_images = (img, table_bbox) + + table_bbox, v_segments, h_segments = scale_to_pdf(table_bbox, v_segments, + h_segments, factors_pdf) + + if self.debug: + self.debug_segments = (v_segments, h_segments) + self.debug_tables = [] + + page = {} + tables = {} + # sort tables based on y-coord + for table_no, k in enumerate(sorted(table_bbox.keys(), key=lambda x: x[1], reverse=True)): + # select elements which lie within table_bbox + table_data = {} + t_bbox = {} + v_s, h_s = segments_bbox(k, v_segments, h_segments) + t_bbox['horizontal'] = text_in_bbox(k, lttextlh) + t_bbox['vertical'] = text_in_bbox(k, lttextlv) + char_bbox = text_in_bbox(k, ltchar) + table_data['text_p'] = 100 * (1 - (len(char_bbox) / len(ltchar))) + for direction in t_bbox: + t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) + cols, rows = zip(*table_bbox[k]) + cols, rows = list(cols), list(rows) + cols.extend([k[0], k[2]]) + rows.extend([k[1], k[3]]) + # sort horizontal and vertical segments + cols = merge_close_values(sorted(cols), mtol=mtolerance[table_no]) + rows = merge_close_values( + sorted(rows, reverse=True), mtol=mtolerance[table_no]) + # make grid using x and y coord of shortlisted rows and cols + cols = [(cols[i], cols[i + 1]) + for i in range(0, len(cols) - 1)] + rows = [(rows[i], rows[i + 1]) + for i in range(0, len(rows) - 1)] + + table = Table(cols, rows) + # set table edges to True using ver+hor lines + table = table.set_edges(v_s, h_s, jtol=jtolerance[table_no]) + nouse = table.nocont_ / (len(v_s) + len(h_s)) + table_data['line_p'] = 100 * (1 - nouse) + # set spanning cells to True + table = table.set_spanning() + # set table border edges to True + table = table.set_border_edges() + + if self.debug: + self.debug_tables.append(table) + + assignment_errors = [] + table_data['split_text'] = [] + table_data['superscript'] = [] + for direction in ['vertical', 'horizontal']: + for t in t_bbox[direction]: + indices, error = get_table_index( + table, t, direction, split_text=self.split_text, + flag_size=self.flag_size) + if indices[:2] != (-1, -1): + assignment_errors.append(error) + indices = _reduce_index(table, indices, shift_text=self.shift_text) + if len(indices) > 1: + table_data['split_text'].append(indices) + for r_idx, c_idx, text in indices: + if all(s in text for s in ['', '']): + table_data['superscript'].append((r_idx, c_idx, text)) + table.cells[r_idx][c_idx].add_text(text) + score = get_score([[100, assignment_errors]]) + table_data['score'] = score + + if self.fill is not None: + table = _fill_spanning(table, fill=self.fill) + ar = table.get_list() + ar = encode_list(ar) + table_data['data'] = ar + empty_p, r_nempty_cells, c_nempty_cells = count_empty(ar) + table_data['empty_p'] = empty_p + table_data['r_nempty_cells'] = r_nempty_cells + table_data['c_nempty_cells'] = c_nempty_cells + table_data['nrows'] = len(ar) + table_data['ncols'] = len(ar[0]) + tables['table-{0}'.format(table_no + 1)] = table_data + page[os.path.basename(bname)] = tables + + if self.debug: + return None + return page \ No newline at end of file From 941994f0bfb90dfa6c8bffb267bd4297f267b14e Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Tue, 4 Sep 2018 23:34:49 +0530 Subject: [PATCH 08/39] Make present code work with new API --- camelot/__init__.py | 2 +- camelot/core.py | 80 +------------------------------------------ camelot/handlers.py | 83 +++++++++++++++++++++++++++++++++++++++++++++ camelot/io.py | 8 +++-- camelot/parsers.py | 2 +- 5 files changed, 91 insertions(+), 84 deletions(-) create mode 100644 camelot/handlers.py diff --git a/camelot/__init__.py b/camelot/__init__.py index 24ff0f1..b762cea 100644 --- a/camelot/__init__.py +++ b/camelot/__init__.py @@ -1,3 +1,3 @@ from .__version__ import __version__ -from .io import * \ No newline at end of file +from .io import read_pdf \ No newline at end of file diff --git a/camelot/core.py b/camelot/core.py index 2cca37d..0b7a21b 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -1,11 +1,5 @@ -import os -import tempfile - import numpy as np import pandas as pd -from PyPDF2 import PdfFileReader, PdfFileWriter - -from .utils import get_page_layout, get_text_objects, get_rotation class Cell(object): @@ -238,76 +232,4 @@ class TableSet(object): pass def __repr__(self): - pass - - -class FileHandler(object): - def __init__(self, filename, pages='1'): - self.filename = filename - if not self.filename.endswith('.pdf'): - raise TypeError("File format not supported.") - self.pages = __get_pages(pages) - self.temp = tempfile.mkdtemp() - - @staticmethod - def __get_pages(filename, pages): - p = {} - if pages == '1': - p.append({'start': 1, 'end': 1}) - else: - infile = PdfFileReader(open(filename, 'rb'), strict=False) - if pages == 'all': - p.append({'start': 1, 'end': infile.getNumPages()}) - else: - for r in pages.split(','): - if '-' in r: - a, b = r.split('-') - if b == 'end': - b = infile.getNumPages() - p.append({'start': int(a), 'end': int(b)}) - else: - p.append({'start': int(r), 'end': int(r)}) - return p - - @staticmethod - def __save_page(filename, page, temp): - with open(filename, 'rb') as fileobj: - infile = PdfFileReader(fileobj, strict=False) - fpath = os.path.join(temp, 'page-{0}.pdf'.format(page)) - fname, fext = os.path.splitext(fpath) - p = infile.getPage(page - 1) - outfile = PdfFileWriter() - outfile.addPage(p) - with open(fpath, 'wb') as f: - outfile.write(f) - layout, dim = get_page_layout(fpath) - # fix rotated pdf - lttextlh = get_text_objects(layout, ltype="lh") - lttextlv = get_text_objects(layout, ltype="lv") - ltchar = get_text_objects(layout, ltype="char") - rotation = get_rotation(lttextlh, lttextlv, ltchar) - if rotation != '': - fpath_new = ''.join([fname.replace('page', 'p'), '_rotated', fext]) - os.rename(fpath, fpath_new) - infile = PdfFileReader(open(fpath_new, 'rb'), strict=False) - outfile = PdfFileWriter() - p = infile.getPage(0) - if rotation == 'left': - p.rotateClockwise(90) - elif rotation == 'right': - p.rotateCounterClockwise(90) - outfile.addPage(p) - with open(fpath, 'wb') as f: - outfile.write(f) - - def parse(self): - for p in self.pages: - __save_page(self.filename, p, self.temp) - pages = [os.path.join(self.temp, 'page-{0}.pdf'.format(p)) - for p in self.pagenos] - tables = {} - for p in pages: - table = self.parser.get_tables(p) - if table is not None: - tables.update(table) - return tables \ No newline at end of file + pass \ No newline at end of file diff --git a/camelot/handlers.py b/camelot/handlers.py new file mode 100644 index 0000000..83fe4ae --- /dev/null +++ b/camelot/handlers.py @@ -0,0 +1,83 @@ +import os +import tempfile + +from PyPDF2 import PdfFileReader, PdfFileWriter + +from .parsers import Stream, Lattice +from .utils import get_page_layout, get_text_objects, get_rotation + + +class PDFHandler(object): + def __init__(self, filename, pages='1'): + self.filename = filename + if not self.filename.endswith('.pdf'): + raise TypeError("File format not supported.") + self.pages = self.__get_pages(self.filename, pages) + self.temp = tempfile.mkdtemp() + + def __get_pages(self, filename, pages): + # refactor + page_numbers = [] + if pages == '1': + page_numbers.append({'start': 1, 'end': 1}) + else: + infile = PdfFileReader(open(filename, 'rb'), strict=False) + if pages == 'all': + page_numbers.append({'start': 1, 'end': infile.getNumPages()}) + else: + for r in pages.split(','): + if '-' in r: + a, b = r.split('-') + if b == 'end': + b = infile.getNumPages() + page_numbers.append({'start': int(a), 'end': int(b)}) + else: + page_numbers.append({'start': int(r), 'end': int(r)}) + P = [] + for p in page_numbers: + P.extend(range(p['start'], p['end'] + 1)) + return sorted(set(P)) + + def __save_page(self, filename, page, temp): + # refactor + with open(filename, 'rb') as fileobj: + infile = PdfFileReader(fileobj, strict=False) + fpath = os.path.join(temp, 'page-{0}.pdf'.format(page)) + fname, fext = os.path.splitext(fpath) + p = infile.getPage(page - 1) + outfile = PdfFileWriter() + outfile.addPage(p) + with open(fpath, 'wb') as f: + outfile.write(f) + layout, dim = get_page_layout(fpath) + # fix rotated pdf + lttextlh = get_text_objects(layout, ltype="lh") + lttextlv = get_text_objects(layout, ltype="lv") + ltchar = get_text_objects(layout, ltype="char") + rotation = get_rotation(lttextlh, lttextlv, ltchar) + if rotation != '': + fpath_new = ''.join([fname.replace('page', 'p'), '_rotated', fext]) + os.rename(fpath, fpath_new) + infile = PdfFileReader(open(fpath_new, 'rb'), strict=False) + outfile = PdfFileWriter() + p = infile.getPage(0) + if rotation == 'left': + p.rotateClockwise(90) + elif rotation == 'right': + p.rotateCounterClockwise(90) + outfile.addPage(p) + with open(fpath, 'wb') as f: + outfile.write(f) + + def parse(self, mesh=False, **kwargs): + for p in self.pages: + self.__save_page(self.filename, p, self.temp) + pages = [os.path.join(self.temp, 'page-{0}.pdf'.format(p)) + for p in self.pages] + tables = {} + parser = Stream(**kwargs) if not mesh else Lattice(**kwargs) + for p in pages: + table = parser.get_tables(p) + if table is not None: + tables.update(table) + return tables \ No newline at end of file diff --git a/camelot/io.py b/camelot/io.py index a78cf3a..fcae040 100644 --- a/camelot/io.py +++ b/camelot/io.py @@ -1,5 +1,7 @@ -from .core import * +from .handlers import PDFHandler -def read_pdf(filepath, pages='1', grid=True): - pass \ No newline at end of file +def read_pdf(filepath, pages='1', mesh=False, **kwargs): + # explicit type conversion + p = PDFHandler(filepath, pages) + return p.parse(mesh=mesh, **kwargs) \ No newline at end of file diff --git a/camelot/parsers.py b/camelot/parsers.py index f47f51a..c175fee 100644 --- a/camelot/parsers.py +++ b/camelot/parsers.py @@ -10,7 +10,7 @@ import subprocess import numpy as np -from .core import TableSet +from .core import Table from .image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) from .utils import (scale_to_pdf, scale_to_image, segments_bbox, text_in_bbox, From b9d77cb983e8d836ea9b9c42aa4e607e37722d84 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Wed, 5 Sep 2018 15:18:31 +0530 Subject: [PATCH 09/39] Decouple debug geometry from tables --- README.md | 4 +- camelot/__init__.py | 3 +- camelot/core.py | 70 +++++- camelot/handlers.py | 11 +- camelot/io.py | 3 +- camelot/parsers.py | 580 ++++++++++++++++++++++---------------------- camelot/plot.py | 98 ++++++++ 7 files changed, 463 insertions(+), 306 deletions(-) create mode 100644 camelot/plot.py diff --git a/README.md b/README.md index 7efc6f2..4a5227f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Camelot is a Python 2.7 library and command-line tool for getting tables out of >>> import camelot >>> tables = camelot.read_pdf("foo.pdf") >>> tables -<TableSet n=2> +<TableList n=2> >>> tables.to_csv(zip=True) # to_json, to_excel, to_html >>> tables[0] <Table shape=(3,4)> @@ -19,8 +19,8 @@ Camelot is a Python 2.7 library and command-line tool for getting tables out of "time_taken": 0.5, "page": 1 } +>>> df = tables[0].df >>> tables[0].to_csv("foo.csv") # to_json, to_excel, to_html ->>> df = tables[0].to_df() Camelot comes with a CLI where you can specify page numbers, output format, output directory etc. By default, the output files are placed in the same directory as the PDF. diff --git a/camelot/__init__.py b/camelot/__init__.py index b762cea..9762184 100644 --- a/camelot/__init__.py +++ b/camelot/__init__.py @@ -1,3 +1,4 @@ from .__version__ import __version__ -from .io import read_pdf \ No newline at end of file +from .io import read_pdf +from .plot import plot_geometry \ No newline at end of file diff --git a/camelot/core.py b/camelot/core.py index 0b7a21b..ec74eb3 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -21,7 +21,6 @@ class Cell(object): self.text = '' self.spanning_h = False self.spanning_v = False - self.image = None def __repr__(self): pass @@ -49,8 +48,6 @@ class Table(object): self.rows = rows self.cells = [[Cell(c[0], r[1], c[1], r[0]) for c in cols] for r in rows] - self.nocont_ = 0 - self.image = None def __repr__(self): pass @@ -127,7 +124,7 @@ class Table(object): J += 1 for h in horizontal: - # find closest y coord + # find closest y coord # iterate over x coords and find closest points i = [i for i, t in enumerate(self.rows) if np.isclose(h[1], t[0], atol=jtol)] @@ -227,9 +224,66 @@ class Table(object): return ar -class TableSet(object): - def __init__(self): - pass +class TableList(list): + def __init__(self, tables): + self._tables = tables def __repr__(self): - pass \ No newline at end of file + return '<{} tables={}>'.format( + self.__class__.__name__, len(self._tables)) + + +class Geometry(object): + def __init__(self): + self._text = [] + self._images = [] + self._segments = [] + self._tables = [] + + @property + def text(self): + return self._text + + @text.setter + def text(self, t): + self._text = t + + @property + def images(self): + return self._images + + @images.setter + def images(self, i): + self._images = i + + @property + def segments(self): + return self._segments + + @segments.setter + def segments(self, s): + self._segments = s + + @property + def tables(self): + return self._tables + + @tables.setter + def tables(self, tb): + self._tables = tb + + +class GeometryList(object): + def __init__(self, geometry): + self._text = [g.text for g in geometry] + self._images = [g.images for g in geometry] + self._segments = [g.segments for g in geometry] + self._tables = [g.tables for g in geometry] + + def __repr__(self): + return '<{} text={} images={} segments={} tables={}>'.format( + self.__class__.__name__, + len(self._text), + len(self._images), + len(self._segments), + len(self._tables)) \ No newline at end of file diff --git a/camelot/handlers.py b/camelot/handlers.py index 83fe4ae..35f14f4 100644 --- a/camelot/handlers.py +++ b/camelot/handlers.py @@ -74,10 +74,11 @@ class PDFHandler(object): self.__save_page(self.filename, p, self.temp) pages = [os.path.join(self.temp, 'page-{0}.pdf'.format(p)) for p in self.pages] - tables = {} + tables = [] + geometry = [] parser = Stream(**kwargs) if not mesh else Lattice(**kwargs) for p in pages: - table = parser.get_tables(p) - if table is not None: - tables.update(table) - return tables \ No newline at end of file + t, g = parser.extract_tables(p) + tables.extend(t) + geometry.extend(g) + return TableList(tables), GeometryList(geometry) \ No newline at end of file diff --git a/camelot/io.py b/camelot/io.py index fcae040..c2b319b 100644 --- a/camelot/io.py +++ b/camelot/io.py @@ -4,4 +4,5 @@ from .handlers import PDFHandler def read_pdf(filepath, pages='1', mesh=False, **kwargs): # explicit type conversion p = PDFHandler(filepath, pages) - return p.parse(mesh=mesh, **kwargs) \ No newline at end of file + tables, __ = p.parse(mesh=mesh, **kwargs) + return tables \ No newline at end of file diff --git a/camelot/parsers.py b/camelot/parsers.py index c175fee..205743c 100644 --- a/camelot/parsers.py +++ b/camelot/parsers.py @@ -10,7 +10,7 @@ import subprocess import numpy as np -from .core import Table +from .core import Table, Geometry from .image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) from .utils import (scale_to_pdf, scale_to_image, segments_bbox, text_in_bbox, @@ -30,192 +30,6 @@ def _reduce_method(m): copy_reg.pickle(types.MethodType, _reduce_method) -def _text_bbox(t_bbox): - """Returns bounding box for the text present on a page. - - Parameters - ---------- - t_bbox : dict - Dict with two keys 'horizontal' and 'vertical' with lists of - LTTextLineHorizontals and LTTextLineVerticals respectively. - - Returns - ------- - text_bbox : tuple - Tuple of the form (x0, y0, x1, y1) in PDFMiner's coordinate - space. - """ - xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) - ymin = min([t.y0 for direction in t_bbox for t in t_bbox[direction]]) - xmax = max([t.x1 for direction in t_bbox for t in t_bbox[direction]]) - ymax = max([t.y1 for direction in t_bbox for t in t_bbox[direction]]) - text_bbox = (xmin, ymin, xmax, ymax) - return text_bbox - - -def _group_rows(text, ytol=2): - """Groups PDFMiner text objects into rows using their - y-coordinates taking into account some tolerance ytol. - - Parameters - ---------- - text : list - List of PDFMiner text objects. - - ytol : int - Tolerance parameter. - (optional, default: 2) - - Returns - ------- - rows : list - Two-dimensional list of text objects grouped into rows. - """ - row_y = 0 - rows = [] - temp = [] - for t in text: - # is checking for upright necessary? - # if t.get_text().strip() and all([obj.upright for obj in t._objs if - # type(obj) is LTChar]): - if t.get_text().strip(): - if not np.isclose(row_y, t.y0, atol=ytol): - rows.append(sorted(temp, key=lambda t: t.x0)) - temp = [] - row_y = t.y0 - temp.append(t) - rows.append(sorted(temp, key=lambda t: t.x0)) - __ = rows.pop(0) # hacky - return rows - - -def _merge_columns(l, mtol=0): - """Merges column boundaries if they overlap or lie within some - tolerance mtol. - - Parameters - ---------- - l : list - List of column coordinate tuples. - - mtol : int - TODO - (optional, default: 0) - - Returns - ------- - merged : list - List of merged column coordinate tuples. - """ - merged = [] - for higher in l: - if not merged: - merged.append(higher) - else: - lower = merged[-1] - if mtol >= 0: - if (higher[0] <= lower[1] or - np.isclose(higher[0], lower[1], atol=mtol)): - upper_bound = max(lower[1], higher[1]) - lower_bound = min(lower[0], higher[0]) - merged[-1] = (lower_bound, upper_bound) - else: - merged.append(higher) - elif mtol < 0: - if higher[0] <= lower[1]: - if np.isclose(higher[0], lower[1], atol=abs(mtol)): - merged.append(higher) - else: - upper_bound = max(lower[1], higher[1]) - lower_bound = min(lower[0], higher[0]) - merged[-1] = (lower_bound, upper_bound) - else: - merged.append(higher) - return merged - - -def _join_rows(rows_grouped, text_y_max, text_y_min): - """Makes row coordinates continuous. - - Parameters - ---------- - rows_grouped : list - Two-dimensional list of text objects grouped into rows. - - text_y_max : int - - text_y_min : int - - Returns - ------- - rows : list - List of continuous row coordinate tuples. - """ - row_mids = [sum([(t.y0 + t.y1) / 2 for t in r]) / len(r) - if len(r) > 0 else 0 for r in rows_grouped] - rows = [(row_mids[i] + row_mids[i - 1]) / 2 for i in range(1, len(row_mids))] - rows.insert(0, text_y_max) - rows.append(text_y_min) - rows = [(rows[i], rows[i + 1]) - for i in range(0, len(rows) - 1)] - return rows - - -def _join_columns(cols, text_x_min, text_x_max): - """Makes column coordinates continuous. - - Parameters - ---------- - cols : list - List of column coordinate tuples. - - text_x_min : int - - text_y_max : int - - Returns - ------- - cols : list - Updated list of column coordinate tuples. - """ - cols = sorted(cols) - cols = [(cols[i][0] + cols[i - 1][1]) / 2 for i in range(1, len(cols))] - cols.insert(0, text_x_min) - cols.append(text_x_max) - cols = [(cols[i], cols[i + 1]) - for i in range(0, len(cols) - 1)] - return cols - - -def _add_columns(cols, text, ytol): - """Adds columns to existing list by taking into account - the text that lies outside the current column coordinates. - - Parameters - ---------- - cols : list - List of column coordinate tuples. - - text : list - List of PDFMiner text objects. - - ytol : int - Tolerance parameter. - - Returns - ------- - cols : list - Updated list of column coordinate tuples. - """ - if text: - text = _group_rows(text, ytol=ytol) - elements = [len(r) for r in text] - new_cols = [(t.x0, t.x1) - for r in text if len(r) == max(elements) for t in r] - cols.extend(_merge_columns(sorted(new_cols))) - return cols - - class Stream: """Stream looks for spaces between text elements to form a table. @@ -283,7 +97,193 @@ class Stream: self.flag_size = flag_size self.debug = debug - def get_tables(self, pdfname): + @staticmethod + def _text_bbox(t_bbox): + """Returns bounding box for the text present on a page. + + Parameters + ---------- + t_bbox : dict + Dict with two keys 'horizontal' and 'vertical' with lists of + LTTextLineHorizontals and LTTextLineVerticals respectively. + + Returns + ------- + text_bbox : tuple + Tuple of the form (x0, y0, x1, y1) in PDFMiner's coordinate + space. + """ + xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) + ymin = min([t.y0 for direction in t_bbox for t in t_bbox[direction]]) + xmax = max([t.x1 for direction in t_bbox for t in t_bbox[direction]]) + ymax = max([t.y1 for direction in t_bbox for t in t_bbox[direction]]) + text_bbox = (xmin, ymin, xmax, ymax) + return text_bbox + + @staticmethod + def _group_rows(text, ytol=2): + """Groups PDFMiner text objects into rows using their + y-coordinates taking into account some tolerance ytol. + + Parameters + ---------- + text : list + List of PDFMiner text objects. + + ytol : int + Tolerance parameter. + (optional, default: 2) + + Returns + ------- + rows : list + Two-dimensional list of text objects grouped into rows. + """ + row_y = 0 + rows = [] + temp = [] + for t in text: + # is checking for upright necessary? + # if t.get_text().strip() and all([obj.upright for obj in t._objs if + # type(obj) is LTChar]): + if t.get_text().strip(): + if not np.isclose(row_y, t.y0, atol=ytol): + rows.append(sorted(temp, key=lambda t: t.x0)) + temp = [] + row_y = t.y0 + temp.append(t) + rows.append(sorted(temp, key=lambda t: t.x0)) + __ = rows.pop(0) # hacky + return rows + + @staticmethod + def _merge_columns(l, mtol=0): + """Merges column boundaries if they overlap or lie within some + tolerance mtol. + + Parameters + ---------- + l : list + List of column coordinate tuples. + + mtol : int + TODO + (optional, default: 0) + + Returns + ------- + merged : list + List of merged column coordinate tuples. + """ + merged = [] + for higher in l: + if not merged: + merged.append(higher) + else: + lower = merged[-1] + if mtol >= 0: + if (higher[0] <= lower[1] or + np.isclose(higher[0], lower[1], atol=mtol)): + upper_bound = max(lower[1], higher[1]) + lower_bound = min(lower[0], higher[0]) + merged[-1] = (lower_bound, upper_bound) + else: + merged.append(higher) + elif mtol < 0: + if higher[0] <= lower[1]: + if np.isclose(higher[0], lower[1], atol=abs(mtol)): + merged.append(higher) + else: + upper_bound = max(lower[1], higher[1]) + lower_bound = min(lower[0], higher[0]) + merged[-1] = (lower_bound, upper_bound) + else: + merged.append(higher) + return merged + + @staticmethod + def _join_rows(rows_grouped, text_y_max, text_y_min): + """Makes row coordinates continuous. + + Parameters + ---------- + rows_grouped : list + Two-dimensional list of text objects grouped into rows. + + text_y_max : int + + text_y_min : int + + Returns + ------- + rows : list + List of continuous row coordinate tuples. + """ + row_mids = [sum([(t.y0 + t.y1) / 2 for t in r]) / len(r) + if len(r) > 0 else 0 for r in rows_grouped] + rows = [(row_mids[i] + row_mids[i - 1]) / 2 for i in range(1, len(row_mids))] + rows.insert(0, text_y_max) + rows.append(text_y_min) + rows = [(rows[i], rows[i + 1]) + for i in range(0, len(rows) - 1)] + return rows + + @staticmethod + def _add_columns(cols, text, ytol): + """Adds columns to existing list by taking into account + the text that lies outside the current column coordinates. + + Parameters + ---------- + cols : list + List of column coordinate tuples. + + text : list + List of PDFMiner text objects. + + ytol : int + Tolerance parameter. + + Returns + ------- + cols : list + Updated list of column coordinate tuples. + """ + if text: + text = Stream._group_rows(text, ytol=ytol) + elements = [len(r) for r in text] + new_cols = [(t.x0, t.x1) + for r in text if len(r) == max(elements) for t in r] + cols.extend(Stream._merge_columns(sorted(new_cols))) + return cols + + @staticmethod + def _join_columns(cols, text_x_min, text_x_max): + """Makes column coordinates continuous. + + Parameters + ---------- + cols : list + List of column coordinate tuples. + + text_x_min : int + + text_y_max : int + + Returns + ------- + cols : list + Updated list of column coordinate tuples. + """ + cols = sorted(cols) + cols = [(cols[i][0] + cols[i - 1][1]) / 2 for i in range(1, len(cols))] + cols.insert(0, text_x_min) + cols.append(text_x_max) + cols = [(cols[i], cols[i + 1]) + for i in range(0, len(cols) - 1)] + return cols + + def extract_tables(self, pdfname): """Expects a single page pdf as input with rotation corrected. Parameters @@ -308,11 +308,13 @@ class Stream: os.path.basename(bname))) return {os.path.basename(bname): None} + g = Geometry() if self.debug: - self.debug_text = [] - self.debug_text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlh]) - self.debug_text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlv]) - return None + text = [] + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlh]) + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlv]) + g.text = text + return [None], [g] if self.table_area is not None: if self.columns is not None: @@ -354,9 +356,9 @@ class Stream: table_data['text_p'] = 100 * (1 - (len(char_bbox) / len(ltchar))) for direction in t_bbox: t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) - text_x_min, text_y_min, text_x_max, text_y_max = _text_bbox(t_bbox) - rows_grouped = _group_rows(t_bbox['horizontal'], ytol=ytolerance[table_no]) - rows = _join_rows(rows_grouped, text_y_max, text_y_min) + text_x_min, text_y_min, text_x_max, text_y_max = self._text_bbox(t_bbox) + rows_grouped = self._group_rows(t_bbox['horizontal'], ytol=ytolerance[table_no]) + rows = self._join_rows(rows_grouped, text_y_max, text_y_min) elements = [len(r) for r in rows_grouped] guess = False @@ -380,7 +382,7 @@ class Stream: os.path.basename(bname))) cols = [(t.x0, t.x1) for r in rows_grouped if len(r) == ncols for t in r] - cols = _merge_columns(sorted(cols), mtol=mtolerance[table_no]) + cols = self._merge_columns(sorted(cols), mtol=mtolerance[table_no]) inner_text = [] for i in range(1, len(cols)): left = cols[i - 1][1] @@ -392,8 +394,8 @@ class Stream: for t in t_bbox[direction] if t.x0 > cols[-1][1] or t.x1 < cols[0][0]] inner_text.extend(outer_text) - cols = _add_columns(cols, inner_text, ytolerance[table_no]) - cols = _join_columns(cols, text_x_min, text_x_max) + cols = self._add_columns(cols, inner_text, ytolerance[table_no]) + cols = self._join_columns(cols, text_x_min, text_x_max) table = Table(cols, rows) table = table.set_all_edges() @@ -433,87 +435,6 @@ class Stream: return page -def _reduce_index(t, idx, shift_text): - """Reduces index of a text object if it lies within a spanning - cell. - - Parameters - ---------- - table : object - camelot.table.Table - - idx : list - List of tuples of the form (r_idx, c_idx, text). - - shift_text : list - {'l', 'r', 't', 'b'} - Select one or more from above and pass them as a list to - specify where the text in a spanning cell should flow. - - Returns - ------- - indices : list - List of tuples of the form (idx, text) where idx is the reduced - index of row/column and text is the an lttextline substring. - """ - indices = [] - for r_idx, c_idx, text in idx: - for d in shift_text: - if d == 'l': - if t.cells[r_idx][c_idx].spanning_h: - while not t.cells[r_idx][c_idx].left: - c_idx -= 1 - if d == 'r': - if t.cells[r_idx][c_idx].spanning_h: - while not t.cells[r_idx][c_idx].right: - c_idx += 1 - if d == 't': - if t.cells[r_idx][c_idx].spanning_v: - while not t.cells[r_idx][c_idx].top: - r_idx -= 1 - if d == 'b': - if t.cells[r_idx][c_idx].spanning_v: - while not t.cells[r_idx][c_idx].bottom: - r_idx += 1 - indices.append((r_idx, c_idx, text)) - return indices - - -def _fill_spanning(t, fill=None): - """Fills spanning cells. - - Parameters - ---------- - t : object - camelot.table.Table - - fill : list - {'h', 'v'} - Specify to fill spanning cells in horizontal or vertical - direction. - (optional, default: None) - - Returns - ------- - t : object - camelot.table.Table - """ - for f in fill: - if f == "h": - for i in range(len(t.cells)): - for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_h and not t.cells[i][j].left: - t.cells[i][j].add_text(t.cells[i][j - 1].get_text()) - elif f == "v": - for i in range(len(t.cells)): - for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_v and not t.cells[i][j].top: - t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) - return t - - class Lattice: """Lattice looks for lines in the pdf to form a table. @@ -617,7 +538,88 @@ class Lattice: self.shift_text = shift_text self.debug = debug - def get_tables(self, pdfname): + @staticmethod + def _reduce_index(t, idx, shift_text): + """Reduces index of a text object if it lies within a spanning + cell. + + Parameters + ---------- + table : object + camelot.table.Table + + idx : list + List of tuples of the form (r_idx, c_idx, text). + + shift_text : list + {'l', 'r', 't', 'b'} + Select one or more from above and pass them as a list to + specify where the text in a spanning cell should flow. + + Returns + ------- + indices : list + List of tuples of the form (idx, text) where idx is the reduced + index of row/column and text is the an lttextline substring. + """ + indices = [] + for r_idx, c_idx, text in idx: + for d in shift_text: + if d == 'l': + if t.cells[r_idx][c_idx].spanning_h: + while not t.cells[r_idx][c_idx].left: + c_idx -= 1 + if d == 'r': + if t.cells[r_idx][c_idx].spanning_h: + while not t.cells[r_idx][c_idx].right: + c_idx += 1 + if d == 't': + if t.cells[r_idx][c_idx].spanning_v: + while not t.cells[r_idx][c_idx].top: + r_idx -= 1 + if d == 'b': + if t.cells[r_idx][c_idx].spanning_v: + while not t.cells[r_idx][c_idx].bottom: + r_idx += 1 + indices.append((r_idx, c_idx, text)) + return indices + + + def _fill_spanning(t, fill=None): + """Fills spanning cells. + + Parameters + ---------- + t : object + camelot.table.Table + + fill : list + {'h', 'v'} + Specify to fill spanning cells in horizontal or vertical + direction. + (optional, default: None) + + Returns + ------- + t : object + camelot.table.Table + """ + for f in fill: + if f == "h": + for i in range(len(t.cells)): + for j in range(len(t.cells[i])): + if t.cells[i][j].get_text().strip() == '': + if t.cells[i][j].spanning_h and not t.cells[i][j].left: + t.cells[i][j].add_text(t.cells[i][j - 1].get_text()) + elif f == "v": + for i in range(len(t.cells)): + for j in range(len(t.cells[i])): + if t.cells[i][j].get_text().strip() == '': + if t.cells[i][j].spanning_v and not t.cells[i][j].top: + t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) + return t + + def extract_tables(self, pdfname): """Expects a single page pdf as input with rotation corrected. Parameters @@ -696,15 +698,16 @@ class Lattice: else: jtolerance = copy.deepcopy(self.jtol) + g = Geometry() if self.debug: - self.debug_images = (img, table_bbox) + g.images = [(img, table_bbox)] table_bbox, v_segments, h_segments = scale_to_pdf(table_bbox, v_segments, h_segments, factors_pdf) if self.debug: - self.debug_segments = (v_segments, h_segments) - self.debug_tables = [] + g.segments = [(v_segments, h_segments)] + _tables = [] page = {} tables = {} @@ -737,15 +740,13 @@ class Lattice: table = Table(cols, rows) # set table edges to True using ver+hor lines table = table.set_edges(v_s, h_s, jtol=jtolerance[table_no]) - nouse = table.nocont_ / (len(v_s) + len(h_s)) - table_data['line_p'] = 100 * (1 - nouse) # set spanning cells to True table = table.set_spanning() # set table border edges to True table = table.set_border_edges() if self.debug: - self.debug_tables.append(table) + _tables.append(table) assignment_errors = [] table_data['split_text'] = [] @@ -757,7 +758,7 @@ class Lattice: flag_size=self.flag_size) if indices[:2] != (-1, -1): assignment_errors.append(error) - indices = _reduce_index(table, indices, shift_text=self.shift_text) + indices = self._reduce_index(table, indices, shift_text=self.shift_text) if len(indices) > 1: table_data['split_text'].append(indices) for r_idx, c_idx, text in indices: @@ -768,7 +769,7 @@ class Lattice: table_data['score'] = score if self.fill is not None: - table = _fill_spanning(table, fill=self.fill) + table = self._fill_spanning(table, fill=self.fill) ar = table.get_list() ar = encode_list(ar) table_data['data'] = ar @@ -782,6 +783,7 @@ class Lattice: page[os.path.basename(bname)] = tables if self.debug: - return None + g.tables = _tables + return [None], [g] return page \ No newline at end of file diff --git a/camelot/plot.py b/camelot/plot.py new file mode 100644 index 0000000..92bcd69 --- /dev/null +++ b/camelot/plot.py @@ -0,0 +1,98 @@ +import matplotlib.pyplot as plt +import matplotlib.patches as patches + +from .handlers import PDFHandler + + +def plot_geometry(filepath, pages='1', mesh=False, geometry_type='text', **kwargs): + # explicit type conversion + p = PDFHandler(filepath, pages) + kwargs.update({'debug': geometry_type}) + __, geometry = p.parse(mesh=mesh, **kwargs) + + if geometry_type == 'text': + for text in geometry.text: + fig = plt.figure() + ax = fig.add_subplot(111, aspect='equal') + xs, ys = [], [] + for t in text: + xs.extend([t[0], t[1]]) + ys.extend([t[2], t[3]]) + ax.add_patch( + patches.Rectangle( + (t[0], t[1]), + t[2] - t[0], + t[3] - t[1] + ) + ) + ax.set_xlim(min(xs) - 10, max(xs) + 10) + ax.set_ylim(min(ys) - 10, max(ys) + 10) + plt.show() + elif geometry_type == 'contour': + try: + for img, table_bbox in geometry.images: + for t in table_bbox.keys(): + cv2.rectangle(img, (t[0], t[1]), + (t[2], t[3]), (255, 0, 0), 3) + plt.imshow(img) + plt.show() + except AttributeError: + raise ValueError("This option can only be used with Lattice.") + elif geometry_type == 'joint': + try: + for img, table_bbox in geometry.images: + x_coord = [] + y_coord = [] + for k in table_bbox.keys(): + for coord in table_bbox[k]: + x_coord.append(coord[0]) + y_coord.append(coord[1]) + max_x, max_y = max(x_coord), max(y_coord) + plt.plot(x_coord, y_coord, 'ro') + plt.axis([0, max_x + 100, max_y + 100, 0]) + plt.imshow(img) + plt.show() + except AttributeError: + raise ValueError("This option can only be used with Lattice.") + elif geometry_type == 'line': + try: + for v_s, h_s in geometry.segments: + for v in v_s: + plt.plot([v[0], v[2]], [v[1], v[3]]) + for h in h_s: + plt.plot([h[0], h[2]], [h[1], h[3]]) + plt.show() + except AttributeError: + raise ValueError("This option can only be used with Lattice.") + elif geometry_type == 'table': + try: + for tables in geometry.tables: + for table in tables: + for r in range(len(table.rows)): + for c in range(len(table.cols)): + if table.cells[r][c].left: + plt.plot([table.cells[r][c].lb[0], + table.cells[r][c].lt[0]], + [table.cells[r][c].lb[1], + table.cells[r][c].lt[1]]) + if table.cells[r][c].right: + plt.plot([table.cells[r][c].rb[0], + table.cells[r][c].rt[0]], + [table.cells[r][c].rb[1], + table.cells[r][c].rt[1]]) + if table.cells[r][c].top: + plt.plot([table.cells[r][c].lt[0], + table.cells[r][c].rt[0]], + [table.cells[r][c].lt[1], + table.cells[r][c].rt[1]]) + if table.cells[r][c].bottom: + plt.plot([table.cells[r][c].lb[0], + table.cells[r][c].rb[0]], + [table.cells[r][c].lb[1], + table.cells[r][c].rb[1]]) + plt.show() + except AttributeError: + raise ValueError("This option can only be used with Lattice.") + else: + raise UserWarning("This method can only be called after" + " debug has been specified.") \ No newline at end of file From 9124e3374c5d0aec61b53a7c7725d3839effacdd Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Wed, 5 Sep 2018 18:20:46 +0530 Subject: [PATCH 10/39] Add properties to Table --- camelot/core.py | 70 +++++++- camelot/handlers.py | 3 +- camelot/parsers.py | 405 +++++--------------------------------------- camelot/utils.py | 4 +- 4 files changed, 110 insertions(+), 372 deletions(-) diff --git a/camelot/core.py b/camelot/core.py index ec74eb3..9089593 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -1,5 +1,4 @@ import numpy as np -import pandas as pd class Cell(object): @@ -48,9 +47,15 @@ class Table(object): self.rows = rows self.cells = [[Cell(c[0], r[1], c[1], r[0]) for c in cols] for r in rows] + self._df = None + self._shape = (0, 0) + self._accuracy = 0 + self._whitespace = 0 + self._order = None + self._page = None def __repr__(self): - pass + return '<{} shape={}>'.format(self.__class__.__name__, self._shape) def set_all_edges(self): for r in range(len(self.rows)): @@ -216,12 +221,61 @@ class Table(object): return self - def get_list(self): - ar = [] + @property + def data(self): + d = [] for r in range(len(self.rows)): - ar.append([self.cells[r][c].get_text().strip() + d.append([self.cells[r][c].get_text().strip() for c in range(len(self.cols))]) - return ar + return d + + @property + def df(self): + return self._df + + @df.setter + def df(self, dataframe): + self._df = dataframe + + @property + def shape(self): + return self._shape + + @shape.setter + def shape(self, s): + self._shape = s + + @property + def accuracy(self): + return self._accuracy + + @accuracy.setter + def accuracy(self, a): + self._accuracy = a + + @property + def whitespace(self): + return self._whitespace + + @whitespace.setter + def whitespace(self, w): + self._whitespace = w + + @property + def order(self): + return self._order + + @order.setter + def order(self, o): + self._order = o + + @property + def page(self): + return self._page + + @page.setter + def page(self, p): + self._page = p class TableList(list): @@ -236,8 +290,8 @@ class TableList(list): class Geometry(object): def __init__(self): self._text = [] - self._images = [] - self._segments = [] + self._images = () + self._segments = () self._tables = [] @property diff --git a/camelot/handlers.py b/camelot/handlers.py index 35f14f4..dce3b05 100644 --- a/camelot/handlers.py +++ b/camelot/handlers.py @@ -3,6 +3,7 @@ import tempfile from PyPDF2 import PdfFileReader, PdfFileWriter +from .core import TableList, GeometryList from .parsers import Stream, Lattice from .utils import get_page_layout, get_text_objects, get_rotation @@ -80,5 +81,5 @@ class PDFHandler(object): for p in pages: t, g = parser.extract_tables(p) tables.extend(t) - geometry.extend(g) + geometry.append(g) return TableList(tables), GeometryList(geometry) \ No newline at end of file diff --git a/camelot/parsers.py b/camelot/parsers.py index 205743c..20820da 100644 --- a/camelot/parsers.py +++ b/camelot/parsers.py @@ -9,13 +9,14 @@ import warnings import subprocess import numpy as np +import pandas as pd from .core import Table, Geometry from .image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) from .utils import (scale_to_pdf, scale_to_image, segments_bbox, text_in_bbox, - merge_close_values, get_table_index, get_score, count_empty, - encode_list, get_text_objects, get_page_layout) + merge_close_values, get_table_index, compute_accuracy, count_empty, + get_text_objects, get_page_layout, encode_) __all__ = ['Stream', 'Lattice'] @@ -31,58 +32,6 @@ copy_reg.pickle(types.MethodType, _reduce_method) class Stream: - """Stream looks for spaces between text elements to form a table. - - If you want to give columns, ytol or mtol for each table - when specifying multiple table areas, make sure that their length - is equal to the length of table_area. Mapping between them is based - on index. - - If you don't want to specify columns for the some tables in a pdf - page having multiple tables, pass them as empty strings. - For example: ['', 'x1,x2,x3,x4', ''] - - Parameters - ---------- - table_area : list - List of strings of the form x1,y1,x2,y2 where - (x1, y1) -> left-top and (x2, y2) -> right-bottom in PDFMiner's - coordinate space, denoting table areas to analyze. - (optional, default: None) - - columns : list - List of strings where each string is comma-separated values of - x-coordinates in PDFMiner's coordinate space. - (optional, default: None) - - ytol : list - List of ints specifying the y-tolerance parameters. - (optional, default: [2]) - - mtol : list - List of ints specifying the m-tolerance parameters. - (optional, default: [0]) - - margins : tuple - PDFMiner margins. (char_margin, line_margin, word_margin) - (optional, default: (1.0, 0.5, 0.1)) - - split_text : bool - Whether or not to split a text line if it spans across - different cells. - (optional, default: False) - - flag_size : bool - Whether or not to highlight a substring using - if its size is different from rest of the string, useful for - super and subscripts. - (optional, default: True) - - debug : bool - Set to True to generate a matplotlib plot of - LTTextLineHorizontals in order to select table_area, columns. - (optional, default: False) - """ def __init__(self, table_area=None, columns=None, ytol=[2], mtol=[0], margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, debug=False): @@ -99,20 +48,6 @@ class Stream: @staticmethod def _text_bbox(t_bbox): - """Returns bounding box for the text present on a page. - - Parameters - ---------- - t_bbox : dict - Dict with two keys 'horizontal' and 'vertical' with lists of - LTTextLineHorizontals and LTTextLineVerticals respectively. - - Returns - ------- - text_bbox : tuple - Tuple of the form (x0, y0, x1, y1) in PDFMiner's coordinate - space. - """ xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) ymin = min([t.y0 for direction in t_bbox for t in t_bbox[direction]]) xmax = max([t.x1 for direction in t_bbox for t in t_bbox[direction]]) @@ -122,23 +57,6 @@ class Stream: @staticmethod def _group_rows(text, ytol=2): - """Groups PDFMiner text objects into rows using their - y-coordinates taking into account some tolerance ytol. - - Parameters - ---------- - text : list - List of PDFMiner text objects. - - ytol : int - Tolerance parameter. - (optional, default: 2) - - Returns - ------- - rows : list - Two-dimensional list of text objects grouped into rows. - """ row_y = 0 rows = [] temp = [] @@ -158,23 +76,6 @@ class Stream: @staticmethod def _merge_columns(l, mtol=0): - """Merges column boundaries if they overlap or lie within some - tolerance mtol. - - Parameters - ---------- - l : list - List of column coordinate tuples. - - mtol : int - TODO - (optional, default: 0) - - Returns - ------- - merged : list - List of merged column coordinate tuples. - """ merged = [] for higher in l: if not merged: @@ -203,22 +104,6 @@ class Stream: @staticmethod def _join_rows(rows_grouped, text_y_max, text_y_min): - """Makes row coordinates continuous. - - Parameters - ---------- - rows_grouped : list - Two-dimensional list of text objects grouped into rows. - - text_y_max : int - - text_y_min : int - - Returns - ------- - rows : list - List of continuous row coordinate tuples. - """ row_mids = [sum([(t.y0 + t.y1) / 2 for t in r]) / len(r) if len(r) > 0 else 0 for r in rows_grouped] rows = [(row_mids[i] + row_mids[i - 1]) / 2 for i in range(1, len(row_mids))] @@ -230,25 +115,6 @@ class Stream: @staticmethod def _add_columns(cols, text, ytol): - """Adds columns to existing list by taking into account - the text that lies outside the current column coordinates. - - Parameters - ---------- - cols : list - List of column coordinate tuples. - - text : list - List of PDFMiner text objects. - - ytol : int - Tolerance parameter. - - Returns - ------- - cols : list - Updated list of column coordinate tuples. - """ if text: text = Stream._group_rows(text, ytol=ytol) elements = [len(r) for r in text] @@ -259,22 +125,6 @@ class Stream: @staticmethod def _join_columns(cols, text_x_min, text_x_max): - """Makes column coordinates continuous. - - Parameters - ---------- - cols : list - List of column coordinate tuples. - - text_x_min : int - - text_y_max : int - - Returns - ------- - cols : list - Updated list of column coordinate tuples. - """ cols = sorted(cols) cols = [(cols[i][0] + cols[i - 1][1]) / 2 for i in range(1, len(cols))] cols.insert(0, text_x_min) @@ -284,17 +134,6 @@ class Stream: return cols def extract_tables(self, pdfname): - """Expects a single page pdf as input with rotation corrected. - - Parameters - --------- - pdfname : string - Path to single page pdf file. - - Returns - ------- - page : dict - """ layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, line_margin=self.line_margin, word_margin=self.word_margin) lttextlh = get_text_objects(layout, ltype="lh") @@ -314,7 +153,6 @@ class Stream: text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlh]) text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlv]) g.text = text - return [None], [g] if self.table_area is not None: if self.columns is not None: @@ -343,17 +181,13 @@ class Stream: else: mtolerance = copy.deepcopy(self.mtol) - page = {} - tables = {} + _tables = [] # sort tables based on y-coord for table_no, k in enumerate(sorted(table_bbox.keys(), key=lambda x: x[1], reverse=True)): # select elements which lie within table_bbox - table_data = {} t_bbox = {} t_bbox['horizontal'] = text_in_bbox(k, lttextlh) t_bbox['vertical'] = text_in_bbox(k, lttextlv) - char_bbox = text_in_bbox(k, ltchar) - table_data['text_p'] = 100 * (1 - (len(char_bbox) / len(ltchar))) for direction in t_bbox: t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) text_x_min, text_y_min, text_x_max, text_y_max = self._text_bbox(t_bbox) @@ -399,124 +233,38 @@ class Stream: table = Table(cols, rows) table = table.set_all_edges() - assignment_errors = [] - table_data['split_text'] = [] - table_data['superscript'] = [] + pos_errors = [] for direction in t_bbox: for t in t_bbox[direction]: indices, error = get_table_index( table, t, direction, split_text=self.split_text, flag_size=self.flag_size) - assignment_errors.append(error) - if len(indices) > 1: - table_data['split_text'].append(indices) - for r_idx, c_idx, text in indices: - if all(s in text for s in ['', '']): - table_data['superscript'].append((r_idx, c_idx, text)) - table.cells[r_idx][c_idx].add_text(text) + if indices[:2] != (-1, -1): + pos_errors.append(error) + for r_idx, c_idx, text in indices: + table.cells[r_idx][c_idx].add_text(text) if guess: - score = get_score([[66, assignment_errors], [34, [len_non_mode / len(elements)]]]) + accuracy = compute_accuracy([[66, pos_errors], [34, [len_non_mode / len(elements)]]]) else: - score = get_score([[100, assignment_errors]]) + accuracy = compute_accuracy([[100, pos_errors]]) - table_data['score'] = score - ar = table.get_list() - ar = encode_list(ar) - table_data['data'] = ar - empty_p, r_nempty_cells, c_nempty_cells = count_empty(ar) - table_data['empty_p'] = empty_p - table_data['r_nempty_cells'] = r_nempty_cells - table_data['c_nempty_cells'] = c_nempty_cells - table_data['nrows'] = len(ar) - table_data['ncols'] = len(ar[0]) - tables['table-{0}'.format(table_no + 1)] = table_data - page[os.path.basename(bname)] = tables + data = table.data + data = encode_(data) + table.df = pd.DataFrame(data) + table.shape = table.df.shape - return page + whitespace, __, __ = count_empty(data) + table.accuracy = accuracy + table.whitespace = whitespace + table.order = table_no + 1 + table.page = os.path.basename(bname).replace('page-', '') + + _tables.append(table) + + return _tables, g class Lattice: - """Lattice looks for lines in the pdf to form a table. - - If you want to give fill and mtol for each table when specifying - multiple table areas, make sure that the length of fill and mtol - is equal to the length of table_area. Mapping between them is based - on index. - - Parameters - ---------- - table_area : list - List of strings of the form x1,y1,x2,y2 where - (x1, y1) -> left-top and (x2, y2) -> right-bottom in PDFMiner's - coordinate space, denoting table areas to analyze. - (optional, default: None) - - fill : list - List of strings specifying directions to fill spanning cells. - {'h', 'v'} to fill spanning cells in horizontal or vertical - direction. - (optional, default: None) - - mtol : list - List of ints specifying m-tolerance parameters. - (optional, default: [2]) - - jtol : list - List of ints specifying j-tolerance parameters. - (optional, default: [2]) - - blocksize : int - Size of a pixel neighborhood that is used to calculate a - threshold value for the pixel: 3, 5, 7, and so on. - (optional, default: 15) - - threshold_constant : float - Constant subtracted from the mean or weighted mean - (see the details below). Normally, it is positive but may be - zero or negative as well. - (optional, default: -2) - - scale : int - Used to divide the height/width of a pdf to get a structuring - element for image processing. - (optional, default: 15) - - iterations : int - Number of iterations for dilation. - (optional, default: 0) - - invert : bool - Whether or not to invert the image. Useful when pdfs have - tables with lines in background. - (optional, default: False) - - margins : tuple - PDFMiner margins. (char_margin, line_margin, word_margin) - (optional, default: (1.0, 0.5, 0.1)) - - split_text : bool - Whether or not to split a text line if it spans across - different cells. - (optional, default: False) - - flag_size : bool - Whether or not to highlight a substring using - if its size is different from rest of the string, useful for - super and subscripts. - (optional, default: True) - - shift_text : list - {'l', 'r', 't', 'b'} - Select one or more from above and pass them as a list to - specify where the text in a spanning cell should flow. - (optional, default: ['l', 't']) - - debug : string - {'contour', 'line', 'joint', 'table'} - Set to one of the above values to generate a matplotlib plot - of detected contours, lines, joints and the table generated. - (optional, default: None) - """ def __init__(self, table_area=None, fill=None, mtol=[2], jtol=[2], blocksize=15, threshold_constant=-2, scale=15, iterations=0, invert=False, margins=(1.0, 0.5, 0.1), split_text=False, @@ -540,28 +288,6 @@ class Lattice: @staticmethod def _reduce_index(t, idx, shift_text): - """Reduces index of a text object if it lies within a spanning - cell. - - Parameters - ---------- - table : object - camelot.table.Table - - idx : list - List of tuples of the form (r_idx, c_idx, text). - - shift_text : list - {'l', 'r', 't', 'b'} - Select one or more from above and pass them as a list to - specify where the text in a spanning cell should flow. - - Returns - ------- - indices : list - List of tuples of the form (idx, text) where idx is the reduced - index of row/column and text is the an lttextline substring. - """ indices = [] for r_idx, c_idx, text in idx: for d in shift_text: @@ -586,24 +312,6 @@ class Lattice: def _fill_spanning(t, fill=None): - """Fills spanning cells. - - Parameters - ---------- - t : object - camelot.table.Table - - fill : list - {'h', 'v'} - Specify to fill spanning cells in horizontal or vertical - direction. - (optional, default: None) - - Returns - ------- - t : object - camelot.table.Table - """ for f in fill: if f == "h": for i in range(len(t.cells)): @@ -620,17 +328,6 @@ class Lattice: return t def extract_tables(self, pdfname): - """Expects a single page pdf as input with rotation corrected. - - Parameters - ---------- - pdfname : string - Path to single page pdf file. - - Returns - ------- - page : dict - """ layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, line_margin=self.line_margin, word_margin=self.word_margin) lttextlh = get_text_objects(layout, ltype="lh") @@ -700,27 +397,22 @@ class Lattice: g = Geometry() if self.debug: - g.images = [(img, table_bbox)] + g.images = (img, table_bbox) table_bbox, v_segments, h_segments = scale_to_pdf(table_bbox, v_segments, h_segments, factors_pdf) if self.debug: - g.segments = [(v_segments, h_segments)] - _tables = [] + g.segments = (v_segments, h_segments) - page = {} - tables = {} + _tables = [] # sort tables based on y-coord for table_no, k in enumerate(sorted(table_bbox.keys(), key=lambda x: x[1], reverse=True)): # select elements which lie within table_bbox - table_data = {} t_bbox = {} v_s, h_s = segments_bbox(k, v_segments, h_segments) t_bbox['horizontal'] = text_in_bbox(k, lttextlh) t_bbox['vertical'] = text_in_bbox(k, lttextlv) - char_bbox = text_in_bbox(k, ltchar) - table_data['text_p'] = 100 * (1 - (len(char_bbox) / len(ltchar))) for direction in t_bbox: t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) cols, rows = zip(*table_bbox[k]) @@ -745,45 +437,36 @@ class Lattice: # set table border edges to True table = table.set_border_edges() - if self.debug: - _tables.append(table) - - assignment_errors = [] - table_data['split_text'] = [] - table_data['superscript'] = [] + pos_errors = [] for direction in ['vertical', 'horizontal']: for t in t_bbox[direction]: indices, error = get_table_index( table, t, direction, split_text=self.split_text, flag_size=self.flag_size) if indices[:2] != (-1, -1): - assignment_errors.append(error) + pos_errors.append(error) indices = self._reduce_index(table, indices, shift_text=self.shift_text) - if len(indices) > 1: - table_data['split_text'].append(indices) for r_idx, c_idx, text in indices: - if all(s in text for s in ['', '']): - table_data['superscript'].append((r_idx, c_idx, text)) table.cells[r_idx][c_idx].add_text(text) - score = get_score([[100, assignment_errors]]) - table_data['score'] = score + accuracy = compute_accuracy([[100, pos_errors]]) if self.fill is not None: table = self._fill_spanning(table, fill=self.fill) - ar = table.get_list() - ar = encode_list(ar) - table_data['data'] = ar - empty_p, r_nempty_cells, c_nempty_cells = count_empty(ar) - table_data['empty_p'] = empty_p - table_data['r_nempty_cells'] = r_nempty_cells - table_data['c_nempty_cells'] = c_nempty_cells - table_data['nrows'] = len(ar) - table_data['ncols'] = len(ar[0]) - tables['table-{0}'.format(table_no + 1)] = table_data - page[os.path.basename(bname)] = tables + + data = table.data + data = encode_(data) + table.df = pd.DataFrame(data) + table.shape = table.df.shape + + whitespace, __, __ = count_empty(data) + table.accuracy = accuracy + table.whitespace = whitespace + table.order = table_no + 1 + table.page = os.path.basename(bname).replace('page-', '') + + _tables.append(table) if self.debug: g.tables = _tables - return [None], [g] - return page \ No newline at end of file + return _tables, g \ No newline at end of file diff --git a/camelot/utils.py b/camelot/utils.py index 3640b37..650e62a 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -557,7 +557,7 @@ def get_table_index(table, t, direction, split_text=False, flag_size=True): return [(r_idx, c_idx, t.get_text().strip('\n'))], error -def get_score(error_weights): +def compute_accuracy(error_weights): """Calculates score based on weights assigned to various parameters, and their error percentages. @@ -648,7 +648,7 @@ def count_empty(d): return empty_p, r_nempty_cells, c_nempty_cells -def encode_list(ar): +def encode_(ar): """Encodes list of text. Parameters From 73e52939f5d295f521e4ba4846f5b3c3e36367c5 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Wed, 5 Sep 2018 18:50:10 +0530 Subject: [PATCH 11/39] Add parsing_report property --- camelot/core.py | 19 +++++++++++++++++++ camelot/parsers.py | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/camelot/core.py b/camelot/core.py index 9089593..0c66d7a 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -1,3 +1,5 @@ +import json + import numpy as np @@ -277,6 +279,17 @@ class Table(object): def page(self, p): self._page = p + @property + def parsing_report(self): + # pretty? + report = { + 'accuracy': self._accuracy, + 'whitespace': self._whitespace, + 'order': self._order, + 'page': self._page + } + return report + class TableList(list): def __init__(self, tables): @@ -286,6 +299,12 @@ class TableList(list): return '<{} tables={}>'.format( self.__class__.__name__, len(self._tables)) + def __len__(self): + return len(self._tables) + + def __getitem__(self, idx): + return self._tables[idx] + class Geometry(object): def __init__(self): diff --git a/camelot/parsers.py b/camelot/parsers.py index 20820da..50bd8a5 100644 --- a/camelot/parsers.py +++ b/camelot/parsers.py @@ -257,7 +257,7 @@ class Stream: table.accuracy = accuracy table.whitespace = whitespace table.order = table_no + 1 - table.page = os.path.basename(bname).replace('page-', '') + table.page = int(os.path.basename(bname).replace('page-', '')) _tables.append(table) @@ -462,7 +462,7 @@ class Lattice: table.accuracy = accuracy table.whitespace = whitespace table.order = table_no + 1 - table.page = os.path.basename(bname).replace('page-', '') + table.page = int(os.path.basename(bname).replace('page-', '')) _tables.append(table) From 08cbababca5c1fbd01edf46949cc41105b40d806 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Wed, 5 Sep 2018 19:00:30 +0530 Subject: [PATCH 12/39] Add properties to GeometryList --- camelot/core.py | 18 +++++++++++++++++- camelot/plot.py | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/camelot/core.py b/camelot/core.py index 0c66d7a..d25a810 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -359,4 +359,20 @@ class GeometryList(object): len(self._text), len(self._images), len(self._segments), - len(self._tables)) \ No newline at end of file + len(self._tables)) + + @property + def text(self): + return self._text + + @property + def images(self): + return self._images + + @property + def segments(self): + return self._segments + + @property + def tables(self): + return self._tables \ No newline at end of file diff --git a/camelot/plot.py b/camelot/plot.py index 92bcd69..0b37ed9 100644 --- a/camelot/plot.py +++ b/camelot/plot.py @@ -1,3 +1,4 @@ +import cv2 import matplotlib.pyplot as plt import matplotlib.patches as patches From bf63432494fd604f98eaf7c7320e4163212d1adf Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Wed, 5 Sep 2018 19:04:40 +0530 Subject: [PATCH 13/39] Remove docstrings --- camelot/image_processing.py | 135 ------------- camelot/utils.py | 382 ------------------------------------ 2 files changed, 517 deletions(-) diff --git a/camelot/image_processing.py b/camelot/image_processing.py index 1621bea..fc284e4 100644 --- a/camelot/image_processing.py +++ b/camelot/image_processing.py @@ -8,35 +8,6 @@ from .utils import merge_tuples def adaptive_threshold(imagename, invert=False, blocksize=15, c=-2): - """Thresholds an image using OpenCV's adaptiveThreshold. - - Parameters - ---------- - imagename : string - Path to image file. - - invert : bool - Whether or not to invert the image. Useful when pdfs have - tables with lines in background. - (optional, default: False) - - blocksize: int - Size of a pixel neighborhood that is used to calculate a - threshold value for the pixel: 3, 5, 7, and so on. - - c: float - Constant subtracted from the mean or weighted mean - (see the details below). Normally, it is positive but may be - zero or negative as well. - - Returns - ------- - img : object - numpy.ndarray representing the original image. - - threshold : object - numpy.ndarray representing the thresholded image. - """ img = cv2.imread(imagename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) @@ -50,38 +21,6 @@ def adaptive_threshold(imagename, invert=False, blocksize=15, c=-2): def find_lines(threshold, direction='horizontal', scale=15, iterations=0): - """Finds horizontal and vertical lines by applying morphological - transformations on an image. - - Parameters - ---------- - threshold : object - numpy.ndarray representing the thresholded image. - - direction : string - Specifies whether to find vertical or horizontal lines. - (default: 'horizontal') - - scale : int - Used to divide the height/width to get a structuring element - for morph transform. - (optional, default: 15) - - iterations : int - Number of iterations for dilation. - (optional, default: 2) - - Returns - ------- - dmask : object - numpy.ndarray representing pixels where vertical/horizontal - lines lie. - - lines : list - List of tuples representing vertical/horizontal lines with - coordinates relative to a left-top origin in - OpenCV's coordinate space. - """ lines = [] if direction == 'vertical': @@ -118,23 +57,6 @@ def find_lines(threshold, direction='horizontal', scale=15, iterations=0): def find_table_contours(vertical, horizontal): - """Finds table boundaries using OpenCV's findContours. - - Parameters - ---------- - vertical : object - numpy.ndarray representing pixels where vertical lines lie. - - horizontal : object - numpy.ndarray representing pixels where horizontal lines lie. - - Returns - ------- - cont : list - List of tuples representing table boundaries. Each tuple is of - the form (x, y, w, h) where (x, y) -> left-top, w -> width and - h -> height in OpenCV's coordinate space. - """ mask = vertical + horizontal try: @@ -154,30 +76,6 @@ def find_table_contours(vertical, horizontal): def find_table_joints(contours, vertical, horizontal): - """Finds joints/intersections present inside each table boundary. - - Parameters - ---------- - contours : list - List of tuples representing table boundaries. Each tuple is of - the form (x, y, w, h) where (x, y) -> left-top, w -> width and - h -> height in OpenCV's coordinate space. - - vertical : object - numpy.ndarray representing pixels where vertical lines lie. - - horizontal : object - numpy.ndarray representing pixels where horizontal lines lie. - - Returns - ------- - tables : dict - Dict with table boundaries as keys and list of intersections - in that boundary as their value. - - Keys are of the form (x1, y1, x2, y2) where (x1, y1) -> lb - and (x2, y2) -> rt in OpenCV's coordinate space. - """ joints = np.bitwise_and(vertical, horizontal) tables = {} for c in contours: @@ -202,23 +100,6 @@ def find_table_joints(contours, vertical, horizontal): def remove_lines(threshold, line_scale=15): - """Removes lines from a thresholded image. - - Parameters - ---------- - threshold : object - numpy.ndarray representing the thresholded image. - - line_scale : int - Line scaling factor. - (optional, default: 15) - - Returns - ------- - threshold : object - numpy.ndarray representing the thresholded image - with horizontal and vertical lines removed. - """ size = threshold.shape[0] // line_scale vertical_erode_el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) horizontal_erode_el = cv2.getStructuringElement(cv2.MORPH_RECT, (size, 1)) @@ -236,22 +117,6 @@ def remove_lines(threshold, line_scale=15): def find_cuts(threshold, char_scale=200): - """Finds cuts made by text projections on y-axis. - - Parameters - ---------- - threshold : object - numpy.ndarray representing the thresholded image. - - char_scale : int - Char scaling factor. - (optional, default: 200) - - Returns - ------- - y_cuts : list - List of cuts on y-axis. - """ size = threshold.shape[0] // char_scale char_el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) diff --git a/camelot/utils.py b/camelot/utils.py index 650e62a..df82a8a 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -19,61 +19,16 @@ from pdfminer.layout import (LAParams, LTAnno, LTChar, LTTextLineHorizontal, def translate(x1, x2): - """Translates x2 by x1. - - Parameters - ---------- - x1 : float - - x2 : float - - Returns - ------- - x2 : float - """ x2 += x1 return x2 def scale(x, s): - """Scales x by scaling factor s. - - Parameters - ---------- - x : float - - s : float - - Returns - ------- - x : float - """ x *= s return x def rotate(x1, y1, x2, y2, angle): - """Rotates point x2, y2 about point x1, y1 by angle. - - Parameters - ---------- - x1 : float - - y1 : float - - x2 : float - - y2 : float - - angle : float - Angle in radians. - - Returns - ------- - xnew : float - - ynew : float - """ s = np.sin(angle) c = np.cos(angle) x2 = translate(-x1, x2) @@ -86,28 +41,6 @@ def rotate(x1, y1, x2, y2, angle): def scale_to_image(k, factors): - """Translates and scales PDFMiner coordinates to OpenCV's coordinate - space. - - Parameters - ---------- - k : tuple - Tuple (x1, y1, x2, y2) representing table bounding box where - (x1, y1) -> lt and (x2, y2) -> rb in PDFMiner's coordinate - space. - - factors : tuple - Tuple (scaling_factor_x, scaling_factor_y, pdf_y) where the - first two elements are scaling factors and pdf_y is height of - pdf. - - Returns - ------- - knew : tuple - Tuple (x1, y1, x2, y2) representing table bounding box where - (x1, y1) -> lt and (x2, y2) -> rb in OpenCV's coordinate - space. - """ x1, y1, x2, y2 = k scaling_factor_x, scaling_factor_y, pdf_y = factors x1 = scale(x1, scaling_factor_x) @@ -119,34 +52,6 @@ def scale_to_image(k, factors): def scale_to_pdf(tables, v_segments, h_segments, factors): - """Translates and scales OpenCV coordinates to PDFMiner's coordinate - space. - - Parameters - ---------- - tables : dict - Dict with table boundaries as keys and list of intersections - in that boundary as their value. - - v_segments : list - List of vertical line segments. - - h_segments : list - List of horizontal line segments. - - factors : tuple - Tuple (scaling_factor_x, scaling_factor_y, img_y) where the - first two elements are scaling factors and img_y is height of - image. - - Returns - ------- - tables_new : dict - - v_segments_new : dict - - h_segments_new : dict - """ scaling_factor_x, scaling_factor_y, img_y = factors tables_new = {} for k in tables.keys(): @@ -179,12 +84,6 @@ def scale_to_pdf(tables, v_segments, h_segments, factors): def setup_logging(log_filepath): - """Setup logging - Args: - log_filepath (string): Path to log file - Returns: - logging.Logger: Logger object - """ logger = logging.getLogger("app_logger") logger.setLevel(logging.DEBUG) # Log File Handler (Associating one log file per webservice run) @@ -206,27 +105,6 @@ def setup_logging(log_filepath): def get_rotation(lttextlh, lttextlv, ltchar): - """Detects if text in table is vertical or not using the current - transformation matrix (CTM) and returns its orientation. - - Parameters - ---------- - lttextlh : list - List of PDFMiner LTTextLineHorizontal objects. - - lttextlv : list - List of PDFMiner LTTextLineVertical objects. - - ltchar : list - List of PDFMiner LTChar objects. - - Returns - ------- - rotation : string - {'', 'left', 'right'} - '' if text in table is upright, 'left' if rotated 90 degree - anti-clockwise and 'right' if rotated 90 degree clockwise. - """ rotation = '' hlen = len([t for t in lttextlh if t.get_text().strip()]) vlen = len([t for t in lttextlv if t.get_text().strip()]) @@ -238,29 +116,6 @@ def get_rotation(lttextlh, lttextlv, ltchar): def segments_bbox(bbox, v_segments, h_segments): - """Returns all line segments present inside a - table's bounding box. - - Parameters - ---------- - bbox : tuple - Tuple (x1, y1, x2, y2) representing table bounding box where - (x1, y1) -> lb and (x2, y2) -> rt in PDFMiner's coordinate space. - - v_segments : list - List of vertical line segments. - - h_segments : list - List of vertical horizontal segments. - - Returns - ------- - v_s : list - List of vertical line segments that lie inside table. - - h_s : list - List of horizontal line segments that lie inside table. - """ lb = (bbox[0], bbox[1]) rt = (bbox[2], bbox[3]) v_s = [v for v in v_segments if v[1] > lb[1] - 2 and @@ -271,23 +126,6 @@ def segments_bbox(bbox, v_segments, h_segments): def text_in_bbox(bbox, text): - """Returns all text objects present inside a - table's bounding box. - - Parameters - ---------- - bbox : tuple - Tuple (x1, y1, x2, y2) representing table bounding box where - (x1, y1) -> lb and (x2, y2) -> rt in PDFMiner's coordinate space. - - text : list - List of PDFMiner text objects. - - Returns - ------- - t_bbox : list - List of PDFMiner text objects that lie inside table. - """ lb = (bbox[0], bbox[1]) rt = (bbox[2], bbox[3]) t_bbox = [t for t in text if lb[0] - 2 <= (t.x0 + t.x1) / 2.0 @@ -297,20 +135,6 @@ def text_in_bbox(bbox, text): def remove_close_values(ar, mtol=2): - """Removes values which are within a tolerance of mtol of another value - present in list. - - Parameters - ---------- - ar : list - - mtol : int - (optional, default: 2) - - Returns - ------- - ret : list - """ ret = [] for a in ar: if not ret: @@ -325,20 +149,6 @@ def remove_close_values(ar, mtol=2): def merge_close_values(ar, mtol=2): - """Merges values which are within a tolerance of mtol by calculating - a moving mean. - - Parameters - ---------- - ar : list - - mtol : int - (optional, default: 2) - - Returns - ------- - ret : list - """ ret = [] for a in ar: if not ret: @@ -354,22 +164,6 @@ def merge_close_values(ar, mtol=2): def flag_on_size(textline, direction): - """Flags a super/subscript by enclosing it with . May give - false positives. - - Parameters - ---------- - textline : list - List of PDFMiner LTChar objects. - - direction : string - {'horizontal', 'vertical'} - Direction of the PDFMiner LTTextLine object. - - Returns - ------- - fstring : string - """ if direction == 'horizontal': d = [(t.get_text(), np.round(t.height, decimals=6)) for t in textline if not isinstance(t, LTAnno)] elif direction == 'vertical': @@ -396,33 +190,6 @@ def flag_on_size(textline, direction): def split_textline(table, textline, direction, flag_size=True): - """Splits PDFMiner LTTextLine into substrings if it spans across - multiple rows/columns. - - Parameters - ---------- - table : object - camelot.pdf.Pdf - - textline : object - PDFMiner LTTextLine object. - - direction : string - {'horizontal', 'vertical'} - Direction of the PDFMiner LTTextLine object. - - flag_size : bool - Whether or not to highlight a substring using - if its size is different from rest of the string, useful for - super and subscripts. - (optional, default: True) - - Returns - ------- - grouped_chars : list - List of tuples of the form (idx, text) where idx is the index - of row/column and text is the an lttextline substring. - """ idx = 0 cut_text = [] bbox = textline.bbox @@ -474,47 +241,6 @@ def split_textline(table, textline, direction, flag_size=True): def get_table_index(table, t, direction, split_text=False, flag_size=True): - """Gets indices of the cell where given text object lies by - comparing their y and x-coordinates. - - Parameters - ---------- - table : object - camelot.table.Table - - t : object - PDFMiner LTTextLine object. - - direction : string - {'horizontal', 'vertical'} - Direction of the PDFMiner LTTextLine object. - - split_text : bool - Whether or not to split a text line if it spans across - multiple cells. - (optional, default: False) - - flag_size : bool - Whether or not to highlight a substring using - if its size is different from rest of the string, useful for - super and subscripts. - (optional, default: True) - - Returns - ------- - indices : list - List of tuples of the form (idx, text) where idx is the index - of row/column and text is the an lttextline substring. - - error : float - Assignment error, percentage of text area that lies outside - a cell. - +-------+ - | | - | [Text bounding box] - | | - +-------+ - """ r_idx, c_idx = [-1] * 2 for r in range(len(table.rows)): if ((t.y0 + t.y1) / 2.0 < table.rows[r][0] and @@ -558,20 +284,6 @@ def get_table_index(table, t, direction, split_text=False, flag_size=True): def compute_accuracy(error_weights): - """Calculates score based on weights assigned to various parameters, - and their error percentages. - - Parameters - ---------- - error_weights : list - Two-dimensional list of the form [[p1, e1], [p2, e2], ...] - where pn is the weight assigned to list of errors en. - Sum of pn should be equal to 100. - - Returns - ------- - score : float - """ SCORE_VAL = 100 try: score = 0 @@ -587,16 +299,6 @@ def compute_accuracy(error_weights): def remove_empty(d): - """Removes empty rows and columns from a two-dimensional list. - - Parameters - ---------- - d : list - - Returns - ------- - d : list - """ for i, row in enumerate(d): if row == [''] * len(row): d.pop(i) @@ -607,23 +309,6 @@ def remove_empty(d): def count_empty(d): - """Counts empty rows and columns in a two-dimensional list. - - Parameters - ---------- - d : list - - Returns - ------- - n_empty_rows : list - Number of empty rows. - - n_empty_cols : list - Number of empty columns. - - empty_p : float - Percentage of empty cells. - """ empty_p = 0 r_nempty_cells, c_nempty_cells = [], [] for i in d: @@ -649,41 +334,11 @@ def count_empty(d): def encode_(ar): - """Encodes list of text. - - Parameters - ---------- - ar : list - - Returns - ------- - ar : list - """ ar = [[r.encode('utf-8') for r in row] for row in ar] return ar def get_text_objects(layout, ltype="char", t=None): - """Recursively parses pdf layout to get a list of - text objects. - - Parameters - ---------- - layout : object - PDFMiner LTPage object. - - ltype : string - {'char', 'lh', 'lv'} - Specify 'char', 'lh', 'lv' to get LTChar, LTTextLineHorizontal, - and LTTextLineVertical objects respectively. - - t : list - - Returns - ------- - t : list - List of PDFMiner text objects. - """ if ltype == "char": LTObject = LTChar elif ltype == "lh": @@ -705,33 +360,6 @@ def get_text_objects(layout, ltype="char", t=None): def get_page_layout(pname, char_margin=1.0, line_margin=0.5, word_margin=0.1, detect_vertical=True, all_texts=True): - """Returns a PDFMiner LTPage object and page dimension of a single - page pdf. See https://euske.github.io/pdfminer/ to get definitions - of kwargs. - - Parameters - ---------- - pname : string - Path to pdf file. - - char_margin : float - - line_margin : float - - word_margin : float - - detect_vertical : bool - - all_texts : bool - - Returns - ------- - layout : object - PDFMiner LTPage object. - - dim : tuple - pdf page dimension of the form (width, height). - """ with open(pname, 'r') as f: parser = PDFParser(f) document = PDFDocument(parser) @@ -755,16 +383,6 @@ def get_page_layout(pname, char_margin=1.0, line_margin=0.5, word_margin=0.1, def merge_tuples(tuples): - """Merges a list of overlapping tuples. - - Parameters - ---------- - tuples : list - - Returns - ------- - merged : list - """ merged = list(tuples[0]) for s, e in tuples: if s <= merged[1]: From a4d3165e9417817d9710ab8da23703afbdbaf5b6 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Wed, 5 Sep 2018 19:35:46 +0530 Subject: [PATCH 14/39] Add docstring stubs --- camelot/core.py | 171 ++++++++++++++++++++++++++ camelot/handlers.py | 14 +++ camelot/image_processing.py | 71 +++++++++++ camelot/io.py | 13 ++ camelot/parsers.py | 26 ++++ camelot/plot.py | 10 ++ camelot/utils.py | 238 ++++++++++++++++++++++++++++++++++++ 7 files changed, 543 insertions(+) diff --git a/camelot/core.py b/camelot/core.py index d25a810..87cb6ae 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -4,6 +4,9 @@ import numpy as np class Cell(object): + """ + + """ def __init__(self, x1, y1, x2, y2): self.x1 = x1 self.y1 = y1 @@ -27,23 +30,56 @@ class Cell(object): pass def add_text(self, text): + """ + + Parameters + ---------- + text + """ self.text = ''.join([self.text, text]) def get_text(self): + """ + + Returns + ------- + + """ return self.text def add_object(self, t_object): + """ + + Parameters + ---------- + t_object + """ self.text_objects.append(t_object) def get_objects(self): + """ + + Returns + ------- + + """ return self.text_objects def get_bounded_edges(self): + """ + + Returns + ------- + + """ self.bounded_edges = self.top + self.bottom + self.left + self.right return self.bounded_edges class Table(object): + """ + + """ def __init__(self, cols, rows): self.cols = cols self.rows = rows @@ -60,6 +96,12 @@ class Table(object): return '<{} shape={}>'.format(self.__class__.__name__, self._shape) def set_all_edges(self): + """ + + Returns + ------- + + """ for r in range(len(self.rows)): for c in range(len(self.cols)): self.cells[r][c].left = True @@ -69,6 +111,12 @@ class Table(object): return self def set_border_edges(self): + """ + + Returns + ------- + + """ for r in range(len(self.rows)): self.cells[r][0].left = True self.cells[r][len(self.cols) - 1].right = True @@ -78,6 +126,18 @@ class Table(object): return self def set_edges(self, vertical, horizontal, jtol=2): + """ + + Parameters + ---------- + vertical + horizontal + jtol + + Returns + ------- + + """ for v in vertical: # find closest x coord # iterate over y coords and find closest points @@ -185,6 +245,12 @@ class Table(object): return self def set_spanning(self): + """ + + Returns + ------- + + """ for r in range(len(self.rows)): for c in range(len(self.cols)): bound = self.cells[r][c].get_bounded_edges() @@ -225,6 +291,12 @@ class Table(object): @property def data(self): + """ + + Returns + ------- + + """ d = [] for r in range(len(self.rows)): d.append([self.cells[r][c].get_text().strip() @@ -233,6 +305,12 @@ class Table(object): @property def df(self): + """ + + Returns + ------- + + """ return self._df @df.setter @@ -241,6 +319,12 @@ class Table(object): @property def shape(self): + """ + + Returns + ------- + + """ return self._shape @shape.setter @@ -249,6 +333,12 @@ class Table(object): @property def accuracy(self): + """ + + Returns + ------- + + """ return self._accuracy @accuracy.setter @@ -257,6 +347,12 @@ class Table(object): @property def whitespace(self): + """ + + Returns + ------- + + """ return self._whitespace @whitespace.setter @@ -265,6 +361,12 @@ class Table(object): @property def order(self): + """ + + Returns + ------- + + """ return self._order @order.setter @@ -273,6 +375,12 @@ class Table(object): @property def page(self): + """ + + Returns + ------- + + """ return self._page @page.setter @@ -281,6 +389,12 @@ class Table(object): @property def parsing_report(self): + """ + + Returns + ------- + + """ # pretty? report = { 'accuracy': self._accuracy, @@ -292,6 +406,9 @@ class Table(object): class TableList(list): + """ + + """ def __init__(self, tables): self._tables = tables @@ -307,6 +424,9 @@ class TableList(list): class Geometry(object): + """ + + """ def __init__(self): self._text = [] self._images = () @@ -315,6 +435,12 @@ class Geometry(object): @property def text(self): + """ + + Returns + ------- + + """ return self._text @text.setter @@ -323,6 +449,12 @@ class Geometry(object): @property def images(self): + """ + + Returns + ------- + + """ return self._images @images.setter @@ -331,6 +463,12 @@ class Geometry(object): @property def segments(self): + """ + + Returns + ------- + + """ return self._segments @segments.setter @@ -339,6 +477,12 @@ class Geometry(object): @property def tables(self): + """ + + Returns + ------- + + """ return self._tables @tables.setter @@ -347,6 +491,9 @@ class Geometry(object): class GeometryList(object): + """ + + """ def __init__(self, geometry): self._text = [g.text for g in geometry] self._images = [g.images for g in geometry] @@ -363,16 +510,40 @@ class GeometryList(object): @property def text(self): + """ + + Returns + ------- + + """ return self._text @property def images(self): + """ + + Returns + ------- + + """ return self._images @property def segments(self): + """ + + Returns + ------- + + """ return self._segments @property def tables(self): + """ + + Returns + ------- + + """ return self._tables \ No newline at end of file diff --git a/camelot/handlers.py b/camelot/handlers.py index dce3b05..c4bcfd8 100644 --- a/camelot/handlers.py +++ b/camelot/handlers.py @@ -9,6 +9,9 @@ from .utils import get_page_layout, get_text_objects, get_rotation class PDFHandler(object): + """ + + """ def __init__(self, filename, pages='1'): self.filename = filename if not self.filename.endswith('.pdf'): @@ -71,6 +74,17 @@ class PDFHandler(object): outfile.write(f) def parse(self, mesh=False, **kwargs): + """ + + Parameters + ---------- + mesh + kwargs + + Returns + ------- + + """ for p in self.pages: self.__save_page(self.filename, p, self.temp) pages = [os.path.join(self.temp, 'page-{0}.pdf'.format(p)) diff --git a/camelot/image_processing.py b/camelot/image_processing.py index fc284e4..a1526ef 100644 --- a/camelot/image_processing.py +++ b/camelot/image_processing.py @@ -8,6 +8,19 @@ from .utils import merge_tuples def adaptive_threshold(imagename, invert=False, blocksize=15, c=-2): + """ + + Parameters + ---------- + imagename + invert + blocksize + c + + Returns + ------- + + """ img = cv2.imread(imagename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) @@ -21,6 +34,19 @@ def adaptive_threshold(imagename, invert=False, blocksize=15, c=-2): def find_lines(threshold, direction='horizontal', scale=15, iterations=0): + """ + + Parameters + ---------- + threshold + direction + scale + iterations + + Returns + ------- + + """ lines = [] if direction == 'vertical': @@ -57,6 +83,17 @@ def find_lines(threshold, direction='horizontal', scale=15, iterations=0): def find_table_contours(vertical, horizontal): + """ + + Parameters + ---------- + vertical + horizontal + + Returns + ------- + + """ mask = vertical + horizontal try: @@ -76,6 +113,18 @@ def find_table_contours(vertical, horizontal): def find_table_joints(contours, vertical, horizontal): + """ + + Parameters + ---------- + contours + vertical + horizontal + + Returns + ------- + + """ joints = np.bitwise_and(vertical, horizontal) tables = {} for c in contours: @@ -100,6 +149,17 @@ def find_table_joints(contours, vertical, horizontal): def remove_lines(threshold, line_scale=15): + """ + + Parameters + ---------- + threshold + line_scale + + Returns + ------- + + """ size = threshold.shape[0] // line_scale vertical_erode_el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) horizontal_erode_el = cv2.getStructuringElement(cv2.MORPH_RECT, (size, 1)) @@ -117,6 +177,17 @@ def remove_lines(threshold, line_scale=15): def find_cuts(threshold, char_scale=200): + """ + + Parameters + ---------- + threshold + char_scale + + Returns + ------- + + """ size = threshold.shape[0] // char_scale char_el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) diff --git a/camelot/io.py b/camelot/io.py index c2b319b..54f8ef5 100644 --- a/camelot/io.py +++ b/camelot/io.py @@ -2,6 +2,19 @@ from .handlers import PDFHandler def read_pdf(filepath, pages='1', mesh=False, **kwargs): + """ + + Parameters + ---------- + filepath + pages + mesh + kwargs + + Returns + ------- + + """ # explicit type conversion p = PDFHandler(filepath, pages) tables, __ = p.parse(mesh=mesh, **kwargs) diff --git a/camelot/parsers.py b/camelot/parsers.py index 50bd8a5..c9b5d2a 100644 --- a/camelot/parsers.py +++ b/camelot/parsers.py @@ -32,6 +32,9 @@ copy_reg.pickle(types.MethodType, _reduce_method) class Stream: + """ + + """ def __init__(self, table_area=None, columns=None, ytol=[2], mtol=[0], margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, debug=False): @@ -134,6 +137,16 @@ class Stream: return cols def extract_tables(self, pdfname): + """ + + Parameters + ---------- + pdfname + + Returns + ------- + + """ layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, line_margin=self.line_margin, word_margin=self.word_margin) lttextlh = get_text_objects(layout, ltype="lh") @@ -265,6 +278,9 @@ class Stream: class Lattice: + """ + + """ def __init__(self, table_area=None, fill=None, mtol=[2], jtol=[2], blocksize=15, threshold_constant=-2, scale=15, iterations=0, invert=False, margins=(1.0, 0.5, 0.1), split_text=False, @@ -328,6 +344,16 @@ class Lattice: return t def extract_tables(self, pdfname): + """ + + Parameters + ---------- + pdfname + + Returns + ------- + + """ layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, line_margin=self.line_margin, word_margin=self.word_margin) lttextlh = get_text_objects(layout, ltype="lh") diff --git a/camelot/plot.py b/camelot/plot.py index 0b37ed9..793764e 100644 --- a/camelot/plot.py +++ b/camelot/plot.py @@ -6,6 +6,16 @@ from .handlers import PDFHandler def plot_geometry(filepath, pages='1', mesh=False, geometry_type='text', **kwargs): + """ + + Parameters + ---------- + filepath + pages + mesh + geometry_type + kwargs + """ # explicit type conversion p = PDFHandler(filepath, pages) kwargs.update({'debug': geometry_type}) diff --git a/camelot/utils.py b/camelot/utils.py index df82a8a..c6b1705 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -19,16 +19,52 @@ from pdfminer.layout import (LAParams, LTAnno, LTChar, LTTextLineHorizontal, def translate(x1, x2): + """ + + Parameters + ---------- + x1 + x2 + + Returns + ------- + + """ x2 += x1 return x2 def scale(x, s): + """ + + Parameters + ---------- + x + s + + Returns + ------- + + """ x *= s return x def rotate(x1, y1, x2, y2, angle): + """ + + Parameters + ---------- + x1 + y1 + x2 + y2 + angle + + Returns + ------- + + """ s = np.sin(angle) c = np.cos(angle) x2 = translate(-x1, x2) @@ -41,6 +77,17 @@ def rotate(x1, y1, x2, y2, angle): def scale_to_image(k, factors): + """ + + Parameters + ---------- + k + factors + + Returns + ------- + + """ x1, y1, x2, y2 = k scaling_factor_x, scaling_factor_y, pdf_y = factors x1 = scale(x1, scaling_factor_x) @@ -52,6 +99,19 @@ def scale_to_image(k, factors): def scale_to_pdf(tables, v_segments, h_segments, factors): + """ + + Parameters + ---------- + tables + v_segments + h_segments + factors + + Returns + ------- + + """ scaling_factor_x, scaling_factor_y, img_y = factors tables_new = {} for k in tables.keys(): @@ -84,6 +144,16 @@ def scale_to_pdf(tables, v_segments, h_segments, factors): def setup_logging(log_filepath): + """ + + Parameters + ---------- + log_filepath + + Returns + ------- + + """ logger = logging.getLogger("app_logger") logger.setLevel(logging.DEBUG) # Log File Handler (Associating one log file per webservice run) @@ -105,6 +175,18 @@ def setup_logging(log_filepath): def get_rotation(lttextlh, lttextlv, ltchar): + """ + + Parameters + ---------- + lttextlh + lttextlv + ltchar + + Returns + ------- + + """ rotation = '' hlen = len([t for t in lttextlh if t.get_text().strip()]) vlen = len([t for t in lttextlv if t.get_text().strip()]) @@ -116,6 +198,18 @@ def get_rotation(lttextlh, lttextlv, ltchar): def segments_bbox(bbox, v_segments, h_segments): + """ + + Parameters + ---------- + bbox + v_segments + h_segments + + Returns + ------- + + """ lb = (bbox[0], bbox[1]) rt = (bbox[2], bbox[3]) v_s = [v for v in v_segments if v[1] > lb[1] - 2 and @@ -126,6 +220,17 @@ def segments_bbox(bbox, v_segments, h_segments): def text_in_bbox(bbox, text): + """ + + Parameters + ---------- + bbox + text + + Returns + ------- + + """ lb = (bbox[0], bbox[1]) rt = (bbox[2], bbox[3]) t_bbox = [t for t in text if lb[0] - 2 <= (t.x0 + t.x1) / 2.0 @@ -135,6 +240,17 @@ def text_in_bbox(bbox, text): def remove_close_values(ar, mtol=2): + """ + + Parameters + ---------- + ar + mtol + + Returns + ------- + + """ ret = [] for a in ar: if not ret: @@ -149,6 +265,17 @@ def remove_close_values(ar, mtol=2): def merge_close_values(ar, mtol=2): + """ + + Parameters + ---------- + ar + mtol + + Returns + ------- + + """ ret = [] for a in ar: if not ret: @@ -164,6 +291,17 @@ def merge_close_values(ar, mtol=2): def flag_on_size(textline, direction): + """ + + Parameters + ---------- + textline + direction + + Returns + ------- + + """ if direction == 'horizontal': d = [(t.get_text(), np.round(t.height, decimals=6)) for t in textline if not isinstance(t, LTAnno)] elif direction == 'vertical': @@ -190,6 +328,19 @@ def flag_on_size(textline, direction): def split_textline(table, textline, direction, flag_size=True): + """ + + Parameters + ---------- + table + textline + direction + flag_size + + Returns + ------- + + """ idx = 0 cut_text = [] bbox = textline.bbox @@ -241,6 +392,20 @@ def split_textline(table, textline, direction, flag_size=True): def get_table_index(table, t, direction, split_text=False, flag_size=True): + """ + + Parameters + ---------- + table + t + direction + split_text + flag_size + + Returns + ------- + + """ r_idx, c_idx = [-1] * 2 for r in range(len(table.rows)): if ((t.y0 + t.y1) / 2.0 < table.rows[r][0] and @@ -284,6 +449,16 @@ def get_table_index(table, t, direction, split_text=False, flag_size=True): def compute_accuracy(error_weights): + """ + + Parameters + ---------- + error_weights + + Returns + ------- + + """ SCORE_VAL = 100 try: score = 0 @@ -299,6 +474,16 @@ def compute_accuracy(error_weights): def remove_empty(d): + """ + + Parameters + ---------- + d + + Returns + ------- + + """ for i, row in enumerate(d): if row == [''] * len(row): d.pop(i) @@ -309,6 +494,16 @@ def remove_empty(d): def count_empty(d): + """ + + Parameters + ---------- + d + + Returns + ------- + + """ empty_p = 0 r_nempty_cells, c_nempty_cells = [], [] for i in d: @@ -334,11 +529,33 @@ def count_empty(d): def encode_(ar): + """ + + Parameters + ---------- + ar + + Returns + ------- + + """ ar = [[r.encode('utf-8') for r in row] for row in ar] return ar def get_text_objects(layout, ltype="char", t=None): + """ + + Parameters + ---------- + layout + ltype + t + + Returns + ------- + + """ if ltype == "char": LTObject = LTChar elif ltype == "lh": @@ -360,6 +577,21 @@ def get_text_objects(layout, ltype="char", t=None): def get_page_layout(pname, char_margin=1.0, line_margin=0.5, word_margin=0.1, detect_vertical=True, all_texts=True): + """ + + Parameters + ---------- + pname + char_margin + line_margin + word_margin + detect_vertical + all_texts + + Returns + ------- + + """ with open(pname, 'r') as f: parser = PDFParser(f) document = PDFDocument(parser) @@ -383,6 +615,12 @@ def get_page_layout(pname, char_margin=1.0, line_margin=0.5, word_margin=0.1, def merge_tuples(tuples): + """ + + Parameters + ---------- + tuples + """ merged = list(tuples[0]) for s, e in tuples: if s <= merged[1]: From 96af09d9cd559212ca2081f9cdadbe3cf361eeca Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Thu, 6 Sep 2018 05:28:34 +0530 Subject: [PATCH 15/39] Add BaseParser and refactor extract_tables --- camelot/handlers.py | 2 +- camelot/parsers.py | 513 +++++++++++++++++++++++--------------------- camelot/utils.py | 6 +- 3 files changed, 268 insertions(+), 253 deletions(-) diff --git a/camelot/handlers.py b/camelot/handlers.py index c4bcfd8..f231d96 100644 --- a/camelot/handlers.py +++ b/camelot/handlers.py @@ -91,8 +91,8 @@ class PDFHandler(object): for p in self.pages] tables = [] geometry = [] - parser = Stream(**kwargs) if not mesh else Lattice(**kwargs) for p in pages: + parser = Stream(**kwargs) if not mesh else Lattice(**kwargs) t, g = parser.extract_tables(p) tables.extend(t) geometry.append(g) diff --git a/camelot/parsers.py b/camelot/parsers.py index c9b5d2a..ac9216e 100644 --- a/camelot/parsers.py +++ b/camelot/parsers.py @@ -14,7 +14,7 @@ import pandas as pd from .core import Table, Geometry from .image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) -from .utils import (scale_to_pdf, scale_to_image, segments_bbox, text_in_bbox, +from .utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, merge_close_values, get_table_index, compute_accuracy, count_empty, get_text_objects, get_page_layout, encode_) @@ -31,17 +31,40 @@ def _reduce_method(m): copy_reg.pickle(types.MethodType, _reduce_method) -class Stream: +class BaseParser(object): + # init objects + # no tables condition + # convert pdf to image - lattice + # image processing - lattice + # user given table area condition + # scale image components to pdf components - lattice + # compute cols and rows for each table + # create table for each table + + def _generate_layout(self, filename): + self.filename = filename + self.layout, self.dimensions = get_page_layout( + self.filename, + char_margin=self.char_margin, + line_margin=self.line_margin, + word_margin=self.word_margin) + self.horizontal_text = get_text_objects(self.layout, ltype="lh") + self.vertical_text = get_text_objects(self.layout, ltype="lv") + self.pdf_width, self.pdf_height = self.dimensions + self.basename, __ = os.path.splitext(self.filename) + self.g = Geometry() + + +class Stream(BaseParser): """ """ - def __init__(self, table_area=None, columns=None, ytol=[2], mtol=[0], + def __init__(self, table_area=None, columns=None, ytol=2, mtol=0, margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, debug=False): - - self.method = 'stream' self.table_area = table_area self.columns = columns + self._validate_columns() self.ytol = ytol self.mtol = mtol self.char_margin, self.line_margin, self.word_margin = margins @@ -49,6 +72,12 @@ class Stream: self.flag_size = flag_size self.debug = debug + def _validate_columns(self): + if self.table_area is not None and self.columns is not None: + if len(self.table_area) != len(self.columns): + raise ValueError("Length of table_area and columns" + " should be equal.") + @staticmethod def _text_bbox(t_bbox): xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) @@ -136,43 +165,8 @@ class Stream: for i in range(0, len(cols) - 1)] return cols - def extract_tables(self, pdfname): - """ - - Parameters - ---------- - pdfname - - Returns - ------- - - """ - layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, - line_margin=self.line_margin, word_margin=self.word_margin) - lttextlh = get_text_objects(layout, ltype="lh") - lttextlv = get_text_objects(layout, ltype="lv") - ltchar = get_text_objects(layout, ltype="char") - width, height = dim - bname, __ = os.path.splitext(pdfname) - logger.info('Processing {0}.'.format(os.path.basename(bname))) - if not lttextlh: - warnings.warn("{0}: Page contains no text.".format( - os.path.basename(bname))) - return {os.path.basename(bname): None} - - g = Geometry() - if self.debug: - text = [] - text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlh]) - text.extend([(t.x0, t.y0, t.x1, t.y1) for t in lttextlv]) - g.text = text - + def _generate_table_bbox(self): if self.table_area is not None: - if self.columns is not None: - if len(self.table_area) != len(self.columns): - raise ValueError("{0}: Length of table area and columns" - " should be equal.".format(os.path.basename(bname))) - table_bbox = {} for area in self.table_area: x1, y1, x2, y2 = area.split(",") @@ -182,111 +176,133 @@ class Stream: y2 = float(y2) table_bbox[(x1, y2, x2, y1)] = None else: - table_bbox = {(0, 0, width, height): None} + table_bbox = {(0, 0, self.pdf_width, self.pdf_height): None} + self.table_bbox = table_bbox - if len(self.ytol) == 1 and self.ytol[0] == 2: - ytolerance = copy.deepcopy(self.ytol) * len(table_bbox) - else: - ytolerance = copy.deepcopy(self.ytol) + def _generate_columns_and_rows(self, table_idx, tk): + # select elements which lie within table_bbox + t_bbox = {} + t_bbox['horizontal'] = text_in_bbox(tk, self.horizontal_text) + t_bbox['vertical'] = text_in_bbox(tk, self.vertical_text) + self.t_bbox = t_bbox - if len(self.mtol) == 1 and self.mtol[0] == 0: - mtolerance = copy.deepcopy(self.mtol) * len(table_bbox) + for direction in self.t_bbox: + self.t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) + + text_x_min, text_y_min, text_x_max, text_y_max = self._text_bbox(self.t_bbox) + rows_grouped = self._group_rows(self.t_bbox['horizontal'], ytol=self.ytol) + rows = self._join_rows(rows_grouped, text_y_max, text_y_min) + elements = [len(r) for r in rows_grouped] + + if self.columns is not None and self.columns[table_idx] != "": + # user has to input boundary columns too + # take (0, pdf_width) by default + # similar to else condition + # len can't be 1 + cols = self.columns[table_idx].split(',') + cols = [float(c) for c in cols] + cols.insert(0, text_x_min) + cols.append(text_x_max) + cols = [(cols[i], cols[i + 1]) for i in range(0, len(cols) - 1)] else: - mtolerance = copy.deepcopy(self.mtol) + ncols = max(set(elements), key=elements.count) + if ncols == 1: + # no tables condition + warnings.warn("No tables found on {}".format( + os.path.basename(self.basename))) + cols = [(t.x0, t.x1) + for r in rows_grouped if len(r) == ncols for t in r] + cols = self._merge_columns(sorted(cols), mtol=self.mtol) + inner_text = [] + for i in range(1, len(cols)): + left = cols[i - 1][1] + right = cols[i][0] + inner_text.extend([t for direction in self.t_bbox + for t in self.t_bbox[direction] + if t.x0 > left and t.x1 < right]) + outer_text = [t for direction in self.t_bbox + for t in self.t_bbox[direction] + if t.x0 > cols[-1][1] or t.x1 < cols[0][0]] + inner_text.extend(outer_text) + cols = self._add_columns(cols, inner_text, self.ytol) + cols = self._join_columns(cols, text_x_min, text_x_max) + + return cols, rows + + def _generate_table(self, table_idx, cols, rows): + table = Table(cols, rows) + table = table.set_all_edges() + pos_errors = [] + for direction in self.t_bbox: + for t in self.t_bbox[direction]: + indices, error = get_table_index( + table, t, direction, split_text=self.split_text, + flag_size=self.flag_size) + if indices[:2] != (-1, -1): + pos_errors.append(error) + for r_idx, c_idx, text in indices: + table.cells[r_idx][c_idx].add_text(text) + accuracy = compute_accuracy([[100, pos_errors]]) + + data = table.data + data = encode_(data) + table.df = pd.DataFrame(data) + table.shape = table.df.shape + + whitespace, __, __ = count_empty(data) + table.accuracy = accuracy + table.whitespace = whitespace + table.order = table_idx + 1 + table.page = int(os.path.basename(self.basename).replace('page-', '')) + + return table + + def extract_tables(self, filename): + """ + + Parameters + ---------- + filename + + Returns + ------- + + """ + logger.info('Processing {}'.format(os.path.basename(filename))) + self._generate_layout(filename) + + if not self.horizontal_text: + warnings.warn("No tables found on {}".format( + os.path.basename(self.basename))) + return [], self.g + + if self.debug: + text = [] + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) + self.g.text = text + + self._generate_table_bbox() _tables = [] # sort tables based on y-coord - for table_no, k in enumerate(sorted(table_bbox.keys(), key=lambda x: x[1], reverse=True)): - # select elements which lie within table_bbox - t_bbox = {} - t_bbox['horizontal'] = text_in_bbox(k, lttextlh) - t_bbox['vertical'] = text_in_bbox(k, lttextlv) - for direction in t_bbox: - t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) - text_x_min, text_y_min, text_x_max, text_y_max = self._text_bbox(t_bbox) - rows_grouped = self._group_rows(t_bbox['horizontal'], ytol=ytolerance[table_no]) - rows = self._join_rows(rows_grouped, text_y_max, text_y_min) - elements = [len(r) for r in rows_grouped] - - guess = False - if self.columns is not None and self.columns[table_no] != "": - # user has to input boundary columns too - # take (0, width) by default - # similar to else condition - # len can't be 1 - cols = self.columns[table_no].split(',') - cols = [float(c) for c in cols] - cols.insert(0, text_x_min) - cols.append(text_x_max) - cols = [(cols[i], cols[i + 1]) for i in range(0, len(cols) - 1)] - else: - guess = True - ncols = max(set(elements), key=elements.count) - len_non_mode = len(filter(lambda x: x != ncols, elements)) - if ncols == 1: - # no tables detected - warnings.warn("{0}: Page contains no tables.".format( - os.path.basename(bname))) - cols = [(t.x0, t.x1) - for r in rows_grouped if len(r) == ncols for t in r] - cols = self._merge_columns(sorted(cols), mtol=mtolerance[table_no]) - inner_text = [] - for i in range(1, len(cols)): - left = cols[i - 1][1] - right = cols[i][0] - inner_text.extend([t for direction in t_bbox - for t in t_bbox[direction] - if t.x0 > left and t.x1 < right]) - outer_text = [t for direction in t_bbox - for t in t_bbox[direction] - if t.x0 > cols[-1][1] or t.x1 < cols[0][0]] - inner_text.extend(outer_text) - cols = self._add_columns(cols, inner_text, ytolerance[table_no]) - cols = self._join_columns(cols, text_x_min, text_x_max) - - table = Table(cols, rows) - table = table.set_all_edges() - pos_errors = [] - for direction in t_bbox: - for t in t_bbox[direction]: - indices, error = get_table_index( - table, t, direction, split_text=self.split_text, - flag_size=self.flag_size) - if indices[:2] != (-1, -1): - pos_errors.append(error) - for r_idx, c_idx, text in indices: - table.cells[r_idx][c_idx].add_text(text) - if guess: - accuracy = compute_accuracy([[66, pos_errors], [34, [len_non_mode / len(elements)]]]) - else: - accuracy = compute_accuracy([[100, pos_errors]]) - - data = table.data - data = encode_(data) - table.df = pd.DataFrame(data) - table.shape = table.df.shape - - whitespace, __, __ = count_empty(data) - table.accuracy = accuracy - table.whitespace = whitespace - table.order = table_no + 1 - table.page = int(os.path.basename(bname).replace('page-', '')) - + for table_idx, tk in enumerate(sorted(self.table_bbox.keys(), + key=lambda x: x[1], reverse=True)): + cols, rows = self._generate_columns_and_rows(table_idx, tk) + table = self._generate_table(table_idx, cols, rows) _tables.append(table) - return _tables, g + return _tables, self.g -class Lattice: +class Lattice(BaseParser): """ """ - def __init__(self, table_area=None, fill=None, mtol=[2], jtol=[2], + def __init__(self, table_area=None, fill=None, mtol=2, jtol=2, blocksize=15, threshold_constant=-2, scale=15, iterations=0, invert=False, margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, shift_text=['l', 't'], debug=None): - - self.method = 'lattice' self.table_area = table_area self.fill = fill self.mtol = mtol @@ -326,7 +342,7 @@ class Lattice: indices.append((r_idx, c_idx, text)) return indices - + @staticmethod def _fill_spanning(t, fill=None): for f in fill: if f == "h": @@ -343,33 +359,10 @@ class Lattice: t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) return t - def extract_tables(self, pdfname): - """ - - Parameters - ---------- - pdfname - - Returns - ------- - - """ - layout, dim = get_page_layout(pdfname, char_margin=self.char_margin, - line_margin=self.line_margin, word_margin=self.word_margin) - lttextlh = get_text_objects(layout, ltype="lh") - lttextlv = get_text_objects(layout, ltype="lv") - ltchar = get_text_objects(layout, ltype="char") - width, height = dim - bname, __ = os.path.splitext(pdfname) - logger.info('Processing {0}.'.format(os.path.basename(bname))) - if not ltchar: - warnings.warn("{0}: Page contains no text.".format( - os.path.basename(bname))) - return {os.path.basename(bname): None} - - imagename = ''.join([bname, '.png']) + def _generate_image(self): + self.imagename = ''.join([self.basename, '.png']) gs_call = [ - "-q", "-sDEVICE=png16m", "-o", imagename, "-r600", pdfname + "-q", "-sDEVICE=png16m", "-o", self.imagename, "-r600", self.filename ] if "ghostscript" in subprocess.check_output(["gs", "-version"]).lower(): gs_call.insert(0, "gs") @@ -378,23 +371,22 @@ class Lattice: subprocess.call(gs_call, stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT) - img, threshold = adaptive_threshold(imagename, invert=self.invert, + def _generate_table_bbox(self): + self.image, self.threshold = adaptive_threshold(self.imagename, invert=self.invert, blocksize=self.blocksize, c=self.threshold_constant) - pdf_x = width - pdf_y = height - img_x = img.shape[1] - img_y = img.shape[0] - sc_x_image = img_x / float(pdf_x) - sc_y_image = img_y / float(pdf_y) - sc_x_pdf = pdf_x / float(img_x) - sc_y_pdf = pdf_y / float(img_y) - factors_image = (sc_x_image, sc_y_image, pdf_y) - factors_pdf = (sc_x_pdf, sc_y_pdf, img_y) + image_width = self.image.shape[1] + image_height = self.image.shape[0] + image_width_scaler = image_width / float(self.pdf_width) + image_height_scaler = image_height / float(self.pdf_height) + pdf_width_scaler = self.pdf_width / float(image_width) + pdf_height_scaler = self.pdf_height / float(image_height) + image_scalers = (image_width_scaler, image_height_scaler, self.pdf_height) + pdf_scalers = (pdf_width_scaler, pdf_height_scaler, image_height) - vmask, v_segments = find_lines(threshold, direction='vertical', - scale=self.scale, iterations=self.iterations) - hmask, h_segments = find_lines(threshold, direction='horizontal', - scale=self.scale, iterations=self.iterations) + vertical_mask, vertical_segments = find_lines(self.threshold, + direction='vertical', scale=self.scale, iterations=self.iterations) + horizontal_mask, horizontal_segments = find_lines(self.threshold, + direction='horizontal', scale=self.scale, iterations=self.iterations) if self.table_area is not None: areas = [] @@ -404,95 +396,118 @@ class Lattice: y1 = float(y1) x2 = float(x2) y2 = float(y2) - x1, y1, x2, y2 = scale_to_image((x1, y1, x2, y2), factors_image) + 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, vmask, hmask) + table_bbox = find_table_joints(areas, vertical_mask, horizontal_mask) else: - contours = find_table_contours(vmask, hmask) - table_bbox = find_table_joints(contours, vmask, hmask) + contours = find_table_contours(vertical_mask, horizontal_mask) + table_bbox = find_table_joints(contours, vertical_mask, horizontal_mask) - if len(self.mtol) == 1 and self.mtol[0] == 2: - mtolerance = copy.deepcopy(self.mtol) * len(table_bbox) - else: - mtolerance = copy.deepcopy(self.mtol) + self.table_bbox_unscaled = copy.deepcopy(table_bbox) - if len(self.jtol) == 1 and self.jtol[0] == 2: - jtolerance = copy.deepcopy(self.jtol) * len(table_bbox) - else: - jtolerance = copy.deepcopy(self.jtol) + self.table_bbox, self.vertical_segments, self.horizontal_segments = scale_image( + table_bbox, vertical_segments, horizontal_segments, pdf_scalers) - g = Geometry() - if self.debug: - g.images = (img, table_bbox) + def _generate_columns_and_rows(self, table_idx, tk): + # select elements which lie within table_bbox + t_bbox = {} + v_s, h_s = segments_in_bbox( + tk, self.vertical_segments, self.horizontal_segments) + t_bbox['horizontal'] = text_in_bbox(tk, self.horizontal_text) + t_bbox['vertical'] = text_in_bbox(tk, self.vertical_text) + self.t_bbox = t_bbox - table_bbox, v_segments, h_segments = scale_to_pdf(table_bbox, v_segments, - h_segments, factors_pdf) + for direction in t_bbox: + t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) + + cols, rows = zip(*self.table_bbox[tk]) + cols, rows = list(cols), list(rows) + cols.extend([tk[0], tk[2]]) + rows.extend([tk[1], tk[3]]) + # sort horizontal and vertical segments + cols = merge_close_values(sorted(cols), mtol=self.mtol) + rows = merge_close_values(sorted(rows, reverse=True), mtol=self.mtol) + # make grid using x and y coord of shortlisted rows and cols + cols = [(cols[i], cols[i + 1]) + for i in range(0, len(cols) - 1)] + rows = [(rows[i], rows[i + 1]) + for i in range(0, len(rows) - 1)] + + return cols, rows, v_s, h_s + + def _generate_table(self, table_idx, cols, rows, v_s, h_s): + table = Table(cols, rows) + # set table edges to True using ver+hor lines + table = table.set_edges(v_s, h_s, jtol=self.jtol) + # set spanning cells to True + table = table.set_spanning() + # set table border edges to True + table = table.set_border_edges() + + pos_errors = [] + for direction in self.t_bbox: + for t in self.t_bbox[direction]: + indices, error = get_table_index( + table, t, direction, split_text=self.split_text, + flag_size=self.flag_size) + if indices[:2] != (-1, -1): + pos_errors.append(error) + indices = Lattice._reduce_index(table, indices, shift_text=self.shift_text) + for r_idx, c_idx, text in indices: + table.cells[r_idx][c_idx].add_text(text) + accuracy = compute_accuracy([[100, pos_errors]]) + + if self.fill is not None: + table = Lattice._fill_spanning(table, fill=self.fill) + + data = table.data + data = encode_(data) + table.df = pd.DataFrame(data) + table.shape = table.df.shape + + whitespace, __, __ = count_empty(data) + table.accuracy = accuracy + table.whitespace = whitespace + table.order = table_idx + 1 + table.page = int(os.path.basename(self.basename).replace('page-', '')) + + return table + + def extract_tables(self, filename): + """ + + Parameters + ---------- + filename + + Returns + ------- + + """ + logger.info('Processing {}'.format(os.path.basename(filename))) + self._generate_layout(filename) + + if not self.horizontal_text: + warnings.warn("No tables found on {}".format( + os.path.basename(self.basename))) + return [], self.g + + self._generate_image() + self._generate_table_bbox() if self.debug: - g.segments = (v_segments, h_segments) + self.g.images = (self.image, self.table_bbox_unscaled) + self.g.segments = (self.vertical_segments, self.horizontal_segments) _tables = [] # sort tables based on y-coord - for table_no, k in enumerate(sorted(table_bbox.keys(), key=lambda x: x[1], reverse=True)): - # select elements which lie within table_bbox - t_bbox = {} - v_s, h_s = segments_bbox(k, v_segments, h_segments) - t_bbox['horizontal'] = text_in_bbox(k, lttextlh) - t_bbox['vertical'] = text_in_bbox(k, lttextlv) - for direction in t_bbox: - t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) - cols, rows = zip(*table_bbox[k]) - cols, rows = list(cols), list(rows) - cols.extend([k[0], k[2]]) - rows.extend([k[1], k[3]]) - # sort horizontal and vertical segments - cols = merge_close_values(sorted(cols), mtol=mtolerance[table_no]) - rows = merge_close_values( - sorted(rows, reverse=True), mtol=mtolerance[table_no]) - # make grid using x and y coord of shortlisted rows and cols - cols = [(cols[i], cols[i + 1]) - for i in range(0, len(cols) - 1)] - rows = [(rows[i], rows[i + 1]) - for i in range(0, len(rows) - 1)] - - table = Table(cols, rows) - # set table edges to True using ver+hor lines - table = table.set_edges(v_s, h_s, jtol=jtolerance[table_no]) - # set spanning cells to True - table = table.set_spanning() - # set table border edges to True - table = table.set_border_edges() - - pos_errors = [] - for direction in ['vertical', 'horizontal']: - for t in t_bbox[direction]: - indices, error = get_table_index( - table, t, direction, split_text=self.split_text, - flag_size=self.flag_size) - if indices[:2] != (-1, -1): - pos_errors.append(error) - indices = self._reduce_index(table, indices, shift_text=self.shift_text) - for r_idx, c_idx, text in indices: - table.cells[r_idx][c_idx].add_text(text) - accuracy = compute_accuracy([[100, pos_errors]]) - - if self.fill is not None: - table = self._fill_spanning(table, fill=self.fill) - - data = table.data - data = encode_(data) - table.df = pd.DataFrame(data) - table.shape = table.df.shape - - whitespace, __, __ = count_empty(data) - table.accuracy = accuracy - table.whitespace = whitespace - table.order = table_no + 1 - table.page = int(os.path.basename(bname).replace('page-', '')) - + for table_idx, tk in enumerate(sorted(self.table_bbox.keys(), + key=lambda x: x[1], reverse=True)): + cols, rows, v_s, h_s = self._generate_columns_and_rows(table_idx, tk) + table = self._generate_table(table_idx, cols, rows, v_s, h_s) _tables.append(table) if self.debug: - g.tables = _tables + self.g.tables = _tables - return _tables, g \ No newline at end of file + return _tables, self.g \ No newline at end of file diff --git a/camelot/utils.py b/camelot/utils.py index c6b1705..6ec04af 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -76,7 +76,7 @@ def rotate(x1, y1, x2, y2, angle): return xnew, ynew -def scale_to_image(k, factors): +def scale_pdf(k, factors): """ Parameters @@ -98,7 +98,7 @@ def scale_to_image(k, factors): return knew -def scale_to_pdf(tables, v_segments, h_segments, factors): +def scale_image(tables, v_segments, h_segments, factors): """ Parameters @@ -197,7 +197,7 @@ def get_rotation(lttextlh, lttextlv, ltchar): return rotation -def segments_bbox(bbox, v_segments, h_segments): +def segments_in_bbox(bbox, v_segments, h_segments): """ Parameters From d0005101a782c61a30f9728616049ef72f316a70 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Thu, 6 Sep 2018 05:55:05 +0530 Subject: [PATCH 16/39] Add BaseParser docstring stub --- camelot/handlers.py | 2 +- camelot/parsers.py | 39 ++++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/camelot/handlers.py b/camelot/handlers.py index f231d96..c4bcfd8 100644 --- a/camelot/handlers.py +++ b/camelot/handlers.py @@ -91,8 +91,8 @@ class PDFHandler(object): for p in self.pages] tables = [] geometry = [] + parser = Stream(**kwargs) if not mesh else Lattice(**kwargs) for p in pages: - parser = Stream(**kwargs) if not mesh else Lattice(**kwargs) t, g = parser.extract_tables(p) tables.extend(t) geometry.append(g) diff --git a/camelot/parsers.py b/camelot/parsers.py index ac9216e..d45c441 100644 --- a/camelot/parsers.py +++ b/camelot/parsers.py @@ -32,15 +32,9 @@ copy_reg.pickle(types.MethodType, _reduce_method) class BaseParser(object): - # init objects - # no tables condition - # convert pdf to image - lattice - # image processing - lattice - # user given table area condition - # scale image components to pdf components - lattice - # compute cols and rows for each table - # create table for each table + """ + """ def _generate_layout(self, filename): self.filename = filename self.layout, self.dimensions = get_page_layout( @@ -229,7 +223,7 @@ class Stream(BaseParser): return cols, rows - def _generate_table(self, table_idx, cols, rows): + def _generate_table(self, table_idx, cols, rows, **kwargs): table = Table(cols, rows) table = table.set_all_edges() pos_errors = [] @@ -276,12 +270,6 @@ class Stream(BaseParser): os.path.basename(self.basename))) return [], self.g - if self.debug: - text = [] - text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) - text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) - self.g.text = text - self._generate_table_bbox() _tables = [] @@ -292,6 +280,12 @@ class Stream(BaseParser): table = self._generate_table(table_idx, cols, rows) _tables.append(table) + if self.debug: + text = [] + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) + self.g.text = text + return _tables, self.g @@ -435,7 +429,12 @@ class Lattice(BaseParser): return cols, rows, v_s, h_s - def _generate_table(self, table_idx, cols, rows, v_s, h_s): + def _generate_table(self, table_idx, cols, rows, **kwargs): + v_s = kwargs.get('v_s') + h_s = kwargs.get('h_s') + if v_s is None or h_s is None: + raise ValueError('No segments found on {}'.format(self.basename)) + table = Table(cols, rows) # set table edges to True using ver+hor lines table = table.set_edges(v_s, h_s, jtol=self.jtol) @@ -495,19 +494,17 @@ class Lattice(BaseParser): self._generate_image() self._generate_table_bbox() - if self.debug: - self.g.images = (self.image, self.table_bbox_unscaled) - self.g.segments = (self.vertical_segments, self.horizontal_segments) - _tables = [] # sort tables based on y-coord for table_idx, tk in enumerate(sorted(self.table_bbox.keys(), key=lambda x: x[1], reverse=True)): cols, rows, v_s, h_s = self._generate_columns_and_rows(table_idx, tk) - table = self._generate_table(table_idx, cols, rows, v_s, h_s) + table = self._generate_table(table_idx, cols, rows, v_s=v_s, h_s=h_s) _tables.append(table) if self.debug: + self.g.images = (self.image, self.table_bbox_unscaled) + self.g.segments = (self.vertical_segments, self.horizontal_segments) self.g.tables = _tables return _tables, self.g \ No newline at end of file From b91df8a1b8b7a42fb1aa9fc17fd1f76bfb8346c1 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Thu, 6 Sep 2018 06:13:58 +0530 Subject: [PATCH 17/39] Create parsers module --- camelot/parsers.py | 510 ------------------------------------ camelot/parsers/__init__.py | 2 + camelot/parsers/base.py | 20 ++ camelot/parsers/lattice.py | 244 +++++++++++++++++ camelot/parsers/stream.py | 260 ++++++++++++++++++ camelot/utils.py | 2 +- 6 files changed, 527 insertions(+), 511 deletions(-) delete mode 100644 camelot/parsers.py create mode 100644 camelot/parsers/__init__.py create mode 100644 camelot/parsers/base.py create mode 100644 camelot/parsers/lattice.py create mode 100644 camelot/parsers/stream.py diff --git a/camelot/parsers.py b/camelot/parsers.py deleted file mode 100644 index d45c441..0000000 --- a/camelot/parsers.py +++ /dev/null @@ -1,510 +0,0 @@ -from __future__ import division -import os -import sys -import copy -import types -import logging -import copy_reg -import warnings -import subprocess - -import numpy as np -import pandas as pd - -from .core import Table, Geometry -from .image_processing import (adaptive_threshold, find_lines, find_table_contours, - find_table_joints) -from .utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, - merge_close_values, get_table_index, compute_accuracy, count_empty, - get_text_objects, get_page_layout, encode_) - - -__all__ = ['Stream', 'Lattice'] -logger = logging.getLogger('app_logger') - - -def _reduce_method(m): - if m.im_self is None: - return getattr, (m.im_class, m.im_func.func_name) - else: - return getattr, (m.im_self, m.im_func.func_name) -copy_reg.pickle(types.MethodType, _reduce_method) - - -class BaseParser(object): - """ - - """ - def _generate_layout(self, filename): - self.filename = filename - self.layout, self.dimensions = get_page_layout( - self.filename, - char_margin=self.char_margin, - line_margin=self.line_margin, - word_margin=self.word_margin) - self.horizontal_text = get_text_objects(self.layout, ltype="lh") - self.vertical_text = get_text_objects(self.layout, ltype="lv") - self.pdf_width, self.pdf_height = self.dimensions - self.basename, __ = os.path.splitext(self.filename) - self.g = Geometry() - - -class Stream(BaseParser): - """ - - """ - def __init__(self, table_area=None, columns=None, ytol=2, mtol=0, - margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, - debug=False): - self.table_area = table_area - self.columns = columns - self._validate_columns() - self.ytol = ytol - self.mtol = mtol - self.char_margin, self.line_margin, self.word_margin = margins - self.split_text = split_text - self.flag_size = flag_size - self.debug = debug - - def _validate_columns(self): - if self.table_area is not None and self.columns is not None: - if len(self.table_area) != len(self.columns): - raise ValueError("Length of table_area and columns" - " should be equal.") - - @staticmethod - def _text_bbox(t_bbox): - xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) - ymin = min([t.y0 for direction in t_bbox for t in t_bbox[direction]]) - xmax = max([t.x1 for direction in t_bbox for t in t_bbox[direction]]) - ymax = max([t.y1 for direction in t_bbox for t in t_bbox[direction]]) - text_bbox = (xmin, ymin, xmax, ymax) - return text_bbox - - @staticmethod - def _group_rows(text, ytol=2): - row_y = 0 - rows = [] - temp = [] - for t in text: - # is checking for upright necessary? - # if t.get_text().strip() and all([obj.upright for obj in t._objs if - # type(obj) is LTChar]): - if t.get_text().strip(): - if not np.isclose(row_y, t.y0, atol=ytol): - rows.append(sorted(temp, key=lambda t: t.x0)) - temp = [] - row_y = t.y0 - temp.append(t) - rows.append(sorted(temp, key=lambda t: t.x0)) - __ = rows.pop(0) # hacky - return rows - - @staticmethod - def _merge_columns(l, mtol=0): - merged = [] - for higher in l: - if not merged: - merged.append(higher) - else: - lower = merged[-1] - if mtol >= 0: - if (higher[0] <= lower[1] or - np.isclose(higher[0], lower[1], atol=mtol)): - upper_bound = max(lower[1], higher[1]) - lower_bound = min(lower[0], higher[0]) - merged[-1] = (lower_bound, upper_bound) - else: - merged.append(higher) - elif mtol < 0: - if higher[0] <= lower[1]: - if np.isclose(higher[0], lower[1], atol=abs(mtol)): - merged.append(higher) - else: - upper_bound = max(lower[1], higher[1]) - lower_bound = min(lower[0], higher[0]) - merged[-1] = (lower_bound, upper_bound) - else: - merged.append(higher) - return merged - - @staticmethod - def _join_rows(rows_grouped, text_y_max, text_y_min): - row_mids = [sum([(t.y0 + t.y1) / 2 for t in r]) / len(r) - if len(r) > 0 else 0 for r in rows_grouped] - rows = [(row_mids[i] + row_mids[i - 1]) / 2 for i in range(1, len(row_mids))] - rows.insert(0, text_y_max) - rows.append(text_y_min) - rows = [(rows[i], rows[i + 1]) - for i in range(0, len(rows) - 1)] - return rows - - @staticmethod - def _add_columns(cols, text, ytol): - if text: - text = Stream._group_rows(text, ytol=ytol) - elements = [len(r) for r in text] - new_cols = [(t.x0, t.x1) - for r in text if len(r) == max(elements) for t in r] - cols.extend(Stream._merge_columns(sorted(new_cols))) - return cols - - @staticmethod - def _join_columns(cols, text_x_min, text_x_max): - cols = sorted(cols) - cols = [(cols[i][0] + cols[i - 1][1]) / 2 for i in range(1, len(cols))] - cols.insert(0, text_x_min) - cols.append(text_x_max) - cols = [(cols[i], cols[i + 1]) - for i in range(0, len(cols) - 1)] - return cols - - def _generate_table_bbox(self): - if self.table_area is not None: - table_bbox = {} - for area in self.table_area: - x1, y1, x2, y2 = area.split(",") - x1 = float(x1) - y1 = float(y1) - x2 = float(x2) - y2 = float(y2) - table_bbox[(x1, y2, x2, y1)] = None - else: - table_bbox = {(0, 0, self.pdf_width, self.pdf_height): None} - self.table_bbox = table_bbox - - def _generate_columns_and_rows(self, table_idx, tk): - # select elements which lie within table_bbox - t_bbox = {} - t_bbox['horizontal'] = text_in_bbox(tk, self.horizontal_text) - t_bbox['vertical'] = text_in_bbox(tk, self.vertical_text) - self.t_bbox = t_bbox - - for direction in self.t_bbox: - self.t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) - - text_x_min, text_y_min, text_x_max, text_y_max = self._text_bbox(self.t_bbox) - rows_grouped = self._group_rows(self.t_bbox['horizontal'], ytol=self.ytol) - rows = self._join_rows(rows_grouped, text_y_max, text_y_min) - elements = [len(r) for r in rows_grouped] - - if self.columns is not None and self.columns[table_idx] != "": - # user has to input boundary columns too - # take (0, pdf_width) by default - # similar to else condition - # len can't be 1 - cols = self.columns[table_idx].split(',') - cols = [float(c) for c in cols] - cols.insert(0, text_x_min) - cols.append(text_x_max) - cols = [(cols[i], cols[i + 1]) for i in range(0, len(cols) - 1)] - else: - ncols = max(set(elements), key=elements.count) - if ncols == 1: - # no tables condition - warnings.warn("No tables found on {}".format( - os.path.basename(self.basename))) - cols = [(t.x0, t.x1) - for r in rows_grouped if len(r) == ncols for t in r] - cols = self._merge_columns(sorted(cols), mtol=self.mtol) - inner_text = [] - for i in range(1, len(cols)): - left = cols[i - 1][1] - right = cols[i][0] - inner_text.extend([t for direction in self.t_bbox - for t in self.t_bbox[direction] - if t.x0 > left and t.x1 < right]) - outer_text = [t for direction in self.t_bbox - for t in self.t_bbox[direction] - if t.x0 > cols[-1][1] or t.x1 < cols[0][0]] - inner_text.extend(outer_text) - cols = self._add_columns(cols, inner_text, self.ytol) - cols = self._join_columns(cols, text_x_min, text_x_max) - - return cols, rows - - def _generate_table(self, table_idx, cols, rows, **kwargs): - table = Table(cols, rows) - table = table.set_all_edges() - pos_errors = [] - for direction in self.t_bbox: - for t in self.t_bbox[direction]: - indices, error = get_table_index( - table, t, direction, split_text=self.split_text, - flag_size=self.flag_size) - if indices[:2] != (-1, -1): - pos_errors.append(error) - for r_idx, c_idx, text in indices: - table.cells[r_idx][c_idx].add_text(text) - accuracy = compute_accuracy([[100, pos_errors]]) - - data = table.data - data = encode_(data) - table.df = pd.DataFrame(data) - table.shape = table.df.shape - - whitespace, __, __ = count_empty(data) - table.accuracy = accuracy - table.whitespace = whitespace - table.order = table_idx + 1 - table.page = int(os.path.basename(self.basename).replace('page-', '')) - - return table - - def extract_tables(self, filename): - """ - - Parameters - ---------- - filename - - Returns - ------- - - """ - logger.info('Processing {}'.format(os.path.basename(filename))) - self._generate_layout(filename) - - if not self.horizontal_text: - warnings.warn("No tables found on {}".format( - os.path.basename(self.basename))) - return [], self.g - - self._generate_table_bbox() - - _tables = [] - # sort tables based on y-coord - for table_idx, tk in enumerate(sorted(self.table_bbox.keys(), - key=lambda x: x[1], reverse=True)): - cols, rows = self._generate_columns_and_rows(table_idx, tk) - table = self._generate_table(table_idx, cols, rows) - _tables.append(table) - - if self.debug: - text = [] - text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) - text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) - self.g.text = text - - return _tables, self.g - - -class Lattice(BaseParser): - """ - - """ - def __init__(self, table_area=None, fill=None, mtol=2, jtol=2, - blocksize=15, threshold_constant=-2, scale=15, iterations=0, - invert=False, margins=(1.0, 0.5, 0.1), split_text=False, - flag_size=True, shift_text=['l', 't'], debug=None): - self.table_area = table_area - self.fill = fill - self.mtol = mtol - self.jtol = jtol - self.blocksize = blocksize - self.threshold_constant = threshold_constant - self.scale = scale - self.iterations = iterations - self.invert = invert - self.char_margin, self.line_margin, self.word_margin = margins - self.split_text = split_text - self.flag_size = flag_size - self.shift_text = shift_text - self.debug = debug - - @staticmethod - def _reduce_index(t, idx, shift_text): - indices = [] - for r_idx, c_idx, text in idx: - for d in shift_text: - if d == 'l': - if t.cells[r_idx][c_idx].spanning_h: - while not t.cells[r_idx][c_idx].left: - c_idx -= 1 - if d == 'r': - if t.cells[r_idx][c_idx].spanning_h: - while not t.cells[r_idx][c_idx].right: - c_idx += 1 - if d == 't': - if t.cells[r_idx][c_idx].spanning_v: - while not t.cells[r_idx][c_idx].top: - r_idx -= 1 - if d == 'b': - if t.cells[r_idx][c_idx].spanning_v: - while not t.cells[r_idx][c_idx].bottom: - r_idx += 1 - indices.append((r_idx, c_idx, text)) - return indices - - @staticmethod - def _fill_spanning(t, fill=None): - for f in fill: - if f == "h": - for i in range(len(t.cells)): - for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_h and not t.cells[i][j].left: - t.cells[i][j].add_text(t.cells[i][j - 1].get_text()) - elif f == "v": - for i in range(len(t.cells)): - for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_v and not t.cells[i][j].top: - t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) - return t - - def _generate_image(self): - self.imagename = ''.join([self.basename, '.png']) - gs_call = [ - "-q", "-sDEVICE=png16m", "-o", self.imagename, "-r600", self.filename - ] - if "ghostscript" in subprocess.check_output(["gs", "-version"]).lower(): - gs_call.insert(0, "gs") - else: - gs_call.insert(0, "gsc") - subprocess.call(gs_call, stdout=open(os.devnull, 'w'), - stderr=subprocess.STDOUT) - - def _generate_table_bbox(self): - self.image, self.threshold = adaptive_threshold(self.imagename, invert=self.invert, - blocksize=self.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) - image_height_scaler = image_height / float(self.pdf_height) - pdf_width_scaler = self.pdf_width / float(image_width) - pdf_height_scaler = self.pdf_height / float(image_height) - 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', scale=self.scale, iterations=self.iterations) - horizontal_mask, horizontal_segments = find_lines(self.threshold, - direction='horizontal', scale=self.scale, iterations=self.iterations) - - if self.table_area is not None: - areas = [] - for area in self.table_area: - 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))) - 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) - - self.table_bbox_unscaled = copy.deepcopy(table_bbox) - - self.table_bbox, self.vertical_segments, self.horizontal_segments = scale_image( - table_bbox, vertical_segments, horizontal_segments, pdf_scalers) - - def _generate_columns_and_rows(self, table_idx, tk): - # select elements which lie within table_bbox - t_bbox = {} - v_s, h_s = segments_in_bbox( - tk, self.vertical_segments, self.horizontal_segments) - t_bbox['horizontal'] = text_in_bbox(tk, self.horizontal_text) - t_bbox['vertical'] = text_in_bbox(tk, self.vertical_text) - self.t_bbox = t_bbox - - for direction in t_bbox: - t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) - - cols, rows = zip(*self.table_bbox[tk]) - cols, rows = list(cols), list(rows) - cols.extend([tk[0], tk[2]]) - rows.extend([tk[1], tk[3]]) - # sort horizontal and vertical segments - cols = merge_close_values(sorted(cols), mtol=self.mtol) - rows = merge_close_values(sorted(rows, reverse=True), mtol=self.mtol) - # make grid using x and y coord of shortlisted rows and cols - cols = [(cols[i], cols[i + 1]) - for i in range(0, len(cols) - 1)] - rows = [(rows[i], rows[i + 1]) - for i in range(0, len(rows) - 1)] - - return cols, rows, v_s, h_s - - def _generate_table(self, table_idx, cols, rows, **kwargs): - v_s = kwargs.get('v_s') - h_s = kwargs.get('h_s') - if v_s is None or h_s is None: - raise ValueError('No segments found on {}'.format(self.basename)) - - table = Table(cols, rows) - # set table edges to True using ver+hor lines - table = table.set_edges(v_s, h_s, jtol=self.jtol) - # set spanning cells to True - table = table.set_spanning() - # set table border edges to True - table = table.set_border_edges() - - pos_errors = [] - for direction in self.t_bbox: - for t in self.t_bbox[direction]: - indices, error = get_table_index( - table, t, direction, split_text=self.split_text, - flag_size=self.flag_size) - if indices[:2] != (-1, -1): - pos_errors.append(error) - indices = Lattice._reduce_index(table, indices, shift_text=self.shift_text) - for r_idx, c_idx, text in indices: - table.cells[r_idx][c_idx].add_text(text) - accuracy = compute_accuracy([[100, pos_errors]]) - - if self.fill is not None: - table = Lattice._fill_spanning(table, fill=self.fill) - - data = table.data - data = encode_(data) - table.df = pd.DataFrame(data) - table.shape = table.df.shape - - whitespace, __, __ = count_empty(data) - table.accuracy = accuracy - table.whitespace = whitespace - table.order = table_idx + 1 - table.page = int(os.path.basename(self.basename).replace('page-', '')) - - return table - - def extract_tables(self, filename): - """ - - Parameters - ---------- - filename - - Returns - ------- - - """ - logger.info('Processing {}'.format(os.path.basename(filename))) - self._generate_layout(filename) - - if not self.horizontal_text: - warnings.warn("No tables found on {}".format( - os.path.basename(self.basename))) - return [], self.g - - self._generate_image() - self._generate_table_bbox() - - _tables = [] - # sort tables based on y-coord - for table_idx, tk in enumerate(sorted(self.table_bbox.keys(), - key=lambda x: x[1], reverse=True)): - cols, rows, v_s, h_s = self._generate_columns_and_rows(table_idx, tk) - table = self._generate_table(table_idx, cols, rows, v_s=v_s, h_s=h_s) - _tables.append(table) - - if self.debug: - self.g.images = (self.image, self.table_bbox_unscaled) - self.g.segments = (self.vertical_segments, self.horizontal_segments) - self.g.tables = _tables - - return _tables, self.g \ No newline at end of file diff --git a/camelot/parsers/__init__.py b/camelot/parsers/__init__.py new file mode 100644 index 0000000..e046b46 --- /dev/null +++ b/camelot/parsers/__init__.py @@ -0,0 +1,2 @@ +from .stream import Stream +from .lattice import Lattice \ No newline at end of file diff --git a/camelot/parsers/base.py b/camelot/parsers/base.py new file mode 100644 index 0000000..16eb083 --- /dev/null +++ b/camelot/parsers/base.py @@ -0,0 +1,20 @@ +from ..core import Geometry +from ..utils import get_page_layout, get_text_objects + + +class BaseParser(object): + """ + + """ + def _generate_layout(self, filename): + self.filename = filename + self.layout, self.dimensions = get_page_layout( + self.filename, + char_margin=self.char_margin, + line_margin=self.line_margin, + word_margin=self.word_margin) + self.horizontal_text = get_text_objects(self.layout, ltype="lh") + self.vertical_text = get_text_objects(self.layout, ltype="lv") + self.pdf_width, self.pdf_height = self.dimensions + self.basename, __ = os.path.splitext(self.filename) + self.g = Geometry() \ No newline at end of file diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py new file mode 100644 index 0000000..a8067ab --- /dev/null +++ b/camelot/parsers/lattice.py @@ -0,0 +1,244 @@ +from __future__ import division +import os +import sys +import copy +import types +import logging +import copy_reg +import warnings +import subprocess + +import numpy as np +import pandas as pd + +from .base import BaseParser +from ..core import Table +from ..utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, + merge_close_values, get_table_index, compute_accuracy, + count_empty, encode_) +from ..image_processing import (adaptive_threshold, find_lines, + find_table_contours, find_table_joints) + + +logger = logging.getLogger('camelot') + + +class Lattice(BaseParser): + """ + + """ + def __init__(self, table_area=None, fill=None, mtol=2, jtol=2, + blocksize=15, threshold_constant=-2, scale=15, iterations=0, + invert=False, margins=(1.0, 0.5, 0.1), split_text=False, + flag_size=True, shift_text=['l', 't'], debug=None): + self.table_area = table_area + self.fill = fill + self.mtol = mtol + self.jtol = jtol + self.blocksize = blocksize + self.threshold_constant = threshold_constant + self.scale = scale + self.iterations = iterations + self.invert = invert + self.char_margin, self.line_margin, self.word_margin = margins + self.split_text = split_text + self.flag_size = flag_size + self.shift_text = shift_text + self.debug = debug + + @staticmethod + def _reduce_index(t, idx, shift_text): + indices = [] + for r_idx, c_idx, text in idx: + for d in shift_text: + if d == 'l': + if t.cells[r_idx][c_idx].spanning_h: + while not t.cells[r_idx][c_idx].left: + c_idx -= 1 + if d == 'r': + if t.cells[r_idx][c_idx].spanning_h: + while not t.cells[r_idx][c_idx].right: + c_idx += 1 + if d == 't': + if t.cells[r_idx][c_idx].spanning_v: + while not t.cells[r_idx][c_idx].top: + r_idx -= 1 + if d == 'b': + if t.cells[r_idx][c_idx].spanning_v: + while not t.cells[r_idx][c_idx].bottom: + r_idx += 1 + indices.append((r_idx, c_idx, text)) + return indices + + @staticmethod + def _fill_spanning(t, fill=None): + for f in fill: + if f == "h": + for i in range(len(t.cells)): + for j in range(len(t.cells[i])): + if t.cells[i][j].get_text().strip() == '': + if t.cells[i][j].spanning_h and not t.cells[i][j].left: + t.cells[i][j].add_text(t.cells[i][j - 1].get_text()) + elif f == "v": + for i in range(len(t.cells)): + for j in range(len(t.cells[i])): + if t.cells[i][j].get_text().strip() == '': + if t.cells[i][j].spanning_v and not t.cells[i][j].top: + t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) + return t + + def _generate_image(self): + self.imagename = ''.join([self.basename, '.png']) + gs_call = [ + "-q", "-sDEVICE=png16m", "-o", self.imagename, "-r600", self.filename + ] + if "ghostscript" in subprocess.check_output(["gs", "-version"]).lower(): + gs_call.insert(0, "gs") + else: + gs_call.insert(0, "gsc") + subprocess.call(gs_call, stdout=open(os.devnull, 'w'), + stderr=subprocess.STDOUT) + + def _generate_table_bbox(self): + self.image, self.threshold = adaptive_threshold(self.imagename, invert=self.invert, + blocksize=self.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) + image_height_scaler = image_height / float(self.pdf_height) + pdf_width_scaler = self.pdf_width / float(image_width) + pdf_height_scaler = self.pdf_height / float(image_height) + 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', scale=self.scale, iterations=self.iterations) + horizontal_mask, horizontal_segments = find_lines(self.threshold, + direction='horizontal', scale=self.scale, iterations=self.iterations) + + if self.table_area is not None: + areas = [] + for area in self.table_area: + 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))) + 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) + + self.table_bbox_unscaled = copy.deepcopy(table_bbox) + + self.table_bbox, self.vertical_segments, self.horizontal_segments = scale_image( + table_bbox, vertical_segments, horizontal_segments, pdf_scalers) + + def _generate_columns_and_rows(self, table_idx, tk): + # select elements which lie within table_bbox + t_bbox = {} + v_s, h_s = segments_in_bbox( + tk, self.vertical_segments, self.horizontal_segments) + t_bbox['horizontal'] = text_in_bbox(tk, self.horizontal_text) + t_bbox['vertical'] = text_in_bbox(tk, self.vertical_text) + self.t_bbox = t_bbox + + for direction in t_bbox: + t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) + + cols, rows = zip(*self.table_bbox[tk]) + cols, rows = list(cols), list(rows) + cols.extend([tk[0], tk[2]]) + rows.extend([tk[1], tk[3]]) + # sort horizontal and vertical segments + cols = merge_close_values(sorted(cols), mtol=self.mtol) + rows = merge_close_values(sorted(rows, reverse=True), mtol=self.mtol) + # make grid using x and y coord of shortlisted rows and cols + cols = [(cols[i], cols[i + 1]) + for i in range(0, len(cols) - 1)] + rows = [(rows[i], rows[i + 1]) + for i in range(0, len(rows) - 1)] + + return cols, rows, v_s, h_s + + def _generate_table(self, table_idx, cols, rows, **kwargs): + v_s = kwargs.get('v_s') + h_s = kwargs.get('h_s') + if v_s is None or h_s is None: + raise ValueError('No segments found on {}'.format(self.basename)) + + table = Table(cols, rows) + # set table edges to True using ver+hor lines + table = table.set_edges(v_s, h_s, jtol=self.jtol) + # set spanning cells to True + table = table.set_spanning() + # set table border edges to True + table = table.set_border_edges() + + pos_errors = [] + for direction in self.t_bbox: + for t in self.t_bbox[direction]: + indices, error = get_table_index( + table, t, direction, split_text=self.split_text, + flag_size=self.flag_size) + if indices[:2] != (-1, -1): + pos_errors.append(error) + indices = Lattice._reduce_index(table, indices, shift_text=self.shift_text) + for r_idx, c_idx, text in indices: + table.cells[r_idx][c_idx].add_text(text) + accuracy = compute_accuracy([[100, pos_errors]]) + + if self.fill is not None: + table = Lattice._fill_spanning(table, fill=self.fill) + + data = table.data + data = encode_(data) + table.df = pd.DataFrame(data) + table.shape = table.df.shape + + whitespace, __, __ = count_empty(data) + table.accuracy = accuracy + table.whitespace = whitespace + table.order = table_idx + 1 + table.page = int(os.path.basename(self.basename).replace('page-', '')) + + return table + + def extract_tables(self, filename): + """ + + Parameters + ---------- + filename + + Returns + ------- + + """ + logger.info('Processing {}'.format(os.path.basename(filename))) + self._generate_layout(filename) + + if not self.horizontal_text: + warnings.warn("No tables found on {}".format( + os.path.basename(self.basename))) + return [], self.g + + self._generate_image() + self._generate_table_bbox() + + _tables = [] + # sort tables based on y-coord + for table_idx, tk in enumerate(sorted(self.table_bbox.keys(), + key=lambda x: x[1], reverse=True)): + cols, rows, v_s, h_s = self._generate_columns_and_rows(table_idx, tk) + table = self._generate_table(table_idx, cols, rows, v_s=v_s, h_s=h_s) + _tables.append(table) + + if self.debug: + self.g.images = (self.image, self.table_bbox_unscaled) + self.g.segments = (self.vertical_segments, self.horizontal_segments) + self.g.tables = _tables + + return _tables, self.g \ No newline at end of file diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py new file mode 100644 index 0000000..3daa9e6 --- /dev/null +++ b/camelot/parsers/stream.py @@ -0,0 +1,260 @@ +from __future__ import division +import os +import sys +import copy +import types +import logging +import copy_reg +import warnings +import subprocess + +import numpy as np +import pandas as pd + +from .base import BaseParser +from ..core import Table +from ..utils import (text_in_bbox, get_table_index, compute_accuracy, + count_empty, encode_) + + +logger = logging.getLogger('camelot') + + +class Stream(BaseParser): + """ + + """ + def __init__(self, table_area=None, columns=None, ytol=2, mtol=0, + margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, + debug=False): + self.table_area = table_area + self.columns = columns + self._validate_columns() + self.ytol = ytol + self.mtol = mtol + self.char_margin, self.line_margin, self.word_margin = margins + self.split_text = split_text + self.flag_size = flag_size + self.debug = debug + + def _validate_columns(self): + if self.table_area is not None and self.columns is not None: + if len(self.table_area) != len(self.columns): + raise ValueError("Length of table_area and columns" + " should be equal") + + @staticmethod + def _text_bbox(t_bbox): + xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) + ymin = min([t.y0 for direction in t_bbox for t in t_bbox[direction]]) + xmax = max([t.x1 for direction in t_bbox for t in t_bbox[direction]]) + ymax = max([t.y1 for direction in t_bbox for t in t_bbox[direction]]) + text_bbox = (xmin, ymin, xmax, ymax) + return text_bbox + + @staticmethod + def _group_rows(text, ytol=2): + row_y = 0 + rows = [] + temp = [] + for t in text: + # is checking for upright necessary? + # if t.get_text().strip() and all([obj.upright for obj in t._objs if + # type(obj) is LTChar]): + if t.get_text().strip(): + if not np.isclose(row_y, t.y0, atol=ytol): + rows.append(sorted(temp, key=lambda t: t.x0)) + temp = [] + row_y = t.y0 + temp.append(t) + rows.append(sorted(temp, key=lambda t: t.x0)) + __ = rows.pop(0) # hacky + return rows + + @staticmethod + def _merge_columns(l, mtol=0): + merged = [] + for higher in l: + if not merged: + merged.append(higher) + else: + lower = merged[-1] + if mtol >= 0: + if (higher[0] <= lower[1] or + np.isclose(higher[0], lower[1], atol=mtol)): + upper_bound = max(lower[1], higher[1]) + lower_bound = min(lower[0], higher[0]) + merged[-1] = (lower_bound, upper_bound) + else: + merged.append(higher) + elif mtol < 0: + if higher[0] <= lower[1]: + if np.isclose(higher[0], lower[1], atol=abs(mtol)): + merged.append(higher) + else: + upper_bound = max(lower[1], higher[1]) + lower_bound = min(lower[0], higher[0]) + merged[-1] = (lower_bound, upper_bound) + else: + merged.append(higher) + return merged + + @staticmethod + def _join_rows(rows_grouped, text_y_max, text_y_min): + row_mids = [sum([(t.y0 + t.y1) / 2 for t in r]) / len(r) + if len(r) > 0 else 0 for r in rows_grouped] + rows = [(row_mids[i] + row_mids[i - 1]) / 2 for i in range(1, len(row_mids))] + rows.insert(0, text_y_max) + rows.append(text_y_min) + rows = [(rows[i], rows[i + 1]) + for i in range(0, len(rows) - 1)] + return rows + + @staticmethod + def _add_columns(cols, text, ytol): + if text: + text = Stream._group_rows(text, ytol=ytol) + elements = [len(r) for r in text] + new_cols = [(t.x0, t.x1) + for r in text if len(r) == max(elements) for t in r] + cols.extend(Stream._merge_columns(sorted(new_cols))) + return cols + + @staticmethod + def _join_columns(cols, text_x_min, text_x_max): + cols = sorted(cols) + cols = [(cols[i][0] + cols[i - 1][1]) / 2 for i in range(1, len(cols))] + cols.insert(0, text_x_min) + cols.append(text_x_max) + cols = [(cols[i], cols[i + 1]) + for i in range(0, len(cols) - 1)] + return cols + + def _generate_table_bbox(self): + if self.table_area is not None: + table_bbox = {} + for area in self.table_area: + x1, y1, x2, y2 = area.split(",") + x1 = float(x1) + y1 = float(y1) + x2 = float(x2) + y2 = float(y2) + table_bbox[(x1, y2, x2, y1)] = None + else: + table_bbox = {(0, 0, self.pdf_width, self.pdf_height): None} + self.table_bbox = table_bbox + + def _generate_columns_and_rows(self, table_idx, tk): + # select elements which lie within table_bbox + t_bbox = {} + t_bbox['horizontal'] = text_in_bbox(tk, self.horizontal_text) + t_bbox['vertical'] = text_in_bbox(tk, self.vertical_text) + self.t_bbox = t_bbox + + for direction in self.t_bbox: + self.t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) + + text_x_min, text_y_min, text_x_max, text_y_max = self._text_bbox(self.t_bbox) + rows_grouped = self._group_rows(self.t_bbox['horizontal'], ytol=self.ytol) + rows = self._join_rows(rows_grouped, text_y_max, text_y_min) + elements = [len(r) for r in rows_grouped] + + if self.columns is not None and self.columns[table_idx] != "": + # user has to input boundary columns too + # take (0, pdf_width) by default + # similar to else condition + # len can't be 1 + cols = self.columns[table_idx].split(',') + cols = [float(c) for c in cols] + cols.insert(0, text_x_min) + cols.append(text_x_max) + cols = [(cols[i], cols[i + 1]) for i in range(0, len(cols) - 1)] + else: + ncols = max(set(elements), key=elements.count) + if ncols == 1: + # no tables condition + warnings.warn("No tables found on {}".format( + os.path.basename(self.basename))) + cols = [(t.x0, t.x1) + for r in rows_grouped if len(r) == ncols for t in r] + cols = self._merge_columns(sorted(cols), mtol=self.mtol) + inner_text = [] + for i in range(1, len(cols)): + left = cols[i - 1][1] + right = cols[i][0] + inner_text.extend([t for direction in self.t_bbox + for t in self.t_bbox[direction] + if t.x0 > left and t.x1 < right]) + outer_text = [t for direction in self.t_bbox + for t in self.t_bbox[direction] + if t.x0 > cols[-1][1] or t.x1 < cols[0][0]] + inner_text.extend(outer_text) + cols = self._add_columns(cols, inner_text, self.ytol) + cols = self._join_columns(cols, text_x_min, text_x_max) + + return cols, rows + + def _generate_table(self, table_idx, cols, rows, **kwargs): + table = Table(cols, rows) + table = table.set_all_edges() + pos_errors = [] + for direction in self.t_bbox: + for t in self.t_bbox[direction]: + indices, error = get_table_index( + table, t, direction, split_text=self.split_text, + flag_size=self.flag_size) + if indices[:2] != (-1, -1): + pos_errors.append(error) + for r_idx, c_idx, text in indices: + table.cells[r_idx][c_idx].add_text(text) + accuracy = compute_accuracy([[100, pos_errors]]) + + data = table.data + data = encode_(data) + table.df = pd.DataFrame(data) + table.shape = table.df.shape + + whitespace, __, __ = count_empty(data) + table.accuracy = accuracy + table.whitespace = whitespace + table.order = table_idx + 1 + table.page = int(os.path.basename(self.basename).replace('page-', '')) + + return table + + def extract_tables(self, filename): + """ + + Parameters + ---------- + filename + + Returns + ------- + + """ + logger.info('Processing {}'.format(os.path.basename(filename))) + self._generate_layout(filename) + + if not self.horizontal_text: + warnings.warn("No tables found on {}".format( + os.path.basename(self.basename))) + return [], self.g + + self._generate_table_bbox() + + _tables = [] + # sort tables based on y-coord + for table_idx, tk in enumerate(sorted(self.table_bbox.keys(), + key=lambda x: x[1], reverse=True)): + cols, rows = self._generate_columns_and_rows(table_idx, tk) + table = self._generate_table(table_idx, cols, rows) + _tables.append(table) + + if self.debug: + text = [] + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) + self.g.text = text + + return _tables, self.g \ No newline at end of file diff --git a/camelot/utils.py b/camelot/utils.py index 6ec04af..39ab918 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -154,7 +154,7 @@ def setup_logging(log_filepath): ------- """ - logger = logging.getLogger("app_logger") + logger = logging.getLogger("camelot") logger.setLevel(logging.DEBUG) # Log File Handler (Associating one log file per webservice run) log_file_handler = logging.FileHandler(log_filepath, From 42d7a4ac02125f815c6522e4880222f07a9593eb Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Thu, 6 Sep 2018 06:15:13 +0530 Subject: [PATCH 18/39] Add import os --- camelot/parsers/base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/camelot/parsers/base.py b/camelot/parsers/base.py index 16eb083..0c1b54b 100644 --- a/camelot/parsers/base.py +++ b/camelot/parsers/base.py @@ -1,3 +1,5 @@ +import os + from ..core import Geometry from ..utils import get_page_layout, get_text_objects From ffeb853c552f2acc449d76948c9c6a22afee7c55 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Thu, 6 Sep 2018 06:21:54 +0530 Subject: [PATCH 19/39] Rename plot.py to plotting.py --- camelot/__init__.py | 2 +- camelot/{plot.py => plotting.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename camelot/{plot.py => plotting.py} (100%) diff --git a/camelot/__init__.py b/camelot/__init__.py index 9762184..6e416e4 100644 --- a/camelot/__init__.py +++ b/camelot/__init__.py @@ -1,4 +1,4 @@ from .__version__ import __version__ from .io import read_pdf -from .plot import plot_geometry \ No newline at end of file +from .plotting import plot_geometry \ No newline at end of file diff --git a/camelot/plot.py b/camelot/plotting.py similarity index 100% rename from camelot/plot.py rename to camelot/plotting.py From 557189da2434794dbac8e7a2ae8d703aaa45f43e Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Thu, 6 Sep 2018 07:42:41 +0530 Subject: [PATCH 20/39] Refactor core --- camelot/core.py | 203 +++++++++++++++---------------------- camelot/parsers/lattice.py | 29 +++--- camelot/parsers/stream.py | 7 +- 3 files changed, 97 insertions(+), 142 deletions(-) diff --git a/camelot/core.py b/camelot/core.py index 87cb6ae..9f98f16 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -16,64 +16,47 @@ class Cell(object): self.lt = (x1, y2) self.rb = (x2, y1) self.rt = (x2, y2) - self.bbox = (x1, y1, x2, y2) self.left = False self.right = False self.top = False self.bottom = False - self.text_objects = [] - self.text = '' - self.spanning_h = False - self.spanning_v = False + self.hspan = False + self.vspan = False + self._text = '' def __repr__(self): - pass + return ''.format(self.__class__.__name__, self._shape) - def set_all_edges(self): - """ - - Returns - ------- - - """ - for r in range(len(self.rows)): - for c in range(len(self.cols)): - self.cells[r][c].left = True - self.cells[r][c].right = True - self.cells[r][c].top = True - self.cells[r][c].bottom = True - return self - - def set_border_edges(self): + def set_border(self): """ Returns @@ -125,6 +93,18 @@ class Table(object): self.cells[len(self.rows) - 1][c].bottom = True return self + def set_all_edges(self): + """ + + Returns + ------- + + """ + for row in self.cells: + for cell in row: + cell.left = cell.right = cell.top = cell.bottom = True + return self + def set_edges(self, vertical, horizontal, jtol=2): """ @@ -140,7 +120,7 @@ class Table(object): """ for v in vertical: # find closest x coord - # iterate over y coords and find closest points + # iterate over y coords and find closest start and end points i = [i for i, t in enumerate(self.cols) if np.isclose(v[0], t[0], atol=jtol)] j = [j for j, t in enumerate(self.rows) @@ -148,51 +128,50 @@ class Table(object): k = [k for k, t in enumerate(self.rows) if np.isclose(v[1], t[0], atol=jtol)] if not j: - self.nocont_ += 1 continue J = j[0] if i == [0]: # only left edge - I = i[0] + L = i[0] if k: K = k[0] while J < K: - self.cells[J][I].left = True + self.cells[J][L].left = True J += 1 else: K = len(self.rows) while J < K: - self.cells[J][I].left = True + self.cells[J][L].left = True J += 1 elif i == []: # only right edge - I = len(self.cols) - 1 + L = len(self.cols) - 1 if k: K = k[0] while J < K: - self.cells[J][I].right = True + self.cells[J][L].right = True J += 1 else: K = len(self.rows) while J < K: - self.cells[J][I].right = True + self.cells[J][L].right = True J += 1 else: # both left and right edges - I = i[0] + L = i[0] if k: K = k[0] while J < K: - self.cells[J][I].left = True - self.cells[J][I - 1].right = True + self.cells[J][L].left = True + self.cells[J][L - 1].right = True J += 1 else: K = len(self.rows) while J < K: - self.cells[J][I].left = True - self.cells[J][I - 1].right = True + self.cells[J][L].left = True + self.cells[J][L - 1].right = True J += 1 for h in horizontal: # find closest y coord - # iterate over x coords and find closest points + # iterate over x coords and find closest start and end points i = [i for i, t in enumerate(self.rows) if np.isclose(h[1], t[0], atol=jtol)] j = [j for j, t in enumerate(self.cols) @@ -200,93 +179,78 @@ class Table(object): k = [k for k, t in enumerate(self.cols) if np.isclose(h[2], t[0], atol=jtol)] if not j: - self.nocont_ += 1 continue J = j[0] if i == [0]: # only top edge - I = i[0] + L = i[0] if k: K = k[0] while J < K: - self.cells[I][J].top = True + self.cells[L][J].top = True J += 1 else: K = len(self.cols) while J < K: - self.cells[I][J].top = True + self.cells[L][J].top = True J += 1 elif i == []: # only bottom edge I = len(self.rows) - 1 if k: K = k[0] while J < K: - self.cells[I][J].bottom = True + self.cells[L][J].bottom = True J += 1 else: K = len(self.cols) while J < K: - self.cells[I][J].bottom = True + self.cells[L][J].bottom = True J += 1 else: # both top and bottom edges - I = i[0] + L = i[0] if k: K = k[0] while J < K: - self.cells[I][J].top = True - self.cells[I - 1][J].bottom = True + self.cells[L][J].top = True + self.cells[L - 1][J].bottom = True J += 1 else: K = len(self.cols) while J < K: - self.cells[I][J].top = True - self.cells[I - 1][J].bottom = True + self.cells[L][J].top = True + self.cells[L - 1][J].bottom = True J += 1 return self - def set_spanning(self): + def set_span(self): """ Returns ------- """ - for r in range(len(self.rows)): - for c in range(len(self.cols)): - bound = self.cells[r][c].get_bounded_edges() - if bound == 4: + for row in self.cells: + for cell in row: + left = cell.left + right = cell.right + top = cell.top + bottom = cell.bottom + if cell.bound == 4: continue - elif bound == 3: - if not self.cells[r][c].left: - if (self.cells[r][c].right and - self.cells[r][c].top and - self.cells[r][c].bottom): - self.cells[r][c].spanning_h = True - elif not self.cells[r][c].right: - if (self.cells[r][c].left and - self.cells[r][c].top and - self.cells[r][c].bottom): - self.cells[r][c].spanning_h = True - elif not self.cells[r][c].top: - if (self.cells[r][c].left and - self.cells[r][c].right and - self.cells[r][c].bottom): - self.cells[r][c].spanning_v = True - elif not self.cells[r][c].bottom: - if (self.cells[r][c].left and - self.cells[r][c].right and - self.cells[r][c].top): - self.cells[r][c].spanning_v = True - elif bound == 2: - if self.cells[r][c].left and self.cells[r][c].right: - if (not self.cells[r][c].top and - not self.cells[r][c].bottom): - self.cells[r][c].spanning_v = True - elif self.cells[r][c].top and self.cells[r][c].bottom: - if (not self.cells[r][c].left and - not self.cells[r][c].right): - self.cells[r][c].spanning_h = True - + elif cell.bound == 3: + if not left and (right and top and bottom): + cell.hspan = True + elif not right and (left and top and bottom): + cell.hspan = True + elif not top and (left and right and bottom): + cell.vspan = True + elif not bottom and (left and right and top): + cell.vspan = True + elif cell.bound == 2: + if left and right and (not top and not bottom): + cell.vspan = True + elif top and bottom and (not left and not right): + cell.hspan = True return self @property @@ -298,9 +262,8 @@ class Table(object): """ d = [] - for r in range(len(self.rows)): - d.append([self.cells[r][c].get_text().strip() - for c in range(len(self.cols))]) + for row in self.cells: + d.append([cell.text.strip() for cell in row]) return d @property @@ -405,7 +368,7 @@ class Table(object): return report -class TableList(list): +class TableList(object): """ """ diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index a8067ab..282a96a 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -1,10 +1,7 @@ from __future__ import division import os -import sys import copy -import types import logging -import copy_reg import warnings import subprocess @@ -52,19 +49,19 @@ class Lattice(BaseParser): for r_idx, c_idx, text in idx: for d in shift_text: if d == 'l': - if t.cells[r_idx][c_idx].spanning_h: + if t.cells[r_idx][c_idx].hspan: while not t.cells[r_idx][c_idx].left: c_idx -= 1 if d == 'r': - if t.cells[r_idx][c_idx].spanning_h: + if t.cells[r_idx][c_idx].hspan: while not t.cells[r_idx][c_idx].right: c_idx += 1 if d == 't': - if t.cells[r_idx][c_idx].spanning_v: + if t.cells[r_idx][c_idx].vspan: while not t.cells[r_idx][c_idx].top: r_idx -= 1 if d == 'b': - if t.cells[r_idx][c_idx].spanning_v: + if t.cells[r_idx][c_idx].vspan: while not t.cells[r_idx][c_idx].bottom: r_idx += 1 indices.append((r_idx, c_idx, text)) @@ -76,15 +73,15 @@ class Lattice(BaseParser): if f == "h": for i in range(len(t.cells)): for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_h and not t.cells[i][j].left: - t.cells[i][j].add_text(t.cells[i][j - 1].get_text()) + if t.cells[i][j].text.strip() == '': + if t.cells[i][j].hspan and not t.cells[i][j].left: + t.cells[i][j].text = t.cells[i][j - 1].text elif f == "v": for i in range(len(t.cells)): for j in range(len(t.cells[i])): - if t.cells[i][j].get_text().strip() == '': - if t.cells[i][j].spanning_v and not t.cells[i][j].top: - t.cells[i][j].add_text(t.cells[i - 1][j].get_text()) + if t.cells[i][j].text.strip() == '': + if t.cells[i][j].vspan and not t.cells[i][j].top: + t.cells[i][j].text = t.cells[i - 1][j].text return t def _generate_image(self): @@ -173,9 +170,9 @@ class Lattice(BaseParser): # set table edges to True using ver+hor lines table = table.set_edges(v_s, h_s, jtol=self.jtol) # set spanning cells to True - table = table.set_spanning() + table = table.set_span() # set table border edges to True - table = table.set_border_edges() + table = table.set_border() pos_errors = [] for direction in self.t_bbox: @@ -187,7 +184,7 @@ class Lattice(BaseParser): pos_errors.append(error) indices = Lattice._reduce_index(table, indices, shift_text=self.shift_text) for r_idx, c_idx, text in indices: - table.cells[r_idx][c_idx].add_text(text) + table.cells[r_idx][c_idx].text = text accuracy = compute_accuracy([[100, pos_errors]]) if self.fill is not None: diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index 3daa9e6..1849a0c 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -1,12 +1,7 @@ from __future__ import division import os -import sys -import copy -import types import logging -import copy_reg import warnings -import subprocess import numpy as np import pandas as pd @@ -206,7 +201,7 @@ class Stream(BaseParser): if indices[:2] != (-1, -1): pos_errors.append(error) for r_idx, c_idx, text in indices: - table.cells[r_idx][c_idx].add_text(text) + table.cells[r_idx][c_idx].text = text accuracy = compute_accuracy([[100, pos_errors]]) data = table.data From ed1641e26f27d66f7583d3ffa558fa537f7d856c Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 7 Sep 2018 02:34:59 +0530 Subject: [PATCH 21/39] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a5227f..88dcafe 100644 --- a/README.md +++ b/README.md @@ -85,13 +85,13 @@ numpy can be install using `pip`. OpenCV and ghostscript can be installed using * Arch Linux
-sudo pacman -S opencv ghostscript
+sudo pacman -S opencv tk ghostscript
 
* Ubuntu
-sudo apt-get install libopencv-dev python-opencv python-tk ghostscript
+sudo apt-get install python-opencv python-tk ghostscript
 
#### OS X From 0c329634e738be01c937d724f47826fbe8d5843a Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 7 Sep 2018 05:13:34 +0530 Subject: [PATCH 22/39] Add export to TableList and Table --- README.md | 4 +- camelot/core.py | 373 +++++++++++++++---------------------- camelot/handlers.py | 10 +- camelot/parsers/base.py | 2 +- camelot/parsers/lattice.py | 8 +- camelot/parsers/stream.py | 18 +- 6 files changed, 169 insertions(+), 246 deletions(-) diff --git a/README.md b/README.md index 4a5227f..b5a3e8b 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,10 @@ Camelot is a Python 2.7 library and command-line tool for getting tables out of >>> tables = camelot.read_pdf("foo.pdf") >>> tables <TableList n=2> ->>> tables.to_csv(zip=True) # to_json, to_excel, to_html +>>> tables.export("foo.csv", f="csv", compress=True) # json, excel, html >>> tables[0] <Table shape=(3,4)> +>>> tables[0].to_csv("foo.csv") # to_json, to_excel, to_html >>> tables[0].parsing_report { "accuracy": 96, @@ -20,7 +21,6 @@ Camelot is a Python 2.7 library and command-line tool for getting tables out of "page": 1 } >>> df = tables[0].df ->>> tables[0].to_csv("foo.csv") # to_json, to_excel, to_html Camelot comes with a CLI where you can specify page numbers, output format, output directory etc. By default, the output files are placed in the same directory as the PDF. diff --git a/camelot/core.py b/camelot/core.py index 9f98f16..2003979 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -1,6 +1,10 @@ +import os import json +import zipfile +import tempfile import numpy as np +import pandas as pd class Cell(object): @@ -68,16 +72,46 @@ class Table(object): self.rows = rows self.cells = [[Cell(c[0], r[1], c[1], r[0]) for c in cols] for r in rows] - self._df = None - self._shape = (0, 0) - self._accuracy = 0 - self._whitespace = 0 - self._order = None - self._page = None + self.df = None + self.shape = (0, 0) + self.accuracy = 0 + self.whitespace = 0 + self.order = None + self.page = None def __repr__(self): return '<{} shape={}>'.format(self.__class__.__name__, self._shape) + @property + def data(self): + """ + + Returns + ------- + + """ + d = [] + for row in self.cells: + d.append([cell.text.strip() for cell in row]) + return d + + @property + def parsing_report(self): + """ + + Returns + ------- + + """ + # pretty? + report = { + 'accuracy': self.accuracy, + 'whitespace': self.whitespace, + 'order': self.order, + 'page': self.page + } + return report + def set_border(self): """ @@ -253,119 +287,38 @@ class Table(object): cell.hspan = True return self - @property - def data(self): - """ - - Returns - ------- - - """ - d = [] - for row in self.cells: - d.append([cell.text.strip() for cell in row]) - return d - - @property - def df(self): - """ - - Returns - ------- - - """ - return self._df - - @df.setter - def df(self, dataframe): - self._df = dataframe - - @property - def shape(self): - """ - - Returns - ------- - - """ - return self._shape - - @shape.setter - def shape(self, s): - self._shape = s - - @property - def accuracy(self): - """ - - Returns - ------- - - """ - return self._accuracy - - @accuracy.setter - def accuracy(self, a): - self._accuracy = a - - @property - def whitespace(self): - """ - - Returns - ------- - - """ - return self._whitespace - - @whitespace.setter - def whitespace(self, w): - self._whitespace = w - - @property - def order(self): - """ - - Returns - ------- - - """ - return self._order - - @order.setter - def order(self, o): - self._order = o - - @property - def page(self): - """ - - Returns - ------- - - """ - return self._page - - @page.setter - def page(self, p): - self._page = p - - @property - def parsing_report(self): - """ - - Returns - ------- - - """ - # pretty? - report = { - 'accuracy': self._accuracy, - 'whitespace': self._whitespace, - 'order': self._order, - 'page': self._page + def to_csv(self, path, **kwargs): + kw = { + 'encoding': 'utf-8', + 'index': False, + 'quoting': 1 } - return report + kw.update(kwargs) + self.df.to_csv(path, **kw) + + def to_json(self, path, **kwargs): + kw = { + 'orient': 'records' + } + kw.update(kwargs) + json_string = self.df.to_json(**kw) + with open(path, 'w') as f: + f.write(json_string) + + def to_excel(self, path, **kwargs): + kw = { + 'sheet_name': 'page-{}-table-{}'.format(self.page, self.order), + 'encoding': 'utf-8' + } + kw.update(kwargs) + writer = pd.ExcelWriter(path) + self.df.to_excel(writer, **kw) + writer.save() + + def to_html(self, path, **kwargs): + html_string = self.df.to_html(**kwargs) + with open(path, 'w') as f: + f.write(html_string) class TableList(object): @@ -385,72 +338,82 @@ class TableList(object): def __getitem__(self, idx): return self._tables[idx] + @staticmethod + def _format_func(table, f): + return getattr(table, 'to_{}'.format(f)) + + def _write_file(self, f=None, **kwargs): + dirname = kwargs.get('dirname') + root = kwargs.get('root') + ext = kwargs.get('ext') + for table in self._tables: + filename = os.path.join('{}-page-{}-table-{}{}'.format( + root, table.page, table.order, ext)) + filepath = os.path.join(dirname, filename) + to_format = self._format_func(table, f) + to_format(filepath) + + def _compress_dir(self, **kwargs): + path = kwargs.get('path') + dirname = kwargs.get('dirname') + root = kwargs.get('root') + ext = kwargs.get('ext') + zipname = os.path.join(os.path.dirname(path), root) + '.zip' + with zipfile.ZipFile(zipname, 'w', allowZip64=True) as z: + for table in self._tables: + filename = os.path.join('{}-page-{}-table-{}{}'.format( + root, table.page, table.order, ext)) + filepath = os.path.join(dirname, filename) + z.write(filepath, os.path.basename(filepath)) + + def export(self, path, f='csv', compress=False): + dirname = os.path.dirname(path) + basename = os.path.basename(path) + root, ext = os.path.splitext(basename) + if compress: + dirname = tempfile.mkdtemp() + + kwargs = { + 'path': path, + 'dirname': dirname, + 'root': root, + 'ext': ext + } + + if f in ['csv', 'json', 'html']: + self._write_file(f=f, **kwargs) + if compress: + self._compress_dir(**kwargs) + elif f == 'excel': + filepath = os.path.join(dirname, basename) + writer = pd.ExcelWriter(filepath) + for table in self._tables: + sheet_name = 'page-{}-table-{}'.format(table.page, table.order) + table.df.to_excel(writer, sheet_name=sheet_name, encoding='utf-8') + writer.save() + if compress: + zipname = os.path.join(os.path.dirname(path), root) + '.zip' + with zipfile.ZipFile(zipname, 'w', allowZip64=True) as z: + z.write(filepath, os.path.basename(filepath)) + class Geometry(object): """ """ def __init__(self): - self._text = [] - self._images = () - self._segments = () - self._tables = [] + self.text = [] + self.images = () + self.segments = () + self.tables = [] - @property - def text(self): - """ - - Returns - ------- - - """ - return self._text - - @text.setter - def text(self, t): - self._text = t - - @property - def images(self): - """ - - Returns - ------- - - """ - return self._images - - @images.setter - def images(self, i): - self._images = i - - @property - def segments(self): - """ - - Returns - ------- - - """ - return self._segments - - @segments.setter - def segments(self, s): - self._segments = s - - @property - def tables(self): - """ - - Returns - ------- - - """ - return self._tables - - @tables.setter - def tables(self, tb): - self._tables = tb + def __repr__(self): + return '<{} text={} images={} segments={} tables={}>'.format( + self.__class__.__name__, + len(self.text), + len(self.images), + len(self.segments), + len(self.tables)) class GeometryList(object): @@ -458,55 +421,15 @@ class GeometryList(object): """ def __init__(self, geometry): - self._text = [g.text for g in geometry] - self._images = [g.images for g in geometry] - self._segments = [g.segments for g in geometry] - self._tables = [g.tables for g in geometry] + self.text = [g.text for g in geometry] + self.images = [g.images for g in geometry] + self.segments = [g.segments for g in geometry] + self.tables = [g.tables for g in geometry] def __repr__(self): return '<{} text={} images={} segments={} tables={}>'.format( self.__class__.__name__, - len(self._text), - len(self._images), - len(self._segments), - len(self._tables)) - - @property - def text(self): - """ - - Returns - ------- - - """ - return self._text - - @property - def images(self): - """ - - Returns - ------- - - """ - return self._images - - @property - def segments(self): - """ - - Returns - ------- - - """ - return self._segments - - @property - def tables(self): - """ - - Returns - ------- - - """ - return self._tables \ No newline at end of file + len(self.text), + len(self.images), + len(self.segments), + len(self.tables)) \ No newline at end of file diff --git a/camelot/handlers.py b/camelot/handlers.py index c4bcfd8..af4db00 100644 --- a/camelot/handlers.py +++ b/camelot/handlers.py @@ -17,7 +17,7 @@ class PDFHandler(object): if not self.filename.endswith('.pdf'): raise TypeError("File format not supported.") self.pages = self.__get_pages(self.filename, pages) - self.temp = tempfile.mkdtemp() + self.tempdir = tempfile.mkdtemp() def __get_pages(self, filename, pages): # refactor @@ -47,7 +47,7 @@ class PDFHandler(object): with open(filename, 'rb') as fileobj: infile = PdfFileReader(fileobj, strict=False) fpath = os.path.join(temp, 'page-{0}.pdf'.format(page)) - fname, fext = os.path.splitext(fpath) + froot, fext = os.path.splitext(fpath) p = infile.getPage(page - 1) outfile = PdfFileWriter() outfile.addPage(p) @@ -60,7 +60,7 @@ class PDFHandler(object): ltchar = get_text_objects(layout, ltype="char") rotation = get_rotation(lttextlh, lttextlv, ltchar) if rotation != '': - fpath_new = ''.join([fname.replace('page', 'p'), '_rotated', fext]) + fpath_new = ''.join([froot.replace('page', 'p'), '_rotated', fext]) os.rename(fpath, fpath_new) infile = PdfFileReader(open(fpath_new, 'rb'), strict=False) outfile = PdfFileWriter() @@ -86,8 +86,8 @@ class PDFHandler(object): """ for p in self.pages: - self.__save_page(self.filename, p, self.temp) - pages = [os.path.join(self.temp, 'page-{0}.pdf'.format(p)) + self.__save_page(self.filename, p, self.tempdir) + pages = [os.path.join(self.tempdir, 'page-{0}.pdf'.format(p)) for p in self.pages] tables = [] geometry = [] diff --git a/camelot/parsers/base.py b/camelot/parsers/base.py index 0c1b54b..79cb986 100644 --- a/camelot/parsers/base.py +++ b/camelot/parsers/base.py @@ -18,5 +18,5 @@ class BaseParser(object): self.horizontal_text = get_text_objects(self.layout, ltype="lh") self.vertical_text = get_text_objects(self.layout, ltype="lv") self.pdf_width, self.pdf_height = self.dimensions - self.basename, __ = os.path.splitext(self.filename) + self.rootname, __ = os.path.splitext(self.filename) self.g = Geometry() \ No newline at end of file diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index 282a96a..a758af7 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -85,7 +85,7 @@ class Lattice(BaseParser): return t def _generate_image(self): - self.imagename = ''.join([self.basename, '.png']) + self.imagename = ''.join([self.rootname, '.png']) gs_call = [ "-q", "-sDEVICE=png16m", "-o", self.imagename, "-r600", self.filename ] @@ -164,7 +164,7 @@ class Lattice(BaseParser): v_s = kwargs.get('v_s') h_s = kwargs.get('h_s') if v_s is None or h_s is None: - raise ValueError('No segments found on {}'.format(self.basename)) + raise ValueError('No segments found on {}'.format(self.rootname)) table = Table(cols, rows) # set table edges to True using ver+hor lines @@ -199,7 +199,7 @@ class Lattice(BaseParser): table.accuracy = accuracy table.whitespace = whitespace table.order = table_idx + 1 - table.page = int(os.path.basename(self.basename).replace('page-', '')) + table.page = int(os.path.basename(self.rootname).replace('page-', '')) return table @@ -219,7 +219,7 @@ class Lattice(BaseParser): if not self.horizontal_text: warnings.warn("No tables found on {}".format( - os.path.basename(self.basename))) + os.path.basename(self.rootname))) return [], self.g self._generate_image() diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index 1849a0c..fe3a3e8 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -32,12 +32,6 @@ class Stream(BaseParser): self.flag_size = flag_size self.debug = debug - def _validate_columns(self): - if self.table_area is not None and self.columns is not None: - if len(self.table_area) != len(self.columns): - raise ValueError("Length of table_area and columns" - " should be equal") - @staticmethod def _text_bbox(t_bbox): xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) @@ -125,6 +119,12 @@ class Stream(BaseParser): for i in range(0, len(cols) - 1)] return cols + def _validate_columns(self): + if self.table_area is not None and self.columns is not None: + if len(self.table_area) != len(self.columns): + raise ValueError("Length of table_area and columns" + " should be equal") + def _generate_table_bbox(self): if self.table_area is not None: table_bbox = {} @@ -169,7 +169,7 @@ class Stream(BaseParser): if ncols == 1: # no tables condition warnings.warn("No tables found on {}".format( - os.path.basename(self.basename))) + os.path.basename(self.rootname))) cols = [(t.x0, t.x1) for r in rows_grouped if len(r) == ncols for t in r] cols = self._merge_columns(sorted(cols), mtol=self.mtol) @@ -213,7 +213,7 @@ class Stream(BaseParser): table.accuracy = accuracy table.whitespace = whitespace table.order = table_idx + 1 - table.page = int(os.path.basename(self.basename).replace('page-', '')) + table.page = int(os.path.basename(self.rootname).replace('page-', '')) return table @@ -233,7 +233,7 @@ class Stream(BaseParser): if not self.horizontal_text: warnings.warn("No tables found on {}".format( - os.path.basename(self.basename))) + os.path.basename(self.rootname))) return [], self.g self._generate_table_bbox() From 09ac8f46403a51658cfddf63d62f6c5eef9fc621 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 7 Sep 2018 05:17:09 +0530 Subject: [PATCH 23/39] Add property n to TableList --- camelot/core.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/camelot/core.py b/camelot/core.py index 2003979..015c533 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -342,6 +342,10 @@ class TableList(object): def _format_func(table, f): return getattr(table, 'to_{}'.format(f)) + @property + def n(self): + return len(self._tables) + def _write_file(self, f=None, **kwargs): dirname = kwargs.get('dirname') root = kwargs.get('root') From 20acda22591d5f91ef3f9c569cc33340b7087e0e Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 7 Sep 2018 05:53:19 +0530 Subject: [PATCH 24/39] Fix current logging --- camelot/parsers/lattice.py | 7 ++-- camelot/parsers/stream.py | 8 ++--- camelot/utils.py | 65 +++++++++++++++++++------------------- 3 files changed, 39 insertions(+), 41 deletions(-) diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index a758af7..8b0fc2b 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -2,7 +2,6 @@ from __future__ import division import os import copy import logging -import warnings import subprocess import numpy as np @@ -12,12 +11,12 @@ from .base import BaseParser from ..core import Table from ..utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, merge_close_values, get_table_index, compute_accuracy, - count_empty, encode_) + count_empty, encode_, setup_logging) from ..image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) -logger = logging.getLogger('camelot') +logger = setup_logging(__name__) class Lattice(BaseParser): @@ -218,7 +217,7 @@ class Lattice(BaseParser): self._generate_layout(filename) if not self.horizontal_text: - warnings.warn("No tables found on {}".format( + logger.info("No tables found on {}".format( os.path.basename(self.rootname))) return [], self.g diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index fe3a3e8..37e9bcf 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -1,7 +1,6 @@ from __future__ import division import os import logging -import warnings import numpy as np import pandas as pd @@ -12,7 +11,7 @@ from ..utils import (text_in_bbox, get_table_index, compute_accuracy, count_empty, encode_) -logger = logging.getLogger('camelot') +logger = setup_logging(__name__) class Stream(BaseParser): @@ -167,8 +166,7 @@ class Stream(BaseParser): else: ncols = max(set(elements), key=elements.count) if ncols == 1: - # no tables condition - warnings.warn("No tables found on {}".format( + logger.info("No tables found on {}".format( os.path.basename(self.rootname))) cols = [(t.x0, t.x1) for r in rows_grouped if len(r) == ncols for t in r] @@ -232,7 +230,7 @@ class Stream(BaseParser): self._generate_layout(filename) if not self.horizontal_text: - warnings.warn("No tables found on {}".format( + logger.info("No tables found on {}".format( os.path.basename(self.rootname))) return [], self.g diff --git a/camelot/utils.py b/camelot/utils.py index 39ab918..7eaad84 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -18,6 +18,34 @@ from pdfminer.layout import (LAParams, LTAnno, LTChar, LTTextLineHorizontal, LTTextLineVertical) +def setup_logging(name): + """ + + Parameters + ---------- + name + + Returns + ------- + + """ + logger = logging.getLogger(name) + + format_string = '%(asctime)s - %(levelname)s - %(funcName)s - %(message)s' + formatter = logging.Formatter(format_string, datefmt='%Y-%m-%dT%H:%M:%S') + + handler = logging.StreamHandler() + handler.setLevel(logging.INFO) + handler.setFormatter(formatter) + + logger.addHandler(handler) + + return logger + + +logger = setup_logging(__name__) + + def translate(x1, x2): """ @@ -143,37 +171,6 @@ def scale_image(tables, v_segments, h_segments, factors): return tables_new, v_segments_new, h_segments_new -def setup_logging(log_filepath): - """ - - Parameters - ---------- - log_filepath - - Returns - ------- - - """ - logger = logging.getLogger("camelot") - logger.setLevel(logging.DEBUG) - # Log File Handler (Associating one log file per webservice run) - log_file_handler = logging.FileHandler(log_filepath, - mode='a', - encoding='utf-8') - log_file_handler.setLevel(logging.DEBUG) - format_string = '%(asctime)s - %(levelname)s - %(funcName)s - %(message)s' - formatter = logging.Formatter(format_string, datefmt='%Y-%m-%dT%H:%M:%S') - log_file_handler.setFormatter(formatter) - logger.addHandler(log_file_handler) - # Stream Log Handler (For console) - stream_log_handler = logging.StreamHandler() - stream_log_handler.setLevel(logging.INFO) - formatter = logging.Formatter(format_string, datefmt='%Y-%m-%dT%H:%M:%S') - stream_log_handler.setFormatter(formatter) - logger.addHandler(stream_log_handler) - return logger - - def get_rotation(lttextlh, lttextlv, ltchar): """ @@ -419,7 +416,11 @@ def get_table_index(table, t, direction, split_text=False, flag_size=True): else: lt_col_overlap.append(-1) if len(filter(lambda x: x != -1, lt_col_overlap)) == 0: - logging.warning("Text did not fit any column.") + text = t.get_text().strip('\n') + text_range = (t.x0, t.x1) + col_range = (table.cols[0][0], table.cols[-1][1]) + logger.info("{} {} does not lie in column range {}".format( + text, text_range, col_range)) r_idx = r c_idx = lt_col_overlap.index(max(lt_col_overlap)) break From b3f840bba99419c169dcc28d361f2dbe54bbf0fa Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 7 Sep 2018 06:04:45 +0530 Subject: [PATCH 25/39] Change utils function names --- camelot/parsers/lattice.py | 4 ++-- camelot/parsers/stream.py | 4 ++-- camelot/utils.py | 48 +++++++++++++++++++------------------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index 8b0fc2b..727e00b 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -11,7 +11,7 @@ from .base import BaseParser from ..core import Table from ..utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, merge_close_values, get_table_index, compute_accuracy, - count_empty, encode_, setup_logging) + count_empty_strings, encode_, setup_logging) from ..image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) @@ -194,7 +194,7 @@ class Lattice(BaseParser): table.df = pd.DataFrame(data) table.shape = table.df.shape - whitespace, __, __ = count_empty(data) + whitespace, __, __ = count_empty_strings(data) table.accuracy = accuracy table.whitespace = whitespace table.order = table_idx + 1 diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index 37e9bcf..9d12384 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -8,7 +8,7 @@ import pandas as pd from .base import BaseParser from ..core import Table from ..utils import (text_in_bbox, get_table_index, compute_accuracy, - count_empty, encode_) + count_empty_strings, encode_) logger = setup_logging(__name__) @@ -207,7 +207,7 @@ class Stream(BaseParser): table.df = pd.DataFrame(data) table.shape = table.df.shape - whitespace, __, __ = count_empty(data) + whitespace, __, __ = count_empty_strings(data) table.accuracy = accuracy table.whitespace = whitespace table.order = table_idx + 1 diff --git a/camelot/utils.py b/camelot/utils.py index 7eaad84..c957a4e 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -287,7 +287,7 @@ def merge_close_values(ar, mtol=2): return ret -def flag_on_size(textline, direction): +def flag_font_size(textline, direction): """ Parameters @@ -381,7 +381,7 @@ def split_textline(table, textline, direction, flag_size=True): grouped_chars = [] for key, chars in groupby(cut_text, itemgetter(0, 1)): if flag_size: - grouped_chars.append((key[0], key[1], flag_on_size([t[2] for t in chars], direction))) + grouped_chars.append((key[0], key[1], flag_font_size([t[2] for t in chars], direction))) else: gchars = [t[2].get_text() for t in chars] grouped_chars.append((key[0], key[1], ''.join(gchars).strip('\n'))) @@ -444,7 +444,7 @@ def get_table_index(table, t, direction, split_text=False, flag_size=True): return split_textline(table, t, direction, flag_size=flag_size), error else: if flag_size: - return [(r_idx, c_idx, flag_on_size(t._objs, direction))], error + return [(r_idx, c_idx, flag_font_size(t._objs, direction))], error else: return [(r_idx, c_idx, t.get_text().strip('\n'))], error @@ -474,27 +474,7 @@ def compute_accuracy(error_weights): return score -def remove_empty(d): - """ - - Parameters - ---------- - d - - Returns - ------- - - """ - for i, row in enumerate(d): - if row == [''] * len(row): - d.pop(i) - d = zip(*d) - d = [list(row) for row in d if any(row)] - d = zip(*d) - return d - - -def count_empty(d): +def count_empty_strings(d): """ Parameters @@ -529,6 +509,26 @@ def count_empty(d): return empty_p, r_nempty_cells, c_nempty_cells +def remove_empty_strings(d): + """ + + Parameters + ---------- + d + + Returns + ------- + + """ + for i, row in enumerate(d): + if row == [''] * len(row): + d.pop(i) + d = zip(*d) + d = [list(row) for row in d if any(row)] + d = zip(*d) + return d + + def encode_(ar): """ From e615580e5541005e17bb8008d1d6a70ffa50d789 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Fri, 7 Sep 2018 06:25:13 +0530 Subject: [PATCH 26/39] Fix plot_geometry --- camelot/parsers/lattice.py | 6 +- camelot/parsers/stream.py | 7 ++- camelot/plotting.py | 117 ++++++++++++++++--------------------- 3 files changed, 59 insertions(+), 71 deletions(-) diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index 727e00b..bf4fca3 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -232,7 +232,11 @@ class Lattice(BaseParser): table = self._generate_table(table_idx, cols, rows, v_s=v_s, h_s=h_s) _tables.append(table) - if self.debug: + if self.debug is not None: + text = [] + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) + text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) + self.g.text = text self.g.images = (self.image, self.table_bbox_unscaled) self.g.segments = (self.vertical_segments, self.horizontal_segments) self.g.tables = _tables diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index 9d12384..1976505 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -8,7 +8,7 @@ import pandas as pd from .base import BaseParser from ..core import Table from ..utils import (text_in_bbox, get_table_index, compute_accuracy, - count_empty_strings, encode_) + count_empty_strings, encode_, setup_logging) logger = setup_logging(__name__) @@ -20,7 +20,7 @@ class Stream(BaseParser): """ def __init__(self, table_area=None, columns=None, ytol=2, mtol=0, margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, - debug=False): + debug=None): self.table_area = table_area self.columns = columns self._validate_columns() @@ -244,10 +244,11 @@ class Stream(BaseParser): table = self._generate_table(table_idx, cols, rows) _tables.append(table) - if self.debug: + if self.debug is not None: text = [] text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) self.g.text = text + self.g.tables = _tables return _tables, self.g \ No newline at end of file diff --git a/camelot/plotting.py b/camelot/plotting.py index 793764e..7d4e4d3 100644 --- a/camelot/plotting.py +++ b/camelot/plotting.py @@ -39,71 +39,54 @@ def plot_geometry(filepath, pages='1', mesh=False, geometry_type='text', **kwarg ax.set_xlim(min(xs) - 10, max(xs) + 10) ax.set_ylim(min(ys) - 10, max(ys) + 10) plt.show() - elif geometry_type == 'contour': - try: - for img, table_bbox in geometry.images: - for t in table_bbox.keys(): - cv2.rectangle(img, (t[0], t[1]), - (t[2], t[3]), (255, 0, 0), 3) - plt.imshow(img) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") - elif geometry_type == 'joint': - try: - for img, table_bbox in geometry.images: - x_coord = [] - y_coord = [] - for k in table_bbox.keys(): - for coord in table_bbox[k]: - x_coord.append(coord[0]) - y_coord.append(coord[1]) - max_x, max_y = max(x_coord), max(y_coord) - plt.plot(x_coord, y_coord, 'ro') - plt.axis([0, max_x + 100, max_y + 100, 0]) - plt.imshow(img) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") - elif geometry_type == 'line': - try: - for v_s, h_s in geometry.segments: - for v in v_s: - plt.plot([v[0], v[2]], [v[1], v[3]]) - for h in h_s: - plt.plot([h[0], h[2]], [h[1], h[3]]) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") elif geometry_type == 'table': - try: - for tables in geometry.tables: - for table in tables: - for r in range(len(table.rows)): - for c in range(len(table.cols)): - if table.cells[r][c].left: - plt.plot([table.cells[r][c].lb[0], - table.cells[r][c].lt[0]], - [table.cells[r][c].lb[1], - table.cells[r][c].lt[1]]) - if table.cells[r][c].right: - plt.plot([table.cells[r][c].rb[0], - table.cells[r][c].rt[0]], - [table.cells[r][c].rb[1], - table.cells[r][c].rt[1]]) - if table.cells[r][c].top: - plt.plot([table.cells[r][c].lt[0], - table.cells[r][c].rt[0]], - [table.cells[r][c].lt[1], - table.cells[r][c].rt[1]]) - if table.cells[r][c].bottom: - plt.plot([table.cells[r][c].lb[0], - table.cells[r][c].rb[0]], - [table.cells[r][c].lb[1], - table.cells[r][c].rb[1]]) - plt.show() - except AttributeError: - raise ValueError("This option can only be used with Lattice.") - else: - raise UserWarning("This method can only be called after" - " debug has been specified.") \ No newline at end of file + for tables in geometry.tables: + for table in tables: + for row in table.cells: + for cell in row: + if cell.left: + plt.plot([cell.lb[0], cell.lt[0]], + [cell.lb[1], cell.lt[1]]) + if cell.right: + plt.plot([cell.rb[0], cell.rt[0]], + [cell.rb[1], cell.rt[1]]) + if cell.top: + plt.plot([cell.lt[0], cell.rt[0]], + [cell.lt[1], cell.rt[1]]) + if cell.bottom: + plt.plot([cell.lb[0], cell.rb[0]], + [cell.lb[1], cell.rb[1]]) + plt.show() + elif geometry_type == 'contour': + if not mesh: + raise ValueError("Use mesh=True") + for img, table_bbox in geometry.images: + for t in table_bbox.keys(): + cv2.rectangle(img, (t[0], t[1]), + (t[2], t[3]), (255, 0, 0), 3) + plt.imshow(img) + plt.show() + elif geometry_type == 'joint': + if not mesh: + raise ValueError("Use mesh=True") + for img, table_bbox in geometry.images: + x_coord = [] + y_coord = [] + for k in table_bbox.keys(): + for coord in table_bbox[k]: + x_coord.append(coord[0]) + y_coord.append(coord[1]) + max_x, max_y = max(x_coord), max(y_coord) + plt.plot(x_coord, y_coord, 'ro') + plt.axis([0, max_x + 100, max_y + 100, 0]) + plt.imshow(img) + plt.show() + elif geometry_type == 'line': + if not mesh: + raise ValueError("Use mesh=True") + for v_s, h_s in geometry.segments: + for v in v_s: + plt.plot([v[0], v[2]], [v[1], v[3]]) + for h in h_s: + plt.plot([h[0], h[2]], [h[1], h[3]]) + plt.show() \ No newline at end of file From d02e5ac6028c59684e237133926e9fbde90e733c Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 8 Sep 2018 01:42:26 +0530 Subject: [PATCH 27/39] Fix code in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac28387..6e82334 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Camelot is a Python 2.7 library and command-line tool for getting tables out of { "accuracy": 96, "whitespace": 80, - "time_taken": 0.5, + "order": 1, "page": 1 } >>> df = tables[0].df From 6948f16f1367045cc01dac4f45410354223726bf Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 8 Sep 2018 01:56:16 +0530 Subject: [PATCH 28/39] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e82334..a2d9810 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# camelot +# Camelot: PDF Table Parsing for Humans Camelot is a Python 2.7 library and command-line tool for getting tables out of PDF files. From 0f2876a679018969d44e9b522b870b790dcad7aa Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 8 Sep 2018 01:58:56 +0530 Subject: [PATCH 29/39] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a2d9810..3dbaa79 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Camelot: PDF Table Parsing for Humans -Camelot is a Python 2.7 library and command-line tool for getting tables out of PDF files. +Camelot is a Python 2.7 library and command-line tool for extracting tabular data from PDF files. ## Usage From 04383920b41bbdf461a4868df8054ebb477ab667 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 8 Sep 2018 05:38:43 +0530 Subject: [PATCH 30/39] Rename parser keyword arguments --- camelot/core.py | 16 +++++----- camelot/image_processing.py | 26 ++++++++-------- camelot/parsers/lattice.py | 59 ++++++++++++++++++++----------------- camelot/parsers/stream.py | 36 +++++++++++----------- camelot/utils.py | 12 ++++---- 5 files changed, 77 insertions(+), 72 deletions(-) diff --git a/camelot/core.py b/camelot/core.py index 015c533..e3f9bb3 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -139,14 +139,14 @@ class Table(object): cell.left = cell.right = cell.top = cell.bottom = True return self - def set_edges(self, vertical, horizontal, jtol=2): + def set_edges(self, vertical, horizontal, joint_close_tol=2): """ Parameters ---------- vertical horizontal - jtol + joint_close_tol Returns ------- @@ -156,11 +156,11 @@ class Table(object): # find closest x coord # iterate over y coords and find closest start and end points i = [i for i, t in enumerate(self.cols) - if np.isclose(v[0], t[0], atol=jtol)] + if np.isclose(v[0], t[0], atol=joint_close_tol)] j = [j for j, t in enumerate(self.rows) - if np.isclose(v[3], t[0], atol=jtol)] + if np.isclose(v[3], t[0], atol=joint_close_tol)] k = [k for k, t in enumerate(self.rows) - if np.isclose(v[1], t[0], atol=jtol)] + if np.isclose(v[1], t[0], atol=joint_close_tol)] if not j: continue J = j[0] @@ -207,11 +207,11 @@ class Table(object): # find closest y coord # iterate over x coords and find closest start and end points i = [i for i, t in enumerate(self.rows) - if np.isclose(h[1], t[0], atol=jtol)] + if np.isclose(h[1], t[0], atol=joint_close_tol)] j = [j for j, t in enumerate(self.cols) - if np.isclose(h[0], t[0], atol=jtol)] + if np.isclose(h[0], t[0], atol=joint_close_tol)] k = [k for k, t in enumerate(self.cols) - if np.isclose(h[2], t[0], atol=jtol)] + if np.isclose(h[2], t[0], atol=joint_close_tol)] if not j: continue J = j[0] diff --git a/camelot/image_processing.py b/camelot/image_processing.py index a1526ef..bdd82fb 100644 --- a/camelot/image_processing.py +++ b/camelot/image_processing.py @@ -7,13 +7,13 @@ import numpy as np from .utils import merge_tuples -def adaptive_threshold(imagename, invert=False, blocksize=15, c=-2): +def adaptive_threshold(imagename, process_background=False, blocksize=15, c=-2): """ Parameters ---------- imagename - invert + process_background blocksize c @@ -24,7 +24,7 @@ def adaptive_threshold(imagename, invert=False, blocksize=15, c=-2): img = cv2.imread(imagename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - if invert: + if process_background: threshold = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, blocksize, c) else: @@ -33,14 +33,14 @@ def adaptive_threshold(imagename, invert=False, blocksize=15, c=-2): return img, threshold -def find_lines(threshold, direction='horizontal', scale=15, iterations=0): +def find_lines(threshold, direction='horizontal', line_size_scaling=15, iterations=0): """ Parameters ---------- threshold direction - scale + line_size_scaling iterations Returns @@ -50,10 +50,10 @@ def find_lines(threshold, direction='horizontal', scale=15, iterations=0): lines = [] if direction == 'vertical': - size = threshold.shape[0] // scale + size = threshold.shape[0] // line_size_scaling el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) elif direction == 'horizontal': - size = threshold.shape[1] // scale + size = threshold.shape[1] // line_size_scaling el = cv2.getStructuringElement(cv2.MORPH_RECT, (size, 1)) elif direction is None: raise ValueError("Specify direction as either 'vertical' or" @@ -148,19 +148,19 @@ def find_table_joints(contours, vertical, horizontal): return tables -def remove_lines(threshold, line_scale=15): +def remove_lines(threshold, line_size_scaling=15): """ Parameters ---------- threshold - line_scale + line_size_scaling Returns ------- """ - size = threshold.shape[0] // line_scale + size = threshold.shape[0] // line_size_scaling vertical_erode_el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) horizontal_erode_el = cv2.getStructuringElement(cv2.MORPH_RECT, (size, 1)) dilate_el = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10)) @@ -176,19 +176,19 @@ def remove_lines(threshold, line_scale=15): return threshold -def find_cuts(threshold, char_scale=200): +def find_cuts(threshold, char_size_scaling=200): """ Parameters ---------- threshold - char_scale + char_size_scaling Returns ------- """ - size = threshold.shape[0] // char_scale + size = threshold.shape[0] // char_size_scaling char_el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) threshold = cv2.erode(threshold, char_el) diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index bf4fca3..ba79230 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -10,7 +10,7 @@ import pandas as pd from .base import BaseParser from ..core import Table from ..utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, - merge_close_values, get_table_index, compute_accuracy, + merge_close_lines, get_table_index, compute_accuracy, count_empty_strings, encode_, setup_logging) from ..image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) @@ -23,23 +23,24 @@ class Lattice(BaseParser): """ """ - def __init__(self, table_area=None, fill=None, mtol=2, jtol=2, - blocksize=15, threshold_constant=-2, scale=15, iterations=0, - invert=False, margins=(1.0, 0.5, 0.1), split_text=False, - flag_size=True, shift_text=['l', 't'], debug=None): + def __init__(self, table_area=None, process_background=False, + line_size_scaling=15, copy_text=None, shift_text=['l', 't'], + split_text=False, flag_size=True, line_close_tol=2, + joint_close_tol=2, blocksize=15, threshold_constant=-2, + iterations=0, margins=(1.0, 0.5, 0.1), debug=None): self.table_area = table_area - self.fill = fill - self.mtol = mtol - self.jtol = jtol - self.blocksize = blocksize - self.threshold_constant = threshold_constant - self.scale = scale - self.iterations = iterations - self.invert = invert - self.char_margin, self.line_margin, self.word_margin = margins + self.process_background = process_background + self.line_size_scaling = line_size_scaling + self.copy_text = copy_text + self.shift_text = shift_text self.split_text = split_text self.flag_size = flag_size - self.shift_text = shift_text + self.line_close_tol = line_close_tol + self.joint_close_tol = joint_close_tol + self.blocksize = blocksize + self.threshold_constant = threshold_constant + self.iterations = iterations + self.char_margin, self.line_margin, self.word_margin = margins self.debug = debug @staticmethod @@ -67,8 +68,8 @@ class Lattice(BaseParser): return indices @staticmethod - def _fill_spanning(t, fill=None): - for f in fill: + def _copy_spanning_text(t, copy_text=None): + for f in copy_text: if f == "h": for i in range(len(t.cells)): for j in range(len(t.cells[i])): @@ -96,7 +97,7 @@ class Lattice(BaseParser): stderr=subprocess.STDOUT) def _generate_table_bbox(self): - self.image, self.threshold = adaptive_threshold(self.imagename, invert=self.invert, + self.image, self.threshold = adaptive_threshold(self.imagename, process_background=self.process_background, blocksize=self.blocksize, c=self.threshold_constant) image_width = self.image.shape[1] image_height = self.image.shape[0] @@ -107,10 +108,12 @@ 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', scale=self.scale, iterations=self.iterations) - horizontal_mask, horizontal_segments = find_lines(self.threshold, - direction='horizontal', scale=self.scale, iterations=self.iterations) + 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_area is not None: areas = [] @@ -149,8 +152,10 @@ class Lattice(BaseParser): cols.extend([tk[0], tk[2]]) rows.extend([tk[1], tk[3]]) # sort horizontal and vertical segments - cols = merge_close_values(sorted(cols), mtol=self.mtol) - rows = merge_close_values(sorted(rows, reverse=True), mtol=self.mtol) + cols = merge_close_lines( + sorted(cols), line_close_tol=self.line_close_tol) + rows = merge_close_lines( + sorted(rows, reverse=True), line_close_tol=self.line_close_tol) # make grid using x and y coord of shortlisted rows and cols cols = [(cols[i], cols[i + 1]) for i in range(0, len(cols) - 1)] @@ -167,7 +172,7 @@ class Lattice(BaseParser): table = Table(cols, rows) # set table edges to True using ver+hor lines - table = table.set_edges(v_s, h_s, jtol=self.jtol) + table = table.set_edges(v_s, h_s, joint_close_tol=self.joint_close_tol) # set spanning cells to True table = table.set_span() # set table border edges to True @@ -186,8 +191,8 @@ class Lattice(BaseParser): table.cells[r_idx][c_idx].text = text accuracy = compute_accuracy([[100, pos_errors]]) - if self.fill is not None: - table = Lattice._fill_spanning(table, fill=self.fill) + if self.copy_text is not None: + table = Lattice._copy_spanning_text(table, copy_text=self.copy_text) data = table.data data = encode_(data) diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index 1976505..12f4b6b 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -18,17 +18,17 @@ class Stream(BaseParser): """ """ - def __init__(self, table_area=None, columns=None, ytol=2, mtol=0, - margins=(1.0, 0.5, 0.1), split_text=False, flag_size=True, - debug=None): + def __init__(self, table_area=None, columns=None, split_text=False, + flag_size=True, row_close_tol=2, col_close_tol=0, + margins=(1.0, 0.5, 0.1), debug=None): self.table_area = table_area self.columns = columns self._validate_columns() - self.ytol = ytol - self.mtol = mtol - self.char_margin, self.line_margin, self.word_margin = margins self.split_text = split_text self.flag_size = flag_size + self.row_close_tol = row_close_tol + self.col_close_tol = col_close_tol + self.char_margin, self.line_margin, self.word_margin = margins self.debug = debug @staticmethod @@ -41,7 +41,7 @@ class Stream(BaseParser): return text_bbox @staticmethod - def _group_rows(text, ytol=2): + def _group_rows(text, row_close_tol=2): row_y = 0 rows = [] temp = [] @@ -50,7 +50,7 @@ class Stream(BaseParser): # if t.get_text().strip() and all([obj.upright for obj in t._objs if # type(obj) is LTChar]): if t.get_text().strip(): - if not np.isclose(row_y, t.y0, atol=ytol): + if not np.isclose(row_y, t.y0, atol=row_close_tol): rows.append(sorted(temp, key=lambda t: t.x0)) temp = [] row_y = t.y0 @@ -60,24 +60,24 @@ class Stream(BaseParser): return rows @staticmethod - def _merge_columns(l, mtol=0): + def _merge_columns(l, col_close_tol=0): merged = [] for higher in l: if not merged: merged.append(higher) else: lower = merged[-1] - if mtol >= 0: + if col_close_tol >= 0: if (higher[0] <= lower[1] or - np.isclose(higher[0], lower[1], atol=mtol)): + np.isclose(higher[0], lower[1], atol=col_close_tol)): upper_bound = max(lower[1], higher[1]) lower_bound = min(lower[0], higher[0]) merged[-1] = (lower_bound, upper_bound) else: merged.append(higher) - elif mtol < 0: + elif col_close_tol < 0: if higher[0] <= lower[1]: - if np.isclose(higher[0], lower[1], atol=abs(mtol)): + if np.isclose(higher[0], lower[1], atol=abs(col_close_tol)): merged.append(higher) else: upper_bound = max(lower[1], higher[1]) @@ -99,9 +99,9 @@ class Stream(BaseParser): return rows @staticmethod - def _add_columns(cols, text, ytol): + def _add_columns(cols, text, row_close_tol): if text: - text = Stream._group_rows(text, ytol=ytol) + text = Stream._group_rows(text, row_close_tol=row_close_tol) elements = [len(r) for r in text] new_cols = [(t.x0, t.x1) for r in text if len(r) == max(elements) for t in r] @@ -149,7 +149,7 @@ class Stream(BaseParser): self.t_bbox[direction].sort(key=lambda x: (-x.y0, x.x0)) text_x_min, text_y_min, text_x_max, text_y_max = self._text_bbox(self.t_bbox) - rows_grouped = self._group_rows(self.t_bbox['horizontal'], ytol=self.ytol) + rows_grouped = self._group_rows(self.t_bbox['horizontal'], row_close_tol=self.row_close_tol) rows = self._join_rows(rows_grouped, text_y_max, text_y_min) elements = [len(r) for r in rows_grouped] @@ -170,7 +170,7 @@ class Stream(BaseParser): os.path.basename(self.rootname))) cols = [(t.x0, t.x1) for r in rows_grouped if len(r) == ncols for t in r] - cols = self._merge_columns(sorted(cols), mtol=self.mtol) + cols = self._merge_columns(sorted(cols), col_close_tol=self.col_close_tol) inner_text = [] for i in range(1, len(cols)): left = cols[i - 1][1] @@ -182,7 +182,7 @@ class Stream(BaseParser): for t in self.t_bbox[direction] if t.x0 > cols[-1][1] or t.x1 < cols[0][0]] inner_text.extend(outer_text) - cols = self._add_columns(cols, inner_text, self.ytol) + cols = self._add_columns(cols, inner_text, self.row_close_tol) cols = self._join_columns(cols, text_x_min, text_x_max) return cols, rows diff --git a/camelot/utils.py b/camelot/utils.py index c957a4e..d132b5a 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -236,13 +236,13 @@ def text_in_bbox(bbox, text): return t_bbox -def remove_close_values(ar, mtol=2): +def remove_close_lines(ar, line_close_tol=2): """ Parameters ---------- ar - mtol + line_close_tol Returns ------- @@ -254,20 +254,20 @@ def remove_close_values(ar, mtol=2): ret.append(a) else: temp = ret[-1] - if np.isclose(temp, a, atol=mtol): + if np.isclose(temp, a, atol=line_close_tol): pass else: ret.append(a) return ret -def merge_close_values(ar, mtol=2): +def merge_close_lines(ar, line_close_tol=2): """ Parameters ---------- ar - mtol + line_close_tol Returns ------- @@ -279,7 +279,7 @@ def merge_close_values(ar, mtol=2): ret.append(a) else: temp = ret[-1] - if np.isclose(temp, a, atol=mtol): + if np.isclose(temp, a, atol=line_close_tol): temp = (temp + a) / 2.0 ret[-1] = temp else: From 9d2708171b04722157e8d141fcd31d3c25b867c7 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 8 Sep 2018 05:47:32 +0530 Subject: [PATCH 31/39] Remove old CLI code --- tools/camelot | 508 -------------------------------------------------- 1 file changed, 508 deletions(-) delete mode 100755 tools/camelot diff --git a/tools/camelot b/tools/camelot deleted file mode 100755 index 61a687f..0000000 --- a/tools/camelot +++ /dev/null @@ -1,508 +0,0 @@ -#!/usr/bin/env python2 -from __future__ import print_function -import os -import csv -import sys -import glob -import time -import zipfile -import warnings -import cStringIO - -import numpy as np -from docopt import docopt -from collections import Counter -import matplotlib.pyplot as plt -from PyPDF2 import PdfFileReader - -from camelot.pdf import Pdf -from camelot.lattice import Lattice -from camelot.stream import Stream -from camelot import utils - - -doc = """ -Camelot: PDF parsing made simpler! - -usage: - camelot [options] [...] - -options: - -h, --help Show this screen. - -v, --version Show version. - -p, --pages Comma-separated list of page numbers. - Example: -p 1,3-6,10 [default: 1] - -P, --parallel Parallelize the parsing process. - -f, --format Output format. (csv,tsv,zip,html,json,xlsx) [default: csv] - -l, --log Log to file. - -o, --output Output directory. - -M, --cmargin Char margin. Chars closer than cmargin are - grouped together to form a word. [default: 1.0] - -L, --lmargin Line margin. Lines closer than lmargin are - grouped together to form a textbox. [default: 0.5] - -W, --wmargin Word margin. Insert blank spaces between chars - if distance between words is greater than word - margin. [default: 0.1] - -J, --split_text Split text lines if they span across multiple cells. - -K, --flag_size Flag substring if its size differs from the whole string. - Useful for super and subscripts. - -X, --print-stats List stats on the parsing process. - -Y, --save-stats Save stats to a file. - -Z, --plot Plot distributions. (page,all,rc) - -camelot methods: - lattice Looks for lines between data. - stream Looks for spaces between data. - -See 'camelot -h' for more information on a specific method. -""" - -lattice_doc = """ -Lattice method looks for lines between text to form a table. - -usage: - camelot lattice [-t ...] [-F ...] [-m ...] - [-j ...] [options] [--] - -options: - -t, --tarea Specific table areas to analyze. - -F, --fill Fill data in horizontal and/or vertical spanning - cells. Example: -F h, -F v, -F hv - -m, --mtol Tolerance to account for when merging lines - which are very close. [default: 2] - -j, --jtol Tolerance to account for when matching line endings - with intersections. [default: 2] - -b, --blocksize See adaptive threshold doc. [default: 15] - -C, --constant See adaptive threshold doc. [default: -2] - -s, --scale Scaling factor. Large scaling factor leads to - smaller lines being detected. [default: 15] - -I, --iterations Number of iterations for dilation. [default: 0] - -i, --invert Invert pdf image to make sure that lines are - in foreground. - -T, --shift_text Specify where the text in a spanning cell - should flow, order-sensitive. [default: lt] - -d, --debug Debug by visualizing pdf geometry. - (contour,line,joint,table) Example: -d table -""" - -stream_doc = """ -Stream method looks for whitespaces between text to form a table. - -usage: - camelot stream [-t ...] [-c ...] [-m ...] - [-y ...] [options] [--] - -options: - -t, --tarea Specific table areas to analyze. - -c, --columns Comma-separated list of column x-coordinates. - Example: -c 10.1,20.2,30.3 - -m, --mtol Tolerance to account for when merging columns - together. [default: 0] - -y, --ytol Tolerance to account for when grouping rows - together. [default: 2] - -d, --debug Debug by visualizing textboxes. -""" - - -def plot_table_barchart(r, c, p, pno, tno): - row_idx = [i + 1 for i, row in enumerate(r)] - col_idx = [i + 1 for i, col in enumerate(c)] - r_index = np.arange(len(r)) - c_index = np.arange(len(c)) - width = 0.7 - - plt.figure(figsize=(8, 6)) - plt.subplot(2, 1, 1) - plt.title('Percentage of empty cells in table: {0:.2f}'.format(p)) - plt.xlabel('row index') - plt.ylabel('number of non-empty cells in row') - plt.bar(r_index, r) - plt.xticks(r_index + width * 0.5, row_idx) - plt.ylim(0, len(c)) - - plt.subplot(2, 1, 2) - plt.xlabel('column index') - plt.ylabel('number of non-empty cells in column') - plt.bar(c_index, c) - plt.xticks(c_index + width * 0.5, col_idx) - plt.ylim(0, len(r)) - plt.savefig(''.join([pno, '_', tno, '.png']), dpi=300) - - -def plot_all_barchart(data, output): - r_empty_cells = [] - for page_number in data.keys(): - page = data[page_number] - for table_number in page.keys(): - table = page[table_number] - r_empty_cells.extend([r / float(table['ncols']) for r in table['r_nempty_cells']]) - c = Counter(r_empty_cells) - if 0.0 not in c: - c.update({0.0: 0}) - if 1.0 not in c: - c.update({1.0: 0}) - - plt.figure(figsize=(8, 6)) - plt.xlabel('percentage of non-empty cells in a row') - plt.ylabel('percentage of rows processed') - row_p = [count / float(sum(c.values())) for count in c.values()] - plt.bar(c.keys(), row_p, align='center', width=0.05) - plt.ylim(0, 1.0) - plt.savefig(''.join([output, '_all.png']), dpi=300) - - -def plot_rc_piechart(data, output): - from matplotlib import cm - - tables = 0 - rows, cols = [], [] - for page_number in data.keys(): - page = data[page_number] - for table_number in page.keys(): - table = page[table_number] - tables += 1 - rows.append(table['nrows']) - cols.append(table['ncols']) - - r = Counter(rows) - c = Counter(cols) - - plt.figure(figsize=(8, 6)) - cs1 = cm.Set1(np.arange(len(r)) / float(len(r))) - ax1 = plt.subplot(211, aspect='equal') - ax1.pie(r.values(), colors=cs1, labels=r.keys(), startangle=90) - ax1.set_title('row distribution across tables') - - cs2 = cm.Set1(np.arange(len(c)) / float(len(c))) - ax2 = plt.subplot(212, aspect='equal') - ax2.pie(c.values(), colors=cs2, labels=c.keys(), startangle=90) - ax2.set_title('column distribution across tables') - plt.savefig(''.join([output, '_rc.png']), dpi=300) - - -def print_stats(data, p_time): - from operator import itemgetter - from itertools import groupby - - scores = [] - continuous_tables = [] - total_tables = 0 - for page_number in data.keys(): - page = data[page_number] - total_tables += len(page.keys()) - for table_number in page.keys(): - table = page[table_number] - continuous_tables.append((page_number, table_number, table['ncols'])) - scores.append(table['score']) - avg_score = np.mean(scores) - - ct_pages = [] - header_string = "" - if len(continuous_tables) > 1: - tables = sorted(continuous_tables, key=lambda x: (int(x[0][5:]), int(x[1][6:]))) - for k, g in groupby(tables, key=itemgetter(2)): - g = list(g) - tables_same_ncols = set([int(t[0][5:]) for t in g]) - tables_same_ncols = sorted(list(tables_same_ncols)) - for K, G in groupby(enumerate(tables_same_ncols), key=lambda (i, x): i - x): - G = list(G) - ct_pages.append((str(G[0][1]), str(G[-1][1]))) - - result_headers = [] - for ct in ct_pages: - header_idx = {} - possible_headers = [] - ncols = 0 - for page_number in range(int(ct[0]), int(ct[1]) + 1): - page = data['page-{0}'.format(page_number)] - for table_number in page.keys(): - table = page[table_number] - ncols = table['ncols'] - for i, row in enumerate(table['data']): - try: - header_idx[tuple(row)].append(i) - except KeyError: - header_idx[tuple(row)] = [i] - possible_headers = sorted(header_idx, key=lambda k: len(header_idx[k]), reverse=True)[:10] - possible_headers = filter(lambda z: len(z) == ncols, - [filter(lambda x: x != '', p_h) for p_h in possible_headers]) - modes = [] - for p_h in possible_headers: - try: - modes.append((p_h, max(set(header_idx[p_h]), key=header_idx[p_h].count))) - except KeyError: - pass - header = modes[modes.index(min(modes, key=lambda x: x[1]))][0] - result_headers.append(header) - - header_string = "Multi-page table headers*:\n" - header_string = ''.join([header_string, '\n'.join(['pages {0} -> {1}{2}{3}'.format( - '-'.join([cr[0][0], cr[0][1]]), '"', '","'.join(cr[1]), '"') for cr in zip( - ct_pages, result_headers)])]) - - avg_time = "Time taken per page: {0:.2f} seconds\n".format( - p_time / float(len(data))) if len(data) not in [0, 1] else "" - equal_ncols = "\nMulti-page tables on*: {0}\n".format( - ', '.join(['-'.join(ct) for ct in ct_pages])) if len(data) not in [0, 1] else "" - stats = [len(data), p_time, avg_time, total_tables, avg_score, equal_ncols] - stat_string = ("Pages processed: {0}\nTime taken: {1:.2f} seconds\n" - "{2}Tables found: {3}\nAverage score: {4:.2f}{5}".format(*stats)) - - print(''.join([stat_string, header_string])) - - -def convert_to_html(table): - html = '' - html = ''.join([html, '\n']) - for row in table: - html = ''.join([html, ' \n']) - for data in row: - html = ''.join([html, ' \n']) - html = ''.join([html, ' \n']) - html = ''.join([html, '
', data, '
\n']) - return html - - -def write_to_disk(data, f='csv', output=None, filename=None): - # raise something if filename and/or output are None - fname = os.path.basename(filename) - froot, __ = os.path.splitext(fname) - if f in ['csv', 'tsv']: - delimiter = ',' if f == 'csv' else '\t' - for page_number in sorted(data.keys()): - if data[page_number] is not None: - for table_number in sorted(data[page_number].keys()): - dsvname = '{0}.{1}'.format(''.join([page_number, '_', table_number]), f) - with open(os.path.join(output, dsvname), 'w') as outfile: - writer = csv.writer( - outfile, delimiter=delimiter, quoting=csv.QUOTE_ALL) - for row in data[page_number][table_number]['data']: - writer.writerow(row) - elif f == 'zip': - csv_zip = os.path.join(output, '{0}.zip'.format(froot)) - with zipfile.ZipFile(csv_zip, 'w', zipfile.ZIP_DEFLATED, allowZip64=True) \ - as zfile: - for page_number in sorted(data.keys()): - if data[page_number] is not None: - for table_number in sorted(data[page_number].keys()): - csvname = '{0}.{1}'.format(''.join([page_number, '_', table_number]), 'csv') - outfile = cStringIO.StringIO() - writer = csv.writer( - outfile, delimiter=',', quoting=csv.QUOTE_ALL) - for row in data[page_number][table_number]['data']: - writer.writerow(row) - zfile.writestr(csvname, outfile.getvalue()) - outfile.close() - elif f == 'html': - htmlname = '{0}.html'.format(froot) - for page_number in sorted(data.keys()): - for table_number in sorted(data[page_number].keys()): - with open(os.path.join(output, htmlname), 'a') as htmlfile: - htmlfile.write(convert_to_html(data[page_number][table_number]['data'])) - elif f == 'json': - import json - with open(os.path.join(output, '{0}.json'.format(froot)), 'w') \ - as jsonfile: - json.dump(data, jsonfile) - elif f == 'xlsx': - try: - from pyexcel_xlsx import save_data - from collections import OrderedDict - xlsx_data = OrderedDict() - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - for table_number in sorted(data[page_number].keys(), key=lambda x: int(x[6:])): - sheet_name = ''.join([page_number, '_', table_number]) - xlsx_data.update({sheet_name: - [row for row in data[page_number][table_number]['data']]}) - save_data(os.path.join(output, '{0}.xlsx'.format(froot)), xlsx_data) - except ImportError: - print("link to install docs") - - -if __name__ == '__main__': - start_time = time.time() - - args = docopt(doc, version='0.1', options_first=True) - argv = [args['']] + args[''] - if args[''] == 'lattice': - args.update(docopt(lattice_doc, argv=argv)) - elif args[''] == 'stream': - args.update(docopt(stream_doc, argv=argv)) - - filename = args[''] - filedir = os.path.dirname(args['']) - logname, __ = os.path.splitext(filename) - logname = ''.join([logname, '.log']) - scorename, __ = os.path.splitext(filename) - scorename = ''.join([scorename, '_info.csv']) - pngname, __ = os.path.splitext(filename) - - FORMAT = '%(asctime)s - %(levelname)s - %(message)s' - if args['--log'] is not None: - logger = utils.setup_logging(args['--log']) - else: - logger = utils.setup_logging(os.path.join(os.getcwd(), 'camelot.log')) - - p = [] - if args['--pages'] == '1': - p.append({'start': 1, 'end': 1}) - else: - infile = PdfFileReader(open(filename, 'rb'), strict=False) - if args['--pages'] == 'all': - p.append({'start': 1, 'end': infile.getNumPages()}) - else: - for r in args['--pages'].split(','): - if '-' in r: - a, b = r.split('-') - if b == 'end': - b = infile.getNumPages() - p.append({'start': int(a), 'end': int(b)}) - else: - p.append({'start': int(r), 'end': int(r)}) - - logger.info('Applying {0} method on {1}'.format(args[''], - os.path.basename(filename))) - margins = (float(args['--cmargin']), float(args['--lmargin']), - float(args['--wmargin'])) - if args[''] == 'lattice': - try: - kwargs = { - 'table_area': args['--tarea'] if args['--tarea'] else None, - 'fill': args['--fill'] if args['--fill'] else None, - 'mtol': [int(m) for m in args['--mtol']], - 'jtol': [int(j) for j in args['--jtol']], - 'blocksize': int(args['--blocksize']), - 'threshold_constant': float(args['--constant']), - 'scale': int(args['--scale']), - 'iterations': int(args['--iterations']), - 'invert': args['--invert'], - 'margins': margins, - 'split_text': args['--split_text'], - 'flag_size': args['--flag_size'], - 'shift_text': list(args['--shift_text']) if args['--shift_text'] else ['l', 't'], - 'debug': args['--debug'] - } - manager = Pdf(Lattice(**kwargs), filename, pagenos=p, clean=True, - parallel=args['--parallel']) - data = manager.extract() - - processing_time = time.time() - start_time - logger.info("Finished processing in " + str(processing_time) + " seconds") - - if args['--plot']: - if args['--output']: - pngname = os.path.join(args['--output'], os.path.basename(pngname)) - plot_type = args['--plot'].split(',') - if 'page' in plot_type: - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - plot_table_barchart(table['r_nempty_cells'], - table['c_nempty_cells'], - table['empty_p'], - page_number, - table_number) - - if 'all' in plot_type: - plot_all_barchart(data, pngname) - - if 'rc' in plot_type: - plot_rc_piechart(data, pngname) - - if args['--print-stats']: - print_stats(data, processing_time) - - if args['--save-stats']: - if args['--output']: - scorename = os.path.join(args['--output'], os.path.basename(scorename)) - with open(scorename, 'w') as score_file: - score_file.write('table,nrows,ncols,empty_p,line_p,text_p,score\n') - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - score_file.write('{0},{1},{2},{3},{4},{5},{6}\n'.format( - ''.join([page_number, '_', table_number]), - table['nrows'], - table['ncols'], - table['empty_p'], - table['line_p'], - table['text_p'], - table['score'])) - if args['--debug']: - manager.debug_plot() - except Exception as e: - logger.exception(e.message, exc_info=True) - sys.exit() - elif args[''] == 'stream': - try: - kwargs = { - 'table_area': args['--tarea'] if args['--tarea'] else None, - 'columns': args['--columns'] if args['--columns'] else None, - 'ytol': [int(y) for y in args['--ytol']], - 'mtol': [int(m) for m in args['--mtol']], - 'margins': margins, - 'split_text': args['--split_text'], - 'flag_size': args['--flag_size'], - 'debug': args['--debug'] - } - manager = Pdf(Stream(**kwargs), filename, pagenos=p, clean=True, - parallel=args['--parallel']) - data = manager.extract() - - processing_time = time.time() - start_time - logger.info("Finished processing in " + str(processing_time) + " seconds") - - if args['--plot']: - if args['--output']: - pngname = os.path.join(args['--output'], os.path.basename(pngname)) - plot_type = args['--plot'].split(',') - if 'page' in plot_type: - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - plot_table_barchart(table['r_nempty_cells'], - table['c_nempty_cells'], - table['empty_p'], - page_number, - table_number) - - if 'all' in plot_type: - plot_all_barchart(data, pngname) - - if 'rc' in plot_type: - plot_rc_piechart(data, pngname) - - if args['--print-stats']: - print_stats(data, processing_time) - - if args['--save-stats']: - if args['--output']: - scorename = os.path.join(args['--output'], os.path.basename(scorename)) - with open(scorename, 'w') as score_file: - score_file.write('table,nrows,ncols,empty_p,,score\n') - for page_number in sorted(data.keys(), key=lambda x: int(x[5:])): - page = data[page_number] - for table_number in sorted(page.keys(), key=lambda x: int(x[6:])): - table = page[table_number] - score_file.write('{0},{1},{2},{3},{4}\n'.format( - ''.join([page_number, '_', table_number]), - table['nrows'], - table['ncols'], - table['empty_p'], - table['score'])) - - if args['--debug']: - manager.debug_plot() - except Exception as e: - logger.exception(e.message, exc_info=True) - sys.exit() - - if args.get('--debug') is not None and args['--debug']: - print("See 'camelot -h' for various parameters you can tweak.") - else: - output = filedir if args['--output'] is None else args['--output'] - write_to_disk(data, f=args['--format'], - output=output, filename=filename) From e0b55f06931383431938b0900bb78a6568a66769 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 8 Sep 2018 18:38:59 +0530 Subject: [PATCH 32/39] Remove examples and debug, restructure tests dir --- debug/hough_opencv.py | 53 ------ debug/hough_skimage.py | 75 -------- debug/houghp_skimage.py | 49 ----- debug/morph_transform.py | 114 ------------ debug/plot_geo.py | 167 ------------------ debug/plot_intensity.py | 69 -------- debug/print_text.py | 83 --------- debug/threshold.py | 41 ----- examples/demo_lattice.py | 11 -- examples/demo_lattice_fill.py | 13 -- examples/demo_lattice_invert.py | 13 -- examples/demo_lattice_rotation.py | 11 -- examples/demo_lattice_twotables.py | 11 -- examples/demo_stream.py | 8 - examples/demo_stream_columns.py | 13 -- examples/files/consistent_rows.pdf | Bin 184194 -> 0 bytes examples/files/inconsistent_rows.pdf | Bin 45085 -> 0 bytes examples/files/left_rotated_table.pdf | Bin 16638 -> 0 bytes examples/files/right_rotated_table.pdf | Bin 17035 -> 0 bytes tests/budget_2014-15.pdf | Bin 338830 -> 0 bytes tests/column_span_1.pdf | Bin 15014 -> 0 bytes tests/column_span_2.pdf | Bin 24313 -> 0 bytes tests/{ => files}/agstat.pdf | Bin tests/{ => files}/assam.pdf | 0 {examples => tests}/files/budget_2014-15.pdf | Bin {examples => tests}/files/column_span_1.pdf | Bin {examples => tests}/files/column_span_2.pdf | Bin tests/{ => files}/district_health.pdf | Bin tests/{ => files}/electoral_roll.pdf | Bin tests/{ => files}/health.pdf | Bin tests/{ => files}/left_rotated_table_1.pdf | Bin tests/{ => files}/left_rotated_table_2.pdf | Bin .../files/lines_in_background_1.pdf | Bin .../files/lines_in_background_2.pdf | Bin tests/{ => files}/medicine.pdf | Bin tests/{ => files}/mexican_towns.pdf | Bin {examples => tests}/files/missing_values.pdf | Bin tests/{ => files}/population_growth.pdf | Bin tests/{ => files}/rainfall_distribution.pdf | Bin tests/{ => files}/right_rotated_table_1.pdf | Bin tests/{ => files}/right_rotated_table_2.pdf | Bin {examples => tests}/files/row_span_1.pdf | Bin {examples => tests}/files/row_span_2.pdf | Bin tests/{ => files}/row_span_3.pdf | Bin tests/{ => files}/tableception.pdf | Bin .../tabula}/12s0324.pdf | Bin .../{tabula_test_pdfs => files/tabula}/20.pdf | Bin .../tabula}/S2MNCEbirdisland.pdf | Bin .../tabula}/arabic.pdf | Bin .../argentina_diputados_voting_record.pdf | Bin .../tabula}/campaign_donors.pdf | Bin .../tabula}/china.pdf | Bin .../tabula}/eu-002.pdf | Bin .../tabula}/eu-017.pdf | Bin .../tabula}/failing_sort.pdf | Bin .../tabula}/frx_2012_disclosure.pdf | Bin .../competition-dataset-eu/eu-001-reg.xml | 0 .../competition-dataset-eu/eu-001-str.xml | 0 .../competition-dataset-eu/eu-001.json | 0 .../competition-dataset-eu/eu-001.pdf | Bin .../competition-dataset-eu/eu-002-reg.xml | 0 .../competition-dataset-eu/eu-002-str.xml | 0 .../competition-dataset-eu/eu-002.json | 0 .../competition-dataset-eu/eu-002.pdf | Bin .../competition-dataset-eu/eu-003-reg.xml | 0 .../competition-dataset-eu/eu-003-str.xml | 0 .../competition-dataset-eu/eu-003.json | 0 .../competition-dataset-eu/eu-003.pdf | Bin .../competition-dataset-eu/eu-004-reg.xml | 0 .../competition-dataset-eu/eu-004-str.xml | 0 .../competition-dataset-eu/eu-004.json | 0 .../competition-dataset-eu/eu-004.pdf | Bin .../competition-dataset-eu/eu-005-reg.xml | 0 .../competition-dataset-eu/eu-005-str.xml | 0 .../competition-dataset-eu/eu-005.json | 0 .../competition-dataset-eu/eu-005.pdf | Bin .../competition-dataset-eu/eu-006-reg.xml | 0 .../competition-dataset-eu/eu-006-str.xml | 0 .../competition-dataset-eu/eu-006.json | 0 .../competition-dataset-eu/eu-006.pdf | Bin .../competition-dataset-eu/eu-007-reg.xml | 0 .../competition-dataset-eu/eu-007-str.xml | 0 .../competition-dataset-eu/eu-007.json | 0 .../competition-dataset-eu/eu-007.pdf | Bin .../competition-dataset-eu/eu-008-reg.xml | 0 .../competition-dataset-eu/eu-008-str.xml | 0 .../competition-dataset-eu/eu-008.json | 0 .../competition-dataset-eu/eu-008.pdf | Bin .../competition-dataset-eu/eu-009a-reg.xml | 0 .../competition-dataset-eu/eu-009a-str.xml | 0 .../competition-dataset-eu/eu-009a.json | 0 .../competition-dataset-eu/eu-009a.pdf | Bin .../competition-dataset-eu/eu-009b-reg.xml | 0 .../competition-dataset-eu/eu-009b-str.xml | 0 .../competition-dataset-eu/eu-010-reg.xml | 0 .../competition-dataset-eu/eu-010-str.xml | 0 .../competition-dataset-eu/eu-010.json | 0 .../competition-dataset-eu/eu-010.pdf | Bin .../competition-dataset-eu/eu-011-reg.xml | 0 .../competition-dataset-eu/eu-011-str.xml | 0 .../competition-dataset-eu/eu-011.json | 0 .../competition-dataset-eu/eu-011.pdf | Bin .../competition-dataset-eu/eu-012-reg.xml | 0 .../competition-dataset-eu/eu-012-str.xml | 0 .../competition-dataset-eu/eu-012.json | 0 .../competition-dataset-eu/eu-012.pdf | Bin .../competition-dataset-eu/eu-013-reg.xml | 0 .../competition-dataset-eu/eu-013-str.xml | 0 .../competition-dataset-eu/eu-013.json | 0 .../competition-dataset-eu/eu-013.pdf | Bin .../competition-dataset-eu/eu-014-reg.xml | 0 .../competition-dataset-eu/eu-014-str.xml | 0 .../competition-dataset-eu/eu-014.json | 0 .../competition-dataset-eu/eu-014.pdf | Bin .../competition-dataset-eu/eu-015-reg.xml | 0 .../competition-dataset-eu/eu-015-str.xml | 0 .../competition-dataset-eu/eu-015.json | 0 .../competition-dataset-eu/eu-015.pdf | Bin .../competition-dataset-eu/eu-016-reg.xml | 0 .../competition-dataset-eu/eu-016-str.xml | 0 .../competition-dataset-eu/eu-016.json | 0 .../competition-dataset-eu/eu-016.pdf | 0 .../competition-dataset-eu/eu-017-reg.xml | 0 .../competition-dataset-eu/eu-017-str.xml | 0 .../competition-dataset-eu/eu-017.json | 0 .../competition-dataset-eu/eu-017.pdf | 0 .../competition-dataset-eu/eu-018-reg.xml | 0 .../competition-dataset-eu/eu-018-str.xml | 0 .../competition-dataset-eu/eu-018.json | 0 .../competition-dataset-eu/eu-018.pdf | Bin .../competition-dataset-eu/eu-019-reg.xml | 0 .../competition-dataset-eu/eu-019-str.xml | 0 .../competition-dataset-eu/eu-019.json | 0 .../competition-dataset-eu/eu-019.pdf | 0 .../competition-dataset-eu/eu-020-reg.xml | 0 .../competition-dataset-eu/eu-020-str.xml | 0 .../competition-dataset-eu/eu-020.json | 0 .../competition-dataset-eu/eu-020.pdf | Bin .../competition-dataset-eu/eu-021-reg.xml | 0 .../competition-dataset-eu/eu-021-str.xml | 0 .../competition-dataset-eu/eu-021.json | 0 .../competition-dataset-eu/eu-021.pdf | Bin .../competition-dataset-eu/eu-022-reg.xml | 0 .../competition-dataset-eu/eu-022-str.xml | 0 .../competition-dataset-eu/eu-022.json | 0 .../competition-dataset-eu/eu-022.pdf | Bin .../competition-dataset-eu/eu-023-reg.xml | 0 .../competition-dataset-eu/eu-023-str.xml | 0 .../competition-dataset-eu/eu-023.json | 0 .../competition-dataset-eu/eu-023.pdf | Bin .../competition-dataset-eu/eu-024-reg.xml | 0 .../competition-dataset-eu/eu-024-str.xml | 0 .../competition-dataset-eu/eu-024.json | 0 .../competition-dataset-eu/eu-024.pdf | Bin .../competition-dataset-eu/eu-025-reg.xml | 0 .../competition-dataset-eu/eu-025-str.xml | 0 .../competition-dataset-eu/eu-025.json | 0 .../competition-dataset-eu/eu-025.pdf | Bin .../competition-dataset-eu/eu-026-reg.xml | 0 .../competition-dataset-eu/eu-026-str.xml | 0 .../competition-dataset-eu/eu-026.json | 0 .../competition-dataset-eu/eu-026.pdf | Bin .../competition-dataset-eu/eu-027-reg.xml | 0 .../competition-dataset-eu/eu-027-str.xml | 0 .../competition-dataset-eu/eu-027.json | 0 .../competition-dataset-eu/eu-027.pdf | Bin .../competition-dataset-us/us-001-reg.xml | 0 .../competition-dataset-us/us-001-str.xml | 0 .../competition-dataset-us/us-001.json | 0 .../competition-dataset-us/us-001.pdf | Bin .../competition-dataset-us/us-002-reg.xml | 0 .../competition-dataset-us/us-002-str.xml | 0 .../competition-dataset-us/us-002.json | 0 .../competition-dataset-us/us-002.pdf | Bin .../competition-dataset-us/us-003-reg.xml | 0 .../competition-dataset-us/us-003-str.xml | 0 .../competition-dataset-us/us-003.json | 0 .../competition-dataset-us/us-003.pdf | Bin .../competition-dataset-us/us-004-reg.xml | 0 .../competition-dataset-us/us-004-str.xml | 0 .../competition-dataset-us/us-004.json | 0 .../competition-dataset-us/us-004.pdf | Bin .../competition-dataset-us/us-005-reg.xml | 0 .../competition-dataset-us/us-005-str.xml | 0 .../competition-dataset-us/us-005.json | 0 .../competition-dataset-us/us-005.pdf | Bin .../competition-dataset-us/us-006-reg.xml | 0 .../competition-dataset-us/us-006-str.xml | 0 .../competition-dataset-us/us-006.json | 0 .../competition-dataset-us/us-006.pdf | Bin .../competition-dataset-us/us-007-reg.xml | 0 .../competition-dataset-us/us-007-str.xml | 0 .../competition-dataset-us/us-007.json | 0 .../competition-dataset-us/us-007.pdf | Bin .../competition-dataset-us/us-008-reg.xml | 0 .../competition-dataset-us/us-008-str.xml | 0 .../competition-dataset-us/us-008.json | 0 .../competition-dataset-us/us-008.pdf | Bin .../competition-dataset-us/us-009-reg.xml | 0 .../competition-dataset-us/us-009-str.xml | 0 .../competition-dataset-us/us-009.json | 0 .../competition-dataset-us/us-009.pdf | Bin .../competition-dataset-us/us-010-reg.xml | 0 .../competition-dataset-us/us-010-str.xml | 0 .../competition-dataset-us/us-010.json | 0 .../competition-dataset-us/us-010.pdf | Bin .../competition-dataset-us/us-011a-reg.xml | 0 .../competition-dataset-us/us-011a-str.xml | 0 .../competition-dataset-us/us-011a.json | 0 .../competition-dataset-us/us-011a.pdf | Bin .../competition-dataset-us/us-011b-reg.xml | 0 .../competition-dataset-us/us-011b-str.xml | 0 .../competition-dataset-us/us-012-reg.xml | 0 .../competition-dataset-us/us-012-str.xml | 0 .../competition-dataset-us/us-012.json | 0 .../competition-dataset-us/us-012.pdf | Bin .../competition-dataset-us/us-013-reg.xml | 0 .../competition-dataset-us/us-013-str.xml | 0 .../competition-dataset-us/us-013.json | 0 .../competition-dataset-us/us-013.pdf | Bin .../competition-dataset-us/us-014-reg.xml | 0 .../competition-dataset-us/us-014-str.xml | 0 .../competition-dataset-us/us-014.json | 0 .../competition-dataset-us/us-014.pdf | Bin .../competition-dataset-us/us-015-reg.xml | 0 .../competition-dataset-us/us-015-str.xml | 0 .../competition-dataset-us/us-015.json | 0 .../competition-dataset-us/us-015.pdf | Bin .../competition-dataset-us/us-016-reg.xml | 0 .../competition-dataset-us/us-016-str.xml | 0 .../competition-dataset-us/us-016.json | 0 .../competition-dataset-us/us-016.pdf | Bin .../competition-dataset-us/us-017-reg.xml | 0 .../competition-dataset-us/us-017-str.xml | 0 .../competition-dataset-us/us-017.json | 0 .../competition-dataset-us/us-017.pdf | Bin .../competition-dataset-us/us-018-reg.xml | 0 .../competition-dataset-us/us-018-str.xml | 0 .../competition-dataset-us/us-018.json | 0 .../competition-dataset-us/us-018.pdf | Bin .../competition-dataset-us/us-019-reg.xml | 0 .../competition-dataset-us/us-019-str.xml | 0 .../competition-dataset-us/us-019.json | 0 .../competition-dataset-us/us-019.pdf | Bin .../competition-dataset-us/us-020-reg.xml | 0 .../competition-dataset-us/us-020-str.xml | 0 .../competition-dataset-us/us-020.json | 0 .../competition-dataset-us/us-020.pdf | Bin .../competition-dataset-us/us-021-reg.xml | 0 .../competition-dataset-us/us-021-str.xml | 0 .../competition-dataset-us/us-021.json | 0 .../competition-dataset-us/us-021.pdf | Bin .../competition-dataset-us/us-022-reg.xml | 0 .../competition-dataset-us/us-022-str.xml | 0 .../competition-dataset-us/us-022.json | 0 .../competition-dataset-us/us-022.pdf | Bin .../competition-dataset-us/us-023-reg.xml | 0 .../competition-dataset-us/us-023-str.xml | 0 .../competition-dataset-us/us-023.json | 0 .../competition-dataset-us/us-023.pdf | Bin .../competition-dataset-us/us-024-reg.xml | 0 .../competition-dataset-us/us-024-str.xml | 0 .../competition-dataset-us/us-024.json | 0 .../competition-dataset-us/us-024.pdf | Bin .../competition-dataset-us/us-025-reg.xml | 0 .../competition-dataset-us/us-025-str.xml | 0 .../competition-dataset-us/us-025.json | 0 .../competition-dataset-us/us-025.pdf | Bin .../competition-dataset-us/us-026-reg.xml | 0 .../competition-dataset-us/us-026-str.xml | 0 .../competition-dataset-us/us-026.json | 0 .../competition-dataset-us/us-026.pdf | Bin .../competition-dataset-us/us-027-reg.xml | 0 .../competition-dataset-us/us-027-str.xml | 0 .../competition-dataset-us/us-027.json | 0 .../competition-dataset-us/us-027.pdf | Bin .../competition-dataset-us/us-028-reg.xml | 0 .../competition-dataset-us/us-028-str.xml | 0 .../competition-dataset-us/us-028.json | 0 .../competition-dataset-us/us-028.pdf | Bin .../competition-dataset-us/us-029-reg.xml | 0 .../competition-dataset-us/us-029-str.xml | 0 .../competition-dataset-us/us-029.json | 0 .../competition-dataset-us/us-029.pdf | Bin .../competition-dataset-us/us-030-reg.xml | 0 .../competition-dataset-us/us-030-str.xml | 0 .../competition-dataset-us/us-030.json | 0 .../competition-dataset-us/us-030.pdf | Bin .../competition-dataset-us/us-031a-reg.xml | 0 .../competition-dataset-us/us-031a-str.xml | 0 .../competition-dataset-us/us-031a.json | 0 .../competition-dataset-us/us-031a.pdf | Bin .../competition-dataset-us/us-031b-reg.xml | 0 .../competition-dataset-us/us-031b-str.xml | 0 .../competition-dataset-us/us-032-reg.xml | 0 .../competition-dataset-us/us-032-str.xml | 0 .../competition-dataset-us/us-032.json | 0 .../competition-dataset-us/us-032.pdf | Bin .../competition-dataset-us/us-033-reg.xml | 0 .../competition-dataset-us/us-033-str.xml | 0 .../competition-dataset-us/us-033.json | 0 .../competition-dataset-us/us-033.pdf | Bin .../competition-dataset-us/us-034-reg.xml | 0 .../competition-dataset-us/us-034-str.xml | 0 .../competition-dataset-us/us-034.json | 0 .../competition-dataset-us/us-034.pdf | Bin .../competition-dataset-us/us-035a-reg.xml | 0 .../competition-dataset-us/us-035a-str.xml | 0 .../competition-dataset-us/us-035a.json | 0 .../competition-dataset-us/us-035a.pdf | Bin .../competition-dataset-us/us-035b-reg.xml | 0 .../competition-dataset-us/us-035b-str.xml | 0 .../competition-dataset-us/us-036-reg.xml | 0 .../competition-dataset-us/us-036-str.xml | 0 .../competition-dataset-us/us-036.json | 0 .../competition-dataset-us/us-036.pdf | Bin .../competition-dataset-us/us-037-reg.xml | 0 .../competition-dataset-us/us-037-str.xml | 0 .../competition-dataset-us/us-037.json | 0 .../competition-dataset-us/us-037.pdf | Bin .../competition-dataset-us/us-038-reg.xml | 0 .../competition-dataset-us/us-038-str.xml | 0 .../competition-dataset-us/us-038.json | 0 .../competition-dataset-us/us-038.pdf | Bin .../competition-dataset-us/us-039-reg.xml | 0 .../competition-dataset-us/us-039-str.xml | 0 .../competition-dataset-us/us-039.json | 0 .../competition-dataset-us/us-039.pdf | Bin .../competition-dataset-us/us-040-reg.xml | 0 .../competition-dataset-us/us-040-str.xml | 0 .../competition-dataset-us/us-040.json | 0 .../competition-dataset-us/us-040.pdf | Bin .../tabula}/indictb1h_14.pdf | Bin .../tabula}/labor.pdf | Bin .../tabula}/m27.pdf | Bin .../tabula}/mednine.pdf | Bin .../tabula}/offense.pdf | Bin .../tabula}/puertos1.pdf | Bin .../tabula}/rotated_page.pdf | Bin .../tabula}/schools.pdf | Bin .../tabula}/should_detect_rulings.pdf | Bin .../tabula}/sort_exception.pdf | Bin .../tabula}/spanning_cells.pdf | Bin .../tabula}/spreadsheet_no_bounding_frame.pdf | Bin .../tabula}/sydney_disclosure_contract.pdf | Bin .../tabula}/twotables.pdf | Bin .../tabula}/us-007.pdf | Bin .../tabula}/us-017.pdf | Bin .../tabula}/us-024.pdf | Bin {examples => tests}/files/twotables_1.pdf | Bin {examples => tests}/files/twotables_2.pdf | Bin tests/lines_in_background_1.pdf | Bin 85183 -> 0 bytes tests/lines_in_background_2.pdf | Bin 40680 -> 0 bytes tests/missing_values.pdf | Bin 47537 -> 0 bytes tests/row_span_1.pdf | Bin 33228 -> 0 bytes tests/row_span_2.pdf | Bin 15301 -> 0 bytes tests/twotables_1.pdf | Bin 14445 -> 0 bytes tests/twotables_2.pdf | Bin 23667 -> 0 bytes 358 files changed, 731 deletions(-) delete mode 100644 debug/hough_opencv.py delete mode 100644 debug/hough_skimage.py delete mode 100644 debug/houghp_skimage.py delete mode 100644 debug/morph_transform.py delete mode 100644 debug/plot_geo.py delete mode 100644 debug/plot_intensity.py delete mode 100644 debug/print_text.py delete mode 100644 debug/threshold.py delete mode 100644 examples/demo_lattice.py delete mode 100644 examples/demo_lattice_fill.py delete mode 100644 examples/demo_lattice_invert.py delete mode 100644 examples/demo_lattice_rotation.py delete mode 100644 examples/demo_lattice_twotables.py delete mode 100644 examples/demo_stream.py delete mode 100644 examples/demo_stream_columns.py delete mode 100644 examples/files/consistent_rows.pdf delete mode 100644 examples/files/inconsistent_rows.pdf delete mode 100644 examples/files/left_rotated_table.pdf delete mode 100644 examples/files/right_rotated_table.pdf delete mode 100644 tests/budget_2014-15.pdf delete mode 100644 tests/column_span_1.pdf delete mode 100644 tests/column_span_2.pdf rename tests/{ => files}/agstat.pdf (100%) rename tests/{ => files}/assam.pdf (100%) rename {examples => tests}/files/budget_2014-15.pdf (100%) rename {examples => tests}/files/column_span_1.pdf (100%) rename {examples => tests}/files/column_span_2.pdf (100%) rename tests/{ => files}/district_health.pdf (100%) rename tests/{ => files}/electoral_roll.pdf (100%) rename tests/{ => files}/health.pdf (100%) rename tests/{ => files}/left_rotated_table_1.pdf (100%) rename tests/{ => files}/left_rotated_table_2.pdf (100%) rename {examples => tests}/files/lines_in_background_1.pdf (100%) rename {examples => tests}/files/lines_in_background_2.pdf (100%) rename tests/{ => files}/medicine.pdf (100%) rename tests/{ => files}/mexican_towns.pdf (100%) rename {examples => tests}/files/missing_values.pdf (100%) rename tests/{ => files}/population_growth.pdf (100%) rename tests/{ => files}/rainfall_distribution.pdf (100%) rename tests/{ => files}/right_rotated_table_1.pdf (100%) rename tests/{ => files}/right_rotated_table_2.pdf (100%) rename {examples => tests}/files/row_span_1.pdf (100%) rename {examples => tests}/files/row_span_2.pdf (100%) rename tests/{ => files}/row_span_3.pdf (100%) rename tests/{ => files}/tableception.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/12s0324.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/20.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/S2MNCEbirdisland.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/arabic.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/argentina_diputados_voting_record.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/campaign_donors.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/china.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/eu-002.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/eu-017.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/failing_sort.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/frx_2012_disclosure.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-001-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-001-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-001.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-001.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-002-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-002-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-002.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-002.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-003-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-003-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-003.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-003.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-004-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-004-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-004.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-004.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-005-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-005-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-005.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-005.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-006-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-006-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-006.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-006.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-007-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-007-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-007.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-007.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-008-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-008-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-008.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-008.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-009a-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-009a-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-009a.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-009a.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-009b-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-009b-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-010-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-010-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-010.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-010.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-011-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-011-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-011.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-011.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-012-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-012-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-012.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-012.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-013-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-013-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-013.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-013.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-014-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-014-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-014.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-014.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-015-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-015-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-015.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-015.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-016-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-016-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-016.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-016.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-017-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-017-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-017.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-017.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-018-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-018-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-018.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-018.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-019-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-019-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-019.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-019.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-020-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-020-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-020.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-020.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-021-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-021-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-021.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-021.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-022-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-022-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-022.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-022.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-023-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-023-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-023.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-023.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-024-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-024-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-024.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-024.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-025-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-025-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-025.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-025.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-026-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-026-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-026.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-026.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-027-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-027-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-027.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-eu/eu-027.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-001-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-001-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-001.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-001.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-002-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-002-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-002.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-002.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-003-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-003-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-003.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-003.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-004-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-004-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-004.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-004.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-005-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-005-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-005.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-005.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-006-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-006-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-006.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-006.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-007-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-007-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-007.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-007.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-008-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-008-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-008.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-008.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-009-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-009-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-009.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-009.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-010-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-010-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-010.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-010.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-011a-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-011a-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-011a.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-011a.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-011b-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-011b-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-012-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-012-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-012.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-012.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-013-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-013-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-013.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-013.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-014-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-014-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-014.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-014.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-015-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-015-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-015.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-015.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-016-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-016-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-016.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-016.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-017-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-017-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-017.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-017.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-018-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-018-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-018.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-018.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-019-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-019-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-019.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-019.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-020-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-020-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-020.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-020.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-021-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-021-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-021.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-021.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-022-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-022-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-022.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-022.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-023-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-023-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-023.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-023.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-024-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-024-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-024.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-024.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-025-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-025-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-025.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-025.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-026-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-026-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-026.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-026.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-027-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-027-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-027.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-027.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-028-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-028-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-028.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-028.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-029-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-029-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-029.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-029.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-030-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-030-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-030.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-030.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-031a-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-031a-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-031a.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-031a.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-031b-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-031b-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-032-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-032-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-032.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-032.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-033-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-033-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-033.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-033.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-034-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-034-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-034.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-034.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-035a-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-035a-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-035a.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-035a.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-035b-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-035b-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-036-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-036-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-036.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-036.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-037-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-037-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-037.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-037.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-038-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-038-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-038.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-038.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-039-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-039-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-039.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-039.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-040-reg.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-040-str.xml (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-040.json (100%) rename tests/{tabula_test_pdfs => files/tabula}/icdar2013-dataset/competition-dataset-us/us-040.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/indictb1h_14.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/labor.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/m27.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/mednine.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/offense.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/puertos1.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/rotated_page.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/schools.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/should_detect_rulings.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/sort_exception.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/spanning_cells.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/spreadsheet_no_bounding_frame.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/sydney_disclosure_contract.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/twotables.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/us-007.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/us-017.pdf (100%) rename tests/{tabula_test_pdfs => files/tabula}/us-024.pdf (100%) rename {examples => tests}/files/twotables_1.pdf (100%) rename {examples => tests}/files/twotables_2.pdf (100%) delete mode 100644 tests/lines_in_background_1.pdf delete mode 100644 tests/lines_in_background_2.pdf delete mode 100644 tests/missing_values.pdf delete mode 100644 tests/row_span_1.pdf delete mode 100644 tests/row_span_2.pdf delete mode 100644 tests/twotables_1.pdf delete mode 100644 tests/twotables_2.pdf diff --git a/debug/hough_opencv.py b/debug/hough_opencv.py deleted file mode 100644 index 79140f8..0000000 --- a/debug/hough_opencv.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -usage: python hough_opencv.py file.png - -finds lines present in an image using opencv's hough transform. -""" - -import sys -import time - -import cv2 -import numpy as np -import matplotlib.pyplot as plt - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -@timeit -def main(): - image = cv2.imread(sys.argv[1]) - print "image dimensions -> {0}".format(image.shape) - gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) - edges = cv2.Canny(gray, 50, 150, apertureSize=3) - - lines = cv2.HoughLines(edges, 1, np.pi / 180, 200) - print "found {0} lines".format(len(lines)) - for line in lines: - r, theta = line[0] - # filter horizontal and vertical lines - if theta == 0 or np.isclose(theta, np.pi / 2): - x0 = r * np.cos(theta) - y0 = r * np.sin(theta) - x1 = int(x0 + 10000 * (-np.sin(theta))) - y1 = int(y0 + 10000 * (np.cos(theta))) - x2 = int(x0 - 10000 * (-np.sin(theta))) - y2 = int(y0 - 10000 * (np.cos(theta))) - cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 5) - plt.imshow(image) - plt.show() - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() \ No newline at end of file diff --git a/debug/hough_skimage.py b/debug/hough_skimage.py deleted file mode 100644 index 93012fc..0000000 --- a/debug/hough_skimage.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -usage: python hough_skimage.py file.png - -finds lines present in an image using scikit-image's hough transform. -""" - -import sys -import time - -import cv2 -import numpy as np -from scipy.misc import imread -import matplotlib.pyplot as plt -from skimage.transform import hough_line, hough_line_peaks - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -@timeit -def main(): - image = cv2.imread(sys.argv[1]) - print "image dimensions -> {0}".format(image.shape) - ret, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY) - binary = np.min(binary, axis=2) - binary = np.where(binary == 255, 0, 255) - rows, cols = binary.shape - pixel = np.zeros(binary.shape) - - fig, ax = plt.subplots(1, 1, figsize=(8,4)) - ax.imshow(image, cmap=plt.cm.gray) - - theta_in = np.linspace(0, np.pi / 2, 10) - h, theta, d = hough_line(binary, theta_in) - for _, angle, dist in zip(*hough_line_peaks(h, theta, d)): - x0 = dist * np.cos(angle) - y0 = dist * np.sin(angle) - x1 = int(x0 + 1000 * (-np.sin(angle))) - y1 = int(y0 + 1000 * (np.cos(angle))) - x2 = int(x0 - 1000 * (-np.sin(angle))) - y2 = int(y0 - 1000 * (np.cos(angle))) - ax.plot((x1, x2), (y1, y2), '-r') - a = np.cos(angle) - b = np.sin(angle) - x = np.arange(binary.shape[1]) - y = np.arange(binary.shape[0]) - x = a * x - y = b * y - R = np.round(np.add(y.reshape((binary.shape[0], 1)), x.reshape((1, binary.shape[1])))) - pixel += np.isclose(R, np.round(dist)) - - pixel = np.clip(pixel, 0, 1) - pixel = np.where(pixel == 1, 0, 1) - binary = np.where(binary == 0, 255, 0) - binary *= pixel.astype(np.int64) - ax.imshow(binary, cmap=plt.cm.gray) - ax.axis((0, cols, rows, 0)) - ax.set_title('Detected lines') - ax.set_axis_off() - ax.set_adjustable('box-forced') - plt.show() - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() \ No newline at end of file diff --git a/debug/houghp_skimage.py b/debug/houghp_skimage.py deleted file mode 100644 index c7b9aec..0000000 --- a/debug/houghp_skimage.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -usage: python hough_prob.py file.png - -finds lines present in an image using scikit-image's hough transform. -""" - -import sys -import time - -from scipy.misc import imread -import matplotlib.pyplot as plt -from skimage.feature import canny -from skimage.transform import probabilistic_hough_line - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -@timeit -def main(): - image = imread(sys.argv[1], mode='L') - edges = canny(image, 2, 1, 25) - lines = probabilistic_hough_line(edges, threshold=1000) - - fig, ax = plt.subplots(1, 1, figsize=(8,4), sharex=True, sharey=True) - ax.imshow(edges * 0) - - for line in lines: - p0, p1 = line - ax.plot((p0[0], p1[0]), (p0[1], p1[1])) - - ax.set_title('Probabilistic Hough') - ax.set_axis_off() - ax.set_adjustable('box-forced') - plt.show() - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() \ No newline at end of file diff --git a/debug/morph_transform.py b/debug/morph_transform.py deleted file mode 100644 index cd6a6b9..0000000 --- a/debug/morph_transform.py +++ /dev/null @@ -1,114 +0,0 @@ -""" -usage: python morph_transform.py file.png scale={int} invert={bool} - -finds lines present in an image using opencv's morph transform. -""" - -import sys -import time - -import cv2 -import numpy as np -import matplotlib.pyplot as plt - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -def mt(imagename, scale=40, invert=False): - img = cv2.imread(imagename) - gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - if invert: - threshold = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2) - else: - threshold = cv2.adaptiveThreshold(np.invert(gray), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2) - vertical = threshold - horizontal = threshold - - verticalsize = vertical.shape[0] / scale - horizontalsize = horizontal.shape[1] / scale - - ver = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize)) - hor = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontalsize, 1)) - - vertical = cv2.erode(vertical, ver, (-1, -1)) - vertical = cv2.dilate(vertical, ver, (-1, -1)) - - horizontal = cv2.erode(horizontal, hor, (-1, -1)) - horizontal = cv2.dilate(horizontal, hor, (-1, -1)) - - mask = vertical + horizontal - joints = np.bitwise_and(vertical, horizontal) - contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10] - - tables = {} - for c in contours: - x, y, w, h = cv2.boundingRect(c) - x1, x2 = x, x + w - y1, y2 = y, y + h - # find number of non-zero values in joints using what boundingRect returns - roi = joints[y:y+h, x:x+w] - jc, _ = cv2.findContours(roi, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) - if len(jc) <= 4: # remove contours with less than <=4 joints - continue - joint_coords = [] - for j in jc: - jx, jy, jw, jh = cv2.boundingRect(j) - c1, c2 = x + (2*jx + jw) / 2, y + (2*jy + jh) / 2 - joint_coords.append((c1, c2)) - tables[(x1, y2, x2, y1)] = joint_coords - - vcontours, _ = cv2.findContours(vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - for vc in vcontours: - x, y, w, h = cv2.boundingRect(vc) - x1, x2 = x, x + w - y1, y2 = y, y + h - plt.plot([(x1 + x2) / 2, (x1 + x2) / 2], [y2, y1]) - - hcontours, _ = cv2.findContours(horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - for hc in hcontours: - x, y, w, h = cv2.boundingRect(hc) - x1, x2 = x, x + w - y1, y2 = y, y + h - plt.plot([x1, x2], [(y1 + y2) / 2, (y1 + y2) / 2]) - - x_coord = [] - y_coord = [] - for k in tables.keys(): - for coord in tables[k]: - x_coord.append(coord[0]) - y_coord.append(coord[1]) - plt.plot(x_coord, y_coord, 'ro') - - plt.imshow(img) - plt.show() - return tables - - -@timeit -def main(): - try: - scale = int(sys.argv[2].split('=')[1]) - except IndexError: - scale = 40 - try: - invert = bool(sys.argv[3].split('=')[1]) - except IndexError: - invert = False - t = mt(sys.argv[1], scale=scale, invert=invert) - print 'tables found: ', len(t.keys()) - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() diff --git a/debug/plot_geo.py b/debug/plot_geo.py deleted file mode 100644 index 3f7aaf9..0000000 --- a/debug/plot_geo.py +++ /dev/null @@ -1,167 +0,0 @@ -""" -usage: python plot_geo.py file.pdf - python plot_geo.py file.pdf file.png - -prints lines and rectangles present in a pdf file. -""" - -import sys -import time - -import cv2 -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.patches as patches -from pdfminer.pdfpage import PDFPage -from pdfminer.pdfdevice import PDFDevice -from pdfminer.pdfparser import PDFParser -from pdfminer.pdfdocument import PDFDocument -from pdfminer.converter import PDFPageAggregator -from pdfminer.pdfinterp import PDFResourceManager -from pdfminer.pdfinterp import PDFPageInterpreter -from pdfminer.layout import LAParams, LTLine, LTRect -from pdfminer.pdfpage import PDFTextExtractionNotAllowed - - -MIN_LENGTH = 1 -pdf_x, pdf_y, image_x, image_y = [0] * 4 - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -def remove_coords(coords): - merged = [] - for coord in coords: - if not merged: - merged.append(coord) - else: - last = merged[-1] - if np.isclose(last, coord, atol=2): - pass - else: - merged.append(coord) - return merged - - -def parse_layout(pdfname): - global pdf_x, pdf_y - def is_horizontal(line): - if line[0] == line[2]: - return True - return False - - def is_vertical(line): - if line[1] == line[3]: - return True - return False - - vertical, horizontal = [], [] - with open(pdfname, 'rb') as f: - parser = PDFParser(f) - document = PDFDocument(parser) - if not document.is_extractable: - raise PDFTextExtractionNotAllowed - laparams = LAParams() - rsrcmgr = PDFResourceManager() - device = PDFPageAggregator(rsrcmgr, laparams=laparams) - interpreter = PDFPageInterpreter(rsrcmgr, device) - for page in PDFPage.create_pages(document): - interpreter.process_page(page) - layout = device.get_result() - pdf_x, pdf_y = layout.bbox[2], layout.bbox[3] - for obj in layout._objs: - if isinstance(obj, LTLine): - line = (obj.x0, obj.y0, obj.x1, obj.y1) - if is_vertical(line): - vertical.append(line) - elif is_horizontal(line): - horizontal.append(line) - elif isinstance(obj, LTRect): - vertical.append((obj.x0, obj.y1, obj.x0, obj.y0)) - vertical.append((obj.x1, obj.y1, obj.x1, obj.y0)) - horizontal.append((obj.x0, obj.y1, obj.x1, obj.y1)) - horizontal.append((obj.x0, obj.y0, obj.x1, obj.y0)) - return vertical, horizontal - - -def hough_transform(imagename): - global pdf_x, pdf_y, image_x, image_y - img = cv2.imread(imagename) - image_x, image_y = img.shape[1], img.shape[0] - gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - edges = cv2.Canny(gray, 50, 150, apertureSize=3) - lines = cv2.HoughLines(edges, 1, np.pi/180, 1000) - x = [] - for line in lines: - r, theta = line[0] - x0 = r * np.cos(theta) - x0 *= pdf_x / float(image_x) - x.append(x0) - y = [] - for line in lines: - r, theta = line[0] - y0 = r * np.sin(theta) - y0 = abs(y0 - image_y) - y0 *= pdf_y / float(image_y) - y.append(y0) - x = remove_coords(sorted(set([x0 for x0 in x if x0 > 0]))) - y = remove_coords(sorted(set(y), reverse=True)) - return x, y - - -def plot_lines1(vertical, horizontal): - fig = plt.figure() - ax = fig.add_subplot(111, aspect='equal') - ax.set_xlim(0, 1000) - ax.set_ylim(0, 1000) - - vertical = filter(lambda x: abs(x[1] - x[3]) > MIN_LENGTH, vertical) - horizontal = filter(lambda x: abs(x[0] - x[2]) > MIN_LENGTH, horizontal) - for v in vertical: - ax.plot([v[0], v[2]], [v[1], v[3]]) - for h in horizontal: - ax.plot([h[0], h[2]], [h[1], h[3]]) - plt.show() - - -def plot_lines2(imagename, vertical, horizontal): - x, y = hough_transform(imagename) - fig = plt.figure() - ax = fig.add_subplot(111, aspect='equal') - ax.set_xlim(0, 1000) - ax.set_ylim(0, 1000) - - for x0 in x: - for v in vertical: - if np.isclose(x0, v[0], atol=2): - ax.plot([v[0], v[2]], [v[1], v[3]]) - for y0 in y: - for h in horizontal: - if np.isclose(y0, h[1], atol=2): - ax.plot([h[0], h[2]], [h[1], h[3]]) - plt.show() - - -@timeit -def main(): - vertical, horizontal = parse_layout(sys.argv[1]) - if len(sys.argv) == 2: - plot_lines1(vertical, horizontal) - elif len(sys.argv) == 3: - plot_lines1(vertical, horizontal) - plot_lines2(sys.argv[2], vertical, horizontal) - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() \ No newline at end of file diff --git a/debug/plot_intensity.py b/debug/plot_intensity.py deleted file mode 100644 index 87c386b..0000000 --- a/debug/plot_intensity.py +++ /dev/null @@ -1,69 +0,0 @@ -""" -usage: python plot_intensity.py file.png threshold - -plots sum of pixel intensities on both axes for an image. -""" -import sys -import time -from itertools import groupby -from operator import itemgetter - -import cv2 -import numpy as np -import matplotlib.pyplot as plt -from pylab import barh - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -def plot_barchart(ar): - n = len(ar) - ind = np.arange(n) - width = 0.35 - plt.bar(ind, ar, width, color='r', zorder=1) - plt.show() - - -def merge_lines(lines): - ranges = [] - for k, g in groupby(enumerate(lines), lambda (i, x): i-x): - group = map(itemgetter(1), g) - ranges.append((group[0], group[-1])) - merged = [] - for r in ranges: - merged.append((r[0] + r[1]) / 2) - return merged - - -def plot_lines(image, lines): - for y in lines: - plt.plot([0, image.shape[1]], [y, y]) - plt.imshow(image) - plt.show() - - -@timeit -def main(): - image = cv2.imread(sys.argv[1]) - gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) - threshold = cv2.adaptiveThreshold(np.invert(gray), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2) - y_proj = np.sum(threshold, axis=1) - line_threshold = int(sys.argv[2]) - lines = np.where(y_proj < line_threshold)[0] - lines = merge_lines(lines) - plot_lines(image, lines) - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() diff --git a/debug/print_text.py b/debug/print_text.py deleted file mode 100644 index 1ab83d2..0000000 --- a/debug/print_text.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -usage: python print_text.py file.pdf - -prints horizontal and vertical text lines present in a pdf file. -""" - -import sys -import time -from pprint import pprint - -from pdfminer.layout import LAParams -from pdfminer.pdfpage import PDFPage -from pdfminer.pdfdevice import PDFDevice -from pdfminer.pdfparser import PDFParser -from pdfminer.pdfdocument import PDFDocument -from pdfminer.converter import PDFPageAggregator -from pdfminer.pdfinterp import PDFPageInterpreter -from pdfminer.pdfinterp import PDFResourceManager -from pdfminer.pdfpage import PDFTextExtractionNotAllowed -from pdfminer.layout import (LAParams, LTChar, LTAnno, LTTextBoxHorizontal, - LTTextLineHorizontal, LTTextLineVertical, LTLine) - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -def extract_text_objects(layout, LTObject, t=None): - if t is None: - t = [] - try: - for obj in layout._objs: - if isinstance(obj, LTObject): - t.append(obj) - else: - t += extract_text_objects(obj, LTObject) - except AttributeError: - pass - return t - - -@timeit -def main(): - with open(sys.argv[1], 'rb') as f: - parser = PDFParser(f) - document = PDFDocument(parser) - if not document.is_extractable: - raise PDFTextExtractionNotAllowed - # 2.0, 0.5, 0.1 - kwargs = { - 'char_margin': 1.0, - 'line_margin': 0.5, - 'word_margin': 0.1, - 'detect_vertical': True - } - laparams = LAParams(**kwargs) - rsrcmgr = PDFResourceManager() - device = PDFPageAggregator(rsrcmgr, laparams=laparams) - interpreter = PDFPageInterpreter(rsrcmgr, device) - for page in PDFPage.create_pages(document): - interpreter.process_page(page) - layout = device.get_result() - lh = extract_text_objects(layout, LTTextLineHorizontal) - lv = extract_text_objects(layout, LTTextLineVertical) - print "number of horizontal text lines -> {0}".format(len(lh)) - print "horizontal text lines ->" - pprint([t.get_text() for t in lh]) - print "number of vertical text lines -> {0}".format(len(lv)) - print "vertical text lines ->" - pprint([t.get_text() for t in lv]) - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() \ No newline at end of file diff --git a/debug/threshold.py b/debug/threshold.py deleted file mode 100644 index ea716b2..0000000 --- a/debug/threshold.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -usage: python threshold.py file.png blocksize threshold_constant - -shows thresholded image. -""" - -import sys -import time - -import cv2 -import numpy as np -import matplotlib.pyplot as plt - - -def timeit(func): - def timed(*args, **kw): - start = time.time() - result = func(*args, **kw) - end = time.time() - print 'Function: %r took: %2.4f seconds' % (func.__name__, end - start) - return result - return timed - - -@timeit -def main(): - img = cv2.imread(sys.argv[1]) - gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - blocksize = int(sys.argv[2]) - threshold_constant = float(sys.argv[3]) - threshold = cv2.adaptiveThreshold(np.invert(gray), 255, - cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, blocksize, threshold_constant) - plt.imshow(img) - plt.show() - - -if __name__ == '__main__': - if len(sys.argv) == 1: - print __doc__ - else: - main() \ No newline at end of file diff --git a/examples/demo_lattice.py b/examples/demo_lattice.py deleted file mode 100644 index b3ff2ea..0000000 --- a/examples/demo_lattice.py +++ /dev/null @@ -1,11 +0,0 @@ -from camelot import Pdf -from camelot import Lattice - - -extractor = Lattice(Pdf("files/column_span_1.pdf", clean=True), scale=30) -tables = extractor.get_tables() -print tables - -extractor = Lattice(Pdf("files/column_span_2.pdf"), clean=True, scale=30) -tables = extractor.get_tables() -print tables diff --git a/examples/demo_lattice_fill.py b/examples/demo_lattice_fill.py deleted file mode 100644 index 3546b00..0000000 --- a/examples/demo_lattice_fill.py +++ /dev/null @@ -1,13 +0,0 @@ -from camelot import Pdf -from camelot import Lattice - - -extractor = Lattice( - Pdf("files/row_span_1.pdf", clean=True), fill='v', scale=40) -tables = extractor.get_tables() -print tables - -extractor = Lattice( - Pdf("files/row_span_2.pdf", clean=True), fill='v', scale=30) -tables = extractor.get_tables() -print tables diff --git a/examples/demo_lattice_invert.py b/examples/demo_lattice_invert.py deleted file mode 100644 index a0bf41e..0000000 --- a/examples/demo_lattice_invert.py +++ /dev/null @@ -1,13 +0,0 @@ -from camelot import Pdf -from camelot import Lattice - - -extractor = Lattice(Pdf("files/lines_in_background_1.pdf", - clean=True), scale=30, invert=True) -tables = extractor.get_tables() -print tables - -extractor = Lattice(Pdf("files/lines_in_background_2.pdf", - clean=True), scale=30, invert=True) -tables = extractor.get_tables() -print tables diff --git a/examples/demo_lattice_rotation.py b/examples/demo_lattice_rotation.py deleted file mode 100644 index d201cf1..0000000 --- a/examples/demo_lattice_rotation.py +++ /dev/null @@ -1,11 +0,0 @@ -from camelot import Pdf -from camelot import Lattice - - -extractor = Lattice(Pdf("files/left_rotated_table.pdf", clean=True), scale=30) -tables = extractor.get_tables() -print tables - -extractor = Lattice(Pdf("files/right_rotated_table.pdf", clean=True), scale=30) -tables = extractor.get_tables() -print tables diff --git a/examples/demo_lattice_twotables.py b/examples/demo_lattice_twotables.py deleted file mode 100644 index 91c6b93..0000000 --- a/examples/demo_lattice_twotables.py +++ /dev/null @@ -1,11 +0,0 @@ -from camelot import Pdf -from camelot import Lattice - - -extractor = Lattice(Pdf("files/twotables_1.pdf", clean=True), scale=40) -tables = extractor.get_tables() -print tables - -extractor = Lattice(Pdf("files/twotables_2.pdf", clean=True), scale=30) -tables = extractor.get_tables() -print tables diff --git a/examples/demo_stream.py b/examples/demo_stream.py deleted file mode 100644 index baee02f..0000000 --- a/examples/demo_stream.py +++ /dev/null @@ -1,8 +0,0 @@ -from camelot import Pdf -from camelot import Stream - - -extractor = Stream(Pdf("files/budget_2014-15.pdf", - char_margin=1.0, clean=True)) -tables = extractor.get_tables() -print tables diff --git a/examples/demo_stream_columns.py b/examples/demo_stream_columns.py deleted file mode 100644 index 79cc6cb..0000000 --- a/examples/demo_stream_columns.py +++ /dev/null @@ -1,13 +0,0 @@ -from camelot import Pdf -from camelot import Stream - - -extractor = Stream(Pdf("files/inconsistent_rows.pdf", char_margin=1.0), - columns="65,95,285,640,715,780", ytol=10) -tables = extractor.get_tables() -print tables - -extractor = Stream(Pdf("files/consistent_rows.pdf", char_margin=1.0), - columns="28,67,180,230,425,475,700", ytol=5) -tables = extractor.get_tables() -print tables diff --git a/examples/files/consistent_rows.pdf b/examples/files/consistent_rows.pdf deleted file mode 100644 index e0213aa96c405601e7d6131f3a7cd0b5834a52b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184194 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 diff --git a/examples/files/inconsistent_rows.pdf b/examples/files/inconsistent_rows.pdf deleted file mode 100644 index 9eb4b63dbf242afdda235d493654072b820606e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45085 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

Qt4#NFGjdKO6|_tnZRGXQ_O4ZeQaxd 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 diff --git a/examples/files/left_rotated_table.pdf b/examples/files/left_rotated_table.pdf deleted file mode 100644 index 8b7a6152afbadf372e6ad67b0ffa8998b601e89a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16638 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 diff --git a/examples/files/right_rotated_table.pdf b/examples/files/right_rotated_table.pdf deleted file mode 100644 index 9494465873d39a702c96ed865cfd241c9bfbfca1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17035 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 diff --git a/tests/budget_2014-15.pdf b/tests/budget_2014-15.pdf deleted file mode 100644 index 9466e8734c90b8aa7dd52f584551eab6b0e8d9af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 338830 zcmbsQ1z227*EWcv!GpWIOXCEG#@*fB-JReP+@0VAm*9}#?!h&|-5sXM^FIIg&YXYF zHFM6jp}Tigt=g+r-MgyRs=6r^f#Qq+CN3m+%7TXe1tfR?2@8pXu{9DrA0M-#k%gHH z2`eZ?nS@!@%h8Nk)X3Gy*1=7hT}c4UGFGN8Iwb6W1@-=s z{9D(5%d!2poU@sctCfR2(8$${2Kb4U1;EL|#livL2Jo6W>;NVnRuT>#4kk8MJ&<)k60ZN6 zN7>B9!Ohvk%mq}xxP!gx`xk(O^PdNcvy$-q=NB6Z;JxJ_gNn100RGMAAYpxf!h0$w z3G2TFxJX#J{*%g0!uH-X?*({B*#5CBNI{S#OjOKVb(le>VOBNsbY+&Z19h6nKVPE% zd`annN~*XzyP3HDqq7SM3$v<`vCDhg-+T4FZ~ohc@8MXu4c~6;+2@0mUBxAKKRB5|i3>_t=ni4JC5b$}njlAT0J znG0JkR$O_~c#0R91B2Fyw4PnH4(9RcCfaLt^*LROB67(--q@^lr;Y_Vj(c!z^`v2P zgTKq)?QQ$wdQi~+_Tl&Mm*_l$SI@^M3j;nr0fCN(xJm!}mxZ)EKcBbRqwjZdHN@+$ z2MVRkUB2Fr+u;g=564G`?E2Lw2jLod{>nMkr*HG+Rm>-z)=x4jdH$YP2hSS z0guBQXYzY*+%MG#{4lC#e7pR$_4RJAqSMF4 ze`c`zbn;}aePi;5Bbe`gqw7;rfWqX0C@OtXhlX zqvnt8wWISq!;A2wx2O5u_SvuBUzXl(SpDbG7Yw@dvIJfUx^C9WZ{J!UyDMh6%c+Tn z=I7sDsu`Q?mSt4zRs?993Ek}!7Dk&66a+i&pY;3~+h*r8v{(+JK71@)c~teKY7zf^ zs%?_5pXld`X(Ui)$c` z+iG7g%5Q@ieg&UqMUJq~X0q#ymB-qCd%R9+yE$v9c1KQpocnTPb||kFkg@y=sS*Ur zjW=KKBfOfn!jkH#<! zxwW`gSGhE`UURfQ2At-0-V~kmxA!m+%;KE+BmBPDQWF3&5Fs9|x3HfEtcP~BUGrjh z@oMClfVOhRL&%t@^u6`6}sj#INs$TJS(I3GSbP;@?Ne#da{vIGGVWCa*ajp<-)8T zOVTXfEm1dIL$|zs8Q!N3;-9@8H^>z#XRmlU9UhZQT~k}XXSVQW_Ya0VKdJju{qSic z>=fkVTYqzQu8G4bd-|Tc)OzpS}oYF8H$M zE7k3=J)~qk%{#4l)@M0<+aED`|(*_!`deR{H=ERK?De33t)Wcj<+&%ChRXowlo{v%T4!FhZ6e|1jBW`@>(-Opvl#ll%9i3hmbLldt##OLFH-L$-N=LO0{Z zS?Z2oStfq{6f@Gfb&H63I_GYO>+BX^GL29@dvwRS`97CGjavh9d#z#j9}8)K%zg z^2xK)#tM`o;h{A-aHTHe-Ml7{Z(}(n0Eg`ena7VFv1)0c?GD@GR2?{N{Yt>cNAGf<&7m&~AHTkdL)TSR#w?1gur?4v zc-Rj9P$*AtF@Z`RHqqPrgSwP@kcCd8W^$DxITcKO{=IGZ0iT_zA++s6W**A{ohJi4 z)WTeRI!gZ>%3bM>r#*1M%z^rjn~f)H zJ^Qfd;{(F0qM=WB@cfEzu~%M%1iIjqmiZ$pUYZ)STxXML9+vhTLlBBsrXm|V_>wf= zk8pR^u7a#1^It=3A#M8RvA=3I?%_+Zp7EFY{a5HXjMgQtQ^Pkzg`nwr^0O1v0Ody-hbz7NykiJ6bo5@&zt?)f9CkzNvD*`o`u~!qyL_8S{3Qv()Uaq@HK_%w<&W=yxYQ~^Ui9#)X}O`E^$FT zpa^pbOLTWuY8gD_n?kSC#|72w#3X*h-uYMoo^=c+?;xhYuPhk2>xi+V;8`C8vl4uC zig6ywcC>UqsHUp6d5H9O7MONb6NMof2(lykbVCh=TDmAS(dzs2?cxS|BQHAg98cVe z%j(iVv~}|uT{Ig}K(aG^ux*@K6HspgIy!Qx8^i_JY$HC8h zczvG!;5yiq-zY%BX$OZjJ%d|4IBnd*&cYZ*4>%Z`bsvY<5fIVV?fZ&ED$T&Y9m+)# zh0V zESrzbo%uSJzx20+a|Kfxry{6yjDZAfJ*fRaVPi>F7Dn+%8t04hxxvkE;=1Dkz4HPj z!M3m(WUZ*oj=C6(VMJ++qd)L!rrGy=if>*-Y1Ts9Jub61vV;a?a^kjUlPbySMKPNf z)gMMBq9c++o71>-6mLh!xZ^|mkAF&Q6nzk8wZ)@QQ?jp{#jyLXZJGCcbLF9x77cGo zS042%)JBj(u%(Pf@k!KQq0A4hG)`U4Wr9@M z*nk`vM!P>p7EN+KH!?|DV5U~+7m1%}HjHAL!ApczWsT+?&MZY|*VViaA&DvmBz_K{ z(4xU1=*Efm!{VFjP@VdxaJX;~=qomD@p!fVdC>Egq_Do;lBx(ikEl-m+8cpqsQqz5 zF*G|($DV>iK$-nflG2LhPIl_UjwB%JLwaiKCq`IDg&R&e>am%cpd)ZHfkcil$pl%= zO>w?II9i`=N9We`EPj>FM9h+tseO%;pMhCM9W2WvCud@WSal{Yzes2X0HYd(L$dmX zc~oPXg`0&|T?GobU7AWC-rO7Xl_OG?!HaCKe@G){oktj_ne@}(gLIll(cgRmd{2Nh zOL2h(jAZ+nj?nGlNG9{_*Ju8Ykldwd_iga%Op{PMC1)ev(+yu5Jwkdt|6WOq0{)l5BWWZ-s% z%p?uEAst=P*lcF*l3w#bPMkp#q-3V1v6yMVkKSk|{;zWJRV{~!585XSs9}X72|)=W z03hv!FGO-lkdJsFn2J&%##xz>i-b`u*{4AEC{p#vgUOuFX?ot`MPMqmr!!AqEu0mo zqvk1d=R^7;Bcl5vDS>@=*nA!PGi--YOHq|f$N5>1eczaalRy)Ukp%FC z@3W!pE2TGdBE28kI2h2VQejbB<2*0_>TF6+hkjeYUekUp(l|#%Vr2}gvE2_vQ`L4I z!wFte$hqXzW_IyFw{jAiQu$sBo|MP^yGht3`*+8u_YBM?C+X&Kv z!;C^ZKN7Tlz*PGPzr=Ht=&t@E7wS3x^_7K!fzo@*A#@n&~>z&T3k%ugz=pt^? z135x0Z0j)>%^f2-M?PSY4Ygl<*G_D9q1T)hspd0{u8?yt8o>Az!I(KT29;p3tphv% z5CVPT*>1A3XjwWU;|ENU0HUxAVlK&E$DZ>T&I@?#C@DE~qSuO&{c5^$HwHX#3u1;O zEP_%*&;#v6fJP!liF8VHl|R9&T}vaAobysk-Wxlfq7E2?^BT-84Vi>Wx!6X)CPDRl zyEwMd;$W;uiKLrNcVuCyzNq08$WuyAh0Nc-~ zPED8v1gzo>hBj7$&`)h0)e9;`wYaN7GyN#v`!e91*D;hn;*;y=*U7dXO~f(d?-1Q3 z^FG$DD^FV#`Pj3arR}>cBjKM!c&I&DiSs~Ok6CfCreJ-@RuViOGP>RcU=}ff9dB%m$^f_!bORU$h0yh(d@~(8zS3 zi3PKCWvPzWYz`?&ZyFrvhEyl5>U2twjn2*r#7>Xm5zZ*(=(k?9q!qZ*J^>?ZP1Qt| z(>-@opBhrsHP!iog}OSXLH{FV8nu%ngl<~&1jTgdB!M)&jPa=hFJ+Rx2{K|)+gL1{ zWqVjkgk01np^6)Ga$UVQgVS7UTG=P?{u`-oWFlIAG8H?kEmnGz$_1|i7uzp4uazFs zA#TjP{t`aS07Odp{$7MpVp?m-B7}D!Px{v&6vEJ`S=uYfV?xNeNA+}?lu9SivF}8I zWk^SDEJ3oQp1#aFTXWF=rs68%uLNL| z=weW3Yq4kwa5TlHvI&EwG2fMqF$XI#8{b^d?d|c*9Fp$lBZKUvKY&IhIDnSPj&Nf3 z~}bN_2QX{1Xa};3_SxP-e0I?S5ioBz`wpy6m=_V zkAYtQNrehJs>%CVvF^C43R3fXUl)JY(7rsLI6=x;sB}l}axS0LKcbH}chJ-Mt(Kg5 z-Oh1XyA@*7LV+%+@cRY2oI<~y6XoWRS{sn8!sc21HC<`;KR|y%`BLZ>f2@%5<8CovNEE#u%Iumg|K=KpmK4={M1z?zz_ACeTX7U<&74kRXBs5!Y)Y{ z3zH9&A%ch1u4buiikDIOsGXPkDo$$Y%^WyZ3yi(D6OmnFA+cSZfi$i8DkKceB0($#(jnHJv(bE=g{s1=aFxaB({vK z_6Kp`GD=CGIGkc8<~O=92}m6)JOPg;Dz|3s=P-6{C<%sTlro_3Uha?CbG80>OGA3Q zxE*S8knM)33ZKvoF4AI8PQKBnE4T`_#(;oCEgu? zn1>x2vNkM`o40kMgTbK-Dl_Oiur_3 zbz(ef5>8dcsyWRT)#?Q(5c%or27nZm1V%;JuicHS^M@V0pGh}3O9#ZZd(gfD8!Y&; ze;EKUbqeZeKC)U2a_pTfX({rvpuvQ(j1%xeNVoQ3s?cFAMQsOmrc^%?5aJR*t^t_&CxbRNPPGW#rwn(!{eOH#lm!(3PB4k(}Q-Fd*LV&(2p@1I#8%Q zl)Xk1YWxBLO`{AShBDr$!+XzN>}YsiT<&(8YpqN)VviAQ`)cx;<=_KI^x>nYGiN~m z99-A{i5vA;B{sRb6?us}#4wELkohtmcyY{YRJmG=t=L1Yi`!^@v_t^W=a@@Ugpcva z;fjU6f!OMN&njWSOW~EXEFwGB2NYc}o)?*DV|hXA`XuBRj{K2IbT2PMOZwsPuCBT9 z+yFnshfNJ!fBmdbHX#Fw@$=V?YGjr)#GXo|%g_exLgc2|diu0tU|$k8e)`X!L+ZM= zL%MnsLrTRjqnnZnnh;`RzCX~h@Y9`tPHE1eXEekY1gNk$QG-ZmE9wQe8J`2Dd*?Kc^mQ6wtrCA5O3t>NJZ zQ4=K*(+N7t5X2~o5K>@dP~{*#Iq8=eE^XWRvqIltX{2c2XG$Qjl|0wDE~p#>F}A<| z!)?J_HL)~#o?E$ug!K=U%06W{MO|A%cqnomCB|djwZy}1t?WUPui8VwD(VP>iiO%B zi>>yPh>|tspWMmCoklYzAz0QKfmU6%U~=x(1t%I-oMoJDDcCv#1IqOQ8U~r;%Q3V| zf)smiIwLc0HjipU52bOUT>+m2ue2Uh9i-8OoB-cGI0DTLtHpnTp*r$d*AsY&Ly?#O zA_ZMI%LC`LsZ_yPKP7^LX6FKZFdtgYn2&+KNFoIZaFW|sRDLP7^FWpcM+t2~BtnJ7 zQ<}>~Tv@sAM1bZD+|R&QM@tmqTJC^q0d~nPaODqSo|LKlcPNA`T3@iqk>Z_r82RmC znKlf2&AE4@-@ILmP#EgSx;nwW%s84-Kr}K@mxasy@Nr1V3g$?cB*QUIzHjz_2HO_zP;E1HA z(~(YuYo?M9NPaM7xYDH-lQ zz6cLQUNUg+L|&TEI297;Yt~t&AVxxkG;eV6x7Ae0Fy%L9wu7LSw}HlFJb_TCN>yPDKMTLRL#rpK?h;P9ZX_%gvVl?xS_~^QiKqaI zt?HUQgU7d4M!@1|x)68#?xH64ivK3F-fM)WBojC}onRSmp+WT{GZG`$l&nxlF%NCUP zu@@Zu9(m7|YQhNnL0dhk`ztH4nLE+NA1Jqy82Wll>OX86Rb#qP5*@2(G=(h)x$*fE zst%z8J32YsJS_{T)M)@zaxNfEf;I$(i&=(p)sXs_oS-j#`43cVE+{&uEfLY0EtKMYme_oxTsh^#@Ug`i9=|PTMaf?6U=_*g52pue&&a>Vw%jH7 zNFqh2e+P|UdgQreY&o=T@Ui`4*JE1rN2$}Od!U)K&Kv@RZ8k%sa!5VfaRd4LO^2(F z0OKx-X}05Juu86@U>F+p>Q-n9*M3yIWV_{)-|W|?%%(pOBeHoq$!xR2NjcW7ZQ?GJ zRGzF>`ZZYiGP5TdT)*ry>>W;X1xp+DU+OLt4mL_DDgAt)UK&()MglIsJ5Kqg)oR12 z#Y08en8potG#iZwv`cGY0D=8=SF)ixmb$sMag_Eh7PG@~Y7A&RX)%93F3kG`HU?4Z z1Dmjg4)(oDMi`qvXdPYbKa8#2^4UUrjxQ{*_mCGDf?VL05E^3dan;t)0po#BK0b1^ zI;Df`;%DG92%v%Nl>aW?^_frQ01Ge8;?$&EM?l|1nrKlqyE=MC_!i6xMy4YonmKT0 z`bxG*$Chz?cqa#$q5-8}W&$ zlYA_htym|)&Z~s)QvbF2P^DI!fT0O8@HR6TQ|b@ALOQF(;dc=eqY>Y;%EW6r67any zs0hig{`))0cT-d313oKjMeblI`XF5lDERvS@Td%6;>qA1wKfpKg`CqkggTbi zF_V3RQ_L2!IBX%)v4Y^o_s#O!)%^%szEMqqmT%NkpyeB!tFKYNsxL0u{s*`28lT4X z1t&`E9;nBeLhhh1na99h&(4@ic=i9L9@ zt|k`DRF1#zS;KFj324hlX3x5u_WoMb)2nRFp3j2WOSC7hB8xdj>}ql2b}-aH?ev#(Vd^|eFl%Mw}b znIF53CXTLyx05>%zZ6AMDgtjn;i0%@bL$@>CQ_NlzVp)PxM))7qJe1b8pyojnFP4* zPQ)h{_)@X4s*#lPz$5b9_u|ssA|^^Hwa8@$vV&x<7UL8hKOu{x5ig`|)4_`U8aY(1 zF_)q$OhMDcpH9uSLmX38N-f8cia$8gs+9Xb+v-=*NE7I$Z=Xse?rvO$p=;yZt&~dgr-e&Zz zm~>faqw~{aK_GrIB|Doj7((CJuDRw2a1W5i70o=a!)UKyzUhNf{6&tcB=Ec5yy8&A zgw}+{!(9`7@U~+FhmJXYh=@eWI1>Bf5n7RZuiiZB$k-+xfbsEuc+Kvh*ubvLy;nl^ z3__U-w1RO~h}h=w;ZU)}#!G|zb(hvRST*p$H@jfN%DM0*oQY%hLT&n9*2Fhg8@PhUqUG6u=xqJU%W8UB(D(ziuQ zjPxz8T3yNfRanu8$Ok7p>l4%%Luwrn$2k5dC*w3+{AK*%R0SZiT5n z0eC-qVJ0nQv~BT8Q)?whRl!6g5#*{q{bzC!TR4o1VQA!1lzCZxElY-pX^RQ>>#m%$ zg%71D!}}3%_{J%g6yVZch#V@aSWD9Qb}kx&4drFu5Wno#kSa#x#qxV3RLq!oZr1oM~3SW?;P->P7qb_iS(4dOl z^q7>LCIqFSMMT}HU|Q^Ly@1Aq1YOVwLn6+{6I5m%H7sJ{R3YHPDF;{n6BLb_)&VW3 zL@9-6L3wn;phZoE|K6dyc)OLjB_2qoo6Tf&$@DCtXKElblCd z86h^PD`NJf-%*dtfn3v4eG7aB2QiLEb1qe>{lYDTl(f(c7W?M+1Kl|&y`o_XXFrBY7RO>j{s<2B z8;7Z35eK4?w5uLJ7;cr5DHv7NkB>d+^YsC3X-xwK;OUKFAiaKpW_ZSka$%5OzhGw% z#NcO(QE9|vPoNU%e)}nK$DTG(F`p zSmwl&?N)tM!gN8@^dKD^I0Oc@ZN^LsND#0Z%aMCGsA+^r{s~MiMnF>vcC3^9TPlm2 zQ$kfsR#0aZr;4x|>46x+N6Z*f#Uf}dKBM9g+9-tB;x$BGgQj*|Q^_*DYjEjn1O8*2 z6KB)KY5TBVu0%Zi5iHT{h-(SHel$3hk03o{D2^em1KdX|T=2%!`7=FNVRv*p;?FQ>i`OPD zJuZOfSHZC;Dm%mTfUZ@4(ND9k@`IO(1}%dA-+wmz8D%KXg&rN>DlM4C zZagyXrYXRg zC^TO3p=1Ei%oJ|#>=B01$}UPNE`J6;!x1(`DIgbdIq{)n6~Lal zb%})woEKj)i;&a}e_)1HWS;l)%Q$BZSwK;P@M-F%!hyr1Njua{cr{3_{%0ULn&>tSM30%SaUYyIAnEr7T+c>!+>fl;j z5pjt>OK9}lc?gEg(9xumQ*C@6C#Nw5CaYDn22yqOnn5w14W!DEzG%iH>|jC0o@}gG z9-_5Q(jub0S!S+%S)g#cughsp`T?YI|GBv-V#&SePTlHK@;nE%@m_Fe zE6Cg4G|^;jOr^T_Shv=yhd{406^%h_pF`#iqa?<2uX|lA;FXGtrm3Tp?xP^zOq_%K z*{5i1sh7JPOF48uIP1Dj%s&W}L5{Pm1^HmZXvWf^;M2yIEUZ}6_jkYT*^u?u=^PQ+ zCeAG`XeZB!Ln2k4&u1=u+4-rIF_$Mct`EB+SRZOfWJc8bS1HU00TmEUOXX2E9_8%# zq?ZsQL#oOcr_MDT9=BVAiWmm7_6Ol^sndSTFSVcGZ-#OD1_E*$AXP1}e@b*y*6t9f zJ6yeHpXJh6q5@oP+Y)M67Fd5IrAYQ9-N~^~#s!s^i7e{N`^0W(F$wm< z;Zvo14}!cUR=O`?JV{vC>`6Zopa4*G7xxj=RMu=}AUPUAR*6nlnR#aROVOX=+r22o zz~3r0usRg!nS(uz41AV9b2~G3Gk%0&tnm4;4P^XE#7H0z7U@G{ExcjNu2l-A4T`a) zM6JJ4r56DLDTEQHrEK+ik8!}A4Ht{09+6!{tq6s^--};^%h$;SmxssLjtWQ5UU8fA zcYf$k2jy1up)~e|kmt521k=VK%8H5A6Nlh0>sR|bLIDmF7+B5tona{|P+he|>sA{g zA{rx_N4Yv%nWG5!g>)#CKVN=~bdIiqFE1G(<|>ln9HA#OF(F+l%X~)IOw}dN8@)R5 zojKSYn{%`J<4JHxwO1D9CAEPK4BlnkS>$$|nK#*O-&6R};FlmOq|2_FK#$ee#tCB1vf z1X9ZoPL*OVq*Q9vNE+Yd$hgchB{)`XL@=ao<|`zRAuJYP8j7a$kVP!Epia`Xvi#{{P??`HpbmbArNX*cW7f`KL;>P7Usn1#%qU9ySFte`4?*o|CY0d=M5~mM_Y3-iNMfhcCczi4z(= zA>9o$W>AbMpQUq+rTB9lNBa6lulv^a7cUeAjd^nN5r+uX!pRVtiDnMjEkjGh+nTTj z_j_I&zFE@rwgz_$B9cdk2o2+D7i74rH6#^Y9K7hOwPQbyY%Xe}!r$%~`;y@A6PGtQ zhIt2mi7!htR&&*9r`qmMOBU1@u0EP+%a?nT`?rD%35d<}lOh-i_#QO6!f8}Rz{VPj zSV*0lR~K(?ds2HAdylR(3g0(GCK6IZSS_-AkV@WMvV=yK46_<{$=`FaW{+()5)m9{ zeC#2pI+d~rgH8t2+8~DTtuGJ1PpM~KpVqtznB0EyUz9q#qowC-^v^TzG)PUa_LX9o zc8i0xNHs_vb0yDD|Fgz&V+nGxsj@to@B`>4F$sm(7tk0AqY;QEZtT;I8>cjvZ8Ldo zNLpE0wp+qjC=(?El}D_4G4jQlN#=Q3b#HU)S#?4Cw2q)7I1EmwgxTk7EGZVCUDfXK zbtNos`e1T*8#oN7evk*?#U>)@g(>43aRVO7wCu|$OH4zxwykhHe# zvjHJW8|UKB^=TL_9YXBrY-XP|n?+o$_7Wt}8tFp1BN?oC43tL=3Xm?HytJ&yLSQ57 z@qNIx_};LYZ1Fv=pl`{})2JW)+)R=Jx$*CE$4uWDyvT!@G3sHhY*?Ov8(w*#V(FxV ziJ3Fi{CoS6JwS-R{lzSO==3MdYxnEeV5z0E&K7n0>I6XwZ2*+2tUX)5dx4Xev(LAe zggYOLVyz_8~{vQBt!kE3(CX@qI3k7ljob4WR?Gjt{N>s@DUJH{c~MS;$#S`M^+3{ z(vxk+v!G7aYGr!EM_jtShEztNhxV)$F8xy6&iz~Sf%+06iC)?8=n%*i9BIe(g;t~b znvi$NG&L_ubkF5D>S>s(q5#v@Ax-=Hl_k}2QQApb&po|#fs~NOLu+>dRZ;e%L%Mgv zP%~e#{IU05MXFwOe1xvfPf=O7AH7~%NGe7k&uuR}QdNli?%V(l}XxfLP4< zgA5C_i}>w4tegylpDnzsTAU0Xos-Dx4lByZ{W+gN?nYAmNS}&9BGH1l7=AixQ20ZB zdtJSoNNc#j9qhs!=HWJ>V2a&>hmX>p}5KsSUwJ zF7%21HrYXv-?H9V*_X19fMo8ZFHE)!L`h_#WJ~|}GB(2?Uq-)K&x1m_a=jRqp#3+L+7FVkks*PkB9U6?`7MQ$$!22Bg(xfo z5=ifY3FGQFzip#wtTy3EAJ zh=(~sWIZVLKmpK(K&eqw1DTEz)bZeE7=0R7G*NI283}^C78HSKB-y5k9u6A#vj4{Q zeit`=Yv7F4F4m4K9_Y*!M1|uZJy1wL3lu{m%g38~0D}?hxubyiY5hZRqW5t1CQTBW zpbe!h$w^3ktx==K+y$t$1{Bg-W8u&TZOYlZS6k1= z!bZ-;Qu0w?VetvCv6$%<)RozP16MX7b2EuhOhka9Nn|WZ1O>R~V*vu7GadGbTT+|FOi1t9ChrV>sS%@{7mQ6bvr8VDg2%?AL@4K99*zJ_q@ogD8$@55-^(tH%9^~Jy zd>^+jwe=4`VeiM?LwzkRW3?;6B8M+}QfS;u#Td{N!UW3PxL-D?wk991HMHlr;bqnT zaKo`U<<}2IMz}a*w3Once2x*zXmC-dcQKVMa$!IvTdD=SRgSN!Qmps8COYZx*N)2F!2Sz0D4r$KuW;9^(cb2-M1yzI9 z{6wJe1cjr(>p-5ulnDlMV=6`5MKh}**|U^Zq^xnC${9Rrm=V- zDFl<35{YHZY0$64^HzS)X@&Sp0FV)2FCr@?21>sc9w@wBLLP_((l{gwgyHtb1yirX zqR&rCw6jwLH0E?4%=@Y7UmB%s&0EmwyCfxdH(4h_p;$Ml2_?0=sqyH0sp*^2mF3a8 z&dEPFzOilZO_{}C4_ALJ^8FG7TuTb_&28=uptp&{Kteome=E(HVxs%fMw1_nZA?Obm%n0RyIYu$i&G;CiSDK`ZrtbDes z`N%7TiqsvB=vQc{!a)>VG(;B(SOh-VasyB$gtuOPa`^H!dvZZa)!Jddph?^r>Y_%B zgwcPwr{i@GsZa3?tVklk0>6-QQlQL{GiY#2h~pe&Wu1{%AqcH%8e_T%16985vlRO! zROQ>)Bd3C@utuCFBa(C6HvXtGi=8g*Z4NqNlP!om&KM{>Mw7lFhqHAgI3os*`}O2h zPT}aAEa+SB)U>nwJYa`%z>IC6l}eUivl~J3s`O(o!H;ctB9w!JUvc$?wKRCU?u@++ z?H6_)a;=GKd-gmsIz=_|6w=<7vxWL3R5i-IG)r1tfbVdHMBz~Xh}4N%>r|UAYq768l(0b;)sa* zy|QM^kG$WhM!phCZ;a3v{#qDLdC%D*c}4Sa2cPHk-e7I0RReziSh*jWb8u{=~3 z_78-;zQd`Y^m-`T!z563Vn)(HNEKmeTn8dXB1Pq}o_M0^j}^L-ggB~2U+vp`lJ|wg zwSqBP5n0lJ!c{*d*q!D>%0GZK#hCMtx9bx(K*N_f4-Om& zR>n{aCkgg{GMyf zvX-r><3cj$S6E7>l15oKD?_@v*QO-t5#~bhiJC7`6w?S8`r=j@@H0c|h0i5rmRn$3 z3t^$$>_$>59gHeWcT zzZ}wkImPd^*nbJAB1SG|?}S=rVP`8NTLuvaTT>|z3E9eoS7ZYbIM-YdY1y0I&j><&EsjKx|!R6*pto zcRsADvzyspV(j0KzYo{2GIh0dA>sbZ!ToQp?0bFxsw(Va^3Dk6Vc}pFcDMK|Lc-3) z17b}(N}5?&Sh|vMv2uf`$Nv;#WCgIi^J*QZ)KkBk_u>5yh-&_B;tvVoL^83yIzZVxPE2w?%402A+cSHW)UH{*6 zIXK?&@_xPlVq<%!Pyf%w&CNr?2>?;CLI3ZmY@qvp%l(`7S5ohPIPLFb?SDJwf^q1?u1b z1walE!2b(?psfD^An4|Q3qTe&5CAzq0Aytc0g!{`9{_@=;AX5Of6e&LLkB_TA4vY6 z?ebrMWdFYalI6cJ$i>d~9}IG^{=dQC-^c&k-v4`YIu|z!=vDiNsSY3kaIvtlvHmw# z{n!u2S5@utmgi1>TsAR-B8gLKH;j}NMKVxPBmuEVXdmSRnl;sMktALcoSYDb64#iTS_fxMh2!;t z!*#VqOm~#J&C!Z)&XNaRnU5qhomZ*9og$px%RWL3qgOV-Pu#>pWhKpEqK=jG7;j+g zK(4D=KJ~|{WdO^_N~Sg!JJz2`88h1lUP%Yb+b28$Pn&Duxo(1k-wZGvuI1@<*^HGhLGCa7VbnOhzu}9JZBEMWIul-(VPZHY3>j?fvmE>^Zp(gP z=kq-dCc7JC37+h7l#&QO67Uu`e5GI9Gqorb{KV18wt1%O*Y28JNA`ypk+`SgOt0lG ziz`nbQ}6*H)!f*+<<221SN)-U;nx0X_dJ1c7dgg*)Y=^FYoPN7_v8x+6L)`?`*Zm# z7;QPoVBccv$Vs!SbbU6-u>tsuJirsQrN(IC=pHu7d{MWuK?q$##LnJg1{xcHR-aia zQ9gC^WBFvS{lQmv+$@!1nlZ?_q({RJ`4KgoZvDz@d%x^Y%5y{>-?*N^o(zZ)Yif1; zj|G6D?9Xplt|po%ackju(woc;CxY(8uMVHDDcUawPkXyrhZgFEK}m(Ac<+B(rT9ga zUSpub0cP>bi|&TMyBm&wvW<^N!idt^qpsfwFHFrp z_k&@MeyA(3{b*yz$k6kvKF7~bJ5sZxwgdgR;|xKyz2)renCX^BVUO+Uko<<)_dCp` z?1QuUCb4Cmg8XwT-nQ}|UOTj>tsa;;k8h8Rm*sCEg8nqgFKiiJ-rd?4IgKu49dB=S z5^v=sZ!$Jdan%fy*I{b(8Vm-_jU~(NW!7844_CVr8T>ZpJ23~CJ7&eRCEn5{+3a33 zeQ^E12V)r-Z~%PFTo$!H@$?+S_R(=oed%)IpY^F_vXPiQH0J0ER+rT@h!tqRGdb)oO{JqWhm zcNtyfklv3k*|XG6s}wUv9i9+}E9Przm4&;|F6L9MYi=#=Xhys_sq0H_lX(GKJCvfLl=PzIO=Shlo( z<4ZmhH*3JU&YBQo|~TCz59 zzxLK7BrB*wsG$8nSosDZ$+|V$LYHk~BMyNJ&gqRFv7Nt{h!CBqzphq5lZwF+s%FGcG^y5<@5I zszMJmSKO%1;Zixige7e$QUu3Db%EC`Eo~r*HT<1Fi&$0>lK_pDlw9(mH0otJRvc)l za|yQarmncv!)t_kv`NGkvQYd1Nt$e^Ev5R-NO(7K_n_h|Q+Xky` zIpNg1rHgfGRl`f>kAtiReTxRRwb&oE$IX}p7|JyLwXrlrN|cNGqMgbzW$4+J18;fE zauSuOBT_LVyk({073+8vjrWA!XF22qCGT1d}E~Y4J=mnZkQ;8&v z{=#BSA!hw99;_;+6HTEK)6(1}>pn>y8gG>waY?6YK$A;(C$x0t+UawzGMx}lNKA&3fq;D;9UJZ;Gorg7&+F4zCnf5hL~@Upc$4+B5z1lgvJf^xJCq`71ufI`lM%`x8RjA41gX>a za}h2=&(Mk}0O$x8A!jH>LJ=>7>Y-++`Yj3N&~rrrri5uh=BT~&B7ukxLi12ND7mVD zA427*hQWwq!RloFN`#g{#ps4%h!Mfp&@~bODnfMV8UetI&^U@=C8ASM3T;0Pp((T? zWj`!oA&erSNDHEgPy#fgETBZl{Z9^(VK^c=6r%<}Qb-2X@F(JcP$Y(72BJ|gCb38? zVqP#NX}<&^bT9>?VGv?p@Gyp93ZiiEFp41nu|;Sfl2IM92{ABe7+nadmsBJPF;&PI zatD=22f#w86fA*6qyZU>;q8`jmBBCG0t~6mM;;s`RAIh#WAs^DN5g{M) zt}r1y)J*`QAIff((7Pz$DcD^e;1>K`hj;~fLr(Zf(Z42yi@J*-)K1!;F4Ruge&>PtXoAh;Kp1XuGzAm&m(vgqMhhRfqOhJgh)$vi%d&YN~9@K?{CgG!;{-0;sh{7nIKBTa#j6F6=oWg$t*Y* zM%6p1k#k$^#8w^y0s0f^hBgm3Lk!_ASqmav!OQ_;PrwG5mnKCTP0w|p%Q!37gpopM|rwAOD zOu(1RhLIwcf-9N=EkGoVpAk$D85GI=M#NpP0@xkF6i1adE?|LCgpEy|l@Spm66Ubs zlOT}O0-8k{F;1Wu3`-Gfk2x+*3MTly+$6Gvh*wx&Mfr#}vlZ4!@=BD^3VH9r(Expq zHNZ#u8gy(V^#(8`K*l3_^`HF|yH{iS3_kYBeFAJ2(D)TDbECeY417x5v&{%fy@AeX z8GFYc!{si8>E_XN6)l&ER0Sy~`Rl?L(SUzMACoe5O5B6Y+=)ynCV`4f#ob`#7KLRI zdB)Z92;OsG`AOen&e#F)Nj-xc`DAKB0gouW5*7%E8}fs1fJ@TWP;&xB`h)g#LpP)i zNoRs2` z3=w|vRY_;wAFg-{jQlq*avh5hZD6^v1#pU=J#$?|tioEuev0U*xcG-x5uUfl2YyA+gL3jx;#;Hz-y`-kNp6@yTPq70B3kIh zoZw#HqvdpSwGX8^O+geP74%wYpqTQcqCp#1b?l#R>@Z=_#m|tI1{{ifKiDG8DSjl0 zvjkBjQ;=J$b+G*LunT-HS6vBHu%!c%iDHXPE-VqbBA24(awA9rc4Ni2f*_kRfe{h- zT$0>BKBm$y0%2nsL>WLDK-Qov3U(a)H6vq8#Dt7RQIzF)I!u8gDUt#3c-=kIrivb1 zYK!h?Z|)5K1m}SDhFeps{=j=ieg=8QeVp=_k9~yNB>*J=CIAW5{{ni(nf(lZ*7JV~ zc=C7KOVjp?wsP$NeTRA`zGkzA=n2*Ak6j+t=dg}?>M5`AT^=EYk(^n`wuJSNW}h~Zs%SX)M4GOC%V-0Ej*!53W- zSJ>+77WOZ)&KvT57(m1J{1iY}0;H53KYNptol~cLR1Kx`5BW2&RQS2NvqS zNP??eqruT>(qwC~t+95!XtZ|NfL;Igj=c=F4!N$6weyPhoZL;XaCo$xnY2)O_PZ*u z6TKPy)pFhi?X(ryMF)88pxdOopqsRNpj(u}jqtSXyJ_Xwdx}Tpone~x(ctUHC+{Yk>CR?MQ!toBcuo^4encM110t>5N^o7-KjEnjWAbott1h4a{A z4*T}SD&BQ%_j~uE07XtZDl{&v1WmV*=iB2I97i2hcb05`y4C=;U1*b&TWC{9&4d>d z*Rs<3zRl*wz737-^{X4Z`&q2Sij^}zy;qi2l zvK_x4AW#w%93%5m3d2yT*V1Z8CgGhf#~sm>PB-UAy3ecIlsm<3w4mL<<6qfx<~t?_ zGQSDF4Y{t|juI?P)v2y`DzI^E%`Ws`U@G8j?ONU{I5L85$^B z;TmRk6%%dl)=F$5kMTt8*CZsUy3-JgsWPNeXE57>j*vBAtnZX|cW$PSKj3B`d7=L} zIGQ?TtqHCZDts9edOuf?OMHE#QO9P=z%$$|7%P3U_tl-ir%R-RCN1$ZDjR6Z_M%Hq z;-pT{_<^^Ys=-WMkJg(P&Ig&)LY^vHHlnw(u#uQepdGd}TB+ap7>IeLYV=a7_;CVF zRLQrYnQ`!?pJSc#LkCjO0QS?qB-?YF-xcEXtq;G@cSPSZ+Zo*IS0iu{Xc4ehfN}tB zx2ZmgJ#;nFGEh0hBCu6}?RQ9LU@L#Q98hzJRex1|R(qyt5Ef8b0pe{4Y=6%j_-o*X zZYq7!Y7ljJ8qg#VRsq)PZ|bn_0iptE)rjgq;}D0yP63?V*81oSD8=7Qf#w3Bb8sm@ zr2;IvRk}eFfRz2?{YSb<^obaNDZmFo_xx+RG5^#$fr|tY0|^!YW&pv2-v{mU|1E&e z@NF2((Z9zZ2lJaTDD*Z+t-s87P2w$AocH+OfoKR<{aC`151kR7lch#gQBXccf5gf5saur9bSMEkdP z$aWwe1fIXf9I!0lEbuIltZ!LB_z=D@JmBx(?x^nH+%erDml1d%d4Sdt)*;qm)Fqc7t{MQ23{IvqK{5QHMx@Eho0(82gy5YL3{PjS(fPCT4zg0q1 zf>wf60#|}pf>eI11fqkW1Em9_1EvF~1EKpy2Q&#W2|5Wj3G52Q+dbu97f|QV9B@%? zaH<;pF;(-$`N%)?d9?h6`<89=<#g`%{}w%fy0N+)!0j`Dam|2+{#WTgPT<$`j=71gilKoBeANC&W{I%d?GygxKmwfD%>ZH zk7^@U0?%DkhZ+TSMqF!gR%B`V@eSpx)jmzO5X3oJ1-AyvZ#Txfk+IIW*WHefqXeq> zZ2b=m`;lEn8Ktu;uKG}{3Gh3br(Eloesvqx*VfF!RQnFb+~W-%QSbWf%{M!vJGZOu zqU^bd+wr%aeIuaJmtJ9N%&5?B7!SQ+uQpu-nJPD}D35Bes&UO{-Pr&vQ|I*JTEbg8JU55A1*RyK2r&sjVW!dQCtWa8`tl@f8&C#U)s#T1rf@rK(W@Ij^ znPVkQp;=qTvgS6upmAk;`;&#>yIAG94DSkm_`>7*`E=?O6QSdOB;<;;*hhM< za<*&fIsvsf#`^Z-oXeGWF*41Sl4i+DO12}0ckt4h=O(ExhzkhU})1HV>xLvEZH#4Q`}(9*Mowg51Sto^{3X6 zm&Cv-5(3|Ig&b6CjpOVuXmU8yIsaz zhV1%ut`<@Z8n!{31HMrmKFn(qwmnWV2rB(eHChd+Fg3h1fLmU+*0%YQ*E`)05p>>(w+8F(=m`l!??z8gG3?po4?^A7q(pqxrRqI#v_ z>30d9Yg~MA7*5q-EJvK9;ln)eyuoaWFFU=uspF=PrhMW*zhE~a$KV$!CBK8nA*Eui zd}9lpFd4fvs(EgfH${2LbmJNwl_8Eq*v`{7gr)-}8}uk4*Cij=%*@i=?er?&(O%JA z853VuG~~fpT8|^P!}Dmo9@Yv)CPT&F4Yuq2SX^tA&uWmTpz(YwXcCXwf3$83$>$g` zmtks#K$9>E-H)cG!sZpl<|bR>rI4GoHX4k|Cc=oCjN2zMNF^$9pzFH6Q1aMB3alT{ zscn|XPQ=efwVIa3DuE&w~nT( zj}A6Ii1(Y#XUHMT_XFLs!KfkU*_`Gx)Hh0#IpcFIjn)#tZ4&aLidhAleBFBC7~RFLV+u_t31Mb=JY z8u{;4oi}Z9SXZ<1PQ6?pzYLZeSfD!@7J|Z5HeUVmhT~&)s$p_-*Cvf`9^e#w82z?D zjbhFA046W1@WH&J`wkUe)7u$X8VExiO&`gjYh=}LtEdrv(@$cmrcMUyaJm~(@&(1^ za+so9xrW0o&X1GDqv8lz8ALqdK`-jfVUTk+hz&cmXzCcwTPud=SlJkdC#ezFT0Jzj zgn5A_dAghGdr78aYzFV?F?m-oj-^0v> z$5UrJxy!lsI1hHkYvk!sV$3*L3Ln9WPg$kO)M6W7bng5m3DqYhUh)-f@3m#nDWEru zOOu}IVmNzp9XF+b5e6@}Lre~j!v(DHWwM{xe03g|Z7f>;8U3d`DLdcn z#0&X{tYdb2YhNleu)J@8r+2J5}f>bD1bPyDZl)X1^II#Ji zf?1|`$nVMWna@l{&icF2?-y~frty@dPSwOV`^#arj2yy3Vp5KU6DiCtyFug2=RK*a znd1ko`!sDU)@-C`r+5a^dbIjJ;5Q>W6JG;~TbT9<9D0;!Mrm33@PO zumBM7`|Eya#7#h$If>R$c~|#__TM$E@U%5uamK7%ro>isX9GH}7>z_tsBch}&4{!r zw!(j|cqFbQ-Alo6VzfzV;nMhl;kFry@_k&Rl`ewpzPzj!iG1xipEG|aWi;_N+~3|gt@zBuluyAP2n>xK;PdJtuaVAf55qG&|M}BN!CLOa)s9H)jDj&47tL;xU z&ZMLh(>0W37*kh8);%OXQ7yZ#T(OKJjR)fnAG-G$*_y8EkH#L|y_`SdI9jHf{$kG_ zfJja8<81Pi&At|N=~Dd28J1vJZ5i2_v~R^Lb49#1FL&6gGL-j<;D<=hJd+ zrdiXFB&4UAWy59P-j|e+lq;OGkO(M$q`dVQ<=1R5Twvmj8IzHgkgp%zLq|7jCZnO* zHPsSxlnRlZUE+19KRi&2rt=xKY&s?ll-zoLFSD!ExEs9EGw&_Rvj)_ZP&*KN-s5{F zOoTtyeA6_6itQ6Q;9kfgt={bXaMP&g72_QzkkwH!Q_WmnUw7CWB8|i&h6{UUB;^d~ zN>*&w&#;!2k(Zc?Ja|2zR;!$sY>Y$|57{7Lb&rOZR<>rxjM`jQ=GlPyRlPZ-)F;s)9re53i-wN7~#)*x#lKP+^gSS;g-urPKQZF2nTJUW!S(77n!fst3D@Tt_$ex zu|_EmT`nBxxmcrW7S0SA8!To1giI_!)G?-onV&C=7EKq*j4GQ9J7ca<0kt!cJgyb1 z_u3cEoH$N8aT;^pO(`HLW#(S(rfo*!r{sHx%Z5LXrzz_gk`1Old#&W*Gk}dTw1zl$ zV%#(fYlhL=_s?gJvC~JHQ#++Ji96F|+n{^wE;pyREo?DWF^j*;r2Qi_*}o&aq}Chw zXZ}O^_olxQZxrQabGEpsUM&NsdOJ!8b%-+%Yz@RlrHi$VdptV=8d`;mav(}&4Ql*g z+MtRsR^kfjh?gGUi>CCqnLLpBZQ)LIRR}E@$9nS@ZvmWB%jw%j;zcm6wj{9wt!YrO zYeGF3%Vqy%uHx^jO7&L>OM*>ARk;r>I0ZQMSLN&$4bFeIArOgc<;${${$zADw|Q;2 zDl9W9nIBw*jF5kubQZt~&aIKhDOjb8%EPDZYe-vTkuFosL*OH7GcSO9sJFyFi@dMJ zOJb||QL2n*W-ov+kIvmt1Gt)xZz{R6l*YUE&-F=fm%I~-c>Hj9@OlxXEsW+^<|o)^ zwiKOt-NeUI3q4%pqCKj?N5G9eZFtb+#D1{shpB&HuxAT3Z)mV!wVr;T#!Gz(_*6BE z9K2e3t%}Y*B+aP+Pb?92sYIKfS>eY%HBu&#$1ubpZh&BfPW#>PQMW(02tZhD+#4iS zb>j8hom;Jnsn^S?SSGWnoKLvA3<%r8de|KvwFoP(sVO$$ah-muy3biO4QxbSP*r`J z3b>x&U-goWb=g?S*3xNV*}E9NT3Vd6-Y+)uNRtmGk`Gkfa;~rrRrN!ZCm&PbwzwwS24{Kt*1?! zq|Xc#w1#w6JM(74*}z>8o*S^NXI8JRoYadF(Ke~fbR)ei^R4v-pf9q)C&-5$`&);* zy3IecTq!FLD~4cQt@x~u^^D*&J&PKJ*kIMwGFK(mh^Zq^Z>{WHiZVECSuY2-QxZAw9xRq|}t~j!1qptw%7ApB|4T(z?e=gv$iwoP&kJoZi)n@5^8up{? zaiE4*vG_r31JwBz!`x|MWN|A$5}(tuo~fvSZ+d2722(|f8zd7CSg*PuuR|bpb+wen z+QJgvl@jJd=d)YWPgt;|s-b{xI=9}LlCPj5uZO@~t=0QN2YOZuJ5fweOZp7lL`S+> zAiD{#Vmt4j{*nITC4CM4=-CtE?AvJE&ZThHu5Ez(LL9_F;Biv*uZCjGRSO^I!# z-6PmEqhF5x@2--z1&rhDfUw+?0ekq6yhvJ1{#TA72+&S&zjXR)O}v2BbfdbZZ+dQ} zhp+Ik?HvPKKN#BD_@NUGR1Nr4HylP zl|zsrVNr_M347K@FiVa;*16*mfAJN39ldnfP2Q!pWjYkCI39ZZ{(+yC9l!LxNn)I)?$pvXGxE7Pj=xT*36q|X`{P~DsrEL9 zd?-EG+&8A>eaif9j4oLS-{dv%(5)@%U8|DCuS`|!(?~6ipHpMXPO5G8osv@Q)2oWb z?`(0Oz~^1c`ryOPJ7My!JgEAyt4IpzTb%P?sBh#57 zJxXV;*hp*ArsxV}5~}zJKe{Qsa*{B8$LlM(vWjl9rrZc&0-@}RYBHq!=sU_M1@*DD zs_EsRL0Toc;yn78dyY7|DYgQY;Pb1tCBZ$;`;4B>s6X;QZzlKrN5X~tiWUWTz@LV6@s(_4L+Y2!rMJ9|%4NJZx3BPQHQgF=3fJ_F ztfr)Fp0?a&TD~1--*VFdOHL$iS;WPl2CKTdHs>%CM&F<*gI&Y<;^l*4#lZsK+^=VE z(>g=>~2_G2a@|8ZvM7<@fuJ z+V>OQc@7)*3pH1A^IhCCze!r5Up%blweoZsX1U_}N;%HaBTRZ)7s}MCv=Ga$`ua;6hE%Ubjqy6aSWuU~^`?JSMLpz}KJ&?`sVp2vv4yhT#py zU#&lQp__8^2&qroucvz5x_O~b-&K*BEG#@ujUNxM6VL)GP*RgIun;ECSR1s^3AUAK;GfVpOsG@Gutdu{>RoU!0ENf zkd==cGy5ZQN-JvWEplolhVS;6cocfiDe9(W^LgFayVJnimYL6ur3&%uM7gC`o?9wy zraQdX_4n7|+1F(j6v6t}1EZw2%{#o1pOr4DuKwXBrE3^*u2P1w4ABf=9zRAE?e*$w zJi*H7{VeI#&M$N@+G?pkx(m=qA?#PS;yKf>%jI|Dq7)NRrL08XY5Q?Hu(ag;N12k& zdb+f~dDsRfnwh_C?Hq6_Q@Ct@**&|NvUi>?@(Q>9a4SsE2vz}=Surd)v6)jdjCjE~ z)B_-ofsAS8vg}BoX%3t>58eE_t=Xe2$~|`?ZL?+HIBeZ|2(bwBYV~S7p}$PLbSdPO zEF@_=kx&v=3OusV@-qRFkLNtsRMt+sMe0Tv^T_s!3QqVJac8uuoUh%5O3nad(uotgD;o zJalfpfSSePZK%_xD|oa@Uad5HGtSJe$rC8&WwGTCva5=fN>eVszo}on-#nR{+mhI-ERwd8-*RX{E#v)&IZ3=x@gqFhirX~zPL@9^ zz1aw1E4tYrV=FqjVM*UVV{3a8m@T$?)nRU3v*vr#sVf`mv>J<4*>ZxWEK);I+R{zz z$W>T5d)s__ZU0@Qo9M%Lf^vy+X?2o5-z2-mA1n15_1)wtefI0Y{Z{V^XWmF*VH?91 zR|cDr#AY~w(1ZOVvPj-`)k}F~dNV&gq!P>3x_LnYC*+E0_63PO+MPd(58F5E>`8nc zTdjdu_RnjRV8w0zRWW;g_UdsYf6tAN$6J_&eP~s^vWEEH+i1wlbprPnCy~=zGrrg; zKKq)4$KGP3SLRf^gJ?d=UUKwP6u++;yoGX7sP>9RXdQeE_3mAYuUP50QXMw=b7Z|u zuOKmAc24gNRIK$_5aiUtIpxYwE%lYIfTw{W#;r{{Vi<2~v$K%#?nxMHeC^d5x5w?2 zlHcNq8Lz2^sch;GzOtH=XM4Tb$(9kPw!{5{@=?n1l5s^RqC1*9@JSqAyTkSj59y!SHCbP}h^^A24$EKsKbo#@hNdjiS(|7s9WLnI2{nMXI7@JM@7eZgXucC{h zJ{TJ{#~-3*=rOwMDNB@B(LD0Hwwq@j+_$62&N{bqqy)5-db7>*4fPwd=}DWd&abmJ z(qqXFx@?{+pkr+GUT!NjCb2`}yq)(q@=03BF`8Lz?|lbe$=P}{1_OQ6jTH)N@H(kY zj-m8#TjM_nbhrp~c-EfLbtGPScGnyU2TXtYF+VcV<2hi&#H-79otMwC+|^59OyPBQ zV8ropKTFZ&FSqAR{T{h0ys+tt^>{u8Xqw6z!Lvn=H&L#PSEa`{lG!<8uurA#%Z53p zS0=moCDgz4u45^Ot$5TkehoUh$gZyDXZfmSM?|%YKOBjDHvgP|i+y8Zeo>XeWwoR( zbV=vHXPpgRAoLz7WoRAXvNs@IE^T^)sQYT;Px-*R;rzlf>SQ^rnv($# ztnK+SvJV_)FTbNd#d5}CDY)5q-kmS+Q#fgB7FH?IJM`??qWC0sN?Fc1E!@#?chs)+ z6Ffp4_QatxpPC%5B;B1N9L+zEcPt&t)@V3;&%KvSovrU^`B=WXUdqUfbvoED?zko` zbD835)UC2N@(NZ-*=YKtsV2_LUC>~t=BQWAFR>9fiB1Ww=v*j0kiX*bCj0U?#J4q< z6cxHiT=YYylqN4t8M)Dy=h3PubaBEkKvl+c7Ll zui^XTCo__@iSLb`B|mZY+$A|U>N_y9 zY@=<^s)A<}GfVWLz;ARlOLX$VcX;oY?5lp~XSj!sN|jqJHLTK4*c8*|T6%R3u|dux!cSg9-T%KY9@h9Uaq)_!e8f=_LDv zd$>b(OO{dVewfSjyzO?Ea;D!6 zo4Be**=n;YY7F0k36--5xX@@(>=k!d{$M$ON za$+@A@NMx6-AkB9oViIBjrO6ohS_5TVQ+uDVdc-kRLd+9d6?iSaD!c^E{|H8L%0uK z58d}bQCFYHL|rX9ycM_30d!8hs=7ej8+b#@c=Zm-^`m@d-iSFj-)!Me2=C(c2HZF;$hTT4gxUYc^>S3=@wL(aF1dvU+xsfQ&nUVm`8H8cVgYYvb3&5apGq_xWn1Bb^+;|OWsxSRIsd?cMf5@^pK(jc|X&T7fJR5w@0GtLj6D1fk zX<5vf?e!AtwV{vW4SNYkM9b3#xTDd3b1`t!6{f=mt>XgUb4|r_P2F>i!m&%%@5HQA zzLNb*ovr|4L!iqe44cQaYu%JjlphAV?giH8+RCA8W=byp40CO~Q1Qn9cq{jlalQ-i zYFG40xSu7ofm8B^kbo_+kzV}9dioahdWj-A@0g@HsU*$Rpe;@7R8qj-a9@husS5D_6 zapE>6;hp(Gqu36KHeE8a!a{?uf!C@s;i0~ASbMZmSkt#r&T%#rQZS7Ee+s1qc zEj6CMWewWN&Jkjr@75>|=Hh_Z65yRiAA923?XoJUnTM+MhKoJ?Y0DtDR*(_slDqNW4Cb5K?>RH5-ZE~;>*I#(qpsJ1-24is zmZ}|9kbK4HNB0UD+=j%MmW7pL27a6h>}l%%U+FMjZjtDTg`%fsLKb?#-)XE=OxUy$ z(R~UeFIn#s+N}@p-IU1B7s3=Ngfuew87q+cG@uSLfhwr!|CVkWeqsM4kO$8t2g?Uj7BK6ujZ}@sEz65aB3Hf} zu??rdF_{KNYP_TGsk1{c%gHmzQDYX7V-=wtmgI(dV2>k}X^3;zMZ22fT@0_L_WX~b z4$Fid7&-9Ws3xeUi1APg(}^^)<-3(O_@6k_`des%8<7sLCiSc?X4W7Z`;6s$B~O1z zAAgbFe<8nqN&XdGVqZ(@UrHKZN+(}}uij8Tx_MI&8lcSTUrc|G`%k*5-w&LRW@iWS z91I~Z?<99GLK&EWC|$cJT%KbqN`y`{OK+YM$91L&X;0Q{uPp3{zw7e35BchbN)) z&eW`EigQ53Ut3W=yAFHIM7UDaGa9KNPTPv^u#Wop`@JCUA&GpVl&H3yCTI;uic`Ku zcJ-q5>|Yw|`k$y@)S~RF7hcPxg|&`u`pL@^+5_X)thA6$SJ}JZi+9>Dl%%UQMdzhe zCkffagS9_pe@|`E52g_?xat{+BGaBpjB(A@M%R}U|5vJ13rBkNH^3&{NN`r3m6c@w z&!iTDw5rG$K}y#y!C7%uR1$+!=RXlNdQJ{qM~2vSdQYdtwdv;WWnz{bRe`Uo+a22! z$fxd(-k!~ge~;MWFU|_luQkMkk?1RyM@;-oR8lE4zH6lbA>~U{~snrK*hpy^5 zy9RHE(%Pn7hVBY#+EJ^9+YGq4wsObV41C&QuLkAwN7!kqMuFaTyY_Om3dZG66i?Kt z#(C`C(x-pok1rVITSgGI2ZA4E9wp>}&8`bf>0KKItzEulcSZKvVP1xK`wa=-EyzJ4 zO&hx7q>=WEh#F;8K+7EBf)H-jq~L+m9c;S$HH61#gKSE3>+fIfJM^)EyJDmHHRw@8 z)8H%l={QMTJL`(34VU>F#(21{v2q%&wU2dLIBB&qIP12!0%ID(`W_6Ya}C^)7hu-6 zkF_>|OFmlX8ed+Y-U9-q4~DZ$h=jZS4WpS5N>h*tv5FT>6VzcXY)x+6b+-|vDYN+k zFNfF}WYw2L?p&9{pxu+aN-Fly}IGUWR6@kUmIEsJw0T zW;ENt8GG(^V7FdOOqf&#_(7NtKaW$DKR>?l*xbKOehiQ=IuU$f<9EobwNO{Euw7j{1Vdv}>xFZg&MZ8luGw629+9fku0g{>66lqP%@gW32fp z(VD?@G_OADiPH*D+g_*sV{%1D>rYI9T+yg*YLx$xx&l0>zYAHz-PY4es;>QUXud$2 zb#;L-#4%*%Hq}nG&R@pAN2FV8m`3sJd0598c0jBiT~*gHs;jhLk?pl$4+KN*hGwf4 zCgSLZqO%u9uK#H)5ujoYXA{)7`EOo22EzM|GA+k_Q9t(=m;|yy8LG?SsCG+T$9`FKrr+3&ucmX@7H+C-|8R%f{M~sm%@WZy#LH7}mGB|Q zMgr}@rD#xPoNP(tNyf!dXy4UfkHySQtzzhPSs=*8KtS#~>qlP_bN}3F$w^#4znphr z*~y>$CLOtzcl=g?9jlK`>}T02eQD};I_=jqP-i)_#3B$P8)yI-8N_%CGpFv+%>sXE zsKzIWZ|3F@xiP>vWbDz+2$mIRF!YZHfp=W@WG5a7oNW(xVBMgoYh>%6$p*~rAXU9q z*Ie%)|H0Ueux+oy)eLj901Kw8{+4!OguD;zizOLhlV6Wkg=-vqwDM_LI~xbS4tRG< zF8e&&&EnvAPrW|Z$|+>>T&8`vDKMPXKv{9vH5UDaNarOsB7p@Rk~v%bdwO;Vp6t*Olz?qQ7Iqxoh1Z4L+uKt`-pv`r*mWa7*rdEzF0z z#*X|^$dI1o-@$o*1TUJj8aB(H`~ZISheR8+g&N@nRlZJeec3NpwAo4_2N-yFhi>UL zxgG!HN7m`U(-Xmm`nsP<33G9dcllRm6Y*V3>N@KjbJ+_6QQRMUSI=I@IuG}io|Rud(lfbx13}f}-hyxYY7DkU zacuB^0Q~vuoDc|Bp5h%rI0Q>~g}y-Se?>C>ErxFSU%)*ms#8I}pN_~k3xI*-K!sHK zy?1~JFX}O83csFGIGxE^LNrh%t5f3L3*d)vb4B>c+pj0~Zt{PjJ}=TWVJ4bsRZ)z4 z)Lb0vf+7#kBoeL4`zY?EQdiroHJ#Iz$vySRlzE63#L2(a;wJ2{#g@})P|BmbMJ6OO zrq59wn7Ri-zME<|bm5w$9QaU-+$k@f9jj0^5jZ7!!eMFz~prtLSO_1ZmLrR}GHwIXG6E z;2+v(Rj>1>lg*NOo7fubYUPY;)W0sBIV~E$xXtqcdb8Q4G(1Jn48J3xUAM;_!8JSJ zvrp~~dfcl1T9VTxCms;Y|G=b#&%MC-!kgB`<%$tL3aj;}fC2n(g21`}$%}g(g56_k zdoIf7Iq^@6NPjyl;6K|JWl1jfx>7BwzDz?TbQk^7gWcY)Z3#9n`r3Tln_`M@!>F?V zR{?7%KFYxxMbR7oi@Au~{2`*=v&bI#ig1@#q&yT*M$6c6Fe2UW1aOB(nj+lg6yXUC zTBt|V!x*uXjX1!XvwR(xGKo4N{b0XXw_&MBLi&CEQgJLA4WNv{ulc4rrZk6bz|Jdr z;!-ZHvzZoZO$Alx&#pQayNX~HV}DpH=N`&bQ~d= z(r?!KfW~R~RblM>Kle@wtLbWRxc>x$oGR$tp*<4}xMJNBm|#ua74|rhA!|GE%_xK2 z>M3%#f2}9|4DErb+d)bJjp^0?x91FRbs!i6B$^N&br9);pm$d2A6jIuQrLaL_1@oTuveatRu6b1EOLA z(GQAKaYg>{SH=05Twm0OynkL2o3|7B_)lP*7*Rbcs(wIJ?uew?0$HXV^noZp6>q z5uWij{ferY%|v_P+47#Ibaebe#j96vRCe!;M(`Po;Ol+8C!A@~@g9kEjYhmpE!M3T z>0gB@4UvlTxT{EspST-K5cBT7KSa!r|8g@NBks#{yZ0|jT*2Z+*T<;%nZ0?+?#|FL zayv7WVt`RdMJz%pViA*|;z-0qq+BK;mH$@cdEBcZi1~0oA2Q;{f4f?!8`x9& zR{%{H7j{=45u&T-Pf-$g^rPtAb$*9R@FPq6zu0>?et>u3p61CndTwfDYg-=; zUUld1zzV-OBmem`0G{AVN?ZcGnOQBe40Ol?t%6 zOMCtaAVo`7(N=Ph9Qb!q0Iglx{jUHcP%=?7Dx;Xuc(A8-abGYOE@0dLb5kX>)umYL z-vLK(1M*Z%f&FJI(tK2o?KcdT^TYt4aSs1Ekiy9n*vq0ZJ-Ykwg_jw;r~y;u0egJ&>59x z`K)20BBCj35Eht$nBeksm&Lc7H-tYsMBL*))1&;h*2=E)p!rMxMNm)>6+{F3fvTeT z4}t|}ASRqLgJ{YU^gq%neU=~xib!DtT$azwcRR3>Ms(c0W*JujwknM1>R4J;dSEDIYf3;5Uto;(_3R$X{%cY3`) zn=NUrPF5QBqnX&OG&0X97Z8GpDYUl?msF&$Dhu3}X4|YzHX80PSHB8Y3X?X~q_4^f zo)%``EKhtI?mIO-^)9}abYednkwr_U(zditgE@Wa!=<;vB+a#g8bzPgqWl)j%eq!@ z2g1JH!~M1!PWj5(^CZ54q_0t49q&*xhSU*0#ui#aYz>)a4XPw`rWINu`j;VB{>NNV z>51~feTn6(3ad|P8s87u>{78O#MaPh-k?iDXN2EgkQ>6s_(K1b2Q}_n_P5p1T0JOsK~k?arDM zXOdu|1dGpv#KQ8P*fJEWKwddBj7P6ED0lwdH0LExC7Mt%nUAKKmmDz2?t6Fm_~0s(>t zw-DUjgD1GVdvJFNTDSyvso+ipry#gf6z=X6u7y=|&j0>E)d<%pJ8Ut$JyE^fTU%NW>%3HfCvDaI>BK4WdQVX9cv9LwEEc1UR>+Kh^xLVK2|IR3I zX9Wit%fXje0fh$J!9Lnn$mO<7hS*ixmQ=%wU7Kz9_uE2A*T<)l{@1&_=usPLO#)+K zx#!p0XFnYEd~Gi`Z+lpSb^|z{ByQQug?jHHn=Y!GEMZP(sa=I{p4?_uHv&)#qJ_sPq_EX(?N|42A4P)PVijgVK8SQeoC!wr;51Oo0CDKFHN6Gt$5J;F?ofTKIZ;v}_oMZ))b|U>EFA#t{r23w*vO+$*ghby}nP+{aO;N{ZQ{J_QyE&eBAJ^D${9_2A_UhcS`jVF z9gyQy&Gzxw_DG&Cf$b=@-o`Tp&q#b2li`kctiyKqz`44ysMm{8t4`~Rca5otQ74ia zpIzksn7L>ssKknj=F0JfhU;mYLjUW3SM6>nh&q1?ut z>V_3OGF-Q9>h44iLut+|nNdrI5fG}gNQCK$TE-T<3ix0tr|z1H4^tYdfz zXVH|6sjl~3{D}~Br1W#lq~{U7FFw71>9y^(dsU5ktiH^}-%y{$=L_h+>Rq|VpIzxT z)GzPH;`G#{O35F5WLVDZrx#)Pa=o*REqUZM&t)7qAf$*(!r~3V2k)BCw)VXN`LedY zdthxvvRl7m6d5`1wtaJJvV>VnzB&ftEh&5XH;xSyxaTXp<3i2$MX zxUtE`zZlt6Qa)tU-N!mY z5_nO_x}di;K5Yf(rxEpy(ywfe+$zCU^|SRJYYI!-mN$S* z$tQ{Q1Hpem+o-_S&EQDwB;8^q&SzJ3MPwO1nHIPTAOdchMG%=qh@{Y8WEOfqHOSRy z_b6h`r$)h=3)~w@{4__8aBHh0=B^6rlsTUyahP#JF--81Ym54be1G8h8nc`h2aOSw4=De;-u58He}3hmmKJDJ;u zS?LamAQxwM1z~NoYsfIt-^koH06i!uUz8XO*NOc6Uj5ERy{4Idjvd#wY7T~znf)xD z!J}_sIJuB;h-J?%2mM?fj78{%VJT3c8%5hMw4z7!^0*>+7;wc+vc^;?Y05(@UT(2S&e$#H2r)Txd5(N zaS%)`KKsDD*n7Uzz+H!$0oSasE3iV1g$UOS*k(Ir=7BfN$iyxirLSWPz#C?^F-zrQ zA0V7BkZiC@AkZ-j!%NTaRp6Q{MHZMQXQ)Vcp#xJ3&bIylXL7f$9dN)oi=k{+?%|2N zmBL)5-8hu=0b8+zUkCk7-cW-NM@;UuqDhV6=XlC1lta3gJ-Q{E1y#Zfuqa`sp-8_O zMTsdKOfE?Y@b_Gr@Qmeaw=lm-P_Jl2&*;N1D{&bSB<#c1X(0FEh2OR5 z%ea%xZBy>cajyqgMg+d~V3-)i|8D7OGwuH8}J-x4$km z&E@}_uG+kK99Bl9+-%kQg+ZPUWGC5OE*`or*<9_o#~Zb+6-N0WlARTzob61T0$_zL z02HG!WAVJdal>-i!FHfKLwRGJH)zq={mMeq!ChdaYNf(G4T{cT%>m?orc4qGP`B;E zNYSY6!DzwUaD!w&Vd?DG^61~tuS7AwL(!sytb?K6(KANBk%3o)m7P{-QiohRuXJ5O zl8wqf^973oV5t?Wtr)450la0Y6E5#+C=a0@5K0tn0K?!pz?>OK73fkaH?ZC!rD_;3 zzc5=$X1A{u@hnYpQawK48yBx9yA_ekjb@1*W7MviR@8a;Rqv_+JGxGRX?d-c+FO!5 zd%gFqCF_Fni=ACQ6&&4InDpN#a3*-i;NQ~l8hrXQCdN2hTD5WM#%gK!2L)EH6I17_ z7h4US`inYlZVJ7z2U)(WQD7U?mZ4Ve(7VGd`nh0DVI)zHSA^Gx+yKpybvqZ&MdB5U z;Q&~xNC;45Jb-NX3A<JWoPOsq_2ulXThd{cd!hPTi9OF57KyY2)aEv+~Ggzc25=Rl3X80g1 z`%0MAp(L(yA|B z-Jv8ALo*6KpXf)KlPyvY>KMv2hCMO|fz}=c7Wi(*9aM0U6wF;xAD1Qo85|HePDjCirJKba4?+Hf#m zUT=1T8jnSmpVZ!wmY>j7K49srN7g*NVmPTi&zUGAA||SRKWY^?t*srGe5IwWc!>#Q zGF~;f)*ozV5SdFSYVD>ans1nWOB7Rc*3o)~FVk_hIM4vLZT)HIgUA;*+!r*wV=^jL zwOmY=S{-P3{!XQ|xyA}n_J`R!PI5s7Ch92_F(&Gr%K|>|fDRZ(m8e(k;Yf!@z^*VF zOP~gVE@=5CXHxolRvHiCW~O}gTUp3%=Zey8Qfm3PGLPMqJQ3HV)adVYNK}#>5pH7I zWE74hkt9?~`L{B*o$`Y1lhqc96pUj79eBjO;3MV3!oQ+8TeoQ8qGujkzSMm2=cEP! zLHEn3695eT)nd`r&f@EqP?fhiie-RK^;Zo04)zCLR z(=CL$v^HF5LbGhJGXA zQ-gnh>fclhGtJM3ZSo=&Z{#`>3I{4~xMl@%oY7^4DsFPzG71AAo3>fOENgncn8Bxz zTdelzY9rPsq}}y$UNXb(j*Y`xEQ>OP3=qx@$Z5r27o~1DPwopk=qLYwN^QbfC zr=XjzuE_pwFs|a-wnlU( zH?Af=O*~glzR0to0M+hO)ra>~-Pom>e~wGPmho_^`Dk9{U!H9%BWgbJ7%}NTLG!BVbW9=KK)7$ro$byWR9sa|6)C zEI8ysy3H4No+a%y#+$>zY!0S7+!p01_t*F>@9JO`e%$@&`4`3p#mJu%Hf+e6_5;$% zdUZ)Z7Ng`V!rJ%p1IB#kT4VB_@7!35pvexGtYh9qC*e7YQS|TbUqQiI zKB5(1@)?5YK_wYZbhEo(3IOC z&muvK9_ySoeosc$-QRzDmf-74OGY--4>&)|_w}{n93qke7(e)a6d~(_0M0Iqp)3Xd zP?j@>rLe^_n+N2MUXmv4ivrUE%^Kn81|aZg&r0C#2TAsKY0Cv@y1Q!;Nj3p)hp4y5 zM;p!lh3Q&%w+ej{-RrMf2Hd!D8*GBHG^d~Z0mZB&il)f^ap|7OkPW_v7Z6iC3sdx` zaC{|zNa*%g;`MCkp;be5e`*+} z>*DMt1BrA_>Cy-Fz8L6_ricUmDh5ML^NlNGi?%?#`Hy~#D_c#?x65B*b%9T~ zR0ZPnQX8L_qIFqOfNaQ(CX9W?f}|MTTT#a6y)}{M${mrPw`zzPYOuU2#QyQ9YiJzE zh8O#XxJ>CW-VJ*_TJc$EZO_nBbwno^_6@Lf)89w|ewmzBss#{7Zl0a7GP*@>65OhB zDk%`8+*LqkL)p&zKf+C;AK0XxKGFq5Cy9g&k%_DN(s2>`(p@=f<#_+P6xmBH7Kt`> zWE2kKa1>3Wn~;k74W+cR_4b@%@q6{zi1N7C?0FfqFFU^!XN{jn1MY@^J3pNA|&L|*N_zH&#|3uCWohwd>C-Rl_r*n+E@r{`GqP@#eT$ z_ZR%}=Ip~~QxwuZs;V!3v-O#cT;6XH7XP~u`Qp?liS@GSkR{p>b~;CA?Iot|f!gKYP! zQGdlt;YJ21vj-EJ$*vmZCXd$PdtMnHVO5T?jIJ7@rA}Qtlh4OD@`iasrWb(4H ztcqVR&;`2x7oz!~&A$Ldy#2=cTKo)K4`6&t=O1>+_PpOlAFG5E*x6QOKDfg)lF0oMmN4R-M@Pj3?4GI)klr^tsX;n4i zsI>^q)oLr~Q`CFwwk`1yab=sD#1M>4br7l=2vuepHZiX3&lOf;PgY{R-7N+fa<3ZV zRx=mSG$$&<&&65&m=m`P;Mvp!25<1FbrjygrTn~AU7P4&o;rl84Kjwbhx+hyFvEirMCHnMk#jDA6 zc6+{7J)kvF3$>9AM3oU;`h_cZZB8B9W5y!Q0D|jTBt#z=`)liIm)c0{!_U( z5;7+DzoB0RJg#c69_CA9o@*nPYf-t95unBph~-kgF+9le@60-+II!|J0o17avNH;V-HfXpOH#o&OOQ+ zg^&YU6#mGd*n&JDZOManvPe0Ic8?LI6u5kEOnkBsF{T)#S3XRugd9v4Y{P*l^+Dsd2zZ?Ng0`a6qA3S|GBF8 z8I;I}mKRA9u|Ee2Ng4d8CjU$kKa^fp%Dqx`5a15sr>9D-OTAn1wbtZ}-xyFP=8L3~ zcG|k^a`Rs22cN!t2Fj;mGJ`y_D%o6Y^UEH$yC4a}_&roCKhXjft9%uUe?+m$_r)4v z#Vn{K`@>F>9}7jkPRzm?izY;RA&x>}KD%f&%wX}T6$+@pCvQMV*Ps$FfsjN2;Oj(( z8-k?J0avahC)%G9s`%+HLP8`#NfcO;_a4{vS36~Xh?KGz0a&u2@#`gC#0n);_mg*2 zh!~*)1zK@@nCjQ=Nuo9%DsIs##o;TpNwc!=?9-gV))}HqF$F1Ms<49}c>7448?wfn}&sp&^uE4fQLq%kCRgf_Z!HF-rMHz0Ho$k>}&cw2{Kn6fdf z;;S9WB70^|*Z%)gIgf~oWVy$PJgM0`J`Js7C~!!5WWBSWk1Nm}dJ?)ztt&5JNzx~I z)P=*Lz1!jiC;j-LEdBTZmfq?Rg0u4V%(IqLW;`!B-f8V0w)wL@4F?TpDB-{E>3b?o9YK|WYigAAKAnQZz zdhnz$SYE~KAl)f*V%X&AUOdxXw+A972K>(YYUcMWiTr*-O@Sg7myHEwp5M|)dD0RU zgbnbjA~U<%cy~*2^R?CW|+;=gi#;A{TV8?7{b&vPUkH1F%ri^PrE>aB;m;+FFr zlDNhOY7saSC1TGlvnXCY@7u?&hdrY#k_@2BX%s8X9kqYxqN9L+%<5WW(<_e+d+scJ zLZGIYskWCDbChzR%-@Z6S%N5F@NHWfe_(#kl8X3@ zGZa9C()K{vI?)NaKC9((F9?qFi;6pn@;F|_I>Ey9qaZn1>0np^b?~hashqVxW^Uee z=XrJ)jP>z&;jL3B4 zuYb zq>-CWC}V$$#as?Ru^wU5r2y96X1Ai8>v?aLnZ&xBq^n;Rt=w-|^3Yj~a}KMGgz^3? zsqW<5MM0jO8R1#ecPS=F8e!_CLAiE)8m{?70^`93FqHDie>r@-loc{$5x`Rl;uw&a z%N^(=>CP{QKd* zS$nzIk1hrO7nCXwcvW>GnY#k{;*f=W%cF6S`<}MIWxnd)$do z92$~TGOgmylv#MG+gi7A@@s%?)jN-;y5*<;AGqzU^ItmlK9%ML(C_7 z#NYZw7vF0AC7NDd0QMbE{{Jay3hYgzdvoP03zSKD-@MKZFnpN#9Y3D=4m__c^hHpg zxM)00)oSQ-Mjf31x9wo;vma9E{zXgI=ecJ=%l9?5egJ(%%#eDrNXenA-h<2~+|%FH z>p{m=&Hz!*Uznp7-!zFG40)hyFDE5 z^_Sl3zdU7Kb8gzb);#8m3HM`8v+hq=V)*(YVJf&6z+gR}+4+f$8U7dG>8Q_rM8H#P{2Od^@7bdyo&xT7`ReZ!m zEBl|SA1FEafn4bRAKZ}(Jp)euctZ}pA%DEin^^5ADYW;A{=GoY-CI3BxM9fQMb-9o z*}nc7)Al^li^(;0TF1w3s-xohhAY_kv(2lF0M$LIO@|YE6St8Q9wYjMhWIPA{tU{# zs#^FWIDVgVi2Y`GBeI1Pex|FR!S|kbmjO;{KWG1_NNkz~g6)LwQAr&z#u^fqJ}=4Q z@}g-UnM`d(0AfX)i95RqyXXm%f_?!gH17oH`}l^XGJedWlYU$jQh*ee=u-=`5$P%kM>fY zQ+Xg$T=9(j`Ym;(LGV%nfap$39n==-VYML=jbK63w`d&Y$0GGetMw7OYH+fNUc5mN zH}*9hMh0Z|F5VF}P7wKkYrBbj+G-aTThJ>^a(P<^rZ;Yo45S7TA9!vD!}q=_YGgVM zB?<^NLlWzE>N>2r6pwLn4}sNEL^YVLUe~0sUg0(t0li-?&AeHphM#ryNc9O2<7d*b z-Iu~VX%PAK(pwGxGo?$ur&A<62iA@GLa;VoQL@x#_ei%BZjfrlJ?$a0 zMKt~4sMg_*r@5=+;31yphPS~n`Jw>8;YI7jPG zwDRXx%D@fe-8k6R__3Dh6Lo;i)eXlA4$++ zpF4^lXxvs`7)sVY1{A?YR(x(gQ-s8a;PJnuC+|uuSnG}yyqs6YLF#>}At4dDri!T? ziE=9uY19iK!NIwtqsRM@KnZ@Ee`COoI2i#)yn7e&I_K%BH8)#8z{O$*21`H5;%N1; zcOdpF!PSwIh;j?mCiT8WF-id#w7*QdLiWCUb$PiPKj}bGoccw91=}Grzp03fReUPk zDcEb+8AQ6!!#DMseL;eoCu-}XHFf{SN9oG8Pc0+55v!xO%R#0B^(ysFoL$gRW>tNs zrQl5i;uH}wy`z|6w76k3kDH5jE#Jv^OB2!!Fj z?oYthD#}Ncgx^wUNa?|>vO`G?8?wiJ4t_#$IfThU#% zZZ<#JR;#qNbKb(~uMWWYf$>+1iY?>c8EA*DJiIH6eh*=tlCSq`Gtf6tuD=|#{Ha=& zeqV1Z&NN@rn-_LfWheQ*urc42TZSk}k8C%;;iwo!v1a^SHB0VO(}FdLd&29N$ij%p z0(;EG6faz;6_l!>Rq`Dy;gkTBF7*_r{szMapZ_N9&ToSvc@ z<-BaYjsM)5y!!LbD>_xE7~ht~MkD|6H*!@+WFoN?$$J8;d}5tCH+2bb>R*~t-dw*l zrTGs!^=qaYww;|&7JpVU5coQ6RV9~xrHi79p%3aXQ>v28#_c3~6F^)zGbFdA*{6)O zKmA3OhFkT;(Eqc)z>J^a&M{$wt8)93sVCFd_wg!Bn`N>dSzVn98hA}y~)KckuLq>YxYfujR21gag$Phu!LHD@mf@(yvTWRHKZ4Va)Gk zPuB?^ndCruvzjlqb#o!IfF2-G$MU;rTEX44PoIAj78J?PHB|e@E>u1 zuIzBLG+l(6$OM1=0EB}XJ}uQ-_T2OJfscgNs{}MmbhB&}BB+z!MK4tDbpW?s0w3if z@ie)W%1HN32j4iCtM02(QZ*1v5|7t1l?A$S zhVU}N_hG0PIZ^Wgjk+;floeZ(5hd?zCnig%uf3--s(#(MqUlFX9p(>n0R^l+=*vK$ zi>@s4h5NksFYlG^a`47kbwd2!GX=Y`r_?EJ>Q)dlNO#mk!dx@@nN97i&}@dQ3hFCJ zS`)ZyGv`NtCogyLL%C-{m&IG>#BDzvnIrmgI;D(R`lU=+AS)&gAQTuXH$Z*k%JY@` zXNLhI(DOoWhc3c17r0ji8$!ULcWfR1993J@pUq)3jl*X2Wb3A8`1Vzsz&*`LXRgWYc`+PR!9g|x05SW13W#vq z#J;_+5J1F3%n%!^=Sa4%4SQy5c>W%e^BZV9JF;b89lWVkynW#xF25`F;agl>bj9(9%JqJ#i6;RsJ(LNkSl z^aF+q7FdF%N`eduuwm1SUTaVL^!cpj_N#9Xl}Th;*Q>MA+eqnN+uHczh-nk-YRYSr z?n4>H&!yUFplzYf@rExB~Lg;{IxKnvCbGE(W?eNNQ-R`{MLVZQSfd+DZ z?RkIeee%QOhr>C#7vR?7B>emquTcHvYWYt!EQrQn*?S&(d378ybq&ji8h+huCi;@T z14?D(dUeex4t1YtLrxWhieeNF)7JA z&tHmONGmR>{i*S(QEmo!Nvo|BH)CoRnUhB|peCfOm}q{b>77zhxO;$fE(ex4NwPd# zzRR-(V%ShspWEDWZMpd~AvnFj0bv0}ZBU0jo+KXl?ydaRs6R(Xb6c;&dSg7vW7MOp zISqmx!9G8a0IX`PtQ+ndGM$`P-&CjSKgRl7dc_4)2Xy$3pX}cxEkCaKJHTrYX{(0U zr@803DRFm@+h8-YfEp1k;T?<%z@Yz=Bf@-sHK02{75$Xv4tx7cz)z8H!kZ_T9)qG! zqycfhW2+}8slnoZ3G;pWB(8#vy04@qOok$6z8$XQO{*V^k&LRIge{hyF9)}{9dZB1^bFD(Jg)R|Ikk5Tl~Q4>v3xjcWSb^CFSGuHM|vue{1q-YJK2b;#g8uK)XS? zNuKOd3|&p&=rRoHNVMs`=$74{IXyqsY3A`I|49L&Ql}Dc8yTn>;5}&`*cxzka5Ymf zE54D+3+6ll#dr6-W!IdPTxZ{3pS_TK+m8&Q%SFL;`4-Mzbep{ zTTmy-mgMbxg30oh_*0OEJt^R186G&7Nv69-a&t^qupO4fw6bH**;}Qyu{73?Rs_8f@88G zCijSO{O&XH@CXVA1jdu9^48CTP<<>hS6|K40^@kue(Lni?p}ZuW9`!Hhz-u#02m;h zyb@$usU6LqvN;u;qaHjaS@CoDabbiTm0TpAWbP=m5z*i^{k%Q)U&OoV93$dIL?&K$ zY`X`Ti+Xvk4e&lQ(V%uVksr^IfEIn=vfC3+S`wNco`WU6#`j^)sl#u01E(Y9~8MqOkt z=bpe?vCCiS`bm?ea)LhGKzLB2th@|!YV~uUG+ti`?8plgjPlTos6L$^R=8@VGsSZt zUdwC_jU+O2!}rc??S%r*<1sH1x+}M@+i^WO9QZi>P#<+1FBD6{>@3Q}N3oNl#H{DM zHdNHV?(=qK7|N*K3E?yU9&j3J1S#Y_y45z15C;(-(YvE|I=R?v+!otVTlVSVE^fk; zQRq~Oe5hgd7fx{R2M+~X5e4{NXiD4-^Di@u@$Zn@kI4S^Yyv-w7?#uORKTl+A}4hW z87w2N7v@6W|cjFHw)BT1$yB04BSR*KmPPqu;xfeWTP#Qm+d=!0+? zjqr!U$x<|J`MoyJh20(1sncB3287T0{(O@u9@!}F4p~v+ccNla)jZ#Tyg8d4ksZqm zn;bKRqkSjBkU1C5Ie!lElP}IRP#i13q!mAxV>wF99)r%8n0+1{*-E-7ww72oBa%H) ztxLo&`@DFz_w2>hCC=&q5A-ja%*ik9sV6|uhYunW z5beb*WZlKAurBVn@r#0=B@$Gv=eFiUqcUpdOBBhXN z*Nn=PlEO<6`_MScOcBuQ`H;MG_CsObH~#qaukEdra#TEd!r_qs{rQG%Hn{PuqP zQ$LXr`}0>Kfy*1I=dvILe}WFiLzw05_PoBoq)4LMRr%fYyx&vvlNU@>%dW8&V3dt! zBxIB=)a|Wv|2$jMj&f#rL88KA3p(&&2BO1nD-n6-4DSR?5Ql1?u% zT8b_=vGkBS!K@mQb@E0C4jzAmv4RQjCktN2NX$!zfy-ge7j)IevzPqf7;S6Ht#5o@ zD)Ge-)&pUHT4=UfD1|yG{z>Rj1~VfrTYL!bOZihwidd_TR5@GU%$FT{RlK7=;j0l~ zl%oPawd8BlYN_WfL)43Hznam}B;aOApwJ`)CJy|CH6QxZQ**$4ZHt}2xj9+|?%bXw zbAjuNo4j2Px0czoA+O%fZcA}F&)C_jk4~I@Pg7mkydEZlT7pP=S-SnUR+(U+N{W~# zcS7>5bJoUI6Y;yz0JzIo4Q-#M%LPigYU>Fi5Q_X)$!ZvjX&kGNTvnm;ZP*($CK%aN3KFa2J8^P}hs z2Anz4spuTed~KF9l+tO0+6~Mi{_vJYIyv(V83aPHoPpFPnqO$ks(aJE{Yh&Mq(3Bb z^O2e2+0QI#X(s@dBoRp#F43BNl=J|q;ro$U9nWHrZ;L*XJ1xtLglM!J9+$w4qkq4Z zS^&~c%if52J1i4j`mtUY*u&Ubb6#e=xcmNFKuIKcsneTPC2Ws^mP-u-Y4pOIS4CPV~-Gi1bQs9QzBOvZBP0fH&4qd-rm%VvtZ}x-+mdkG_{c=~{C|n=DDnaB4hi72yir4R3wibMqKBy{{&$+#hzSbPpCp5~ zK7f0bpOSc3Us8~8B=Ds0lsV6J&1k5#lPHXp!zKdRZAx5EeNF`mU)u!N5W`&P?XeMt`D>qGaNayV?9FKB z8o4tD5`YfN>`mB2!OU-FyED}MXqgZLHDz|Ck>Wb25~rMbL4wumBvDS8?LeEtgr8XQ zh3}*6lTciTzi2V*kaFSzlWD0l2u3A@l7Z?UstGGm?yRBK;jixF(P8343{a?*xtuGb zOiWa)_~<4OTWQw@%2N_8DUOAQMmJbMLH(k3B@Vd$0oIkD|Avz|;&%9t=(?lQ3#3(1 zUo5|%Q`Ml~FVH%^Jaqi|BFYgM{F0ZKEWG)zTl%Ft@QI@mFEQh$BkT0K(cHR`HX!&r z`kP4-bPHbM_ga*)zi4gx7bsv|EtGAkLO*JV4#OPDiM}f5ZQ=Hi$b|j)nf*a0DVjIw zJztWXV_I4l&&8|`U!6sV-~3tWLrsZ_o5xkb4U5% z5?`xh@kC_C`-6O1M>mX+0Kv&Ul?7DE!@Zr1SYQ4uZ@s!lSDni@2ondZwOU7=&8sx_ z>Ds~xXRkOV8`)2gKY>}zu9l(AlUpK?Pe37!ZAah*vfC1B>uo}6rmv?`hX*yqb zE?*aUyz&*&orWJnS8NN_p2K7#1*}4V>i5@OfnTWo300ZLVM%}=u0zk4C4DhB^SM}U46 zA}&;F_~Iaf_aJ846qBsD{{_@wx;kiOBhQgHE#b|Z&~8yOUS8a@kJo-h9TE==j~rrA ze!?{lY#Vr2L%dV6ZYB8cC7Lt&1{vaDSAh5P6<>m7PsHe={7TX9Cy1}jdumTuSrvGr zQGItfu-Ja1+&mX>{wZ)>8uJ?crs!)EOAQ^?G5#?iiKa_YXL&mr-Io-<@DmJlB}!ImqRk}}nbMMQ6q(l1#Qi*Cl zADL#ws8!#~uI>0FW>2N%Sj+nfL6)iQz&%Ih-%!WeI$U+pRNuZa^Vq7t?woRif9(5B zA(Q!m&)(0z;kp%|X|7;_-H`pO2*SFlULQ&iGk;X`;kL*?O#uS9^G2b!#4@1Q9DqZ4p;NM>f)~NE2(BW@CYps={M^ZxSq=jpJ3C4j{y9ml zBc7Aff_9ql(O1o-@(I@wBpyh){6GD6bWXMRq%M%E%+E@RO8L%>cG<|aVhwnsHXxQ4 z=YQ#q`Ei@%*5W8%C>BTd|FqvLEV(DK&gH=$II?ITlP0>?51Y4(Nsh<*&9f>4o@~?; zng6)cn0#g+ZgtEFdUj@|3*z}0Wv)=BnsGOcWFPi_{^h(S=(d1AECh!i#qEy6b2WFY z=rnGeFRoAK8u7-3Gtnr+9JPea31cKJsVA95XaUrOLO4cfUEb`>*j*Fkwbqqd{3IZ<;S;toOGA*VTc&9L zRnE@s3>k~*y;5)?ch73-%c_3%x!QKyagzd4oG)CfwhuX1laIlGHV3_|1Vl`-h|Mqp zXBOP~yU{9gbP)IM-&0?y43WOR}R)pRP^(7wb4aLwv zs=azIpL-*y^nB5`{IdL1KMP~@UiJ#@P!UfmR*`6`g6A?BY1I1(LFgR$nPg6iv!duO zZpU-_Jd61*wk&e57~OTL$D1#bo+#WkJEM9#b2ls*Ha2O-t_(SHP!~szcDOIn)8&@3 zueg^3XGly41Jg~eH*MpaSF=pZUP=>X07kQEpc--kBZ74Pn`t_@TLZJB!YWT}hxDQ|R%`#m+UAS-`P zT)d>2FUv~zN31@uU@F64|EoO~}m6G}1sE z*mRe&Z-lB5t-4jQtruIXRg5tG8`b9C-{O0#Hf)F4LAX%`E6T$5^VmtW7gf58t7_*d z=eGOBzf!Ol@=&vX?^uWBpeRIIQN_BB+beqOKjADF7U*cd8odq>R8d$)uC%i2)BeWb;|R$rvrtr~BypSBvY|<|k1he7DTW?#`N$Q;l#Vk(5pdL*`;k~x zty%iWYFhleUS+$RBOdhdOYrp;j{f;|H)rl9 zBQ%L+@E+p=c9U{EM^uE%yZ50ZaxrhIV482{2?IYH#>LH^YSKj zUxlcq*g5P5!I_qQBT{aMH0YSamtz5;qI!5<8dt#MuGL6NziFds9jZ?mu}^`g+CpqW z?naWU%gI1b!aOWQxEA{kN(s8f_{5%>V3A9J7}eVx6A5|E$a*v?=VNb?hCjmN-n+Cd zlv{ml&bQyYQBt{YeU~n~X~~TI4hGw(&OF@Yb2T>Xr{$5U#rCwC#=wRti*yZ`Bh+OW{EX$jI_1QL%y-2IGl z+uJSOGg(MPVdamvM95Bb!mZCwhx#I7%LW!ySurG9G3T<|Va+h;Lcg@nlw>(gF)Q8` zF(Onr*xun%7?oNaRwKlrKVLu2KhrY*i#XeS$24TYFJ0SytkZK}E-+&B&`AIn$YG(H z9FrUHAwZ>*?k4Jc>eHB0RX14I*xMv0s`^Vt%8mtb<>-;xLeI_`F&QD)NzW)Fqg?)B z82KVw`(P!dhRU64=a;(EeLecLGlwOKwA;gUOc$KcvX9D_;l{VDe)}A(?W8W~{OU3B zNeV41H|>C#=A<3~3Sdis`Pmmej4as+|8_~+HzjRko8o6R1l4-{Ic9#*p+5p{dh%J0 zh||IcWX83odov%KYq-N?@94%DzK-p9&j^03-h6G_Cbqbu#3>)hp1Dl)LPODUV(S;& zCQCMzgjjR6wh*h7plO%0`mKoj(S|?lZjw40#6C6XReZSKHi_oAvX5NnULk~L>`^DM zkF=Y5EP4Hb=quGcId{-!?GsndY42j-_y0!JR|hrHJ<%?(z_K_j?(XjHzPP*V;KIuNUZ>44`nYnXwdYK2$+pK$G?&Ly-J=E;Rqln{S)wDe3WcIH!?+d-ccpL3DKe7tr_uvUOiT z^gq!01>nBGN7Z^I#hUQ>Ry50($$XjTawpEpmpw0Ou;ox_^xE>Sy}BF}SL<`=ZGQpP z|A6w8Qly*B`CN3aF<-|mIkk+<{#2C&$M(F3^MTD5@M(Vp3|}|kZ@rK_y>V`jobaD` zdmsG)r4ihcboJ%}C~ikSehCB%?3Dsf-=%s3^!*WUXx>y`7M2gNeTO}C4g#x2*!Wj# zuUAe)s(0Ab)?Ss1k%45&)PRsVni|D82rzQUw!6D-Q^=se<(L3L{ceJlTckM0Wf4uT9 zUMY~^bpdD&!T|AtvU~gVM^j&Wfif?SzUjF`>Oh=#U9ZN+@!@C9T5GRfJK-pTI=!_Q z!}H{5f_lBR@36(8)DdNmBjnPd6+u?vNebDsSOq#|LS_DCzqomvTSnp75ZKU?MW#ef zBC+$;^3@7#0sm%)_8(@8^Op?Jt1#1=1})n#Q>MgA59){(Pa3W%*2N zqc3p(m0SDwMWXu}>K^`8i=owL{SfUd-$ku~R+VyDmCEK`_}D^yMgI!R? zHA8wo+t%>ewng#EAzi>jTE2(yf1BD9x;RnhI1@4jAYYU(Ccfq!^$4!A5?TwM(vG80 z4tNvk#E^kG$$wo4ib~U|MV{5KU$7Rf7`h%W~5VM*LfoMMGS**EM=^bovk zMe@a2)kR$8L%r|kxWKU*?=clnV0j{$?P?csLSVHEyRkOta7@cNWX$IIE&m1f89%NO z7G|8&Kpdf`NB*aFiew;m-%RS8@OJ@~bb0V`bq7lQp?oiL1rSS6F2p$vcUA3iT@QF2 zh$5)b|0P}UJr{Wz@=D#gO@D6BM|Iana7pYJKz|_Lmo5~<<`1%T&XB}7Rgo|WgR?R< z2OnfYRj`@-&W5~<(yaLN9&D-k9!#1ISr&;MO*Vc*hgHI@h7*G|4F}1{RxsjY`IY#& z`f=#$?JRQhc?qM_u7Y8ZcP@20Id-h{t4jr@aJXX`uH4BevLk773d7jkqG(L~L0OfT zDkyaRh!n_VY9O923}3~eXk~GNW@UDQ_Vc1EfN@NwAVrU=_SaHtBP?6r#T^ZdT@Obt zb2sERxby?M2dtDwWY^B z?c3V&#a-~*P}0MbP2p*+Ya0RRtsWa?O|4rSa;BF$!RXI!o|ID?=a&5^r9#$p$@1*$Y*TcRtmvqqCo5Z6!Ycdx?Lt1jto*2;?X60{3apn{R0hEX2b=cMfdS#zFyX0^DZ z=OTFCTBbcGE#bm*c3O2+f?g5Xk*Zbkroz$m5_cwdQW=UiE5cXcp;Y0a!uQkGvz)&z zrRR)kaY6o31pY(Sck!mpBa8S<|4iTF2i7+W5Ou-WeygA&_Y@Kq zTP0)!HC$Ib1Hd19JP6o)^Y}%tOxUnYOUtMvKSgCBk60hED9y_l;@*m18Q20sZsF&9 zRd?pGW?9VqL7tC%NaV&`AQ7x&1RbkFXZUTCqO3<|IS=dWkiMZ;F{ zT0sr7iV9ZkS}_^wWoVSi#SID@9?i%PnTzDJ*9xA3jp~Lo?1gI_Q<;R?L;0 zbmdn>;2&MQ71(Ft1)Wm(VcX%^tR(>AC$noE;kE%S8D}MVb|slat?jlkEmiVhW-jDb z1}@}5v*}2}=E6U+VThdn|C?~;s%g=qs_7skZq#gB7xKY;7Dbjy7R8Q7RT=Xax{nk} z$SD}A*(^bbDHtMF3M&&f3M;rNm=wRAwd>zg`2t%q;UI6&N1i`=aKmgt90J|Xq*!2V zevXfiz~I~4M?6CG&v(H>@DBrDMz)907ZHV@9%$K+-Bw>q*DrD0zD1wR`*tsOdDR>r z9H%IimPC*l=)u(`!AKeC!WLRT@-2xrcdzsA-#;bRo(07may)xkI(c~dzC{EPq6q&W z3PO^GBT6DB`c6d_q97bqoTQs#>bjP#oANQ!FbOhc3-JhV4$=BkRqvC6`G@Wi+lsDv z*`s>IG3-&PwtmsEdgVZ(J;kGY_)pJ?_ut}{6R#7mT&J8J{*!dqZD3>L_1l|+na}p2 z-9J6hzfZ_luw^l6s`G$%77)v;uN@gu1G~SJ!Kn0j-zc?#fwUmMKgA41pMX+ETw2_Z z_P99kw2W`}cK;fJOpAC8-G#AL)JUrcRbftHP7m9ILQ(LE|DZ6V;D@}92PGHL644Mv z@+Q_%8=@Vq!K~G#N}%BTH*>*oDS+8RbJ_E7qU`?l>%08szX1l`3h~_*`o|^$QX3wj zJ&)l3OT>$gUyerhUFuOxplG9N!=%25@8iVP%IhEkGsEqKdx+|zi>1|0wr_h?~&v_kv{WOE+5yKw2Olu3X%AVh}(kk_p@D}obf;Kxqh|Gk|uO{&KL znRd2By-pY>(;%?H+zlO&J`lcAoieUR`SSKeax)9~*g7fA@4bj};Any#iC}Anxp7cS4?cg0tg%C0-C7 z+GSQD|LmY{lgR(<4Bk4V8rP8`VqEDywA}Oj_bi!RC;!5KX#5Ye2`KpTZ5br^0=7%E z7h0sjNsAlOEPyg>cqsrYAr*fU&j^;B`$NG0=Z&u5Zl|9BhFly)kp2&f{3(WDr@`@9U9(Q+^r<`A|$&e zv?i1$_Qt=%D@g!ZRs7@=jmAr*xQ`ZsioLLrURVilEED8_teWtXHBdljzB^0wbmu6J z9rMW~f>J^OIU;?3GRSlX2<8KElVQuzs1+iXX+g7hM&^UxCc`uYH`j`JzKF3PzMl{O zA$j80XUf@L34ajZ7+|MR@Dm^Me*p@#56@qKoy3U$5rHVL&s_l^KAPFy6V-=nOX1I) zmD%1>tPjryzj6vNJ2|t2_`+J!85Ygo==K)li!^@az2emIk-gJh{a%n~Ns+$(b4=U@ zt8&9I0HdzHOz*x?{cqwu;Z5%eDPFU^B^BG^>EzFyP5UVU-U2ifjUEg@_vf{3FtrdAAs$i$o> zfapJn`!O*(Cot19WJ|uZxR%>AoX&l8B;P1t;47G86bsJai;D$B9UaXz@tp!;zi=Gw z$JQ@gurB(-zP~X!(|H7a;Jv{x-t9E@LKh*34*|~92B+&k5t0S!eZh;iZMgu}Ni!h3 zzxa-4b}D@!3QttWGe?zCpYiSBEDt=s@oi%P5-xyS5{0n|?cw5cnP5pA6=CU>ggd|| zi9sfTOo$9^)feUtv^4rQ5%=6Wsy5b;FSq6!e&Jy7`K1E(?Tta`NuQb~0ZmAcmIlg8 z?FrW%A*l~GPJNVml%-)N5T8`lrgYaV?&$GGt|#nUqOO3b5`h1bW?u%D6tUwEwW|O@sR&U-_@++$Hls30b?kSfulf!{ zo%HN9`a&Q+yb~5B0FUKM&J0S95E~*UJbHK>Jxv}xU5Hy)At^QILg4I1S?fYsdzUu3 zd>ma#9$j3BE3Xy(s~6j)6W+y(>h8{G?=ah~1HBr;%WyEB=gp;#a7l$x zD}j!Guql1GCVjXJKU$3wuU$&isu#M+4blEMFj~zLuU#wp)Rlm99OAF+ll{hBCpDf! z6VIgXu+e_0P#OhvH<@H`=xo#NBcW2KKY9A5UL#!7^|SpB+m?U>iWdZ7Fjg5y)*JKg z2G21aJ)o9EmP#VygQsz)xcWr0J6;(_qfV%8@J7~Ds?(0Ec}HzBhBlh8 zLMT&nP~uOfP9)<4qv^=iaL6{A@F(u8rE$tT?=#FZOjYqa=WtZ+iLE`XLjHRjIM9LY z?qH?ebCb`YED1}Uh(!-#^2KnJilRnH?mgj-=?Jw5J>3D1`G6xHt2c`Gh3v53ju^2< z1iwof7;pzEIPSMX3{j)pQ|5*IS`=ec4j?NLWT;nhMwSu7V1n!jBP)p1K`wUw_To^2HriWG$(d}=8UZEPj55@AWjLUH_`+Umk9oE$QPFuO?Oa@cb7ONg5D_n zEC1#GZ~ni^%3p~u>i=L~vK z&{u={HI!;rpbGeZBgF;2Y2Y6NN^=6g{XvF59}s24{>Su&`54d>`m93(5IlX2V9WPi z{R1Fajsh8K0tiY3KkL-LYJ71r2yPI+CeT3tswy~8MVOqYkweIk&tHC&dzky(Mqv~K ze8o4zH$&xS=$$2xL;3}!EcLF~VM}Sc_Bfa1k79Sy{gD?W;S!_EJH`uxpn%H2;@#sr z1{ltZdS0u`d*y6NxE=A#eXW0j<^ab%T^`c*;Z9Jq%FN;owI1Y1;T~I^>STC4br!b* zr}!#{Dkqf}fnA`_MHgO+Lc*K zliFvv_x=9vI?F3n=H3&QQJSKEh>>qz;Z6;d2g>hVlpRY6Pu+7{<)kXytK_d!Ni-{m zTb1$>Vf~Urqs%%gf;?U{Xh-=a2Wge5T4rt~G{XzyNd?ZA z_}!xfu8ub!#U9=wjdYPwD$h_4qUekaW=RI6B9$S)!!nu%y+W1U55ZDoXg+5ZA-QId zUMbt+H!FBVIB_1?9JqyS6F4^tp5J1mEtkg}odm;|W^m*c(L;fDjGps^B5+h;!;8yO zRS6&HrDQyxD&>;EJ|?3zS1uQ0C4uns#8LrSWq>yt`Z#-`oI$8K}47E%?N8J1F7a(y;!5v3sT)9js=NCxo zg~CGqactoqNAP9clkO~qd;mWX{XzVHe53J02NiO%f3CsT;5`goh?2=tSk#H=dvAHa zb0AF}znu~MgqEVBPBd3c=M5b%f=e2U&10s2Pva%QMUD}ihz*L(lY1OH2{O);mkv7k z=b+(8?3>Z^yHN;)rv7p)f@T{$@wst<)u&}*+hxjO>u7{%;{ zsRB7y*>CA!O+)l2na44!MT%Th5aqWK5!XJW2NF7z8d#1z;cW2xAa_GB$1@BKKOcX0 z0ER}?|J)1ZYy9z#Pm*^;!bb#JbbeGnu!2AXek3OYKLE)KrAOj%Ugjv{jI%EIA7K9)i zR43$?!jE;1=_QSX95#hSg0w;OSNOtz710672-gVQ2xb4*pk|n57*^Os5PViY;Tabk zJ0qk6*xfl2EK)1s70UdW@C_0b(kYTAQhU8IfcB-=3w`AEOa~9KLl#n$t%fAq1u44z zV94g_>o>d+%ZN|ZvkL#y1R|9Y^PDJ*Bu-zmVrU`;Cn{oJorZlHVF@Pdk$j@7<4Xt`>r> z+6JRb`(8wGEYYJK{?ym7#|bE$JUs|Sg5FPqY_qK$el|KJoWltov#IDn~?r5Lc&k*jWYIz>TFhPnnO5n9Aehepoz?$#ZCia>S<;5;eM` zgYM?QRDf1*{y|B*_f3RHL95}7G;QpGO{3XOhDSpyOg-Aouj5iifsG9)&aFzQtkWeh zy(={6+PUhlFFlCE=gE|Q_eY&t_#2N}X#0G1?5t9kUJ)`59w>~ZRu2+CS5J<&?h4UH z*Bd#C4W58DJO>KG9Zl%8`A%rYZdU;VwQHfi&F$NM9%mZgyv96N;q`JYGXzO{Q%?%A zf^kL(vX}yaig9*C8R3(&ZDl{SZgVn!wfBK~58V4n?P6Bde0P=ci>j+^y?-6sSX7D2 zAKC{RM%!dZ&g@Tm;#m;Z!(QIkE`3kikb<(;bb=z+TVzcdnx7V>1LJS5<>Ql{#qV;p zY+~ah+Y$T8erzB7^AWza74y90$$!PGHN)DUowS}~%dI9ui|(ck|M;uOIeikTMmJ;L zdE6tHS2$I=uo(?0@mp0xZJJg?Z2qzNj@!r%f!|Ow(xqEbu<;sOwwxX-)m(vo4^y6h zAEw$EG*X5ASwD@c7Py$VZop5+R?a+1n@&7+uk# zahNcoaapW!B8$6Tyly6yL~2~mIJp%#MB6!w%n|vlU6U z;#LhIy8LfhjU;m6fHsMkN+;b!(bTU%V1;)IoaG?kaTx-t>%0hA3yb?#<;blcnf7`O zxAj=!U+lu|6f)c=TfZHI#n70++p=PXb>q#mOTk6@qe4BBUHV!y``Q&q&f`Zg{JW5E zv2Gmjcr5t$wzq#&M(D`qeGXu*Tk=s?H~QU$kgGg91Z-yzK0YNgCo)oJPGo6a&!16hs7 zpQcIZ>5tsEdFG?6w&#g-+0hW<$Y`;4izX_>BGod^yDad;H-BJB*p6SC$5ilF?bimyP`DbKqWaE!Bc+a_fBed#XiaIld&)o+jKjTt0%)utA)WK+~Illd=;wbKPrulSt$sjv4 zUrJAr_0dzd>xOTe_CTyFmPcsIXPBF*bfVRMr^-MOwb^0*6m#h@%@oizzL*f46ra2= zt-OExN!0q3{H^14{F}FTaudR(Ia_`YcA52A<+HvjhUVXwMpo_DWiZ?GKey)PGIX8A zmJuMF3_Nd~caEi_6z^FdSAFOQh3(SfAIWPPd@-si5Fj0w>LW(njUIlIU9iCcZ?!h& zCLe95rWwdaisLh=2}NK3W4ByHrluf@H+Ha`(+zOWrB?VG;T?oN8ShT8+K0>godun9 z9;7%Cfsv1)v#g#0zvh%gKiL!(`>cC!2`~&QBU804tMt3t<;_zb(6i(@SX{L?#RsIW z&Q5wCvrFbtKyQHzAoEUrmNzcn_B=2`%cec(1Z{xk`M##9=Z{~y_q`vNccdTC+x1(d z_4m5P;r{jo8@o!E6dI6Kvqk%H?KyQT%%`7f3#)JTx>@=&M+IMsn6Hz1wF`}y_Av_k zs^j~V)tKW*Z%^e|3gT+Ssu>Nq%7!$=T2kWoyAJ0T$6bm(c<^A|f@-T9t<)(sSU^47 zpxKQeOg1!xscu5G)c9${s#Y;BH!37`C;P@apvpuU;-3y`*(rAYY0+KHB|Gvl#!L72 zv(CTk*7LaCb`a+sPpiE1TQwi-FgJO0D4iqVbPsRv)&T5QnC-e81%w|YQYyCVj0%v25+j1utbwi|>lMw7e!rGK>+JZ9 zf2UT-!Ix_$TE_e;|4je2x=~tj*;wnR(S>a}^+Q~r6wK6anebOw(cRE7NK9$gMYNu~ zYYFaSw~4r1-tDr=zN}HHlx=PF$6Kf6Ay}|V28_9@f7y4x!XKV`v&aiSvP))taA z%)jP5%R`uMb*Es~V%7uQWymgD?lCF-f3|{S-~;cs$YNsp#m375ja<`3aAs`6@L%74 zO5f7JcyVG1ZT^m>=A73(WrUJ2;@W?@!VXoHKCf|Y^FxH7LAbimJGmL+w6~vuXd_6g z5E;L=bqM;#p-@!C=EfMZg%=~sRDz9rz0BPrS-d4a!Y)`QGIX|zY+UW1(Q9ZQ06Ggy z3@bHSy>z^QqW>Ai>ejMxvI_krFJfum!E?w-$mU|_hzr%k9Rq&C`_&|3Gr@;}h3R5@ zpA)OAYRoCiU!ManUAd!`tHj`G(n-h9EA&9gUM~BfP1yYVNb~OF)mDuA=hT&V%+Rjz zGuTM>ZuQlG97@-Q_u^Ra>dR_OVQa?}RnW`T!89voG~e{3g0wa11^?+JOtEXO!*OUs zN9pUCNc$E>mRNoOCiE<3b}=KyF71MMc+5sUSI1jKBd^M)_mn1@))t?<`Nox)Io+fO zqg609tMYV+g4i?OIZ&b5EVFSex0qylSwYQ9Z~Mghz7)V&n&AjjDwnbFwe4~GR4&t5 zJ@xqEWx*v~4(7>o3@iUW6?IrpH^%Av8F2a%^iZR8GX2I9Tr=8Ep;AiYausR}L67`< zA(;messykWjP0U2eY+}oE>K(PA}1&SKP{C8X)q1XcAh~SDsq0xi)OXb%q<_x+QELZ z7AI8tS1y$Hp(7Y~HCDaUX*vj;d(It;6(MRb-y-T#0nT~whQG4DO?cp!aq_I%prQv{ zzHXSO3;Rh{?vi`f%14)6fprjbqF^ZfzE0Q?;||zAHAak}VL%xU_JYmd?TFim*?i7_ zn%}jYNv1m)^$lW9*h)68j6T{svgz?LA#WmPk+<;GrK8096zL2tR2pZJuNamuT}{F8 zosWjiya3RQ&c8XXsKci2@=-fr)a!klZReY@k(RAi-IxE*!gvYpWE68FE~pu`2?FY#CDZP@WJSFz|+Y;aad zq)G-L-U`V|3L&5iO-l|S4(6oOm?(<)N)jOw_hd_0AW93^O3M8k=U&se6|%9?QpkT} zK$#Vs|4!`+Eu<@rC?lG`;Aro_i0`U(!KZ4oGeo^1-j4>dCIF= z;Bi1Zf5%YUiaPR^5%q(rL~Hm_PX_>@etZR!4Lj0OW(i%t@euis_jzHbF?Xf;{ECnM z%rI-os$WOLoLe$Af3BJ3wJ|>gp%q#Em^s+cuLaI$L1VdyY6#eVYUAb^u#Z+?*PM63 zI>xtbNOeLF!9`$!LrsI~FYkeQ{JG-|>ZvgN9gBxLO5k6y*x`pf%-hRod<>4a;Q|V( zneZHB39nE=<-mp*IU+rz*0-3xDzKl}$FO|>vIw8W#W@;hhPgjXzg%Bq`mrv-rc6Y*bWs=Rh$xdyFOzerw z(-Ru7o%|&aG&7EHF`kA{4Y~Y51`$ZLE@(4KC!&;$I{pG%+wbx5^@uU&SX0G*H z3;Hn1XE2q*p^NhXo*U}X>Sdcvzl3`2h0Ng^T}xc z;=!Dps&~c&!#<+bp%E-Nzgn$?+lTi|yKw82*g0pzs-I=*o(!cY{_ z&N1u6w#lJ7PQ5NXUe;9Zp?43vkaP*@UUi)2F5&334&Zr2p6h8uS`;0atYWXI`5C5e z@1=x#Gi4V)cc2asdG~eGc1aPqm5Gx4c(yeSOz+gpHE%eW&S~b zn|QDCsqJL;(hxYVfgy;QqIwm%dc9HnKz{DHarj_zm3b)w1$m0RM1h(*Ni>2BDQg8z zmZiBr+*_G=i+cerAq)WXt(qIMX228h{6T$-$hR33;+e>bpP5e?Qd>rr22bQ_2jgx$ zS?!tbsr`}xD)E$X)05ro9Eg0~xboiPdG)-4$oG6Tdfv0o5xU~Xre`AUh?NL4On);8 zVlio(5&bUG;wg>Ibl5IVVu|==q=MD0D6b!Ro#3YCK5Wmgl&xVc?$V!W z$9}aiCTg&UXFxHQzG2ILlLV>-Q_jOWK0Aa3A8|KHBI1Hc$4~Ydhu)n%bbbjQUqK^; zCg;*`g_nl}8vZ_qFWzCGz+7M#&(+kVAk+;3is9Kl$07V2nHM#FEQfW*CkOjeER9ovxH=UPb?>W^tXJuDYeFu@>M%-%|-d$q!_)(#QAK)awAfD$*LN9dgXHN1;g*j*&@N29 z^=aT@^Wc;LADn)rcfGeq;;a@^`a1kU9ntjB`l=RZ{1WTb4wrhi_R0={UICXnrW}-W z`Eeeq_Iz<+M^KS>VOo~akd)8;s-BcTyvl&^8Nh`5DKoV5$sIHDspjX4g=uxQwonU$ zF%R^%;9J@ixqPt2ogV~o2OSJt=6uvB0tnJIX8L^sKf8MJcJ>7bKF{Gny2a+3MtIBs zyCT#P3ZhBqn-5hH>0&@>L zO|?ttoq9RE9^EknzjHm>F$%bQKD=f@1_}X*j_H8NK#9q^ck{bkCXze-ao?e?z-wdM zMEMB;v+ZR4lo{ro1pVYs=tgCbIWRYU>#leFGZIMe9TBrusgbYI|IRQp65%=NBiDb# za?(!GPLVElMO707q_@_UNilZX@`?le%pvlLz_*qD-@o-DaXdD z*f&(yY`mfw<9eYhhD~CeBU^{(RaxnR-)1|CB~%1PJIef3URmDynt5J1d_`VTR1JyJ zosKk~B0$+A4%2`;-6J{8hC7HOp|zi{pB3ZyYM{ouGFok}{P%X+P<}*G8U>IV7YU8B zo{CmG3{ReRD$Ye~!w&)Urm-})Kh{Ha& zd7SieVTt=xw^f{U)4XkIE0L)~T(=!nN-`3GH z)iY@ZJD)L}n%k#0e@Ld9HHzyn;^b8iRWb2Q>N)k{vLTA(LLOHiE8f%J>v8&$3q{3Z zKV&~1xydpc#>ZQ092WWUO8qLrL?;8{((;xEk@>6iCrDNpN)fx5(DCbnenxRWbWf<< zq0Nh@#3N|T8*I)cpbdVL;jTx8?r}IBa;5ut5p_>9>34fT&=lJaK0>~;(Qq7n9_7EI z1b#~y85PpF8_egvByu&g+(UGXWyt}a_4)BWWnc$n_Q!pI7 z<+w0nvmfAO+Z5#hu?xxdO<1Esx&merY6n_*^i4&@No9XCEXe2?XGKM_vIPDPYwBCY zBEvCw@QU;bcF)8j*EbbUL%w74>THA%pDz?0`pt-16q#<~BiHoxlv!PLHrB9DG{lZaC+F78=nO!bu4oj=Ah^{>9)#Yozu9>I*Ub* zgC5fkY@4l~96#lkatGB!(jRI@v`n>3>fcKx+{%UJYfamWw)1Ilvl ztI5LdOX~;SXqR9bpWm6_?rU!~3Q{!2>wi_(FJm7(YRHs-`HJt+kC@H4^r|vZ^(g~v z_{Q*L_y=V8we`<$+uhI-q)YrKn=-+hsmQqTFCV0;GJka}xx9(*%>w5hfb>EuIF1isOI!Zqc=5Dy!00}4n|M*RavUmQv zc~kmiHX!n~zQ_!WF{qc`gfti%dVlsz)}0lv+zWq~^?*-kthib6 z{;eeB$a<(z%4)?m3A(Y5B_8g5>hZX{JK|L@*k`;M29USKJyTBwxalmWseDj!zQZuUe5=C#Y;;71r_>dX9( zbRvN}V-dcd%~`bT27_i-)4JhQSJ)RPA3#PcyT%Dk7i@$uhj&RGpc;|=+j+owH%?%t zm(wr%oRQ;9S6IyRlwCD_O?w&v|I2=Hec)FAV;4^VPj_dar`OfS-WHB^_=IfGv*1nM zj4$l=KtIWIK;OSraXan0El*xIM}@4PIcDFBR?$PAt?SNn?CIUMJ(=825gwozSiraK zyPvJUM)EhU-$E-C zwsaLSFtuhdF$rS!XUeZfig)RxYvm01c*yA%6FDok`HR*t8nazrrpY7tQ zBUJf|pRFK~*k{po@(>meMx5ias5yhC^1YJyUMHNony zwjqCLhV1#S8InZ?&fBs^)Y5UcHPW%S|ACsB`MR<{Oib0>BuxLhaa@BXqyF<;Yc-xM zx=v0UfZhkSHxPQYIeN53kLYUR@=rS{TEgTS?Tj(|x9>G3-w&KnV}vlMN$+h-+r3zs z5_)wrqa(Zd)I;Cu%;T!j7kVpg%}}e)g9@jeOzFnTV=*l#@^&U^)lMA^M@jKk>&rOFB5nuaa9Y zMB^+;f(b6^C*_k1a4h5)Z#7flk zq9)5OqLWngqE{8B*(W_=Ht5!nHfaYaBytW6GC}(Bf!y3>p2cX+Jf|!Gao<}Os zqJ9CtO};K~i4WXEVt7x&hw-Ka`KxFJESFB`&K&NG%s@)t)#_f~wgyh1F^->=Sh<`AC$LA_HL)o3ZuRh%AJNkVsMz6X}=#+ zEhg&Iu{ns2!$&A-Ws>`^14uAp4SmNx&SEe39afjL`7y&r7_Bb)8#wV{W3;jcZsiz_ zZwK8x7fWw3YY-8l)xM<#J8R`}EL4)&=L!Jb`I zR;bTaxK0mA4AF}=vG=!A5{SQ}KIf7uk>;MPRJMWEsGx zF^~E&$FFY%?p@D={Rc-Z=ohiW7rn?+we#YzM49grs!B~i4ph$7u?kBnk^os1O@OY7 zNeisEf{OaNyNb=SPHKj;+VNO%x6c9mQBb&1K*c}6d_@7k@o7Z01VEjoX~9sHfvT&^ z#?aAHLEGVfQdz;<(LRp1HGC3OA?b`Uqr5b4!Lm}Tg>O@>g~q4S%4u%pw= zzOL9zvc|dYr{EDp(+a{D zJVW(z%*djOO?Eos<J`}lQY8PRzu%w%%%8gfET%^;F^E{-vV*{2bJ0rM|^C)MZ zPScvVI0ZO0H1=_AY0~~V2)EM6a>~BXhCL!B<030v!OHVsdWiEJWCP;)#`g3*zmsH0 zwwiymZU$*7SvJKuFvo*ia0q2!#GsJA4 z{Q-G1#0S4M-`F1KmC{y(V8F(L{mYHmSRmMnjO?+qrdrqNrV%_z^APWoy8rJ%nV?t|r8uwYNYjptgR-=7UoXT!>X%m3k8Ab%j&gy~wq z;y|Glz%!@WhRU`lw;08v78?fR)@e02gPLFav=!L+-ZVMWSE!X+y%P969C3QtOvs zCCT3`$1ImDCmrVprH-?&)jPYm5E+tUMJ1>NxJgy10uh4ZEfTNxR`n4;GXi^XR#GY(DYzfezyN_mlXix*E(p z8WBn59CEyUp8GdR9`rbbdLOtzAGi@d;16tdNK2GIBFv}%u;(e31LKPzH>7ekAe4gi z6<%ps3DK}`2&+F0=e2tfeZ!XDb>|uN9z*NTPTL>|WNCb*M*FbMtr9Gw3Hr~>40Q!! z(eMg2i|S!xjl>8F(cpiqWnfl+9hvqKOSJ{+VF6gxi^@pT2{~C@Bng4>G{Q= z$5CVg`$M?j^GcTO#s$XGyi&$^%1f-q1_^3h(zxtoQk8hcF-n$n$#9bMP?n9xU}QXG z6cm;?Is6ioIYs0n2|S5SuqY{<6-z3Gq~&XhCuNCR;W$^n=ZQu$a2in2V= zZ@xd*IdAUzBU*A|na6Za;; z1kdZFE6#oTkRX!VbQc|^gp;s?hJ%LE__pimL(9_JEr2|`)JASX66@%1yhLu&!le0J z?qb#=mR2+3oFZE)Wo#UIjayiyE5AjNHsT|qBjt{gl$|88{eK|jHQc2;g>t|&DTNF< zmud#d)B$O!jHz@&BdI`glFX4~i%Je*slXU2ZYrs(@10D%o08eioEVMpD;$#HDELh;(f!Ym-}LfDc<9^NH9Mog&+G z*DjlJh@+uL>}O2pzJXr2g-r_)cutF>rDY+q{4}{Fn%2#j$X3)X|0=Z)D3ckKK0Pfb z)yunL&SZ%yD-&y#Z40_)sW?lx;ivbebQQ&cZ+?hmQF!(jXN(t)f)lw(s;Yx}X=LRY%=N)ZdI_ICZYj$KaUT;??$ zDZJ^-oWypNdFkB3zNMlSC-&w@w-{;U2OcXX8ybTM_U{Hc580Tr$r{^*#Q6P8-4;cl}jT zdrUjGhHnz-igIsk8}}MT`}8cftBjL{3w@m4QG&pz%j2w$os(|-Pu&$A4m|c&0D12L z=e6A5(v;TZ*7gNU$kzC6oxijW=IxDJsGEsfkXNTl?TwKqTlEs-t{9zkF%wtqSHS7} zt6&p8mqUZDgxsDTv9|-rXXge35@4012de$Z=0p+ev$Sh<=XUqBA{|*fM@MU0E00`< zYnyB5v$Xg#Sb~)^!QWOcxx_>IXNR-I_*chq?`7|4@42n>9%*lDiZ!X236=W}i5pB@ zmz=#r8}S6XHAy>h#Y~;~WG{KBQ@dF6DC1I|jirOL_;cN@82S?_`55y8bGWI%WtJh9 zC6&{H@3E2Zw`0>du*_4S?X`eWc~U6}ADF11t$gn`>5}WH=A?T+G(lA^=me3(H zIYM8OXJGWP_p-{rD0!i9@C_=+M(gJ=rGEiJ2I>ZdU)zDYI94re%z-LFDzu6Qon^e$ zTMu6ww#gSaVQ^0SsyaFc{;DR=FYP z2Kkuw@ol(sAWJsQ-qTZg{96$`xGhh5PWl6_Lhb_e^-O6$Yf2o?kGmhhz`UEkX_2V! zt_8i(Z!$}<>2yy%pGG-j)c_J;1z0_3zge zeK*sb#Qn3G_B8WuWxVFS>O7E4_LnRZV7auOX7Y<>nmaS~!OU_ms`IPPC%45u8Q;Us zCCoF)u?UI`erKWm!ZKX#*T8ieutxoRN_?GamA%n2Qt6vzR6_gf%2@E{-Rj;)f3{?( zWjhkEcMuHRmyZvEQwjTP!XDd?-UJNTU;FpV|H?j@VZVJZ%(36v0~7YUexF6K%ut`S zZ&_@rjgkMb(4J(WJ;*})kHx8$lMVC!0lO_$?8!p=j3uP_BFhrhE>t^+`$g6*mcxDy z{wZ!FwTj>3_WeF^pluDXtGIvZx2;;W|268G*WGH5`ebhw+M6uvm3~`jPqOeH)TR0) z9s}(`mYr(5yZNAjetfVx@jegYkNe*x-NL8(y1V()%-eB?pG@?Xc?mu;!5^Y-rdlUo znFIFGvq^tu=P2OVhS!^8n%NW8GSU@m5#`yBsqxEfij6FNsvn~@oz1#cqxdr`&ppqV z8WYSeQGFTj|Lavh$NEQm^lXwho8(!kzq3hiW|O?xq-V2PCh6GhYSn+n{pC(IHjBqi zp<8|wvQ!!9V~yf3(XWAicz_S?k743|n8(So_#Nrg?1qH)b?SJgDD#Dwi^ev4y;?Rk z0VRWAU@T}K1nRsFjO+SQoq&OHT|7qnuf%41?6=2X2kp1wuEZG2uC{GSn3I9FMfPWD zx8Gq`mXr4W7|X(T-KF@Vet&gd(QC^kRiEPJT&GXfKYo&5v8r}wB^$FE6(ri5HAV3e z)-**wtz!p?V+ht<6?qEa2U&i;`YgOim;ln)(&4}-9Vr-oOK(aN!kAx@RJl1Sa%Vc z6@P4PRrHkiLhB*IF+ztrU!834-ZRv`h*|L;*Tl@}`)-a0Y!nOGC>FA9QOi}IYomC; zwnLH6c4DJBvQZ3RJCLBO@pC|YkD|Qouu{j?rj+r&#u#yE#9M#=*BF0GcV%LZc$oi2 zRof=~To8t262=m833-HkLSe$Qh+rbjAZ-xP!-Q7KOvN=R1w)}uaY3`wbk zbV8O=-v7)dOi=ooH2Kz;lL`pa3B?49A}49C^1Y<_goOl2E%y=vgqR{XX>9p_Wij zSV!1M*h1J&*r7gmCp_cz_Yw}M&n;@Z0}1aB6WR#J38x5W3FmG-d47^E5_eddfg`248U;PNZJz~8uS+z1oamelJJWQL-C6X z!|{s?M*QMJGJbJkBz|!r1;4nEieFrK5WltXkTKKvr0}qDlCek_Z*&;l!Zf4L7!;m1 zMvN~AW@EMSMd2A^jqxSnYsNLkH-u-6`;7;L<;G*i4}_KY^@Z*KANNe78L0{2->bCn z|4lwCPX&3FtU?t@9Pv&idak=M;yrPf`o*5|Ud z34h+8J~yk_mhjCc_0PM6ai%s($4#e9XHDlQT?C&q^-{WOx^5QC2J>(wncB=F&7;g2 z<}p;7L**IfiRLM$bLOe$8Dx{NO4C)cOPkqFYjr<XV&Dh$EzZ45UqGM3Xic#IXoXk*A27BY=Xjo%cqj4O@b62=-^jjckq@lE5K!sEss zV~>#Y|5&=_=GVoq5-%X_(A*q`{7~edME*(SCy6D*ll2jlm!td#$gd{O)Bghb66BS( zPa;1DZJ!{Xfbz+rA9A>D9^{valbH2i=YRX8UrPBDaR#$KO1v9&Ught8g8V1@(T9~N zuRwkh@{^FCtn^mprQjgykjzj1mpG2NTOH9jy!|?Qg^`L+VO$>c+|7C2Y2=geRzRzt zqNEaS%_zAa`Dtjo7}D-XPo{zOs51q1oWv86pNM>(Sb%ab@>3uI<={zpn}@ew6u-o* zuRu=;6vcoQU3$6ifUT)|3dj|thZW&{!Pl?%W?|?r-+chdT zgPXv$V3x23v++HyquT)f9{T(dxEpf1xzCyp^zFn~!5`>f0SCZ~z|aJJ4@r0s>vat^ zyTO-KUI86A#JYi!n~-o55^h4mO=!hAygi4Kb81Nou?}N-M1L4M(+&=R7lBVOLle3c z9pgM{8cREY{09`%b04TgTc9$HMSGOBRGW^Hbd;pSy3<)Q@mt^)Xyy(Y<5ERGA-Ms( zMs3S>5r)n`$p0s9`qnGp0C*AjEpQK*Wu8UbvzU$JkaisTmyv%}WuCn@^z)e^ENz6s zil!mIU19wjSlIy9k>7rV{0D|F^9(D@y%JDDXIkbolpn{+9!JS;*vMFLCcMy-@NX{} zvWZ_r`TOuiSCL=KJBa4r;nPMa{*Y^GhU#6!pMf{40Y8Y@*oiv1u!Xmge+JyB`as%W zG?1?y!fZIft8e%xo((;Gsc7dpG3@2MA(!*Ii_q;x=t&;5w;iqa>UVQnaVL7kZ@r2? zH?Zd%$4s`_37hJK9kF#hiu@Y9{daYYVf4p|wm(DtpJATiVe}VyewfKuGb`&g-az}K zHir5mkUxz2)vEVsf*+{m-2pb}MET3$2f&ZwEAN2+JfwtIbI1;Sm)}0kt4x;5`4p8| z<`-0-yqWT&ppz$1k_kRzc$n80{`OVq^KEoy|jSe!Vbc|I*r@Xe7=cRD_}t@pojdGDECS? zi{I*IDPBdSSVc1$Ha-Kb_8LBhf8hH0+*{IQF1f&#P8$9;?=0wfp6Y*ApeBE18+Z-) zkl``T8@>z6oz1%pEcYzlwyLaHDCbKJr@delC|OzX7*UWHd}BgVLyZB6$i_QA)Qb(tcS zXnzCAKSIrqAo<^r|2O1kLVi2XJTXf)q0fG1VHfh3z|ZN23LICk{4Zgpav-5Y*?&2X zqB!Asct6(gIz%s*L@!3c`u2Ie-H4u_z_<28S{jd3{2kAR9&;jojP;H2{;o@9X}Y&L zFMbL6VvM&JqxcxU;$v818u|%uuWjWX>Lz3C_o=<*o@61PD^l#LIf_yLN~CB|GaY?9 zhPKdlZGq@x8%L{Bj)AqMx<3)G6Q3r@g;>WuqQv^C{SoCmA?R_}w)f;~KA z6lL)!R&vxz`TJNaum@E_S~>bz3ONS-diDUSHuC7+K!2_q#xUzY0>2I3kMbQm%}x6IhcV%kZ=h3*O7mnM?tf?8U1Jer7~X5 zQ{Og2&Stdw2oks?AN~AT?Fs0~d*BB3obnD<=LmH29jw|rm>K9NTN%y3SY9dp zgT$L~Ceos225O!_z6M{Ps^}Zm;-_4q(_y7_D4&J;?}0xCH-e8Kl5aFzz*o5B&%7?Q zzMQ|HGS(XTy^7{=32A}}D`>)s(>YqG(fy9jl{Wn_W&@pDKlv?N;wQh=(<U$ zOvc+^qScR?hdhk(R7ki1-hujd=t(uNh3<8pTU{6OGr^OX#Y|o!F$=m;i~4UuquyoK zZ$q6)(26v!srwFA_D{%r@%C}N9R+PEf&}HPx&vH-Z%so~@G5q|VxBSGd)Ps0;TsQQ z*EquQiEaxb(t7McTM-{FL&-~sYI-5(0JszUHuzo0IS=jtFUH>VF80~I%=%v=Uk%;| z@7jkw=-V8>iQ^E(y{qP%!A;;=a4)~*lb8My=6@Dy4hKJF_y=O;M1~WhZlB6c;94+C z_yuY%L95rfgqTa_aEX2)w4w~L?qaYR96)3kLi|~bGbtiiaV+%b4SWkVb+znEMU)Wp zC@w!?CXJ=WL;xZz7h?0Dl?07_nt0 z&OuKhcFjdpTn~*}42`YlI8a**$-hMY1)N^@pl^Rb`5#!0Xh#3LxI}zd$zX@;ORrwWg0K5qN7V6M^ijVMD z^uOkNMPjbA53TkgpMn|a!z`WAH^CM%_^rY?v0mU4t9X%1^!vFdVl(m|A}>NuMAToV z{{X9?FrQw3%cobG4c3YdaXI?N8Y>{b4?W+9w~7}n1P{}v5DUCs`iBh9P<|_y>mPw8 z{{j4h>Py-4w8EFJL7h6(|0yi)Pq3q5@TmFlz#EZ&gFP_m6}8eI#JU`TOq^bIYazK3 z(#9d*%;#S^;qu!6YPK>b?Pm>75^&o30VLzjWQgMJ{}rd3T3F~MSkUXRjxT_5I@Y}g z2|s}}L41i?wL;FXxNjovsYINJX)SmUm2nmhbDkvhf;(Z?z2Ht*YcIGHz5ONSzl$&K z#Vp<67(n+Uc&DRa5q*1u&&c9GgCop3+??pz46As*gB7nq{&m!U6>Yx@ORwb;gPXm9 zp#tT2~DZ$#kjg|Tm=M6*k zBk1il>{StKB0);4k^LTvW2aQ{8bD1E%>DtFz=xz+#`)cc^AsNQ2rsx&!hZZ zl$Sx;AMh3BmzF3ZRc@?LA2_yP8PPm=02oWXUR-ke(JOro^2_*auB$>` zsZ$9FQ^4Qgc!}ahw#t3tgS;=GhwnqrmDBWBpb0ZE_9t|$G_D0K#}EN8Wfr%HufcP& zMSPX>`X%}$=oQarDe5SH-?1OwOwVt1Vcx~`8puh;{O>~#f6V7@-5KOR9fM}VK>bGm*X_#gNjq5D5Pc0(#=z=SjSIkd9#IbHWz&wkd3bwf)`=DKJXMZw&Y#)A+&1ele_kJd~(-)8}suJ?hm`s!{@;!tj>3^j%Hpp z(q3ZiYbZ%aKR4nOvj#j($>W5w2DY{aC!IBXs-m}a645_~i25LEehd7%{w4TB&KtpI zg(1NV31&!`iJHAQ>y6_QaU4qCLCHpuR$PO&+A-i&I4^$<=jE^A6!sL(cR%E_5@`a} z*Sb;jU3@VW@#lC*8_#XUBIH*njFJ^Bjd(xGv%sUVv(wDzPhfOjkxqrWO_2E%ww{SG)C zC52)QmiwFS}*_3@T zEJ6r~2*^%Eb`aS_M0QXV71=~&6WK&|5D^iOeF=y$Ir(*cXYTKnygu*szW4rlA0Izc zQ(axtU0q#s&YY8jtaxA{^c7&a7^^%^WOW6a$Agu?X_9ZSEFi0C^JElipm0BYu7F$| zV~$1)UlYBxyo=G^#SX)Yyy!Iz)wCWGytNQnRR`yR^SxDo91jvW9b6QWSErl3_>0E*5WI!f zJ@7o!n;qo)y~x8R1e?O%T%b9PQJsVQoj;eFm{*wXI|zLTi-r&%XDBS=Lya+uSs3{& zjCK~rCY%h-E$|XFg@xqF1;H5bEUs7rj0MYs=W#7B1E)a#1&j&RvTP1H4_0=hmy@Db zt00#R$-D1EkgGtCtWa7QM5YA?2;DE>AyXm{>?v|!7uI@_7n!Wt@@XUN-}G_=-lkv- zzrp5r#Hy+6O1r1>Bmaeyyj9M;DLW1`P4TI~Sj+pt>fjKx4uQ8JqOtK5eO>6|LGl?Z z_XWt)eTrpcMEi&z`B<#NJW%91qUVWdO+&AW7@?QpX_yh>?;Q751T%ft%V)@)V6z5M zI^b0giIsa05%czMG~|Ma%of;h3DuCNQjk;Nr$6MmLdGuU2FSp>h}&eeVl|xyp}!t`~q4Fh-@py6050!)_&kDw9Z2WknLO^vbWP?Bx0&G z^xls62AmDgo#CM~JRkO>B(hi8c4J>}#cn;1RX|m7Ttxl}`0*;?Uhvnf3KB`kySy3* z%T!nv^=crl@*VWpeeN*qogI*W%c^I`>D@;bpxPXgSh-I?t_%HD`1uVoDxnGo9|ntf zdloi3z|Z~aRM8T53TG#5)_6M_L@W`tJAE3o;_X(~ft&-a8zDCUTZHb&2%-NOJ|}@I!4>}g^{yqE zzXO?n2Rot#SP%LwkSoLf4S2(S$JvIfhmae%Gdif`TmY6Eku8v&JE+EoA+LbGC1kIz zV)cW|kWsn75vVYDeG)7LZ(c=efzf`NHAg;Uf`_coo0zYqvmH!F9Zp0gSqZj-Wjg9` z6z1aHr=tD38jIYP%1{-Ws)$}yRFyl>=Rh1b`jpzsux#K{JS;)$N}sW~?<66Hu^6Y+ zrC7A?20umLCV0k}hG+N%@uaa}@Dpnp<$t?IzMWDT-^t0uv*ptAEk|dcP%XpfzuWNM z6Hlm|UtIZS&StzL!>28(b}&+QIzGYKE3*0u@=fFL`}VtyBqF7kMJVW!&y^ zb@zRFjUlqS>fVrS6!J}X5y|r9}#wp(- zixLeT5SdO2t-Z)Q#Xe9Keqzxpj^+D%C3vQ+J}(7L^!gaA0!=Bg4{SoOv;Ih= zwIww3c#u>Z=&SjZ?-9Aaw*?XW8GK__ zzSY)5rCL5BPhHdoHBqXr8Y3fDAIQEIS&desEr%%ibX$qNGZ{=2^2@N9uJBz)HOcZ( z9%s24a#>ysKUQ{b!4iE{9rT?DIS;(uk}P$8#MRSP9@)!EvZAHRk8$Rb{8#vtUj?nE zrphUMS(TK%EcQ-gu&I!43z^}eKD@P11*B%Geefyr9rd%^H6X8mWg~b9q3=VG&w*b# z65%x%!$qg4wJhhz6HZ$fttP{fPnk2FG`Sb3IH{{@7(TU^UzWY(oR;wjoti42Xw+J{ zb2-1rJr^tpmJ?cUmh>~^Nnmd06f954PKSKb86~ z4XximK8^7NVKW(AhSqJ6S3|x6J`278J!Zt2=<9jg4UPc2gNI<502%Y*KXAoYAaBKZ z4ucn=c^}?7p;u*C?t;EBlF}6oxIUelc z#Rpe^3M1U?#Y8mro+z>xF~r$j09M5n5pCxNS`kUL0UnTbfob4&*v|(KfX{%Kwd-Zt zT#R!F?2E$#VjeIU1M)|eK<kL#_@>FUM+uMi{nS`iAAjI2kte;Nf#H8u|w? z>r#l!F4#{;EB1(c5WR}wT8J%A^Y$HLcm#bBTQ?Of2|u5}CJz1)PgN6r*FcY57VvVl z8?NQ;#6n)~!OtGZuvFvF>k@3Hf?kFodfeB`WL&o}Vzo->+<;~_uI1%nMeqr*Df;e* zTmc^9!Smqn(2vHoIzny+KbThlR}WNzM@8}EwWgIe*tvn6(BuYD85mi?@TR;i!ybLzWN<0C z1bVMFLgszY?0|dowS?L&i>Y2ZKkU$C@(YA7}$TYLttr?0lljaNCZqOZ56Sa-%s1(8eK8pK}XNg%RU?-hn2D+0KG1(5AQ zL|bF-LA1KCXVfTu9DG);P9*O^-1kEAX;CY%Hh5Xc7r>RmKos;DLgj*QK~oAgZH2)j zuq*>MLTeGo9U!-a070DKoLjlK_{Zx(E7K%RouK9Ji%uR+Wucny3Mt>eKS z;8Wwd@;&?_E15B?7QX!z_1xf%RmYGras8tib(*>bq(obR&h=-p<^s0>~BvnM?zk)?TT-kXy=oTeV+grw-&+Xsr!-Bjls791J-Oauu|Gjb0a_$?bWA=1fT5>6e8~ zZuE)+JD~NjN3_O3PDkrI@K6l;51_9ExeQu^kh?-2{o?tTpECY^2 zYYN6N4RQy_OK`Cj$PrfD8SR%Sd`avlf~SU@C~2a(%QKXoiK><6mJH z&znN>Brq19d--D!{YhCPt|p|D=(`G>1aElaq0U0nTx{GDA^EOab+pzDEw&6%BdgB^ zoARPj*S#^r^8y(|@Ih!citJ2+J~6af@>A^Ht!Owu9Ns2FQyrGqgtp>fy}Ufc_#0s^KVb}~ zkqKTVPm@{OcLApmC9FF*3@eoe`w%>o!?miQH4gc68v4pYTi<0}8u&KCv&ex1@VwuP zzaI@5d2P()G-8zx`W#?OSSI<`&A`6MKZ*7iiKoO@ zsT1<5libs@np*ieWZgyBpboINkH({KWA!aEe?3-H=D69bjj$XFeRD*9n$Xsz^{5q6 zRlF5h0*0YA7PGE}`JMtNfEn;y8|zgAECM$4ZKTQ#@z+r*+f=EUHXqhwH!Vh1WZ;wB z4CHDC@;L)*A@W_sZJ2)-D*%nmdKP9{)w_$K=3K?k;YwyFTk=Bha=A)qX4V<3SEB4ztm!kDR}t^N7Wx{W*XNbdV&uaymsnUPhVYsPeG5_{>odk* zSu1C*6wgHXoi}pj?{xepjY5imK0@?Fq6xK@Z&`<0$v5Fc_vB;xq&`Gz71&oEXQxN+{W+QY!J%d z5fI7Wxrd_VuQ@`|^7kO2kAq3_D>wQL`IQ@yGdGGH8XlY|zjC9mi~rzRp}q$Bg!tDN zApZf`vuO%efMt8Ill<va)hPJ_M}^tpt(24+_dyoULXMC%$* zL;n~oYvEd#q2C3c@z7L3WIRneT3f?D6<6GaD5Zl#arK(8d>DPjG7fSa&=q97HdqLiD;QAK*3YEVOZp4wU;P3bjygE~@o>P`J= zjBlTVG(AYgC=WeKm8_SV^fa}kcJ``?G?<3l%F%=RPzsI3zcJ|bF%)KNMsbR!IC_kp zpjx&%zd$dNqGt3ujiAo-GQC0rXdLAuZqTGjeQKEa>@%^{p?Tudu{0B2?#FM2K4fci z3G1;uRi&q>9z8>?=p|w*L(ORjjifG=M15%>rJ_$b#ZpOOx36k)u(5vHMO_nE=w(FD2<}7)RX$rt2Evp!F?1-Md$%4Z9ODVb*f7Z zs0p>94iunA=s6ljqp2J9qGTE*zh&AnzF$Xv4r~W@0egWd;E;~(lahHfI0>8uE(BMB zYdf~@*O|9~JHfr+LGU#Q>fY6@3pN51JN4?_(`^a1 z13Q5|z&>CKIJisS_8r~f;COHbI3HXFt^qe$$L-yn;9l?`cs!|B|DNt?@EmvPtDtOQmCYk~E9i=W0|bFdZo64(Vy0{iyv+o@Mz zAUFgZ*+=xL;3RMcI0sw+E&*5dvuhMs1Fi$NfIGpx;NgDVdvyt%1kZpMz^h;ynBK2v z$38&D06Yqw0?&dM`}Ob8FL)ii17--d0>ePluYaF@IvR`tW5E(&Suj4?Mp9P> ztAVw_hF}x$IZ$4WD_eV_|Aiylef|Iy{Qr_1{BY?1n*m!f0=9~33j2?pxj6G=$5y@U z%<(tLw$4T3H<$k%$+6Y@ubKOAQ(;Av^(tq0+9US|d6oFLdEejWgZ~$E{cXl#q>Q8U zC&~=|tTX?VZ0}V0DF44G-499G`%{sB=~$GC{Y%HqI-noCK$~)7Jq&vxD>+j+M6 zrXgtH)rf|i#`7t z$L)WzJnLKj;#;2cEzkRw{}}Jn7;htt_Zf`$A1#g1@+?}K{JF*K!U%U`gnKcdBsVlH=R@`l_okfop)%G zbHlkoQ=B`_9h&O=;rv0H+lt%~C~GQJSqv ztI{+_#i=GVS0$_dv`Gz618B3Y{)6Z%^|~5DThvH3lD4WbY7A{t)6_KDuHIH}(+;&z z9ig3^!)8qeCvXCVxE9x@EN;LJ9K~~auETD!`<~+lItDsA@qx~P&Q66u*FaY%A<#Y0 z-KiMp7wG3y3iJ>3cODB22n=v42fh!Ebsmps7SZ0h7BME$aY9kKqUxwuqgqGJQy=E& zl%t2bm1Ag*@haUY6UJetuqn(rO;J;nbD83%INxVVnv$H`ls2U~k9pWU%+cl%^9biP zkD5n0pDAz3^Zh2lByfIH$yDM3rn0HbF{X;C!Vj3LrYaXS)l4;h(9|$BxR9x3YVkv+ zwyDjrroO4qg-tutj*G}YDa=Jp7t@7{nQo>V7dJgkPcC74o8DZ~ykcJAQl`J@&!x=( zGl0vOSIw*Zuo-HGa#{0+d4nG@qs%BSXU3Yb{HRGasT^nCGH-EtGto@scr(RJ;R~ys6eMcC(04%66iuE&@Ir7at8Va`ckeyav+)R3#0^6D7T3yQ{7f8slP>0e~X!VrXCeHZB1J$VLFy_X3+v#Mjz8U+CsbN03D|@bdhe_SN7xtov84E z#NqwIlfz%dv48j=98-Lyzr6D*bhY!WEfA}yQQ^McCaX|P8d+cxRM&g(p zJ_^VF;iGX(2_J*wfbenlm}2cxaZC<>6UYAH<8e$0e+$O};S=p~fVG>1V{-Up9Q%h) z!7(L#Dvkrf2a~d`!!7%VkF`t*pI|xQ--yU`%)DRt3_mh&`;nRHN9G+rGPC^1%=RNP z$B)QdKO*n?5t;8tbVKO&3#h%ELavc!+bQa>Wg{fMmaBeK$u$SOY~ zANmoQX6N58d>$gQ5D{7SZ$@ObACZs!hN90RCB47Ct+2Tj!Yd<1e{fKPyBeKJf$WA{Z-}n*P_N|>PO_F zACXIbL@xUgx#CCUnjewtenf8g5xMC{0ku*dkT{1=fokkfqo~E^=(#`?(E;r(5 zxeIsY9{e)*8UC5i@-KXj&+`TTl`rxozRXwnDqrL4 ze1mWDEl%UxIV#D&qvY&&_S*~0lfTa8r}=48+?X2^b0_XhE_dVZ6y(0#m%=!ilPR22 zIK{pa7{~)Dk_Yo(isB(Wf^zU|o=tgp9q*y&92Ij^#8ZYCif{|L54o{!VYi4|)Gg)~ zcT2b>WoC9nxAAn{d%aT7e>U;3wAnu1vulTw{@0?EZ&6mBO>vTKAvfBUUjQrRmZHc% z_4BS9?dEm!x%a#I-2!fm{Pvx-{Xf@LRE%=Ex!pW&zzw?E4RgcY2shG=a&x%G&FSWH z<$0HD=Qh+1Qu-+ONw*qBxi#IIWNcd{%Fl~<39sM}c`I+@?Yx6`@;AJTzvbP$=dU6z zPs{iN{=j-%EPvO`%Xztt_bRq^)JE=Wd%ZJ!>3_X{V6B$h)^)s|H}FQ@#9#7e{))Ho z*MGIf@VxILG|ukpH)%ZnbpH|tqz~i8v2wzqt9tAePL_GdfGr6 zX%l@(o9QcCIliW?w2ijY4%$iI*gEnp?WR4nm-f+q`p#CB@97{NqQi8Aj?yt(V@}XX z`hiZ-k93-TvK8lNI!nLMIXX`l=vP~RF41MWLRaY;U8fti8r`Bax=nZJH@Zu|Q#$=Y z8I(yO%Cc$fsHQ4WHB-%13-z3OUbR#&s8*`AYNOh!cIrj-l4`FysE(?W>a4n`uBw~r zu6n4KRg&tdda2&3k9tMTS4Y(`bzGfLC)E$?l=@MfRzImT>SuLU{i4pP^Xh{7Rb5n< z)MbuPSJYLGRM*sXbwk}$w^W+Ct?sDb)Lr$vN>_iV43()uD$AB2`L;c?%K;9u<}eQD zrku#lxH-4sw)_&e=broukK|E2n#b@|euwAqN4%Op;WfOLzu>*RkN5L;e1N~_gM5e& z^ASGE$M`s(;FJ6VpW+|+H2>s2;Z~J@x79u99&!)6N8F?CG55H8!aeE!;GS}SbWgiK zxo6y;-Lvj5?m73od%^wHz35(YFS}RVtL`=Tx_iUD>E3eF+}rLQ_c!;h`@5U&{^4f0 znQq9<3gign)-`o4{gke)>*%_=p02MO=!W`f-AF&98|!Cv6WvrN>SnsRZlRyk&+C@@ z1>H)w)@^iK-A=!#U()S$2i?*B*V+Ep)&AFA_s}ovB;8Z@(!F&b{fh3Z`{`ueU#I8+ zdZ2z)53>Ia*01X!dZ-?z-_XPL2t87d(xdelJyws?srpSlUcaR$=!trgo~)JqQm@h<>W}nl{jvT;uhF0C&*a~J z)nDj!dcEGDH|kCLOTAftrMKv>^;W%2Z`V8YPW_GErN7m?^&Y)f@6-GBclv<-ULVwl z^kIEOAJxb7aeYFc)IaD``bT|Q|D@08pY>V&i$15%>kIlcCq>SRoE`Z;?R^Ja6v_5(ou27o=}3?L>HR1g#+QBe^@ zjH|1nm{wQUh@uE6ii$bsyoxzz%sF5dMUi*942!$&y?gI_d+&Si_y5(8s_O2cr%#=# z@B2Z}?LFE&q-$X*rKm-sNK_MswR!|AIgxkU$;jVB`xGy{q9tw|y z$HEh#M0hGZ6P^n%gqOlA;kEEaC>7oc?}Repz3@RO7d{FV8lnLWqfuy-8djsy=xEd$ zT@9zQ(#+M&(`0MrYjQNXnmo+{%|cDSW|3yGrhu+K)46>*$3C2y&me-*ne$vl3*`5+ zidM+)=M_^ zx9(HkdZ5^#*hn5yhIp*3t*irt&cHJ)$8sRC`m8=^=^VSK>W1nr+}DwGyrG27x4-1Z za#;++<#Rh3Gp>kx%XrdR_ZT|gz6ja=1<@tu!~r=!1QpO6WPlxr&iEC424Tb^S}UYA zd5uP&m=bIL0B)b>4`P0iFT(sXf8^_D&tq*jQKOzPC$^{nTt2NH@fYR&{AJ7!^Tn7S z<*#9WoPQ$!r)VOdQ8bm$D4NM|K`{K48zJC`d4}L@8nEFoj9EYogO+rAOp$F8HAkKlCoJFWTu}f zPqs&nl-cnUH^%=(Rvh|I`0$TxI2(EJHwLWCF8{Z&;a9dpUd%-PuFQ&!P<_bSmlXfz zcSSu>Uo`jw`ySvA@wo;z-xrYd{x>CpDovbSGYr2#LfSdO;HLfn*p$ z{9q`|AdO)T%p+Z3Jsc-7Oe&K`hA{(}VPpg|oEb^RF{7BVlm?~VzVuh>1gKSf16^+R*%J^p}{V;kS~#HgRr|t0b!~NRD3aID;E=kZx*;4^2dD$!h`Nco2^>{7 zS2u@a>fF6$a2-9NKTtS)wy4d`6?Tc$5XF5nsoQX@1#olt`Rh-FVbR^8?Puw0ssGFel zG23yXaV+D@!WRu%3@tttO?H8vLoUo8=U?SRinuLe%!|z00Iu95Y&w1=c-hI<3-^;6 zt9GSm37#oZQbl3y1K4YE7q4BglgmhH1kJz#v~v6;hBK{}F!81f@%8%UYM2Yj*DcUv_9xoqRCg@9eb;dC1m@E0q#$tC{S__0Agf^>>6byVE289?uT&l!V<>5_o4s9Pnk=!%W%bu z&L&hBywu+b0QZi1BnaLlsD~T8gyV@Uzld82-G>#$?z<7mr`CT)yp8kxP|^B5tD*tp z)zFV^RsA-Qydr7!T4ovN{~7-kR@>eKKy+qVWIn8u|v)vpubp2@TiqTm4 zmU6C;MH6&i_=>5BmE+ch9jqwR1^ffjc|4Uffgyp$T*mQ}+nv&Tk^xrzkU#_c%8Z>%#|6G4b%Gzx)YU0BXiqnCV`Qf{ zj7XQu$}b!R*j0XOc;Y)ciB%z?RiTiEh_r?X>XVI$z`XKag-WQpC`L`N3Ltno`j5CH zy;~+^FP_X%f(5hyD?I5n5^GXGzvvlx@g&#bM!f4BoPiiZNf5aqcu4?%eDqpp));R^ zr|5y)rp>R8&B*WG0hYO3x)kSMS50A;q&>P|R)CymaH^nwzL76SoxNwA@deY6dc;jC z?V*`tIoQKEMR7HUs}BUN2`Tj?ASj}O?y=do5et6_4MfAgBNmLt6Z7R9iwwpTfU_h>9@hbr>oNt1#dUpo>{AjSrr~E2|7%mXF11F0m|GCR!>6610lffK+ z$_iLB1+0B?SUcn}5J(|{;R5bRA-Ci(=<-1`+RnC0X>_R-@{Zi-K;Oay-g($E4#XQ9k4UDJP@pS=96*#C0l(`#b2`pp_ zxM3XGGUP?}TV>AoZk>McNPL5dC3@*dsD=ufrkp#bDylV8^q@1+l+0Xas#acXb?2a# zx--x_Q*`L}x=6q0y2v2Vy2#!*(iFf{Xfni9YI4|AU~+q$+&(=zzZqKyQ-Z`k=t4#^ zrW#Z;(q^e!vtiVnzh((a2~*u#1&Ud-K)J}MeLXi7PYJZCS}t>gdW>z?bqq?oeiPx=YZkRFMGG13F*!Z&o+moG_krF(K-yq`bbK zmtes98&LkVmr?G1e5Gl6S>ML#E}^JsWrC7ZC;gODCxhU|YE=z-a@t8!Z4CE+#ypri zepe4~$2eEi@6d{J2eMKec3~)XqWvgRHqg#pApX7*d?K>$%eq^166m>#>E=v^E=3Z5 zY)Gvp3OUSP1MPMO&L&WyyZ3=Mcz<}uc_w!78B4Q@Mr;e}u8M^z08Vg-td8SrxoUVh z6PSi6Iu(ZiK2>X%{bxTSfA%AV89Gp@DLPcC89KCuDLR;i89MB#>Cc>oIElJxW$NjX zAD`XSkhc$0&qXyl4^#JAu5JfhdDxZ6_ zP+L=wt1;ER!q?q8>P&~R@Jnd(>-x1?*N#Pb$XbHonGoksu@}hk zePsG6kw5}ne>!McB7L%sp$uc`0RfKCK$s~Uf*i0#oMqCJ**4nQ?58;N!7y|vi0%v?R)!|rnj}qwXYXBsz2y|@hgUx6(KkY zGCf37>~1*VHrZbgs&o^c0XnY~p3Ghyy+L^rvinW0YoDNBg}o6we{S~J>^A~dpRiwv z-ywaHIwv;wY;IhhUS0*>>2!K{c6Gqn{ne+CS^ZFf`3OV(vt$))k=KA-x&>l^%eTl~ zAvXMDwkYNhUISP7v2!bAWv)<9pr8YT`3doP!I3ba_`1ZeHmWqz~NIAaJqeq;Df$PV59qLvRx$B7!bJzgvI)34WOqEjqa zEGG~yi7JWe6I3esA+#P`4M~?^fIP>d(#+AP7Og5f9w~595kU9iju1M1FEoQdcrluf zyng{VvYwmRs-bXUEzsObwSPf7vc8?zx+-@OowJ55*4)bV0k75?kP{<`E%4JF&FBRF z7X}Qy)Zr^((evfc}cU7S`a(SNU?-JR)6yKMlL<57zfxQne&; zhTrW2t`12hB8l+of8XJ?t76r}A~z1*?St4Mva4ZL%AlS=V(4ev(WKKDgTLtu+99as z)%<}HPSH2Nqi)yUB)3LsjqDQI+TXt84e(VZ!a<1%AM8)qF$0vjYPXSTqf~~;^qK5H z0g@gMd@g=`WP4D5z^*$C!+FiULX^cl;;?mg>$DVNeXg6Ps8#F;R;Avda&V)?^l^pr zv+`kjiw(`^_vm8k+iaGuU=9r(4N#>h`DYBb0azaR&=>xn%#y&fe#d=%_{s%%C(sFt zbsZ^tPGutylh;<)F9z`{?LSD}qRv{$uUv}5+WhaOAm2VSXMd2^?aLrsce6lPy)!#K zYV*H8lIT%*rMFDot~#$>%DYH%eGnCR(g1KfrH0fuNg_6hLu_VEUbwYrxOzXvq+W;D zfMZLCvhQL~({o2)3McuVu5S^a#K;hbkmwQfvN`2>m33chgU$##^?@D3HM{N;j?^zZ z(_Y>*+>SaEd|cjlXU{@?`z6^f@T2xrzcf!I3d3GwfcY{EOn6`gNoLY9_zd6?e+dhH&N35QEYs0C4PX{?C*nqA4JHBhgyru8VK&J*vT7ura0PC_#IYRnU^hg49 zC#H36U`LPBUo*2(GnDu_Y9-x8Dz%cen5Q0$FV*i9Ka}9CYjRvC}UWR#V%nciA}ymUo+bOYw-3js%Xi)luSIc z4sD_;SGIuTdGZx(#|5+{CrBvbg1%j)~1Wt;GpN-l!IT$GJYS+T>dzue6+}#8ABN?aH&WDq1r< zoy#4AvovKJ%zPCU8^rGYo?#s&rzKNl+OT2C;oy1@I%NQnj%$UKYJVs_3N_HdwpVp=ChhdGh$v4o znB~LXec!#uTi8@IYY-wOR-(bWWtx9k^|E?P2+5Egb$N#Ka5`e%qGf3ymGyGTn91pZ zRjabnlzyo!L~}RP90kH1Y*1tGc5zV`&GY$+V*PFAmqiy*?-MihZ_6@k#*rR|^@IKX zYLm0YxzW`eME4Cdv*G+j3!3EiQtXz;?uaDpm5!Dfve8~V;)ciV`GU!Wv!rJ|ZH>ji zi%$54-*TR_-1Qrl9Q4cs#&n6=w4j~&7#q7!M-9Bog{hlP&}sTDsEmoP6xWEIbP#_GzS|4> z0Gp|9vVs$C-t6%+&DxqRq?ABt2)F3h_at?(ZnklUv}lNvxa4H{!Cpe<`bLi#RGOAS z5>mJPTk*sP_x#TYzjrZGr-y#h1JR-Da2~oU!;|9@rw3tLQ`kI2LSD_rUyMTM%WLfvZVBrX`F z&(fFY1+`|w*UW6B_nJ@3-L@|q7RQH#_7V}<`>R4Hr;`-qSP2WQHVYRfH23+AYMyMx zO6B*p8qn6RJ*^Ik^T_MCYC(*0r#PSedrnO8;=?p40a*qK3Ysg%RveuipIqeVlDaNgSJhCme>IG|bD@Hakim{c z!~BqeKfm2>(Q~`Oq(Q4GQxe>)f&fZcNV_MTqtO|l1lN$av#;;_OO;p z!gHx=_onZB&LXjrgxkq-RS`2iEB)ZYoQ`6SUNpO5({uHGcLO#;8W>jW(&4dAjHMp% zcnpG#IY(};%R)Jv*S=pRfcV;QzOK+Z2-0|;94(`HJ1^&qID3yT; zA9BIdzWsbw1r;z?dC9tR+7}si^3zl<>zaDZ!_Z8ryg#*?=iHp7(9=u;H{m)O))tW1nQ^5A_VXE{v>nkCLc|?NDV)~oD=q0WRdcCvJc-bur(}WfeK&cOK zUV66JPb{RNL)QFpbT=2@#d$N}F*=e(y*Xv}SeCza=XY5u0xKT^tMz7WMAArYwK?-* zUH$<5!b(Zxa^HNy#9Yy2Yjw9L2g8Hw!S*OnXE!q;A|hPb(x7W0;=J2?wMfU@UP==V zP2HNL(Qv0eF!tD2rG)uxJfI}8)bZg~m}=G8cAbrh#mhMOrn+k`r=q#EwasPnqD6MW z!g0COw;;U?h1+gTt2Y&QwVYW>LTQ;_QeE@Z;bc|F(=iem{<3r;DP+3=b_ky$fk9dN z&}Xrhn+dZn?O0N(*GD}v9=Z}l?$)T z#jDg|SOkX0XX$j8QsM1%@gzU0X6-0$_o->;B+D0Wu(o)wMuv#xeG0Pmpfc-@%o3TC z+~;L$t3yr7i8@K8ow@R(X;5Hc`pBGv)>JV#`#8)Sdzor|ReD4x;mB^-|AUoj{ORCJ%$2@Daqp@^g8m3B zs*}|(tM=xW>GR+jfTGD81`L>a(B~BXXBoD%)54J>B!oEa-k`fRG*52E`wjBO)I+}a z2gvz7sf4w&1Z+}es8$|Bvj|kF=*5!5ly+;~LeJVWu@Gnyk-1f^qE#ikXQ(;HZj`Y2 z+r3;9A}D-id0jaOkB-s+*B=>%^S}l~0!bH#WIe!%lw5Q(-HTq4p2^n~#)36tGyA-@bRuG$U6QyKhma{`k^ms%%z76RCPK!6^xzBJJ?ZH7~EtCD3@_ zuDr1t@$JnG>CKYvt1>AFCgJEzWlD@bc&cVS8XZd0RFs4@F!4K1Jy!U^M6 zR|OSA=lBvWg7%A#syBcucDuY>SngTekC66^fe8;l zNo)OS2<}Bxt(z;2A>W1dV3k0^h=25H)=|xMU&$AvjaH%dLMI-bUGan}B?IZT;_1G2 z_wCfr*lj_pkc$sog_3d4kzUJuX)5=-&1x2xtCP=wbMm~DlPEngt3?p0pPP|&rfIse z>ukBY3+J;Xaa7kEQQDSMbE+&}??+vH6F zs;IG7;10qfPoKbsg9Vz$J}@tuXsO;BOY zTp8?7NA4ZUY?iuGd&&c}UmbVsw8)y94d@4PGUm<>YH1U8ri>J9Hq+;B&O+B+3Oi-p z49Rd_cXsw-uiwW*Rs)P%EySIye_JxZ{(Nwtp>`Vhy|&`e+Int7$Q^k+*Tr~4+6v0z zM9H;@J>7tob65Fu1lKclM<=cuU2C;h=;QV5m84b#p9gyLQlWO#KQpEQdKbu>6*1Xd zhX8wpovcGagmyQwUm+!uL1%F_W6HZceX!jH-5|Oytci!l$o;Zsg=(@5z0INcDHiRp z&`oV(qr@+nPUyWsOlc+?0H)c91FPwAxW21*YC}aSdb5mF(^;9PSO3+sy#et>miPrzuOY*1Nc#FdZhlq~lo;sD#kkgFJFjkL6Ga$Q*^ z7x~8|{_ewjL%)Sk@wFVH8j$ysNC8SU_(WohP~FxBBWF^zPbXi4)8JT{mAqzw4}2ZG zyleDmC`LZA7*RD*649*L5pcZlnJ6o|q`Yk@$3@J5IxIbF;|h2o4|bkefI@t0p>W|X zn&krrwcKwYx*zS>dl;>H=Pgc_c98UvY78z^|_-x-n_*Y#b|nCV9w%{dM8J1m)8np7;Q?{&~XR38qlgswu>>|wJpYU zHaOX>#=`fbQmC4j2R~PUahBRH8!sdPTan594CuZa%_X!~e|}(!@%~M?DjsJ8WusoQkQYVo+}YR z-HO&2ZxY8=z0pXTT|Q4*a69&%oaf~*i;hX2S-hv2#GJWpn-cCk5cz@e^XeWre=@9K6d%)oGLYY)O{VX?2`y32to>wAxO!ev)A!;hZ8(#l z&JptglfDmwQ1>q0)9)e!s##SneuO?%x_<%WtUnzzt>V$HRi^rS#S64J?$LlDb?&)8 zGSaJjhdOo*;mv6@lQVJXY0bs1yLn;apf@Ytf&JKM01a^<-fjG#i)~ zEfI=DX~az}zKTA#r-m+2Y)&)Z~VqSyKlZ~j32%NtHk8h$+oBVikBM;bnR zGd)X6ej7_e8X;=~8$&Z|6B-pWYd&iSvw!KrX7&z_0;YQQcntJ3e`*ODIT+ZR**eZ04Mv8w4e@=h3t72y8XzGAR z$MjcqZtnlU`N!fvaq>AB7+E{wvC%To@Hw0ORSA!gg^fl)&sNmP%*50YkAEv(b5Q8>X|tF6DdExjjIM86*E2SUxj$|w6wH;s%ZU%;xC;4(F1>wsr5L?XTMZWBmRY z{3qUjkd%dq_TMCBVqpGHl71Hbo1~x0eZ>z8+S3n_6|c)QPI@E zsR-IYB4B<9v0y1#d;$7c(Gl7pU{sGi0x zj#g0duZJ5qBt-BJ4<8?Ii=AU!Y!9vbYYvxO4;?9C1K{7j^y&Wg58o+icHpk|vV#ph z^aP7Nq9XrMq1{mpu=a&o1Of*W4?mdfsII=X^u0L*3I%Zpmk{Ui+@YYX_0fUNmDxC{L&2aXc(4aW%FMMJ?d8?g zX}W&Jneuc@ADgmXA2mHpf2b|-RKsJAr89X{dqXdXFgLhzASCpG*;WjH`FU9G+@cZm zeS7gs7DqKtM|1f`^?m{sD$tU}7kShMR(4IXx9TR8uZv*zrFs2N&Sw2VrZL>(Ce16H z8}CHCFE>nmF8V7NT9WdhU<2casdT>eML~`>``kl}h$AxZRQ51*ihg6q@EvBrI zYYpM7x1}FSdY7c9J(h~+!D+faUh+OdoFZ;v1#UOnAsnl;65EIsAsxADH-WUjzFPK)#0|W zUe1__-&q!_wPY~Kpz~UpBTpce%80eWPDsg2Vw;JNL&3#Hhqq?NxMeRFE{_-ddM!>_ z;8ep?I#D@Nlb95x=M({ii4}lx@=DK~1XB+fby}0eF*g$!P3onzGBm@iLL%5ZruCA{ z($tT8dx@a3kEwFBgHC2a)i5{ukki)g8ZDvJrZXVs!WJ1K21NDO=oBSLycSqswu+yG zPwO;J)2`C5nxQ3tt%DMxM5$hzXlSnU-+%W*?K_JvUMDyjvsCX)RNFDVQlYFMCzlqN zsob}sO@FzzFn+0DOIhn%_?|Mn?&i_Td?(ly-lC}xP|$6s9HnEwl|x;eUwVq*V_3m6 zD1SD|_R#LSRx_JzLQV}hRG(6F+wTJQ*U3cJi)-xw)oj~8ip!;fDG*9P2QXC;tnTop zR`IBUYGPKvJ)~q!EZD2XKr8F^Z#FjtpU{_yLi$qiG%nCARA;q!XQ6SN9)G|8{=Kp` zzc%kju|mfJ^S}#-%8zS$%#h z9_~4|Q&SiTN^n2ZyJy5Gt`#`}kY(&LI-}D375)gV&#fiT+&o3z>l1OmrIx*ziWVJJ z>{AV8#WM8nvq$UTsMteH06=zhVLK)>DkNTMMrpQcCR;gW&iBEgKr~0I3nLh6LdM7k#RwGa*4cHdpi{#hN^O3Nryjst zRxP^eU+%aF>V<$;1uYfi(xV!y14EEDL-7X|t-{v2qD{Q43{FnO2yvC#wD)S<-$QC=tSg7ca!0&@Z!@8F~DXHD^fTU4`CW3H8CO(kA zIKHf`5ZlaltYgNmTv02Muy}pe^n55~ILuwg`t7vDIk>5IseAgx0~)h*JVQe#Vv+d> zPU_(K?uf6_l{Z43J6KBuOEJbI0BmT`MZbSj?X+^-C}Dwd{`wSaJA{5zk< zf6-Y;4f3frEXE)I1_6|-0=mS!h!~=jRgDTn%%Uf0QKPD~LwdlpG^YcylD%C5T5N8o zPvzH-(c$^ne8+FA$%$r+n6K^>?0q!K%<9X8#S?Q23o|=z=Lr2@4x_Iy?S#|<_=~@H z9qBG=HlVz=0H=&d;u=_^Jn$A20BurQPOl}Pw7wmTHN$v5&AJjcsFHwzoi1_o6g|4e ztJhl|l0>#9s;$rZgcxZ(=P;5?_H?jSML>wP0`vu}7Oy}*el{CiJN9afw>6ham~g*+ z2~U~eUm)~G6&)Ay#1tJD@DzAVyF$Kui!#?i=)l7w^pt*#q>Mp` zmfbB3lmW*@L({WK z)-OVYfLFq66SwiRin{*1LfD=RM1`P%gP9_@N6aGS6md=d{f4Ni#5@HpilWgEW;Uj|AG+T1$ra)V|ZGxUka8v|paH1%Y z44ES$OQH;sC0@bqK0J;~w)Kwm=eo zLOoZ#|et12UZsAn1R6f=K+DzIg+9XZO9f+bEd?R_300tNZM;b*~#gcA2neV=CR1vif*5JVsV-wvex{Eq_x8U(0+ zmgfn$y7?U3956B;K`5}_7c73B+!)*VE3R$eZPx9}z)SGWYqKDm$LPSyVgN z^`!ePA@pJTEy?%k^_&I@>^(E}lxd}WpU8~)D zmI*X51;`-YPkYLM=tscG%=nU;{u(r!kBO^o4-|p;!>c6$*VHSx<_)O|kD)uUoQ|}`B|h+NzaJZL@F--rd7JF3LfZYYfq+Ms#+)qcq5oT3Z6G^s9NX}PN-Vo zqZZz81Un79f#9Yj$%eRLD#M!3RCaUR&<%0knrIXgd~w$I6nqg>{|8)W!S*6t1&OAR z#51&-wpg+X95rkorLZN*s8rx6xR&1$Mqee+bbY7<(6k9YHH2VxR1+&47p$Ee-m_$1 zWzi*nO`EUeMB}+24it^p3uhT+`C=XIx!v5L?87f^bIo`Z-gDu*ybHm0*gNex4_TL- zjVO22lgy$|A^O>4?!2f|pdI>7dCsb+F~^#T@%MVDJJ88p(PFN4#Iweng>0p8JLDZp zk;)0?Yz1#SmJ`DX$())yzyrWa>Bk5Fu7RHkjPip&v*V#s;o*@6(PDcvV2!*2q& z3RLEY%KcfDW(%XouBVRYulGX_QjcB_L61Q1n;xegRxT~v#Ko~H|5yBQII&Q?K*S#K zgD*JZG5;V{4xuTKvGW|p>d&D`*_dBAd~Zm1h;uOj)(`(@<`a#g&ne=5?r3*ToXG-3 zmATyh&mwbNMX-6?fh{00JH~T3xd{Yb)_Cz+Pfkb~F#H^PRNW$}Qe?ka#|W0d86X(I zO{S6!z^4P@zqb;LApkYhoyUk0obh`hD8>6OTubmHXSx%YThitFSA|x^R{7Fq%Sxw; zq)Lzxj^QUFh=cbBe&=VW(k97=mxmw^G~`FXkBj9EEwmbd*SBK9m-*!#i=0peJ_>jjP^Ne*;Tjay<1$t*T z=T#(=%N_O%Yz}*Zd)0?4==H@3_2jLHrFs@sMm~}SZUHgvTim0Zs3}p|uc|U4RtV@o z_Z~?909g@LX;op?bX$~d$sT!rs@&i!s2&9WOj)TRQdROf18}!M%^p*J82ohF@K~Xt z{91Ies(;~WwB0e$n^{`T#F5S+z-aa+*ry{({ZkNOW~NPFP(_u zR$(louxNBSGi}6N1({u;&u(9N$hxG+MmjIOXL@YwutjWILH|P{ z;)_S0cPQ^V#XT62z-q5PF8EdRlF2EmvcZ>$ZeB(;m1RtqvYN^|=A}#yjI+B1Wap6j ziHN#zT^6HOo=P9bC=l9t2_dibcJ@%vf?}ZkE?t_*(y40<+ zJM-4KC)JI!Tl2=WXg^ z=)}Nf)>2)Cej!Ew6jkF_??HxWBs!Cn4Y~0*v=?#`4yzcN5Us|WL3z?Qw8@7gXcP+H zRtelh=wQ%PN9y2wy}5d~ou9DPGg->hqX`s?=t&N#4-(tfE29=#>M1jj=p8pRUd`~V zW#roAoNXJT)Y3z-G`7$y9_O@IJeHg#n6*!Ej1a5(Sz|BG!*Yu$nEsW6d-374-@E-w zJRa0HaCmUB!3oh&F^c{dSD&&Rl&d@;7bhiaYqyw&&YHE#Qr1}-&6CM8{bnnGeCL5Y z&r(X3+AI}#%AzyW&Y8In;|theoA>m=xNM^Qg-me?z(%5&>cK_7djRrH)i?1%m8@i3 z>j2=!xuGdTZCo_UxwLb)jT++1Hgjmir45@Sb`e8lysdX-M;K$%4C|!}#_ZwBP)fB+ z!gH{zljiM6`Vmg_nvwAFAq^N!`D)tu?N*EHXwx7&#-8EK7iQ26+u44;k8=*w2w^>4;zG^ThkIUlYcgI+FoKHqa-Fz4)<7IqZX z3e}(Uo?~EaPFq_l3om^Kz~MbD10S&(a1f*KaZycb+&=`BQEBvyxOY;WEjA}QG=eDy zL9DO%z{&y~wo|IUP6R~R;%k0S=_}uG=8ALQ`_*-uXZ~i67pk-!+$T8YsscMuWlPBwT04Yg z%jyy8wui&@H2O8?15O=FIK2_6wDZ^e%N3nEj*vtRVLFT3rN~+@AJ!_=B?SAUI@~t! ztwC7kM*VA`_158#bWG-iGmeQf4oCHb^ii~5Z8NHYCruV^#fERTJJohyjP<`=n3W>W)J|}8IllSP8xET5y;JH00+#6M0CWV z#6CZw6ogC1_$WOK;ogmx3S0|E61Xb@e_n;N%PX@7>n>S%JbRN&rWXhobveq4uPurc zf7SkzARp3>S%eI3g>DkLjGsGs5OOyN zqK8NivLUkD9e<%vU+1d{ykZxmY4GkzOyA+O4`YW?%krk`>5Zt(7N){CDoH<(D!7sd zU$rIw%K73Rht}{2Cxf~eT_s>OR~SdM4yp$DAJZ9$jI;E7wPNa6Y%af@6I7uYWIEm! zxX12Aq=q+X_Bx$z=kwr6AB3cbdEBp#mcHTBbH!UYrWVbcGbVp8Wz|z$=(F2}Gzmo< zFj1rL5!_(*-pNOwY3fmw3x{bKgHzLr-FWnlQ?$3wZ=&{6pI5DqO-D~*<}XZ`kstrL zyLWXBk{q@iW}YNXSnRYShZsS5fA5A4_8pKHuOQry8B0Dqln_(e8|_mJ!vTO&0)%nx zh$xsFN6wWoU<%c1HxhF&8SgFaF^r6F8#}4WYwFi1qoNz5X&tb-3FsSVbi<|mOwAbf zG|I{d&VFNgz+EisUXlt~Tn>@(h#EJgCJP;%WKrGSMfB(k)*>8ClLV!F{VFW2nW0NR zz(X1N6;t&k<~+PA^k(q>7Poe|3<AvJ5Rx%|McT2um&265++WJY1Y&XoyTSBL2AoIjZ<+DN8?t^#I30&d(BI zM~Od}jmpH{*kz^&_(oJ9kT0)WGRc02%ORgn9+NP#WDoHYrY@VuTEEF?1BNE`aP!L5a1w)vaz)}BL*BPrhtP22!Pp(uuj(#bT76WDI!u@I?8&FaYpYA zddl+%Y-aX)Z36(xm~kvxE%l)0Zq(3hADS6r4)iH$CtSUt3Uy7bo`I0*eMHA@0-n+(8JW72%@<`!=@zwvpPtCJxrVMm-gQN>G zSRAA*BtHsWJ$IJu5cj_uH1QSC2V$NcDp9vQzCYiKP*Zalr1@4em@^K5_YMR4jSMI< z5lONYl+d#1$kX2jPTU@skMxe2(7>p})m@ZbV^mET`1G6b$75|`$Kt=Tcy!9C>K?(D zSb}O?w3S_oVZ) z9-lxHU-^KfIxb~B^27*aN}YQExiRBL8tii?9N#)PT`Z892cGiTS9JZpQC!9nh6EJB z#GbLAHrQ~9iz)VZ1zX=lzWZ>zDbW(`?fgRc&i{+tir@MEk+F6qgPV@jB;JyFG{N4U zA3YRdodqpnKf($mGGP|{EX0e z0NY7^85_KVt;08F_?GEgAsAOHx=ro>(2%Mtme;zl}&hrpelU)2h+@hk4_&nK7^R4 zH;UVZPl;&QADJH^J~ohu=)Z`sK8WucDQA^Ggbb*CgH>1{!rpN8^&(Thc6WZvbvcA- zga9xoB61Rh1+Hj<)rgbimH9Xy#z)L4QGXagCm)gmHlmBsZ4g8jO*0=tfWk* z`_8e7sE$hgRvYxk1FXv1Vg^{YAq^G5R+w@_oK!6a<53UwnYnL|`khG^meRafTfV+% z*fEVsr0>i}piqrujPVa}H2~O_DRDYdnmsEis)Np_L(ZkSd&V`=o=VzBxKFA{V?3<4 zsm9mxfD8oByVcaEWEf&nCDe>48tSgphDlcoU8W$HBB?u2!(C`s>YSMsFok&s-W2+l zOVpj3Rb6 zRBOHLIAGcK*8#iZ(vkOIRg;qrfZqlnlM$ANJ62yusQs3lEx z?sV_cq1psm&v1I}q6J}6+XEgwX@1)wp1Uuy;3n9QY6EjVI+09Z=)^^(Fxqc_G!N#-ZaRtrbsWl5K zv-O3v2tb8`od zHYuxeWjAGqTFvFUlIhbpicFkBkMi1X_SNaNx}J3+7B|C?wV8!2$HvdKgiA#R-hU@u zi;GAo+^{#d53iDWcv7^DOE0eTclvxZQCnEjLKamrK=m!tb$d14;dPlDrZ$$6?YSw{c({>a?Q@s#@b|7Kl_7X z6>C3E1FQUW&mGq~YvJ6g?PzgE$9goVNkngZ z+Idj<=^R@{Pf@F?gBNCSPW|w4^~A%x2?r;eeSkvNuC>JtvwM3*@zc}!`T0Wf7Ar;C zp~qtLigGh{#emb(-A0mCxps{H$Or{C>zlc;%IZPyR#}1<4yklBl>T}R&}7fCwb`|M zCiHc!vijZzxPDtq{;B z(<93#^&{QQtLgyJ+H`wElTk?Kqr}pM9Dtch-}rJtAJDbyy40Pc1E{eHD#?)rh7PYY z;)H)n3KzDub3f+Fibnb>Rsd-~6NhQRXXN!(Gy~-;H!W_OU@t3$_Jn0d_H?aY=39jc z|7=0;0EYq~T%gk4-4pP4sr7f)rpLMuwJcwh$6~A=zSYf`=Au`kZ~V;ku)13&8MB4@ z$LtAWyqLMqg)8afYaKU*DwA2DhnvxBK&h+$)$e%Vm1?z!x5`>K&cDiEml||_ z6TFOrWti^Uz-G$vl}fzIYg<+W-yqfsVdWtA9H~y1hfW2$_71v6if`4kjthtiMbCq( zm4^M*Z1PI=u$64nxnt%@`7m47(R|8mXO{y;?_^3eNAB*zNQ@Mc9hs(kqdlJJXl}K^ zYW5f;)2<1u9rRW`VYu$yP4blK$5c@az|UQ7Dgo+30NNc|`WFkNy93Q{8ut&)2hfpP zCotLX7~MHg?rz@g%EYF~EFRFmbY(BGZS&=!K&dn;x{1(w+_eU2+b>M6`MaS&USuQH zyNece)mIyBHaj}%)$4QSv7VzjXv6*KjwAubdmE9)-Dn#e%`Vr~(FU9tFO{1}W(ki8WSj+`U7wgm2gO1sgBPmxE^P9NTlpq)3x?~tB8yuROl zty7^nddeTUqmqUT@pv;b@>OlALY*75gM0p9m!>mtUd-Q`x^s=vB>L2>c@tcZN3oMRq@;3|UdHsTaFz3Q+r}wI6O0Zb`R=W(W4{&X#r=*r zMnvc~)Z~Rn&ugXNc#`*4^|qsUP1dATsQE}{C!-C<2cr!w=B7(n993xzPNo8$K<{pV z@PVtduQrh~=>&hC4ot_Omhb^3`S>?yUP3w>AwBNxSI7V#;7daA(Ykq=%sjcJj~`v> zzKV*S0lwzM;y0P@=&`pwu*)6eW5(x))g1p(S*{w0skuf_R)}{1T z0zBzkP&;n1890;Thn^<-D`^mhtkI&bv0Sg%&(wft-wZRt#1nnS+qMeU^u0I_x6AIy zOO!XeKUJg-Kqe%9(%CJ4d!Rczd&wh)f$dJvCsr<|!}g^n>NHIc!&B~J1LjP6P%lQC z$ul=P?+~bDA+}hGwMX!N#>Vxb>P&wTlF=pJLyh{Socvst9$PbxhKMdza`^DdmWTTt z``yuv!JBMM0*o4}#XiHj>+kon)SCjC)N90|ExeQ#ao;yQN@R0r&l#s*ma9o3{1l5c zqR}3xh*YE5U}O70tr4e}7I~{Xou)8icT3|=CMhgS9+GlyHjF;0YTrWCOnps9#Z$U{ zXTKtL%Op2Av9%O<7FPZC*K7j|R8sVnLGuPiPczTcdhi^Lf3$Qoj;vXlM787h;);-4CA533jVNx%`-_Rogv(vo{(8W+*dUnk-Ivl(FLQ~P=!ri>Oj4YV@CG0>P zW-ZOyn*p$nikPyMXe0mOhCu8Jz(Kh<&#Z>@M$~qw&_u`eD%`|c$FaRYI9!T=&)1@< z5pta4J3XLLTi>DvV{TlOuVFt-aFT>HeKW(~vfa#)UVJ-TY%AU<-q_O^x`=%|!jGQD z02;7Q+mRd*lq+>EsGTP~y}HBjMDXmH!70+JuQ50ZH+Qb4u2HQ;;3eQ|;B|5&+TDHR zT0Y_z9IjY|-b5#|yA!DA7WOjX{LF%b%OtPMsQ99=R<-r;E>K1t{ViG4XN?~f!k?UA z;oetN^^#{HaA&=w`#ugHm)7`6DWezF#@_c{4nYFc?0u5>^OtW+#Ljik2}dc~`C#Ru zz0S&sqt>-RIj0K8@vMu>21+>d$h^VyTIFy8hxv4q+VzN=#dHXg5-y3?+7a&4-Dke~ z&~9yqF40`=i(b*x%Ih@Gu$p7pM|$~e;YUJ+%QgFdQe3TdAG zy4LYa%^a0+HYK>vW#u~PrAJdM_Qq+ng=p;%+kTgI-#Be_s>{6EDqgbhdYF%;aC1&q zcd5B5U*l?75k&xu=c3U%t+zKi5qZt1Tq2r;YSr7E^mkmYKMErfT$j%~y4`7|0o90( zj4B)3@B7ye9v#<*(2CFkEo#Y|TB#NR3D<$sJ~?P5FmB#^@+;}J)f>1ykc(4cqLsR8 z+_Q~#vQ~%Oc2xG+wE&Mv?8`P^bEVqLp5lmoI|C5SBDAHmk<==s<8tPjpl^){CKKlu6X`T;BU@5T^Y2(i0W|lTR*=EpL%o1O-FXTj} zm=$KafHB*=NLZMDWE$IOb5}uQS;rIpyu7Rh`UCS+(ZiY%6OD)s|!|Ov{@a4+#O;te-}c>OE|JRf*-) zbg$pFt@4MkB|2~VWNQ=NW82^JaUs%qmD$zO2?8VGED_j@uk$B`vQ{lW#g{87a^a?W zm#t1ZO+Dt@g2ITJEsM2y*!RJHxALb(EUn!FXON|Q0rBI!hqI(MR#J3j=hAkgj-7BF*R3%->#Yhq?cAEWDlpY!p>(OZ(h?*|d~|3^ zU8!dJQ#BhYt6{ft43(Q^o`V-JmjKG15Tl)b2%M3wv5xM}WqV`tX5yA897$cCg2Sh9*d8~_aGa6$2I zKL8Sj6V?a=1&SCM2(Dz6c^M8|DBL=;D)h!o2CmLpbgInfcAC=hRpLEKP1Y<@NT=gC zzHu5=(PqocF^uLMj_tNp^qlfF5fTGioY`|8qPb}aRJB3T5SWxuG0iZkkJ)F0rzgrsElfpg+lnT{wfY%e!xyS-q^o-cVBe=Z3S* zakGWl|Fq2^+&PWH*Yhu@ieDs2yVzvwCj8nY#&(~{+LNr7J!U0c6PPmB{NqqrP0Q~1 zC^MvZsYIWez;Rsu5|^%KD%u>dJhod8p3OC^2NESeZO|NX60E=cb-(Jd-!aVdfN`q?K)aTf9I* zDkGmuIQ3N})k-;cZnJMpuusXx*kON^x1rLJ-RMYKjZbNMIHsEIpUYo3GkIVRGuv== z&D<-_{CY<-tJEY7gK#Oe4aMo&m`g?@Evfuij_I11YRe{dH3LtnKB(iFcj|)dce zQhjh!Cac;yaY=s*`B`{9a4XS=9RV<^nBrAAwTW$%6KCq_mhfd*j0#iVLp^zWPRL zvy2OZ?<>Je>jCTD=hLmc?(KWrm@7SV+z3K#_1tKx;`d?{l25>*%f>J-gSCaw;blLQ ztjFjf)7p`xx5QSZK$Az=Ir<1GC%2P|O1Fi2=flCMG|m0sF{iiOPzKJp{m2ZqW+Xtx<=3v>9b&W9xpUpnO6(P#BMdya8)Cc@(JAJ%z)2v?}^z`QnagV++% z3E}V{UTH(;#t>gK^}y^|&CP7ylwI^s->_QrbB7=;22wp>TyMPO4+<=Mfdpak@)tj) zA?e(>;Ye$VJuE`i|2S26h2^>A#87Pi#nKvX?_H zjblQ5{N>&8yum)B3w|gBF%F0lr?2(}jSzi4@K;BGUN#GX0SnGXM?l4at+*+3_NTcK z;hMvzQJt$7BwfP5Z!6r;rfb}?UdY)GCikhwD@LQ+vdjmA%w`Yj!!WHf^Ihf@ltu$I z4o5ZnXJcwq5$JkSre{z3YxhXG6F2!as;LtmpjJH2k2Vo%-? z9WG{a6X|qHw44~8A~u^kv~eX#JBQ(6fcURYRO0aV3df_$Lp7mKvd2`oXP{EW@a10img+8(Zdom zKK-Ud?dXn5Ek|+!Tg?)?uWrm@rnkX18#5n<%juI!cjcBb3x<#AVqA4T-7p9S z!q~hM1o_#pP;DS_!|HTp(p*&jCpTPIa+i(=XQiVSLQF*6vH`J92>F`87{`+k8fyE- zD@=+NEq={T(}#XdRlE;HFJqIs4xMYwc+pqGme8xfWI4F;)c(1RVZ-d@b3giBXWfhc z8v^8QQ2^!t7AxY-P52{gu1()WUC@~`;g}6rwcji?e5qv`FAjA$7+2jLH_<@o-g}5H zhS_j{_BC7;C=!<{_s~y4BpsXnxf~bo=pGk`;F0u{LSVi8s3GYth;keF54c_+69~cs z`j89i$Oark@V;cczM3+Zg@`f-12zgNCt@}$ya6i{fwq(7EYK;H$)R~egLs96xBob( zpx-4U*)e`;BMI2=wU@*bpJ<=R6TdfZ1PUmr=+SL4+AbV$jDMVdY_&h8ok56s z*deF;>Z-#eC3(|R=&3<&E1qFEiV|ae$c!7``8mI5BDhVe3 zzX@D2`)9tnlLk|lgCe-m)9oIAqeKP_}2Y^y%R>59f2PC!*QFVhrGxUIk zbY=to0hVi>YB5a1hTf|4s18O5oLYw@)H!0yb==;319vQ})H~_%!7%G*;x?wzBLUMO zRQDV-BqU3OrIPHOa#L|#*m2i2rPth29hz1h%7+W^xY7I{yWC{K1IjfK7}n-L^qc$a?a{(nf4(o8rthZ?kZk| z3s!!m2aT>_eI1%(|6t4xwqPZQrzW<#>8Roj2l4)fYLO8L2CYBBZyCxD^XsrhJF$J0BdOieIxi-? z<6yJhof+)PY(+1L)8d(nWovY*H0Sy|?MTCz5O7blCBhH0+vNDLp`?6W{lBqZ9buW~ ze&mCjryZ5`aYC$8%1C8H8H>-Cm-BbiX2||5AQVU0LK2Sq$UY{wF`fJ1*8F@F$%U8j z!G6mhKdqq$uGL|x11`TQk2RcN;xD8i7w%>@sg#{Ya5arK%*XYU?ajAJN7t}qrYkS8po4i$}CL730fc12p4Y%&C`2Y%q+Cqew zp0?I?{++By28ImkT^YDQTifM}{Bg-WcIUtn6=V6klY1>4c2?UWhSY+Yq0t@VecP4J zL~i;j9H?D+^~}&T+jfBH6mEd@rD#IbsV%c+Qgd1KS)^1vT4ZwbPNM|PhGHa~pX=<{bErAp>BKNrk#hVE z-7m>1%*`=J|K*WP{=l;=3k;)Znq-l=_x)4~oWT_mF*5%HD@2e!N^F^7Z78ZM%#__b zE@+h<`v>49p@?1T7bmQ~W%4Vg~Qz!_nd(j);;m7G>J zd#q2J26i0{ub?j%KG8UJ^^{>cbu-OkH?AqC1WZ7*QhqmfPS&J7{urF_BVE;ec)PRa zk)U%4(v_XsRu-UdQVrV?U>kaG97s~`@ZJh_DR^Pf+ihLb^C*yeWe!PXE~s8lbX{N5 zm()P}qP%Ns?fK}v<3_R~nLmqR5^anXsi`;348e-X!ub6PKF^Uyz>x>GnbboFYy08> zOZ)GQHTF%@glxTt03L$vKSlk%Uq{HkA1l628`%vxDp>CZqb00#weWX?Z3cppLKiV% z!`l+d#sb3z5l9I>*C3W~GAVHiGC(XcnHR}$I*~$I3S!Ggulnxqt4aF==DhXEf(zVz*$#<-m2Kzme zpnOs#p&T#i$Ao{ufIt(T=hXK^awCdwBy+>3BMFg?DZq4cLJWLbI_l=8+nx~^xu>vpoQL!MkkaSEWhQ<`-VcN>xVd- z5vQ_`!pLv7r9cnDIX7kf3njTu4rUvZaGd8QiVyLdZ7Z;W{#7exO(8%WpTx-JZ$kM? zDdHZ0teNhos{cj74{hx6!q0Aie`dNiCG>>;M_TOPP$8*3tBdU^=C|6ir3Y!a{+}&# zc0WHgRAU~z^Lu=z?iBY_dx4YzTc)0Rq8-F1&>B=}alno_xvsnZfZNm4<+~ptPhI4n z)J$|3PhDzP9vzyhIcUc^0A|3g{2z&UJI#Ju+MZuT|COlF?0;@2{$hy#yWp*#?E59l z4EtRUdzo|$a|9`f^1c!d{$De`CQgEki$$I>~m@e$!jreq&ciba>^(Zy|*8wlH*7AHgVjbuY2GGS=Zu1wJ0UR7V?i`!)?zMUrv(q8Q;{ zus%A#7cZDD8F#C(FqT z|7tSyaR-?R4w)Htt%?7ZuqzOkz3j~=;hCbyb=y=1rR+y42{@embf;e8+gp~nmThnz zZ;n1rbvVg#$6adNT^7A&YH%KF4n5ZT7p%fO+fUcdrVlfwhU*fEi$pk-Y0>c`f#(>^ z0rwb>Yt>yjHjeAfr#pt0rgE~#C-1LO(5SA_EEk?q&mdzro2{ab!cgt{R1KL$7ZHB} z>ihKCKu;gc(9BJIqx5XfDB3W>sVbBPx(Q4U zC@_oHlZ0&1#AO2`6nP}KXr_eo8Gcp7^efUy{Z*)-&{n4@n$yN+EC0UEC|e5?sUxf_ zdQDIAQ3Cae%bz4u(nMd2TQyB9Wf$>!;1EBUo1d{Vcc8Mm&k&f(faFZ|ybc;HE$8nU z%_q(lO^T-4d&f*Ege{vnZ~p;G!*eZt_QOW!tjuPAROjb3>SN(%Vjun*TES{!UUzNo zZOqkC=}irnYx!htHKBlcmsj?$@Hi!5gu=|uthMdb>q$hp=AHb{o|{9?QMsyU0Nq?y zOZHOY@E@F?yI&V8Sh9}q9HnR@gIx86J7^?^JNrQBjS5=EdQQ=IBz;Ja7i zC^M!${wOodozX|!o(Ase&SEct7Pk3LO*8Oud%WvYKxOeTlT2?(me;{WDArK~QgOFs zc+TDQ?Qsi`(TE?CV4Z%nVB&tJC25h>MMY60$#Avck$<8l5&0bUMW{&OH$RcpBYXP; z=zexQFF-dNPfDuFp>jrxr@C(IapiB{X=WLFGV^Zn9)swSaVA?Q3~^0r1~i-~Tnli- zXP&xq?1rh=5~2V4yroin^|XFQJGm6)GuEqr!?Z%-g@vIpDt>3 z-_>91C>*2nV=@)Hw%^kOeSZP{X3D0kxtdDF-Rr725l5y_k&w&>lPL5{Z zL6IxstW|7!sM)nJ@U(7Y z%y@^<+hUh=SC8!`{T^p(gyQU2fh`4BBKX4Wb4P@(y`1anx3w1ob53oBm^%ej%5#$7 z1ev=!ZvY7e1v%<-NrtPh@ax)IR`m)sl!mN3FgfJbYmeRg>rFbwIG|fM*Dlkyxct<$ zX4)T)2ZkBD>4zEH6&bju)5~9#Hh9Ons~Uuxm##4nw?Xn`kxh`;S*cWIp z_OrJu6GNRge1~SvJBF=pzNr_^U)1**b^0O$m&f*+?Bu3Y&uGXU&*p)vx1NCK`Btma zpO|fFS$-%gV!RX_tp5;`-LWINl#OUtRzp=aJ*{82!F#y+@H(vPc^SVyD!oS_c1yNX z7^J(wgs6KXdlsG4{$#l1#8=C+$7*=5tYOTx+P)JJ+so?+du&%-d*-YmZl-!>Rb3Mo zXL1?qSm74Qp&*}kN;%c6fT`?bZIZfsuC14GN@KWdIwaZSiSoDyW^H_3b{$!3{f$;8 zSauzSc8gtNvb!d*K6%Z%2NN35K>RO{*Taw=_-0K6w zbnWp(?J-;7=j#W#rE}M3(9Z}9o4ZtUlucNyRJn0zG$&n_1`c{e3dXXY|MJHkEaJOJ z=DJMg8uCc>YMvfEce_#-a6cMFy#A(r`r{dDRv!i`k)X^dg)>qdP(6^lx@nCsheo@0 zg)fKo0tNex$EP}L(^8w(yCxmaWotP1{O*&8qyZb05|ojH{ola7M&+vaI)_poOSfg` zjW>H2$T|XkeI5_e1AIa*M9mhNr0>nE406_dTWf1WYWoRY93}5{U0YB_1?@`|I+_eT zW?t0YUu+myLoXskzfdR}oBERd44%vT{{Cax$RmLAE^lSfxiyh*#F;d0MQLd&cla#L ze)$@Tvu6ezyr(=RcVzgrtjdj3FjaIvRdha8v`4ot;p-BmyQG4ygi$nA5V2dGz8 z3B7hR8}o@>Hh!Zhl4!aYy~zS!yQWCEG zuaHak6255Z8v;W&49>>OP{=p1OPfB!!nYav?gQ+Ny%30LGDP3VrTjzFtZ@^NOuOhU zS`9v04e>LqtBI`v0nT)te6ee({im}2F1eqZl*pF9@@eNImnsLS(sj{euZQ=aiX}tD z_!3ev_@#(OFihek6EZQHqTOrJ#++DJEpStbzP4() zM%19Wz`1%`3Jyyy++mRLp|9{D7;#%4j_;j(KRpl<2;2(&6A7W%MQ6fAXCG;q^<$a! zIcoJwUmYs9nOT8V;ARU*G^Q#GG|E*4=zM|E= zB+ajdlycUKo76yrzZeX{}OP#wjos8p&~55*8WDR$(Wm0?w;hM~Diu zpr=@nJn=oWpl^PDCD>h3ahv)GBG^^n5unQz-@3^0S!N$iwsTXGwXPWtg?Ce6x*Jtg zN{Fu-Ri`HsrSuAy#mRJod}Wk1|5Rm`RjoVJ^|d&7+Ba|VJ7bb*^&1WLF*{7g_%SH#gfCS{Fm~;AX8~OW~XJQyk-ZO@E8O0+w+2aQf&}ce+j3WMF z$j(Gzi!Xsh@l_9t@$lPwzIT17Un*dt4!><)e^@z=;R&{1F>IS_I?mNpvH#HPq&6g> zVjne?V#q<=S^r2cz(+J}`Q15uO(2%S21`yKenspvAT_*zm$3MlH9#HEV^V!{$LnE2 z+)|0Lq85CD>|sFcRgNkIl(2N~aIB;#k_f=L0KeD=_D~-rE)nd9D6Fs6I(-t>jV3r$ z@DngIrI?0r#erA`IA(L<8z+Ci<^;?YXQHv*l|={^WuqM=>?NJdZNe_6zh0UB$-H$B z@p{n{PYX438TqMV8n%qPw5KB@p0Xg5?u5V>F9;aDf4nI4^#Y875bqQ|kSZghulO=q8frF`5e zu>b1igF&FRVV8f^9ei=ir$XxonO3};_LdkVkJT3uK0@w^6+#y#UoW;{+{&n%7IXtv zLYtH0YRArMB2M05hZ5Z#DcE6FZbwxsk3olk`LF50Ws0NME0tL=QpH9kFaUW_^|XF* zb(jfTHB)X4Ugd5UgWs1X9HbH>DnCF=93agwmO4=(9%5-+O^u)3gD23v%UZ~USdQoq z^d~?jcR-fvDRT$|q#MR*8P9?DS&K*v4wK6t)Vo^}ZQTbe29UeD-T<3n3*%X~8N)Js zY^{IJ_-sk-+6oAi5U#Xv% z{jz8&g3W>MY%VV*)737vu1ir~s_-+DU45@lF~*;Cxt%x%b=2%M{5w}-J6C684X1in zyxN897Z-0E9hcU1hLRSshgZ-U4ZO*6=AsRUDV#-TqpCsDEqa=JN|j!H5tIDsQ4&HI z0CU4xKeRoy+l>cj%RTxo>Up>7^}CZr{30lyGyFkoa(ig>SK2y4%|I>sa`P>;x7~T?}@$j|gmh;<(j#CY|G8|l#0w{5eJ_8b}Y1fxI{(<1o0bHTfUmzGn{pCrD+o?%Zg%7bE>0gWH9J%df4tIfon95h z=3Mkc(J0rW=Pc?Dn3}ag^>Xe`|@VUUle;S>3;H0V4C!{5CPTAM=C?*xjrE_rE`5k?!s!@x!iOa``Nwc%l% zMnp^-+--QMEb#HHbz$u&t)2J})wXiwB4M4Fi>S_Re)}@4qC>c#4&?;+3B7c6S~@); zcE#PVrm*2r>6tQ|3nTf)!rvvEfa5DNOeKwR$!=6fX%l5ZWD4*O)ajtKq1A+s?=;0@b~7iO!a1V248CHu@ReIt zy1}#vU@XHHR7%GyEx7Ie07OkcU-q|b1BPSKa4?Un6^A$|&{L?_6x_+oy#jQ|@C{ih_$@?qiz2L-uX|0b|nP z%A!(SRT7vy$#2eD^sTuGib3~{r?Oxwd0KU}%_PueC2M=GA!Gp~=)?(D`eW<-u4?j) zC1&f9!!9iTk2ebMau&KAk`t^*(RK>t4%ckhN>5gAxO=#`Tiy)OrHN^M?J1P&3eQ5K zKX&Q$Eg3~===_KW`$vK?`ADsOs3Q{V#Abmn`ChoHe!~%_WL;^uV!YKd)SpUW*N0Bk zZs_uwB!JcorO@^72xk?q?`At?D5DRnXF=QUd+#@)Bb7LvsiNi)}cBP9`!l7MoHmcII)z&6dHu{gl)_biQ5pt zadpVpur0pAoLneMsa4~7{%e+vw+8jL23he-`&`sMnIGQ2S_pzOE$~0(Z+a2>4sBF} zd{o1_!^{P#ro-ga2-UO3B zh@g9Ay%tjVo=)=tHLp$qMduUBO zcc|n#XiCDC)Dwool1-Q}hBCMdZ|nfW*6@i4r-!xBK5?pka9`8dk*SjR8ai{me#s^x z=b49>g|^`$s9AJ&>8xME9{$XsNy7rQxJf(4(%H*gI-;nknn zdaeAFN1Y9V`y0@)9nG^J&nK}c_JKpqd`f=?8r&`1yz7ytztSHum{wyED; zH9pw_Al@F=?haO&J?Arkj_cfoBm^|xK_hD3hZ*(l_6<))D`U{(%9fUMt@~B?i(yB)5k1Xe z_RF8=cxBc^SK*y4wzFKQ_uYCc+#~Ip2?*yt5MHD;SC^MKpGX)2o;yNKu(xGc+5xIB z?zsnad79u$I}yj&9u>wYJn5wU_D=EmQRUjASzwGiPF86X;N&_j5@1H!Do=?9{asl| zaXQXVUorUd1CgaxMaQxyzGj&iC+$Y=eQenEQD1z128$~QHq^M;j9$JIcB!OUW(eU5 zT_4I?W2XA~=`@*PZ}iQFcbE+sR-izJ-QQ&yGAtH5;ya&LUou``xU^XC>u^fG3&!}8 z1sg@<^ZuVmmp;uVLniGHs*9pI93;m9?z*oQkucX=x)ClNWqFcAZwyh2Mo4w{* z32B<^(n-HL!1VT9FO_?^3~m*K%uqkw{euaaMmqfiB8pQXF!Fz7@Xy4P!Z1Xzqy$s$ zE?1ZTfJ=OrzrfTDP39zXPk_BSFz0&of+T5Kc*6bvhdGa(mCN}@`D^APQ7=Ls|78;+ zSd%b+gC2vcM)CB}cx)Fc;UQV{tEpi{&LMM`z`QtEGFupW(cj0qy(*1QR%!J!N> z!T@LS-l9e_6hu$F9h$}*>P8>x_8&WR0~9{*+-e4K&Q9{OzHx|G5UFVlw#W{$Xjh6_ zjzlZqG9**5@az3Sny+S;>=sXhOWDsOQvY6III>Y0F0v$JV@|ZWb4Sw)d`o~%)-M`t zr;w!?^ZTlQCPgKv6~-lE955(TMgB7x4({iQYYRQa*z8nv!PoXtouVP%`Hiy@JXh7Q zCVDX}$Dk}!g-NmyUJ->rn*Fz;#94X5|8DL|lcw%vvw1q?fQB!|5(RlD#7*x0!3;MB zm{)zICklA(2F4#GLMI3>TH+Wed_Lg$e+Wu4IlYySFbT1!h=4`Z z!$KsJ+>U&A{^f`3`(AzwLy|WiK(PH}xLZF$?RrIdHj{1?Fon$4#fK2caH;aei*E9e44&U%ccLaR5lJs8-+Ms-y763YjP?U+1ricBG$qPBH3 zsPUTIVoXF7xJ=}@OrL$~HakT(J6X-Y+w=w-Y{Ch;`p9XoM&sUW!U6JPF8?q<>T2KA z)pVCK%!&!us5tx{+G?pzlLU-pzTZD@oh9Tb_#!NHF*9Vbo!a@dkJtk%!mq=&m(0WN z^-7ZPtw{$p;awg{phpLF`e`4v$JrZFY<3vz%?#g)K6;OsQRJ8(!d7e1&m|a+V7>39-I*EXYZ5dU!Nr#UV_WOLGt^{2|S@$b9AzV;J%8uJjkxM=|QFo5p( z2QKeShoc!$zg3DoOev{K^)SULjYsxH+Un(rZd_2-O%_cHO$c+ydg%WX2@MTlz7qh? z00sfLU%7(I=NWAZU4ZxDb$~`0&CGDjjf+sQ+$Ch4-!;5JMLV~eW@uhbKboGO-KJOsX};%~f!WGW?O&H$Rf|;DfyJPl%U@N;qj$XO zAS8{37@ABu!?TK*mYyk`dOv%<;GjmDvEUX@u@%AWO~x+S`0)YSNA_QhiVfe!XE4M= z>-2e52j6=7?MRI;7>S&dqBr*(#H0816q;NHx34&bwA@i~NI;|2OHR-!E{xB{7%tBD z_C0UKvrgb`;VEXNrC84t#Nz_$^Q2-T6x|6ap7#p$YM@Z$Bj(BP?DbF^%Ily;DS$sx z?T{}Nft4<63t+eLwKn&K?h4M<}A4>dQ7swLLJlsdYSIS270Mfe3c(dV_(YleH$r?hzcoJa$S<&?4OFYv3K(3uV}FP% z+Pbn|##u<*tjV?=yBvxQe-%HIGUBBE(M_ z`Kei=ZY1s7clwqe8Pta5f|b+3o`4E^IY0ezfxuJ)#?m~)5~Zrxr-oy+2L8V?4Tv9d zLkJJZ;Qdd7<=>6$UtR zi-*-g>eG^Zv9#EKFtR$*^z^$o!KW8Lum9vf5+x5K$o?6V$k*5uU`vmgHHshMM`9K_ zh3VG*#)ceOI5!36x^Qk9=6CWVtpb20)9P?U8dDbT86gX~=o?;x5afvGex^25-Ll+z z=5zu#88zf_JdyLTD{$m|(h- z1PMyMv7Y9srwL-`v^%&UlLS()N+i5wTXR0e8uZQ8;~excS$*D=Zo7j&0qw8N(=7Gn zJ$4R0HW|hdhj&_xxbVwREq-rBuTKmMqC^_+b5?~&{qtF#gAd(fPr=mB;FP1q?8jMO zy62fm`okQx_tpPziI#?tgIx&AW6tbAWyX1pYjXb z<|nvKTDZ;kaGP(RA;|Oj6jmXfKO>GmW11I0Sv1j+>jN+M3Z<$kbl7QZnn`_D6sB=k zhxG9v+uQS^6!dgC)+%^6BM!a$FHBYQvBK(I0BJY@eg8BQ^{y;w^IkTW`9y{C ztMGb^XUHUeRHEXQQNm7r&iV!96jD=04*pi72(kgx+)%fh8JSo!Y+K@RT7z|IH5#jE z(X8}E8aKTap#hMnYP|$m0p8Bud)}l^H zoK8Ih%#@|>n-7W9@4gi0KHQZJIp10|{HWpzvWH~+{4!JWHsasfuz1XNy~{)uweRfh zd&g6%R#jC|?k19#Y_)Hs4cEy$O@$_sO%pc{-(?xS9Q#1B|Ea=OeK`=L00%eV8q2SO z=Ys4;;5(h$;?u+CY5uqm72?y%dyl6@N3+I3FehnwfEax1-C&~P@=?x3plN$}L83Eu zQ*xUl;S~CEY=}=s#?{};Q3qe--k)IeE?c{zyXdAjRJ!2L)zL})`T1SF*gW0u6Ohr` zJ5OIr`-toP(ZNdSC5s;+Gx-DJBV^B@9wCDclU)y!t>iH4=@^(ce73mEyi>#}59KWQ zpw1w&G|hIUX-iBxyEPVq?2Opwt$a*V5ik{Mpi=ZCI(}O`%h)?u;A(0+@Yxn29w3tJQzO6YE zAqZ;eE>~!^v67r}*E8pvWV+JCQ5$BR{(@@$z9++q0!|V+$N_x^Xt3s1CxKjs(}_4c zaL=6iYBzVPtzMW&V^@Pfz&ul2cz5V+chVFqpNOi{N0y#OAX~d6eHK&{NF}kyP!zox z!cfwi=|J#U)cHZ?Vk);Z5T-FewSMi+FakI*cesQzZC{h}ox14l(!wS00Y~2z|Bm<1?<)yuJIjG0oj(4L} zx8j7%={wKlt|n!hEx|jI&9S37W0r>IcI$UzLg`Pp7bCgef{*8W>DKVj+z%o@>O&XS zP!l@t|I8hei%*3Teh`I3;*m@={$c-{JTTCeSmo)vBff!FT2DjMmlm*FafZn~p2jTU zx^ff`Uj{}|pFJ>o2ah7wq=_y7Z$P&m4`YvkDdcbqI8cs?8bY?cx(XH4^R4S`!lml) ze0wo+oRF!Gj&#-8r~B1b26LcXto&Nb=S;Zy-T`g ze$|>@JzX^hCyj(yt2JAaGw0#(}GYHV~{-RR|Kxg%iVF^Q?POP^S5-T zm;o&dQ&eUT>&_o4Guu0&E0qnm)?QIiH`*M*eZJ1_EuS%ukS`-Aud_G;e5Z2c%ilrH zK|LxsB}cz(FhPq(MX3903%9tRWWfB_YKLm6He)FT-_aqbp zXqQ23j_mXcf^?RK^NZy94DAQ@ zS~kar+Zmzn4c9q6Yc#zfzHWJQsC|^4J@``A=sndnUNi7+r%~B`1Nr54<(nWrPMLHe zzDrhLDV5V1@p9kjE+J3gTsCX>0N}l@W;5$@@U*Av0z2g)&@%`(z9g}qS?|b=w-d?Xr9H3w< z?%<=@xN^ zLf)h>zb-RiZnj21Ol^d}c`lazCH|LCLB0)O$LIA+4yAvI!=042=$0B$4eeQaHCR7a zCwOUDn)7p&tFv;uI)Oe7*w~abc`LLEtZY~*_A~dnDrb!ORIf$_o{p#cIcD3tP&urB zI#(;mv>J$gX50_RR>2%z=W4O-gt30ixrkc_`*Z_by{0z&AWekR@Or+n`#tcV~zEZ z;Y!4U%;@JAj*=@1)ZgnO{8gO`x%OWaE=j<^vs9wyOL7adtC5#Ntp@LNj}EQK?{bfYmLyKFkFhNePq9x^EwGPL zk5es$mPU@$EqiBc7i#}9F4iv9E-}v8E!r(IE{q(vTBRPlowxxD@2_9P&f(s{d>UM< zKk5W!I`wj^g-SOHXa3$cZJo&6VK;}~W4>HA)4UMh0h&wig^u}}y*K_oT0*{nbxXVo z+sz^agFOp3D}2g`=hm9!IubnlzZ@{bdK2$zb ztm1@Hg_e-UC;nMXrK(SyHir;lx!g`M?k-{SN8O$<|Qy$CV z7_IqoKTKep?VEd@I}9bT^|ZcR(rcE4_j;c^3?_PfN-qCru2qs(ocFjmemb7flOHWM z>6nkalicfG%tYTLR}Zy3Lgo0C44Q1g)3k`vQK2@1T>|fZRm!PIwKkFR~ zTPcRwJOePMJ+*Sc=9tAZlSOsOj-3X-uX{k|6yLR`W6hZSm^LwKdgFWRa_jQ^yM11V zhL|0GQfO4?*5@|XF+6+AaVTL%}7UM;tXWgOPL0b~!+47GP$T7@_R z8@4<9`A|M=^ALOfH=6Iv@PT=c@m0sGjb&4ChRAZ=Sl{|{zHO-o)B}2|_GuSbZQJS@ z?-_QV{b+u-GH&q6^eMfL^U3w;Wm(8E0GTZ2Cj9wy+MndZu=->TbU$6AJT^}p`w9@aDNGT>U38z$>qvE{^C3q2nk_EUVM zxZ+f`S)b8+J!^jCF+X==dUU+pPw>crZ4a5fQj>P-W}oHnDQBk%S4xtm#RxCkMCndu znaZF-{gq#aK*~mX`YJTTQ$t>}L%a2OeyeR&+xgHK(m12_dGGgd)hk-~t#MR&PKq53 z7wf*z*Tfw|`(L_+1UnlmSq3HpCNAz&y z!q(pZrk45YW65QVos5OV)P}Hze8a7y-cgy*S5RvSh>wzEkt1Snp#D&eY~6&6^hVS^ z=5Y0l-3zibPhD?59(X$?x31_|by#k#n{=Gct^;kC(n~^*^BX61OKPV%-zUjCx^OL^ zPAbgeJVeyl0;i;O|MHvX{FR%;VbdeFq0Crvv0@wQ%8zBU%iy~IbzpPbBDm6JCAe6c zHZx`Ilkz<5UC5X2Vb*hDjg>a^LiW}7u#$-le^PB@!GZ@eeAV~b9X-2atcT1 zaNUrn(xmf)Zt2@OQ&&R4&REk+(|f)FALuhnp`g#=cLCz&)LpEIbt6~&$7x&PjNEvE z_==s&;9w4VCRv6RNiY31;xo8cTtS&Lt-AZc4M&ATsdA5UT~nczg$~_j^@+-VRn-mf z4iBA5npyQ3>$jk}b7zE31;wWg~sn8L+8mrG`Y% zYQLP7F!M|xX0q{?SqsalBCJJndFPGcoB^hE#kHl?=Ue$u@Q9zxXNn(9C*h$d>Zcr$3}uIZ1MRpmnF^U1S@tsu6RP1|NCL$|N|0-p7( z!gMa(iFO^4biUXv{Tbu*Ko=Vi>ROgHH4!R3veOpp#lE;+YPLMag;s}X@$A(8!^9cN z&-eJP`UXKK{iP6#W2N>S{=t%nia!L&r?K~n>(9}PVJ*23VcnTlkQW8VM{O@j;a@Om zCh;`JuqK1YNug!LLeIoMP7e;udwD>O*sHz#mQ31Ld7w}^j%jZEljz6CS2>m4-!@Eu zkD3Q$gX0X*DxXjDX50au`C-5q_wz5pjinO}^xVR$@^(pN{kW&ff968P_!o_LwP>|1 z`2M>1ktehlaw7)`k(;)^aP*y)(4;)-y=irxt5&0~oF)?XwNd zRQd{%zQ?~ewM!#X$XviWscoq|zeDjFWdGf5==puqJ`1X&>epS7m%kS&qHAZHuBC;E zqY0}3qR{+2b8V4&g5X@@-H#WQ-tw)2nY+gq=ob-fn`63%TnnsM0Q-{AhEO0@-KUt) z7vNX?3Wm;v=9s>~`sKj$3TR4yr&^ug&&FH2csl(n6IuqxCeJIG1 z{X)VQPhN?11lD8kJHxE^IZY!6kQ_K8$;R0;!byMElwZnIiQCh`N`k$~rVG6J33-^2 z=cusIE@(m6P1>hI7zJPUb zIj!~u;>oS->~IURnsu>qv6%Vr>Tny{2nROx;b`(b3Bz>+s6=8BK;RZaAFCVRqH!UKc zAh)6>dKPGi9~b8o=Tw$3kuiZzj(rPv&=()}fy8}$X1%yIT|b;?n;B`d1FU>Fd^lh{ z#y-ZDhWUY;1%#&CvpULO1AfXw_d+~>lz)_CJe3-Ts0<+R5Sq^P@rRG|ha2Z)$>jSH znaO}R7PF~dFLM?EWx8~|X`g^&(rnyFo~w-7nGUbsjP%|6YPeBC~= znj9;naK)Ew16T;w0OUKwt|HaQHnFnh8XdERzkChNGeq*U4IE)pYcJ~7x zm%pRhe}h`*XzFY`@QLVoqgJ zcW5gh$NK(L_r4?h=R_}2O4Id0-jntC1V=+7iW zGx28aTVj11`5Y{ATlt(UooQ-@8^g#oK{HatOjlN=X{kouJzVAgetF=wT*YB!*w}9^ z>{+-X=3&;jf{@8zMrYlUZo}QNahBJ%VoARrl=hJ{G#bo}CV}FWUy{&Qi<1nuXGp+F ziBL{oM-R`lVrV&TELJ!#+{79-5%OF|Lrf&TVi;Tp4lKh_6X|f&z|=l<{TX2p>&uryhInWX z@F9w`fI>w2RM)jb&OsgnKZBe@I3voek~pV_wE412m6h#5zp!w-ZRIk#!u?j_h@LmBsTj z*AmA7&*uQo{f)1>y>Wi^UMx4bV7HK96P>ATsY>Z0-*qGy>+Hy%g}VtcFuNwuyXc10 z#aV>bp3g@yb#DDFN=eME7v3*$SQmEaor@Tpl~g53xuxs5A~<-JaZF3hsXkkY^x^ zod!FjO}sokl1+sjz!$U!SSb4a7W!69^g#R*sW6l22n&$EM&gIk9^lYppp%oAc`5{< zu(Dm zXQnfOr9(&2hJ~p^$IzBS-j+hwmO|Br^~m*vuMja;os_2?lc%i*x8eG2Natt0`}TLF z_Fw!F8$_Lf0n6F-e5j96_eC02*t1kvr-Y}`Sv~bV7%*t%PkB$uMcd zW}NGbH-hdz%&~{|KJ_=hzVCtpiem0yLY1(s%{=ntOL=y&l|bS{ex%U+9bU@tpI!cqz0T3zMie5B7?&O@lrOmT0qd8ke!p=Ic( zZ)0|F{59sl_t&88?3WGrS0;5Vb3+6lovP=ai1`bVAD5X$goFl5;F4;^(?^aMzqEFA z3l0DNY-&t?@Mzt$=Xy)%^y)=D1R{d#bF4OmE{u1}eDt

fLHN*coG|so(MdOO}oETG&8=B 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

L|L_`Um<;==OU@5 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 diff --git a/tests/column_span_1.pdf b/tests/column_span_1.pdf deleted file mode 100644 index e7c164e19037a66910d5dba02018c5d500865589..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15014 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 diff --git a/tests/column_span_2.pdf b/tests/column_span_2.pdf deleted file mode 100644 index 5cab903153627cacc42161353c657f6742d094ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24313 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 diff --git a/tests/lines_in_background_2.pdf b/tests/lines_in_background_2.pdf deleted file mode 100644 index b64b2f27b7a98dd984896d6aa6cb07136a733404..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40680 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 G>;C{r{VI0= diff --git a/tests/missing_values.pdf b/tests/missing_values.pdf deleted file mode 100644 index 90b620fd0dde585051ff33c5c73712d35c4dfd2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47537 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 diff --git a/tests/row_span_1.pdf b/tests/row_span_1.pdf deleted file mode 100644 index ef2c7ce4c79c8284469753d68a62849ad5f8c036..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33228 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 z 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 diff --git a/tests/twotables_1.pdf b/tests/twotables_1.pdf deleted file mode 100644 index cbbeeda8d32f58d8a3be2b835f986b21138a565a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14445 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 diff --git a/tests/twotables_2.pdf b/tests/twotables_2.pdf deleted file mode 100644 index 52498878ea623bc95445c5783d0ec3574fc16b3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23667 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 From c4d3cac4fb0f00965a8faf5c806f29def3e18029 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sat, 8 Sep 2018 21:54:02 +0530 Subject: [PATCH 33/39] Move tests into one file --- tests/{test_stream.py => test_camelot.py} | 120 ++++++++++++++++++++- tests/test_lattice.py | 125 ---------------------- 2 files changed, 117 insertions(+), 128 deletions(-) rename tests/{test_stream.py => test_camelot.py} (73%) delete mode 100644 tests/test_lattice.py diff --git a/tests/test_stream.py b/tests/test_camelot.py similarity index 73% rename from tests/test_stream.py rename to tests/test_camelot.py index a947b2b..14253a8 100644 --- a/tests/test_stream.py +++ b/tests/test_camelot.py @@ -1,10 +1,9 @@ -# coding: utf8 import os from nose.tools import assert_equal from camelot.pdf import Pdf -from camelot.stream import Stream +from camelot.lattice import Lattice testdir = os.path.dirname(os.path.abspath(__file__)) @@ -217,4 +216,119 @@ def test_stream_table_rotation(): pdfname = os.path.join(testdir, "right_rotated_table_2.pdf") manager = Pdf(Stream(flag_size=False), pdfname, clean=True) tables = manager.extract() - assert_equal(tables["page-1"]["table-1"]["data"], data) \ No newline at end of file + assert_equal(tables["page-1"]["table-1"]["data"], data) + + +def test_lattice_basic(): + + data = [ + ["Cycle Name","KI (1/km)","Distance (mi)","Percent Fuel Savings","","",""], + ["","","","Improved Speed","Decreased Accel","Eliminate Stops","Decreased Idle"], + ["2012_2","3.30","1.3","5.9%","9.5%","29.2%","17.4%"], + ["2145_1","0.68","11.2","2.4%","0.1%","9.5%","2.7%"], + ["4234_1","0.59","58.7","8.5%","1.3%","8.5%","3.3%"], + ["2032_2","0.17","57.8","21.7%","0.3%","2.7%","1.2%"], + ["4171_1","0.07","173.9","58.1%","1.6%","2.1%","0.5%"] + ] + pdfname = os.path.join(testdir, + "tabula_test_pdfs/icdar2013-dataset/competition-dataset-us/us-030.pdf") + manager = Pdf(Lattice(), pdfname, pagenos=[{'start': 2, 'end': 2}], + clean=True) + tables = manager.extract() + assert_equal(tables['page-2']['table-1']['data'], data) + + +def test_lattice_fill(): + + data = [ + ["Plan Type","County","Plan Name","Totals"], + ["GMC","Sacramento","Anthem Blue Cross","164,380"], + ["GMC","Sacramento","Health Net","126,547"], + ["GMC","Sacramento","Kaiser Foundation","74,620"], + ["GMC","Sacramento","Molina Healthcare","59,989"], + ["GMC","San Diego","Care 1st Health Plan","71,831"], + ["GMC","San Diego","Community Health Group","264,639"], + ["GMC","San Diego","Health Net","72,404"], + ["GMC","San Diego","Kaiser","50,415"], + ["GMC","San Diego","Molina Healthcare","206,430"], + ["GMC","Total GMC Enrollment","","1,091,255"], + ["COHS","Marin","Partnership Health Plan of CA","36,006"], + ["COHS","Mendocino","Partnership Health Plan of CA","37,243"], + ["COHS","Napa","Partnership Health Plan of CA","28,398"], + ["COHS","Solano","Partnership Health Plan of CA","113,220"], + ["COHS","Sonoma","Partnership Health Plan of CA","112,271"], + ["COHS","Yolo","Partnership Health Plan of CA","52,674"], + ["COHS","Del Norte","Partnership Health Plan of CA","11,242"], + ["COHS","Humboldt","Partnership Health Plan of CA","49,911"], + ["COHS","Lake","Partnership Health Plan of CA","29,149"], + ["COHS","Lassen","Partnership Health Plan of CA","7,360"], + ["COHS","Modoc","Partnership Health Plan of CA","2,940"], + ["COHS","Shasta","Partnership Health Plan of CA","61,763"], + ["COHS","Siskiyou","Partnership Health Plan of CA","16,715"], + ["COHS","Trinity","Partnership Health Plan of CA","4,542"], + ["COHS","Merced","Central California Alliance for Health","123,907"], + ["COHS","Monterey","Central California Alliance for Health","147,397"], + ["COHS","Santa Cruz","Central California Alliance for Health","69,458"], + ["COHS","Santa Barbara","CenCal","117,609"], + ["COHS","San Luis Obispo","CenCal","55,761"], + ["COHS","Orange","CalOptima","783,079"], + ["COHS","San Mateo","Health Plan of San Mateo","113,202"], + ["COHS","Ventura","Gold Coast Health Plan","202,217"], + ["COHS","Total COHS Enrollment","","2,176,064"], + ["Subtotal for Two-Plan, Regional Model, GMC and COHS","","","10,132,022"], + ["PCCM","Los Angeles","AIDS Healthcare Foundation","828"], + ["PCCM","San Francisco","Family Mosaic","25"], + ["PCCM","Total PHP Enrollment","","853"], + ["All Models Total Enrollments","","","10,132,875"], + ["Source: Data Warehouse 12/14/15","","",""] + ] + pdfname = os.path.join(testdir, 'row_span_1.pdf') + manager = Pdf(Lattice(fill='v', scale=40), pdfname, clean=True) + tables = manager.extract() + assert_equal(tables['page-1']['table-1']['data'], data) + + +def test_lattice_invert(): + + data = [ + ["State","Date","Halt stations","Halt days","Persons directly reached(in lakh)","Persons trained","Persons counseled","Persons testedfor HIV"], + ["Delhi","1.12.2009","8","17","1.29","3,665","2,409","1,000"], + ["Rajasthan","2.12.2009 to 19.12.2009","","","","","",""], + ["Gujarat","20.12.2009 to 3.1.2010","6","13","6.03","3,810","2,317","1,453"], + ["Maharashtra","4.01.2010 to 1.2.2010","13","26","1.27","5,680","9,027","4,153"], + ["Karnataka","2.2.2010 to 22.2.2010","11","19","1.80","5,741","3,658","3,183"], + ["Kerala","23.2.2010 to 11.3.2010","9","17","1.42","3,559","2,173","855"], + ["Total","","47","92","11.81","22,455","19,584","10,644"] + ] + pdfname = os.path.join(testdir, 'lines_in_background_1.pdf') + manager = Pdf(Lattice(invert=True), pdfname, clean=True) + tables = manager.extract() + assert_equal(tables['page-1']['table-2']['data'], data) + + +def test_lattice_table_rotation(): + + data = [ + ["State","Nutritional Assessment (No. of individuals)","","","","IYCF Practices (No. of mothers: 2011-12)","Blood Pressure (No. of adults: 2011-12)","","Fasting Blood Sugar (No. of adults:2011-12)",""], + ["","1975-79","1988-90","1996-97","2011-12","","Men","Women","Men","Women"], + ["Kerala","5738","6633","8864","8297","245","2161","3195","1645","2391"], + ["Tamil Nadu","7387","10217","5813","7851","413","2134","2858","1119","1739"], + ["Karnataka","6453","8138","12606","8958","428","2467","2894","1628","2028"], + ["Andhra Pradesh","5844","9920","9545","8300","557","1899","2493","1111","1529"], + ["Maharashtra","5161","7796","6883","9525","467","2368","2648","1417","1599"], + ["Gujarat","4403","5374","4866","9645","477","2687","3021","2122","2503"], + ["Madhya Pradesh","*","*","*","7942","470","1965","2150","1579","1709"], + ["Orissa","3756","5540","12024","8473","398","2040","2624","1093","1628"], + ["West Bengal","*","*","*","8047","423","2058","2743","1413","2027"], + ["Uttar Pradesh","*","*","*","9860","581","2139","2415","1185","1366"], + ["Pooled","38742","53618","60601","86898","4459","21918","27041","14312","18519"] + ] + pdfname = os.path.join(testdir, 'left_rotated_table_1.pdf') + manager = Pdf(Lattice(), pdfname, clean=True) + tables = manager.extract() + assert_equal(tables['page-1']['table-1']['data'], data) + + pdfname = os.path.join(testdir, 'right_rotated_table_1.pdf') + manager = Pdf(Lattice(), pdfname, clean=True) + tables = manager.extract() + assert_equal(tables['page-1']['table-1']['data'], data) \ No newline at end of file diff --git a/tests/test_lattice.py b/tests/test_lattice.py deleted file mode 100644 index 818e16a..0000000 --- a/tests/test_lattice.py +++ /dev/null @@ -1,125 +0,0 @@ -# coding: utf8 -import os - -from nose.tools import assert_equal - -from camelot.pdf import Pdf -from camelot.lattice import Lattice - - -testdir = os.path.dirname(os.path.abspath(__file__)) - - -def test_lattice_basic(): - - data = [ - ["Cycle Name","KI (1/km)","Distance (mi)","Percent Fuel Savings","","",""], - ["","","","Improved Speed","Decreased Accel","Eliminate Stops","Decreased Idle"], - ["2012_2","3.30","1.3","5.9%","9.5%","29.2%","17.4%"], - ["2145_1","0.68","11.2","2.4%","0.1%","9.5%","2.7%"], - ["4234_1","0.59","58.7","8.5%","1.3%","8.5%","3.3%"], - ["2032_2","0.17","57.8","21.7%","0.3%","2.7%","1.2%"], - ["4171_1","0.07","173.9","58.1%","1.6%","2.1%","0.5%"] - ] - pdfname = os.path.join(testdir, - "tabula_test_pdfs/icdar2013-dataset/competition-dataset-us/us-030.pdf") - manager = Pdf(Lattice(), pdfname, pagenos=[{'start': 2, 'end': 2}], - clean=True) - tables = manager.extract() - assert_equal(tables['page-2']['table-1']['data'], data) - - -def test_lattice_fill(): - - data = [ - ["Plan Type","County","Plan Name","Totals"], - ["GMC","Sacramento","Anthem Blue Cross","164,380"], - ["GMC","Sacramento","Health Net","126,547"], - ["GMC","Sacramento","Kaiser Foundation","74,620"], - ["GMC","Sacramento","Molina Healthcare","59,989"], - ["GMC","San Diego","Care 1st Health Plan","71,831"], - ["GMC","San Diego","Community Health Group","264,639"], - ["GMC","San Diego","Health Net","72,404"], - ["GMC","San Diego","Kaiser","50,415"], - ["GMC","San Diego","Molina Healthcare","206,430"], - ["GMC","Total GMC Enrollment","","1,091,255"], - ["COHS","Marin","Partnership Health Plan of CA","36,006"], - ["COHS","Mendocino","Partnership Health Plan of CA","37,243"], - ["COHS","Napa","Partnership Health Plan of CA","28,398"], - ["COHS","Solano","Partnership Health Plan of CA","113,220"], - ["COHS","Sonoma","Partnership Health Plan of CA","112,271"], - ["COHS","Yolo","Partnership Health Plan of CA","52,674"], - ["COHS","Del Norte","Partnership Health Plan of CA","11,242"], - ["COHS","Humboldt","Partnership Health Plan of CA","49,911"], - ["COHS","Lake","Partnership Health Plan of CA","29,149"], - ["COHS","Lassen","Partnership Health Plan of CA","7,360"], - ["COHS","Modoc","Partnership Health Plan of CA","2,940"], - ["COHS","Shasta","Partnership Health Plan of CA","61,763"], - ["COHS","Siskiyou","Partnership Health Plan of CA","16,715"], - ["COHS","Trinity","Partnership Health Plan of CA","4,542"], - ["COHS","Merced","Central California Alliance for Health","123,907"], - ["COHS","Monterey","Central California Alliance for Health","147,397"], - ["COHS","Santa Cruz","Central California Alliance for Health","69,458"], - ["COHS","Santa Barbara","CenCal","117,609"], - ["COHS","San Luis Obispo","CenCal","55,761"], - ["COHS","Orange","CalOptima","783,079"], - ["COHS","San Mateo","Health Plan of San Mateo","113,202"], - ["COHS","Ventura","Gold Coast Health Plan","202,217"], - ["COHS","Total COHS Enrollment","","2,176,064"], - ["Subtotal for Two-Plan, Regional Model, GMC and COHS","","","10,132,022"], - ["PCCM","Los Angeles","AIDS Healthcare Foundation","828"], - ["PCCM","San Francisco","Family Mosaic","25"], - ["PCCM","Total PHP Enrollment","","853"], - ["All Models Total Enrollments","","","10,132,875"], - ["Source: Data Warehouse 12/14/15","","",""] - ] - pdfname = os.path.join(testdir, 'row_span_1.pdf') - manager = Pdf(Lattice(fill='v', scale=40), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-1']['data'], data) - - -def test_lattice_invert(): - - data = [ - ["State","Date","Halt stations","Halt days","Persons directly reached(in lakh)","Persons trained","Persons counseled","Persons testedfor HIV"], - ["Delhi","1.12.2009","8","17","1.29","3,665","2,409","1,000"], - ["Rajasthan","2.12.2009 to 19.12.2009","","","","","",""], - ["Gujarat","20.12.2009 to 3.1.2010","6","13","6.03","3,810","2,317","1,453"], - ["Maharashtra","4.01.2010 to 1.2.2010","13","26","1.27","5,680","9,027","4,153"], - ["Karnataka","2.2.2010 to 22.2.2010","11","19","1.80","5,741","3,658","3,183"], - ["Kerala","23.2.2010 to 11.3.2010","9","17","1.42","3,559","2,173","855"], - ["Total","","47","92","11.81","22,455","19,584","10,644"] - ] - pdfname = os.path.join(testdir, 'lines_in_background_1.pdf') - manager = Pdf(Lattice(invert=True), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-2']['data'], data) - - -def test_lattice_table_rotation(): - - data = [ - ["State","Nutritional Assessment (No. of individuals)","","","","IYCF Practices (No. of mothers: 2011-12)","Blood Pressure (No. of adults: 2011-12)","","Fasting Blood Sugar (No. of adults:2011-12)",""], - ["","1975-79","1988-90","1996-97","2011-12","","Men","Women","Men","Women"], - ["Kerala","5738","6633","8864","8297","245","2161","3195","1645","2391"], - ["Tamil Nadu","7387","10217","5813","7851","413","2134","2858","1119","1739"], - ["Karnataka","6453","8138","12606","8958","428","2467","2894","1628","2028"], - ["Andhra Pradesh","5844","9920","9545","8300","557","1899","2493","1111","1529"], - ["Maharashtra","5161","7796","6883","9525","467","2368","2648","1417","1599"], - ["Gujarat","4403","5374","4866","9645","477","2687","3021","2122","2503"], - ["Madhya Pradesh","*","*","*","7942","470","1965","2150","1579","1709"], - ["Orissa","3756","5540","12024","8473","398","2040","2624","1093","1628"], - ["West Bengal","*","*","*","8047","423","2058","2743","1413","2027"], - ["Uttar Pradesh","*","*","*","9860","581","2139","2415","1185","1366"], - ["Pooled","38742","53618","60601","86898","4459","21918","27041","14312","18519"] - ] - pdfname = os.path.join(testdir, 'left_rotated_table_1.pdf') - manager = Pdf(Lattice(), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-1']['data'], data) - - pdfname = os.path.join(testdir, 'right_rotated_table_1.pdf') - manager = Pdf(Lattice(), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-1']['data'], data) \ No newline at end of file From 7c3e531b07226505d3ad6664ac054ef08e26d7d5 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sun, 9 Sep 2018 05:29:24 +0530 Subject: [PATCH 34/39] Port tests --- .gitignore | 2 + camelot/core.py | 4 +- camelot/parsers/lattice.py | 12 +- camelot/parsers/stream.py | 2 +- setup.py | 4 +- ..._table_1.pdf => anticlockwise_table_1.pdf} | Bin ..._table_2.pdf => anticlockwise_table_2.pdf} | Bin ...ackground_1.pdf => background_lines_1.pdf} | Bin ...ackground_2.pdf => background_lines_2.pdf} | Bin ...ated_table_1.pdf => clockwise_table_1.pdf} | Bin ...ated_table_2.pdf => clockwise_table_2.pdf} | Bin tests/test_camelot.py | 334 ------------------ tests/test_common.py | 80 +++++ tests/test_data.py | 189 ++++++++++ 14 files changed, 281 insertions(+), 346 deletions(-) rename tests/files/{left_rotated_table_1.pdf => anticlockwise_table_1.pdf} (100%) rename tests/files/{left_rotated_table_2.pdf => anticlockwise_table_2.pdf} (100%) rename tests/files/{lines_in_background_1.pdf => background_lines_1.pdf} (100%) rename tests/files/{lines_in_background_2.pdf => background_lines_2.pdf} (100%) rename tests/files/{right_rotated_table_1.pdf => clockwise_table_1.pdf} (100%) rename tests/files/{right_rotated_table_2.pdf => clockwise_table_2.pdf} (100%) delete mode 100644 tests/test_camelot.py create mode 100644 tests/test_common.py create mode 100644 tests/test_data.py diff --git a/.gitignore b/.gitignore index 14fc340..5351894 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ build/ dist/ *.egg-info/ .coverage + +.pytest_cache/ diff --git a/camelot/core.py b/camelot/core.py index e3f9bb3..2417291 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -29,7 +29,7 @@ class Cell(object): self._text = '' def __repr__(self): - return ''.format( self.x1, self.y1, self.x2, self.y2) @property @@ -80,7 +80,7 @@ class Table(object): self.page = None def __repr__(self): - return '<{} shape={}>'.format(self.__class__.__name__, self._shape) + return '<{} shape={}>'.format(self.__class__.__name__, self.shape) @property def data(self): diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index ba79230..15663dc 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -25,8 +25,8 @@ class Lattice(BaseParser): """ def __init__(self, table_area=None, process_background=False, line_size_scaling=15, copy_text=None, shift_text=['l', 't'], - split_text=False, flag_size=True, line_close_tol=2, - joint_close_tol=2, blocksize=15, threshold_constant=-2, + split_text=False, flag_size=False, line_close_tol=2, + joint_close_tol=2, threshold_blocksize=15, threshold_constant=-2, iterations=0, margins=(1.0, 0.5, 0.1), debug=None): self.table_area = table_area self.process_background = process_background @@ -37,7 +37,7 @@ class Lattice(BaseParser): self.flag_size = flag_size self.line_close_tol = line_close_tol self.joint_close_tol = joint_close_tol - self.blocksize = blocksize + self.threshold_blocksize = threshold_blocksize self.threshold_constant = threshold_constant self.iterations = iterations self.char_margin, self.line_margin, self.word_margin = margins @@ -98,7 +98,7 @@ class Lattice(BaseParser): def _generate_table_bbox(self): self.image, self.threshold = adaptive_threshold(self.imagename, process_background=self.process_background, - blocksize=self.blocksize, c=self.threshold_constant) + 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) @@ -173,10 +173,10 @@ class Lattice(BaseParser): table = Table(cols, rows) # set table edges to True using ver+hor lines table = table.set_edges(v_s, h_s, joint_close_tol=self.joint_close_tol) - # set spanning cells to True - table = table.set_span() # set table border edges to True table = table.set_border() + # set spanning cells to True + table = table.set_span() pos_errors = [] for direction in self.t_bbox: diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index 12f4b6b..e1a4980 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -19,7 +19,7 @@ class Stream(BaseParser): """ def __init__(self, table_area=None, columns=None, split_text=False, - flag_size=True, row_close_tol=2, col_close_tol=0, + flag_size=False, row_close_tol=2, col_close_tol=0, margins=(1.0, 0.5, 0.1), debug=None): self.table_area = table_area self.columns = columns diff --git a/setup.py b/setup.py index 1d1d4ec..b496b51 100644 --- a/setup.py +++ b/setup.py @@ -48,10 +48,8 @@ def setup_package(): author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, - keywords='parse scrape pdf table', packages=['camelot'], - install_requires=reqs, - scripts=['tools/camelot']) + install_requires=reqs) try: from setuptools import setup diff --git a/tests/files/left_rotated_table_1.pdf b/tests/files/anticlockwise_table_1.pdf similarity index 100% rename from tests/files/left_rotated_table_1.pdf rename to tests/files/anticlockwise_table_1.pdf diff --git a/tests/files/left_rotated_table_2.pdf b/tests/files/anticlockwise_table_2.pdf similarity index 100% rename from tests/files/left_rotated_table_2.pdf rename to tests/files/anticlockwise_table_2.pdf diff --git a/tests/files/lines_in_background_1.pdf b/tests/files/background_lines_1.pdf similarity index 100% rename from tests/files/lines_in_background_1.pdf rename to tests/files/background_lines_1.pdf diff --git a/tests/files/lines_in_background_2.pdf b/tests/files/background_lines_2.pdf similarity index 100% rename from tests/files/lines_in_background_2.pdf rename to tests/files/background_lines_2.pdf diff --git a/tests/files/right_rotated_table_1.pdf b/tests/files/clockwise_table_1.pdf similarity index 100% rename from tests/files/right_rotated_table_1.pdf rename to tests/files/clockwise_table_1.pdf diff --git a/tests/files/right_rotated_table_2.pdf b/tests/files/clockwise_table_2.pdf similarity index 100% rename from tests/files/right_rotated_table_2.pdf rename to tests/files/clockwise_table_2.pdf diff --git a/tests/test_camelot.py b/tests/test_camelot.py deleted file mode 100644 index 14253a8..0000000 --- a/tests/test_camelot.py +++ /dev/null @@ -1,334 +0,0 @@ -import os - -from nose.tools import assert_equal - -from camelot.pdf import Pdf -from camelot.lattice import Lattice - - -testdir = os.path.dirname(os.path.abspath(__file__)) - - -def test_stream_basic(): - - data = [ - ["", "Table 6.", ""], - ["", "U.S. Production, Imports, Exports, and Net Supply of Conventional Pesticides", ""], - ["", "at Producer Level, 1994/95 Estimates.", ""], - ["", "Active Ingredient", "Sales Value"], - ["", "(in billions of lbs.)", "(in billions of dollars)"], - ["Category", "1994/95", "1994/95"], - ["U.S. Production", "1.3", "7.0"], - ["U.S. Imports", "0.2", "2.2"], - ["Total Supply", "1.5", "9.2"], - ["U.S. Exports", "0.5", "2.6"], - ["Net Supply/Usage", "1.0", "6.6"], - ["SOURCE:", "EPA estimates based on ACPA Surveys, Department of Commerce Publications, tabulations and other", ""], - ["sources.", "", ""], - ["16\xe2\x80\x9494/95 Pesticides Industry Sales And Usage", "", ""] - ] - - pdfname = os.path.join(testdir, "tabula_test_pdfs/us-024.pdf") - manager = Pdf(Stream(), pdfname, pagenos=[{"start": 1, "end": 1}], - clean=True) - tables = manager.extract() - assert_equal(tables["page-1"]["table-1"]["data"], data) - - -def test_stream_missing_value(): - - data = [ - ["Bhandara - Key Indicators","","","",""], - ["","DLHS-4 (2012-13)","","DLHS-3 (2007-08)",""], - ["Indicators","TOTAL","RURAL","TOTAL","RURAL"], - ["Reported Prevalence of Morbidity","","","",""], - ["Any Injury .....................................................................................................................................","1.9","2.1","",""], - ["Acute Illness .................................................................................................................................","4.5","5.6","",""], - ["Chronic Illness ..............................................................................................................................","5.1","4.1","",""], - ["Reported Prevalence of Chronic Illness during last one year (%)","","","",""], - ["Disease of respiratory system ......................................................................................................","11.7","15.0","",""], - ["Disease of cardiovascular system ................................................................................................","8.9","9.3","",""], - ["Persons suffering from tuberculosis .............................................................................................","2.2","1.5","",""], - ["Anaemia Status by Haemoglobin Level14 (%)","","","",""], - ["Children (6-59 months) having anaemia ......................................................................................","68.5","71.9","",""], - ["Children (6-59 months) having severe anaemia ..........................................................................","6.7","9.4","",""], - ["Children (6-9 Years) having anaemia - Male ................................................................................","67.1","71.4","",""], - ["Children (6-9 Years) having severe anaemia - Male ....................................................................","4.4","2.4","",""], - ["Children (6-9 Years) having anaemia - Female ...........................................................................","52.4","48.8","",""], - ["Children (6-9 Years) having severe anaemia - Female ................................................................","1.2","0.0","",""], - ["Children (6-14 years) having anaemia - Male .............................................................................","50.8","62.5","",""], - ["Children (6-14 years) having severe anaemia - Male ..................................................................","3.7","3.6","",""], - ["Children (6-14 years) having anaemia - Female .........................................................................","48.3","50.0","",""], - ["Children (6-14 years) having severe anaemia - Female ..............................................................","4.3","6.1","",""], - ["Children (10-19 Years15) having anaemia - Male .........................................................................","37.9","51.2","",""], - ["Children (10-19 Years15) having severe anaemia - Male .............................................................","3.5","4.0","",""], - ["Children (10-19 Years15) having anaemia - Female .....................................................................","46.6","52.1","",""], - ["Children (10-19 Years15) having severe anaemia - Female .........................................................","6.4","6.5","",""], - ["Adolescents (15-19 years) having anaemia ................................................................................","39.4","46.5","",""], - ["Adolescents (15-19 years) having severe anaemia .....................................................................","5.4","5.1","",""], - ["Pregnant women (15-49 aged) having anaemia ..........................................................................","48.8","51.5","",""], - ["Pregnant women (15-49 aged) having severe anaemia ..............................................................","7.1","8.8","",""], - ["Women (15-49 aged) having anaemia .........................................................................................","45.2","51.7","",""], - ["Women (15-49 aged) having severe anaemia .............................................................................","4.8","5.9","",""], - ["Persons (20 years and above) having anaemia ...........................................................................","37.8","42.1","",""], - ["Persons (20 years and above) having Severe anaemia ..............................................................","4.6","4.8","",""], - ["Blood Sugar Level (age 18 years and above) (%)","","","",""], - ["Blood Sugar Level >140 mg/dl (high) ...........................................................................................","12.9","11.1","",""], - ["Blood Sugar Level >160 mg/dl (very high) ...................................................................................","7.0","5.1","",""], - ["Hypertension (age 18 years and above) (%)","","","",""], - ["Above Normal Range (Systolic >140 mm of Hg & Diastolic >90 mm of Hg ) ..............................","23.8","22.8","",""], - ["Moderately High (Systolic >160 mm of Hg & Diastolic >100 mm of Hg ) .....................................","8.2","7.1","",""], - ["Very High (Systolic >180 mm of Hg & Diastolic >110 mm of Hg ) ...............................................","3.7","3.1","",""], - ["14 Any anaemia below 11g/dl, severe anaemia below 7g/dl. 15 Excluding age group 19 years","","","",""], - ["Chronic Illness :Any person with symptoms persisting for longer than one month is defined as suffering from chronic illness","","","",""], - ["4","","","",""] - ] - pdfname = os.path.join(testdir, "missing_values.pdf") - manager = Pdf(Stream(flag_size=False), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables["page-1"]["table-1"]["data"], data) - - -def test_stream_single_table_area(): - - data = [ - ["","One Withholding"], - ["Payroll Period","Allowance"], - ["Weekly","$71.15"], - ["Biweekly","142.31"], - ["Semimonthly","154.17"], - ["Monthly","308.33"], - ["Quarterly","925.00"], - ["Semiannually","1,850.00"], - ["Annually","3,700.00"], - ["Daily or Miscellaneous","14.23"], - ["(each day of the payroll period)",""] - ] - pdfname = os.path.join(testdir, "tabula_test_pdfs/us-007.pdf") - manager = Pdf(Stream(table_area=["320,500,573,335"]), - pdfname, pagenos=[{"start": 1, "end": 1}], clean=True) - tables = manager.extract() - assert_equal(tables["page-1"]["table-1"]["data"], data) - - -def test_stream_columns(): - - data = [ - ["Clave","Nombre Entidad","Clave","Nombre Municipio","Clave","Nombre Localidad"], - ["Entidad","","Municipio","","Localidad",""], - ["01","Aguascalientes","001","Aguascalientes","0094","Granja Adelita"], - ["01","Aguascalientes","001","Aguascalientes","0096","Agua Azul"], - ["01","Aguascalientes","001","Aguascalientes","0100","Rancho Alegre"], - ["01","Aguascalientes","001","Aguascalientes","0102","Los Arbolitos [Rancho]"], - ["01","Aguascalientes","001","Aguascalientes","0104","Ardillas de Abajo (Las Ardillas)"], - ["01","Aguascalientes","001","Aguascalientes","0106","Arellano"], - ["01","Aguascalientes","001","Aguascalientes","0112","Bajío los Vázquez"], - ["01","Aguascalientes","001","Aguascalientes","0113","Bajío de Montoro"], - ["01","Aguascalientes","001","Aguascalientes","0114","Residencial San Nicolás [Baños la Cantera]"], - ["01","Aguascalientes","001","Aguascalientes","0120","Buenavista de Peñuelas"], - ["01","Aguascalientes","001","Aguascalientes","0121","Cabecita 3 Marías (Rancho Nuevo)"], - ["01","Aguascalientes","001","Aguascalientes","0125","Cañada Grande de Cotorina"], - ["01","Aguascalientes","001","Aguascalientes","0126","Cañada Honda [Estación]"], - ["01","Aguascalientes","001","Aguascalientes","0127","Los Caños"], - ["01","Aguascalientes","001","Aguascalientes","0128","El Cariñán"], - ["01","Aguascalientes","001","Aguascalientes","0129","El Carmen [Granja]"], - ["01","Aguascalientes","001","Aguascalientes","0135","El Cedazo (Cedazo de San Antonio)"], - ["01","Aguascalientes","001","Aguascalientes","0138","Centro de Arriba (El Taray)"], - ["01","Aguascalientes","001","Aguascalientes","0139","Cieneguilla (La Lumbrera)"], - ["01","Aguascalientes","001","Aguascalientes","0141","Cobos"], - ["01","Aguascalientes","001","Aguascalientes","0144","El Colorado (El Soyatal)"], - ["01","Aguascalientes","001","Aguascalientes","0146","El Conejal"], - ["01","Aguascalientes","001","Aguascalientes","0157","Cotorina de Abajo"], - ["01","Aguascalientes","001","Aguascalientes","0162","Coyotes"], - ["01","Aguascalientes","001","Aguascalientes","0166","La Huerta (La Cruz)"], - ["01","Aguascalientes","001","Aguascalientes","0170","Cuauhtémoc (Las Palomas)"], - ["01","Aguascalientes","001","Aguascalientes","0171","Los Cuervos (Los Ojos de Agua)"], - ["01","Aguascalientes","001","Aguascalientes","0172","San José [Granja]"], - ["01","Aguascalientes","001","Aguascalientes","0176","La Chiripa"], - ["01","Aguascalientes","001","Aguascalientes","0182","Dolores"], - ["01","Aguascalientes","001","Aguascalientes","0183","Los Dolores"], - ["01","Aguascalientes","001","Aguascalientes","0190","El Duraznillo"], - ["01","Aguascalientes","001","Aguascalientes","0191","Los Durón"], - ["01","Aguascalientes","001","Aguascalientes","0197","La Escondida"], - ["01","Aguascalientes","001","Aguascalientes","0201","Brande Vin [Bodegas]"], - ["01","Aguascalientes","001","Aguascalientes","0207","Valle Redondo"], - ["01","Aguascalientes","001","Aguascalientes","0209","La Fortuna"], - ["01","Aguascalientes","001","Aguascalientes","0212","Lomas del Gachupín"], - ["01","Aguascalientes","001","Aguascalientes","0213","El Carmen (Gallinas Güeras) [Rancho]"], - ["01","Aguascalientes","001","Aguascalientes","0216","La Gloria"], - ["01","Aguascalientes","001","Aguascalientes","0226","Hacienda Nueva"], - ] - pdfname = os.path.join(testdir, "mexican_towns.pdf") - manager = Pdf(Stream(columns=["67,180,230,425,475"], ytol=[10]), pdfname, - clean=True) - tables = manager.extract() - assert_equal(tables["page-1"]["table-1"]["data"], data) - - -def test_stream_table_rotation(): - - data = [ - ["","","Table 21 Current use of contraception by background characteristics—Continued","","","","","","","","","","","","","","",""], - ["","","","","","","Modern method","","","","","","","Traditional method","","","",""], - ["","","","Any","","","","","","","Other","Any","","","","Not","","Number"], - ["","","Any","modern","Female","Male","","","","Condom/","modern","traditional","","With-","Folk","currently","","of"], - ["","Background characteristic","method","method","sterilization","sterilization","Pill","IUD","Injectables","Nirodh","method","method","Rhythm","drawal","method","using","Total","women"], - ["","Caste/tribe","","","","","","","","","","","","","","","",""], - ["","Scheduled caste","74.8","55.8","42.9","0.9","9.7","0.0","0.2","2.2","0.0","19.0","11.2","7.4","0.4","25.2","100.0","1,363"], - ["","Scheduled tribe","59.3","39.0","26.8","0.6","6.4","0.6","1.2","3.5","0.0","20.3","10.4","5.8","4.1","40.7","100.0","256"], - ["","Other backward class","71.4","51.1","34.9","0.0","8.6","1.4","0.0","6.2","0.0","20.4","12.6","7.8","0.0","28.6","100.0","211"], - ["","Other","71.1","48.8","28.2","0.8","13.3","0.9","0.3","5.2","0.1","22.3","12.9","9.1","0.3","28.9","100.0","3,319"], - ["","Wealth index","","","","","","","","","","","","","","","",""], - ["","Lowest","64.5","48.6","34.3","0.5","10.5","0.6","0.7","2.0","0.0","15.9","9.9","4.6","1.4","35.5","100.0","1,258"], - ["","Second","68.5","50.4","36.2","1.1","11.4","0.5","0.1","1.1","0.0","18.1","11.2","6.7","0.2","31.5","100.0","1,317"], - ["","Middle","75.5","52.8","33.6","0.6","14.2","0.4","0.5","3.4","0.1","22.7","13.4","8.9","0.4","24.5","100.0","1,018"], - ["","Fourth","73.9","52.3","32.0","0.5","12.5","0.6","0.2","6.3","0.2","21.6","11.5","9.9","0.2","26.1","100.0","908"], - ["","Highest","78.3","44.4","19.5","1.0","9.7","1.4","0.0","12.7","0.0","33.8","18.2","15.6","0.0","21.7","100.0","733"], - ["","Number of living children","","","","","","","","","","","","","","","",""], - ["","No children","25.1","7.6","0.3","0.5","2.0","0.0","0.0","4.8","0.0","17.5","9.0","8.5","0.0","74.9","100.0","563"], - ["","1 child","66.5","32.1","3.7","0.7","20.1","0.7","0.1","6.9","0.0","34.3","18.9","15.2","0.3","33.5","100.0","1,190"], - ["","1 son","66.8","33.2","4.1","0.7","21.1","0.5","0.3","6.6","0.0","33.5","21.2","12.3","0.0","33.2","100.0","672"], - ["","No sons","66.1","30.7","3.1","0.6","18.8","0.8","0.0","7.3","0.0","35.4","15.8","19.0","0.6","33.9","100.0","517"], - ["","2 children","81.6","60.5","41.8","0.9","11.6","0.8","0.3","4.8","0.2","21.1","12.2","8.3","0.6","18.4","100.0","1,576"], - ["","1 or more sons","83.7","64.2","46.4","0.9","10.8","0.8","0.4","4.8","0.1","19.5","11.1","7.6","0.7","16.3","100.0","1,268"], - ["","No sons","73.2","45.5","23.2","1.0","15.1","0.9","0.0","4.8","0.5","27.7","16.8","11.0","0.0","26.8","100.0","308"], - ["","3 children","83.9","71.2","57.7","0.8","9.8","0.6","0.5","1.8","0.0","12.7","8.7","3.3","0.8","16.1","100.0","961"], - ["","1 or more sons","85.0","73.2","60.3","0.9","9.4","0.5","0.5","1.6","0.0","11.8","8.1","3.0","0.7","15.0","100.0","860"], - ["","No sons","74.7","53.8","35.3","0.0","13.7","1.6","0.0","3.2","0.0","20.9","13.4","6.1","1.5","25.3","100.0","101"], - ["","4+ children","74.3","58.1","45.1","0.6","8.7","0.6","0.7","2.4","0.0","16.1","9.9","5.4","0.8","25.7","100.0","944"], - ["","1 or more sons","73.9","58.2","46.0","0.7","8.3","0.7","0.7","1.9","0.0","15.7","9.4","5.5","0.8","26.1","100.0","901"], - ["","No sons","(82.1)","(57.3)","(25.6)","(0.0)","(17.8)","(0.0)","(0.0)","(13.9)","(0.0)","(24.8)","(21.3)","(3.5)","(0.0)","(17.9)","100.0","43"], - ["","Total","71.2","49.9","32.2","0.7","11.7","0.6","0.3","4.3","0.1","21.3","12.3","8.4","0.5","28.8","100.0","5,234"], - ["","NFHS-2 (1998-99)","66.6","47.3","32.0","1.8","9.2","1.4","na","2.9","na","na","8.7","9.8","na","33.4","100.0","4,116"], - ["","NFHS-1 (1992-93)","57.7","37.6","26.5","4.3","3.6","1.3","0.1","1.9","na","na","11.3","8.3","na","42.3","100.0","3,970"], - ["","","Note: If more than one method is used, only the most effective method is considered in this tabulation. Total includes women for whom caste/tribe was not known or is missing, who are","","","","","","","","","","","","","","",""], - ["","not shown separately.","","","","","","","","","","","","","","","",""], - ["","na = Not available","","","","","","","","","","","","","","","",""], - ["","","ns = Not shown; see table 2b, footnote 1","","","","","","","","","","","","","","",""], - ["","( ) Based on 25-49 unweighted cases.","","","","","","","","","","","","","","","",""], - ["","","","","","","","","54","","","","","","","","",""] - ] - pdfname = os.path.join(testdir, "left_rotated_table_2.pdf") - manager = Pdf(Stream(flag_size=False), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables["page-1"]["table-1"]["data"], data) - - pdfname = os.path.join(testdir, "right_rotated_table_2.pdf") - manager = Pdf(Stream(flag_size=False), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables["page-1"]["table-1"]["data"], data) - - -def test_lattice_basic(): - - data = [ - ["Cycle Name","KI (1/km)","Distance (mi)","Percent Fuel Savings","","",""], - ["","","","Improved Speed","Decreased Accel","Eliminate Stops","Decreased Idle"], - ["2012_2","3.30","1.3","5.9%","9.5%","29.2%","17.4%"], - ["2145_1","0.68","11.2","2.4%","0.1%","9.5%","2.7%"], - ["4234_1","0.59","58.7","8.5%","1.3%","8.5%","3.3%"], - ["2032_2","0.17","57.8","21.7%","0.3%","2.7%","1.2%"], - ["4171_1","0.07","173.9","58.1%","1.6%","2.1%","0.5%"] - ] - pdfname = os.path.join(testdir, - "tabula_test_pdfs/icdar2013-dataset/competition-dataset-us/us-030.pdf") - manager = Pdf(Lattice(), pdfname, pagenos=[{'start': 2, 'end': 2}], - clean=True) - tables = manager.extract() - assert_equal(tables['page-2']['table-1']['data'], data) - - -def test_lattice_fill(): - - data = [ - ["Plan Type","County","Plan Name","Totals"], - ["GMC","Sacramento","Anthem Blue Cross","164,380"], - ["GMC","Sacramento","Health Net","126,547"], - ["GMC","Sacramento","Kaiser Foundation","74,620"], - ["GMC","Sacramento","Molina Healthcare","59,989"], - ["GMC","San Diego","Care 1st Health Plan","71,831"], - ["GMC","San Diego","Community Health Group","264,639"], - ["GMC","San Diego","Health Net","72,404"], - ["GMC","San Diego","Kaiser","50,415"], - ["GMC","San Diego","Molina Healthcare","206,430"], - ["GMC","Total GMC Enrollment","","1,091,255"], - ["COHS","Marin","Partnership Health Plan of CA","36,006"], - ["COHS","Mendocino","Partnership Health Plan of CA","37,243"], - ["COHS","Napa","Partnership Health Plan of CA","28,398"], - ["COHS","Solano","Partnership Health Plan of CA","113,220"], - ["COHS","Sonoma","Partnership Health Plan of CA","112,271"], - ["COHS","Yolo","Partnership Health Plan of CA","52,674"], - ["COHS","Del Norte","Partnership Health Plan of CA","11,242"], - ["COHS","Humboldt","Partnership Health Plan of CA","49,911"], - ["COHS","Lake","Partnership Health Plan of CA","29,149"], - ["COHS","Lassen","Partnership Health Plan of CA","7,360"], - ["COHS","Modoc","Partnership Health Plan of CA","2,940"], - ["COHS","Shasta","Partnership Health Plan of CA","61,763"], - ["COHS","Siskiyou","Partnership Health Plan of CA","16,715"], - ["COHS","Trinity","Partnership Health Plan of CA","4,542"], - ["COHS","Merced","Central California Alliance for Health","123,907"], - ["COHS","Monterey","Central California Alliance for Health","147,397"], - ["COHS","Santa Cruz","Central California Alliance for Health","69,458"], - ["COHS","Santa Barbara","CenCal","117,609"], - ["COHS","San Luis Obispo","CenCal","55,761"], - ["COHS","Orange","CalOptima","783,079"], - ["COHS","San Mateo","Health Plan of San Mateo","113,202"], - ["COHS","Ventura","Gold Coast Health Plan","202,217"], - ["COHS","Total COHS Enrollment","","2,176,064"], - ["Subtotal for Two-Plan, Regional Model, GMC and COHS","","","10,132,022"], - ["PCCM","Los Angeles","AIDS Healthcare Foundation","828"], - ["PCCM","San Francisco","Family Mosaic","25"], - ["PCCM","Total PHP Enrollment","","853"], - ["All Models Total Enrollments","","","10,132,875"], - ["Source: Data Warehouse 12/14/15","","",""] - ] - pdfname = os.path.join(testdir, 'row_span_1.pdf') - manager = Pdf(Lattice(fill='v', scale=40), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-1']['data'], data) - - -def test_lattice_invert(): - - data = [ - ["State","Date","Halt stations","Halt days","Persons directly reached(in lakh)","Persons trained","Persons counseled","Persons testedfor HIV"], - ["Delhi","1.12.2009","8","17","1.29","3,665","2,409","1,000"], - ["Rajasthan","2.12.2009 to 19.12.2009","","","","","",""], - ["Gujarat","20.12.2009 to 3.1.2010","6","13","6.03","3,810","2,317","1,453"], - ["Maharashtra","4.01.2010 to 1.2.2010","13","26","1.27","5,680","9,027","4,153"], - ["Karnataka","2.2.2010 to 22.2.2010","11","19","1.80","5,741","3,658","3,183"], - ["Kerala","23.2.2010 to 11.3.2010","9","17","1.42","3,559","2,173","855"], - ["Total","","47","92","11.81","22,455","19,584","10,644"] - ] - pdfname = os.path.join(testdir, 'lines_in_background_1.pdf') - manager = Pdf(Lattice(invert=True), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-2']['data'], data) - - -def test_lattice_table_rotation(): - - data = [ - ["State","Nutritional Assessment (No. of individuals)","","","","IYCF Practices (No. of mothers: 2011-12)","Blood Pressure (No. of adults: 2011-12)","","Fasting Blood Sugar (No. of adults:2011-12)",""], - ["","1975-79","1988-90","1996-97","2011-12","","Men","Women","Men","Women"], - ["Kerala","5738","6633","8864","8297","245","2161","3195","1645","2391"], - ["Tamil Nadu","7387","10217","5813","7851","413","2134","2858","1119","1739"], - ["Karnataka","6453","8138","12606","8958","428","2467","2894","1628","2028"], - ["Andhra Pradesh","5844","9920","9545","8300","557","1899","2493","1111","1529"], - ["Maharashtra","5161","7796","6883","9525","467","2368","2648","1417","1599"], - ["Gujarat","4403","5374","4866","9645","477","2687","3021","2122","2503"], - ["Madhya Pradesh","*","*","*","7942","470","1965","2150","1579","1709"], - ["Orissa","3756","5540","12024","8473","398","2040","2624","1093","1628"], - ["West Bengal","*","*","*","8047","423","2058","2743","1413","2027"], - ["Uttar Pradesh","*","*","*","9860","581","2139","2415","1185","1366"], - ["Pooled","38742","53618","60601","86898","4459","21918","27041","14312","18519"] - ] - pdfname = os.path.join(testdir, 'left_rotated_table_1.pdf') - manager = Pdf(Lattice(), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-1']['data'], data) - - pdfname = os.path.join(testdir, 'right_rotated_table_1.pdf') - manager = Pdf(Lattice(), pdfname, clean=True) - tables = manager.extract() - assert_equal(tables['page-1']['table-1']['data'], data) \ No newline at end of file diff --git a/tests/test_common.py b/tests/test_common.py new file mode 100644 index 0000000..52f966a --- /dev/null +++ b/tests/test_common.py @@ -0,0 +1,80 @@ +import os + +import pandas as pd + +import camelot + +from test_data import * + +testdir = os.path.dirname(os.path.abspath(__file__)) +testdir = os.path.join(testdir, "files") + + +def test_stream(): + pass + + +def test_stream_table_rotated(): + df = pd.DataFrame(data_stream_table_rotated) + + filename = os.path.join(testdir, "clockwise_table_2.pdf") + tables = camelot.read_pdf(filename) + assert df.equals(tables[0].df) + + filename = os.path.join(testdir, "anticlockwise_table_2.pdf") + tables = camelot.read_pdf(filename) + assert df.equals(tables[0].df) + + +def test_stream_table_area(): + df = pd.DataFrame(data_stream_table_area_single) + + filename = os.path.join(testdir, "tabula/us-007.pdf") + tables = camelot.read_pdf(filename, table_area=["320,500,573,335"]) + assert df.equals(tables[0].df) + + +def test_stream_columns(): + df = pd.DataFrame(data_stream_columns) + + filename = os.path.join(testdir, "mexican_towns.pdf") + tables = camelot.read_pdf( + filename, columns=["67,180,230,425,475"], row_close_tol=10) + assert df.equals(tables[0].df) + + +def test_lattice(): + df = pd.DataFrame(data_lattice) + + filename = os.path.join(testdir, + "tabula/icdar2013-dataset/competition-dataset-us/us-030.pdf") + tables = camelot.read_pdf(filename, pages="2", mesh=True) + assert df.equals(tables[0].df) + + +def test_lattice_table_rotated(): + df = pd.DataFrame(data_lattice_table_rotated) + + filename = os.path.join(testdir, "clockwise_table_1.pdf") + tables = camelot.read_pdf(filename, mesh=True) + assert df.equals(tables[0].df) + + filename = os.path.join(testdir, "anticlockwise_table_1.pdf") + tables = camelot.read_pdf(filename, mesh=True) + assert df.equals(tables[0].df) + + +def test_lattice_process_background(): + df = pd.DataFrame(data_lattice_process_background) + + filename = os.path.join(testdir, "background_lines_1.pdf") + tables = camelot.read_pdf(filename, mesh=True, process_background=True) + assert df.equals(tables[1].df) + + +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, mesh=True, line_size_scaling=60, copy_text="v") + assert df.equals(tables[0].df) \ No newline at end of file diff --git a/tests/test_data.py b/tests/test_data.py new file mode 100644 index 0000000..3582937 --- /dev/null +++ b/tests/test_data.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- + +data_stream_table_rotated = [ + ["","","Table 21 Current use of contraception by background characteristics—Continued","","","","","","","","","","","","","","",""], + ["","","","","","","Modern method","","","","","","","Traditional method","","","",""], + ["","","","Any","","","","","","","Other","Any","","","","Not","","Number"], + ["","","Any","modern","Female","Male","","","","Condom/","modern","traditional","","With-","Folk","currently","","of"], + ["","Background characteristic","method","method","sterilization","sterilization","Pill","IUD","Injectables","Nirodh","method","method","Rhythm","drawal","method","using","Total","women"], + ["","Caste/tribe","","","","","","","","","","","","","","","",""], + ["","Scheduled caste","74.8","55.8","42.9","0.9","9.7","0.0","0.2","2.2","0.0","19.0","11.2","7.4","0.4","25.2","100.0","1,363"], + ["","Scheduled tribe","59.3","39.0","26.8","0.6","6.4","0.6","1.2","3.5","0.0","20.3","10.4","5.8","4.1","40.7","100.0","256"], + ["","Other backward class","71.4","51.1","34.9","0.0","8.6","1.4","0.0","6.2","0.0","20.4","12.6","7.8","0.0","28.6","100.0","211"], + ["","Other","71.1","48.8","28.2","0.8","13.3","0.9","0.3","5.2","0.1","22.3","12.9","9.1","0.3","28.9","100.0","3,319"], + ["","Wealth index","","","","","","","","","","","","","","","",""], + ["","Lowest","64.5","48.6","34.3","0.5","10.5","0.6","0.7","2.0","0.0","15.9","9.9","4.6","1.4","35.5","100.0","1,258"], + ["","Second","68.5","50.4","36.2","1.1","11.4","0.5","0.1","1.1","0.0","18.1","11.2","6.7","0.2","31.5","100.0","1,317"], + ["","Middle","75.5","52.8","33.6","0.6","14.2","0.4","0.5","3.4","0.1","22.7","13.4","8.9","0.4","24.5","100.0","1,018"], + ["","Fourth","73.9","52.3","32.0","0.5","12.5","0.6","0.2","6.3","0.2","21.6","11.5","9.9","0.2","26.1","100.0","908"], + ["","Highest","78.3","44.4","19.5","1.0","9.7","1.4","0.0","12.7","0.0","33.8","18.2","15.6","0.0","21.7","100.0","733"], + ["","Number of living children","","","","","","","","","","","","","","","",""], + ["","No children","25.1","7.6","0.3","0.5","2.0","0.0","0.0","4.8","0.0","17.5","9.0","8.5","0.0","74.9","100.0","563"], + ["","1 child","66.5","32.1","3.7","0.7","20.1","0.7","0.1","6.9","0.0","34.3","18.9","15.2","0.3","33.5","100.0","1,190"], + ["","1 son","66.8","33.2","4.1","0.7","21.1","0.5","0.3","6.6","0.0","33.5","21.2","12.3","0.0","33.2","100.0","672"], + ["","No sons","66.1","30.7","3.1","0.6","18.8","0.8","0.0","7.3","0.0","35.4","15.8","19.0","0.6","33.9","100.0","517"], + ["","2 children","81.6","60.5","41.8","0.9","11.6","0.8","0.3","4.8","0.2","21.1","12.2","8.3","0.6","18.4","100.0","1,576"], + ["","1 or more sons","83.7","64.2","46.4","0.9","10.8","0.8","0.4","4.8","0.1","19.5","11.1","7.6","0.7","16.3","100.0","1,268"], + ["","No sons","73.2","45.5","23.2","1.0","15.1","0.9","0.0","4.8","0.5","27.7","16.8","11.0","0.0","26.8","100.0","308"], + ["","3 children","83.9","71.2","57.7","0.8","9.8","0.6","0.5","1.8","0.0","12.7","8.7","3.3","0.8","16.1","100.0","961"], + ["","1 or more sons","85.0","73.2","60.3","0.9","9.4","0.5","0.5","1.6","0.0","11.8","8.1","3.0","0.7","15.0","100.0","860"], + ["","No sons","74.7","53.8","35.3","0.0","13.7","1.6","0.0","3.2","0.0","20.9","13.4","6.1","1.5","25.3","100.0","101"], + ["","4+ children","74.3","58.1","45.1","0.6","8.7","0.6","0.7","2.4","0.0","16.1","9.9","5.4","0.8","25.7","100.0","944"], + ["","1 or more sons","73.9","58.2","46.0","0.7","8.3","0.7","0.7","1.9","0.0","15.7","9.4","5.5","0.8","26.1","100.0","901"], + ["","No sons","(82.1)","(57.3)","(25.6)","(0.0)","(17.8)","(0.0)","(0.0)","(13.9)","(0.0)","(24.8)","(21.3)","(3.5)","(0.0)","(17.9)","100.0","43"], + ["","Total","71.2","49.9","32.2","0.7","11.7","0.6","0.3","4.3","0.1","21.3","12.3","8.4","0.5","28.8","100.0","5,234"], + ["","NFHS-2 (1998-99)","66.6","47.3","32.0","1.8","9.2","1.4","na","2.9","na","na","8.7","9.8","na","33.4","100.0","4,116"], + ["","NFHS-1 (1992-93)","57.7","37.6","26.5","4.3","3.6","1.3","0.1","1.9","na","na","11.3","8.3","na","42.3","100.0","3,970"], + ["","","Note: If more than one method is used, only the most effective method is considered in this tabulation. Total includes women for whom caste/tribe was not known or is missing, who are","","","","","","","","","","","","","","",""], + ["","not shown separately.","","","","","","","","","","","","","","","",""], + ["","na = Not available","","","","","","","","","","","","","","","",""], + ["","","ns = Not shown; see table 2b, footnote 1","","","","","","","","","","","","","","",""], + ["","( ) Based on 25-49 unweighted cases.","","","","","","","","","","","","","","","",""], + ["","","","","","","","","54","","","","","","","","",""] +] + + +data_stream_table_area_single = [ + ["","One Withholding"], + ["Payroll Period","Allowance"], + ["Weekly","$71.15"], + ["Biweekly","142.31"], + ["Semimonthly","154.17"], + ["Monthly","308.33"], + ["Quarterly","925.00"], + ["Semiannually","1,850.00"], + ["Annually","3,700.00"], + ["Daily or Miscellaneous","14.23"], + ["(each day of the payroll period)",""] +] + + +data_stream_columns = [ + ["Clave","Nombre Entidad","Clave","Nombre Municipio","Clave","Nombre Localidad"], + ["Entidad","","Municipio","","Localidad",""], + ["01","Aguascalientes","001","Aguascalientes","0094","Granja Adelita"], + ["01","Aguascalientes","001","Aguascalientes","0096","Agua Azul"], + ["01","Aguascalientes","001","Aguascalientes","0100","Rancho Alegre"], + ["01","Aguascalientes","001","Aguascalientes","0102","Los Arbolitos [Rancho]"], + ["01","Aguascalientes","001","Aguascalientes","0104","Ardillas de Abajo (Las Ardillas)"], + ["01","Aguascalientes","001","Aguascalientes","0106","Arellano"], + ["01","Aguascalientes","001","Aguascalientes","0112","Bajío los Vázquez"], + ["01","Aguascalientes","001","Aguascalientes","0113","Bajío de Montoro"], + ["01","Aguascalientes","001","Aguascalientes","0114","Residencial San Nicolás [Baños la Cantera]"], + ["01","Aguascalientes","001","Aguascalientes","0120","Buenavista de Peñuelas"], + ["01","Aguascalientes","001","Aguascalientes","0121","Cabecita 3 Marías (Rancho Nuevo)"], + ["01","Aguascalientes","001","Aguascalientes","0125","Cañada Grande de Cotorina"], + ["01","Aguascalientes","001","Aguascalientes","0126","Cañada Honda [Estación]"], + ["01","Aguascalientes","001","Aguascalientes","0127","Los Caños"], + ["01","Aguascalientes","001","Aguascalientes","0128","El Cariñán"], + ["01","Aguascalientes","001","Aguascalientes","0129","El Carmen [Granja]"], + ["01","Aguascalientes","001","Aguascalientes","0135","El Cedazo (Cedazo de San Antonio)"], + ["01","Aguascalientes","001","Aguascalientes","0138","Centro de Arriba (El Taray)"], + ["01","Aguascalientes","001","Aguascalientes","0139","Cieneguilla (La Lumbrera)"], + ["01","Aguascalientes","001","Aguascalientes","0141","Cobos"], + ["01","Aguascalientes","001","Aguascalientes","0144","El Colorado (El Soyatal)"], + ["01","Aguascalientes","001","Aguascalientes","0146","El Conejal"], + ["01","Aguascalientes","001","Aguascalientes","0157","Cotorina de Abajo"], + ["01","Aguascalientes","001","Aguascalientes","0162","Coyotes"], + ["01","Aguascalientes","001","Aguascalientes","0166","La Huerta (La Cruz)"], + ["01","Aguascalientes","001","Aguascalientes","0170","Cuauhtémoc (Las Palomas)"], + ["01","Aguascalientes","001","Aguascalientes","0171","Los Cuervos (Los Ojos de Agua)"], + ["01","Aguascalientes","001","Aguascalientes","0172","San José [Granja]"], + ["01","Aguascalientes","001","Aguascalientes","0176","La Chiripa"], + ["01","Aguascalientes","001","Aguascalientes","0182","Dolores"], + ["01","Aguascalientes","001","Aguascalientes","0183","Los Dolores"], + ["01","Aguascalientes","001","Aguascalientes","0190","El Duraznillo"], + ["01","Aguascalientes","001","Aguascalientes","0191","Los Durón"], + ["01","Aguascalientes","001","Aguascalientes","0197","La Escondida"], + ["01","Aguascalientes","001","Aguascalientes","0201","Brande Vin [Bodegas]"], + ["01","Aguascalientes","001","Aguascalientes","0207","Valle Redondo"], + ["01","Aguascalientes","001","Aguascalientes","0209","La Fortuna"], + ["01","Aguascalientes","001","Aguascalientes","0212","Lomas del Gachupín"], + ["01","Aguascalientes","001","Aguascalientes","0213","El Carmen (Gallinas Güeras) [Rancho]"], + ["01","Aguascalientes","001","Aguascalientes","0216","La Gloria"], + ["01","Aguascalientes","001","Aguascalientes","0226","Hacienda Nueva"], +] + + +data_lattice = [ + ["Cycle Name","KI (1/km)","Distance (mi)","Percent Fuel Savings","","",""], + ["","","","Improved Speed","Decreased Accel","Eliminate Stops","Decreased Idle"], + ["2012_2","3.30","1.3","5.9%","9.5%","29.2%","17.4%"], + ["2145_1","0.68","11.2","2.4%","0.1%","9.5%","2.7%"], + ["4234_1","0.59","58.7","8.5%","1.3%","8.5%","3.3%"], + ["2032_2","0.17","57.8","21.7%","0.3%","2.7%","1.2%"], + ["4171_1","0.07","173.9","58.1%","1.6%","2.1%","0.5%"] +] + + +data_lattice_table_rotated = [ + ["State","Nutritional Assessment (No. of individuals)","","","","IYCF Practices (No. of mothers: 2011-12)","Blood Pressure (No. of adults: 2011-12)","","Fasting Blood Sugar (No. of adults:2011-12)",""], + ["","1975-79","1988-90","1996-97","2011-12","","Men","Women","Men","Women"], + ["Kerala","5738","6633","8864","8297","245","2161","3195","1645","2391"], + ["Tamil Nadu","7387","10217","5813","7851","413","2134","2858","1119","1739"], + ["Karnataka","6453","8138","12606","8958","428","2467","2894","1628","2028"], + ["Andhra Pradesh","5844","9920","9545","8300","557","1899","2493","1111","1529"], + ["Maharashtra","5161","7796","6883","9525","467","2368","2648","1417","1599"], + ["Gujarat","4403","5374","4866","9645","477","2687","3021","2122","2503"], + ["Madhya Pradesh","*","*","*","7942","470","1965","2150","1579","1709"], + ["Orissa","3756","5540","12024","8473","398","2040","2624","1093","1628"], + ["West Bengal","*","*","*","8047","423","2058","2743","1413","2027"], + ["Uttar Pradesh","*","*","*","9860","581","2139","2415","1185","1366"], + ["Pooled","38742","53618","60601","86898","4459","21918","27041","14312","18519"] +] + + +data_lattice_process_background = [ + ["State","Date","Halt stations","Halt days","Persons directly reached(in lakh)","Persons trained","Persons counseled","Persons testedfor HIV"], + ["Delhi","1.12.2009","8","17","1.29","3,665","2,409","1,000"], + ["Rajasthan","2.12.2009 to 19.12.2009","","","","","",""], + ["Gujarat","20.12.2009 to 3.1.2010","6","13","6.03","3,810","2,317","1,453"], + ["Maharashtra","4.01.2010 to 1.2.2010","13","26","1.27","5,680","9,027","4,153"], + ["Karnataka","2.2.2010 to 22.2.2010","11","19","1.80","5,741","3,658","3,183"], + ["Kerala","23.2.2010 to 11.3.2010","9","17","1.42","3,559","2,173","855"], + ["Total","","47","92","11.81","22,455","19,584","10,644"] +] + + +data_lattice_copy_text = [ + ["Plan Type","County","Plan Name","Totals"], + ["GMC","Sacramento","Anthem Blue Cross","164,380"], + ["GMC","Sacramento","Health Net","126,547"], + ["GMC","Sacramento","Kaiser Foundation","74,620"], + ["GMC","Sacramento","Molina Healthcare","59,989"], + ["GMC","San Diego","Care 1st Health Plan","71,831"], + ["GMC","San Diego","Community Health Group","264,639"], + ["GMC","San Diego","Health Net","72,404"], + ["GMC","San Diego","Kaiser","50,415"], + ["GMC","San Diego","Molina Healthcare","206,430"], + ["GMC","Total GMC Enrollment","","1,091,255"], + ["COHS","Marin","Partnership Health Plan of CA","36,006"], + ["COHS","Mendocino","Partnership Health Plan of CA","37,243"], + ["COHS","Napa","Partnership Health Plan of CA","28,398"], + ["COHS","Solano","Partnership Health Plan of CA","113,220"], + ["COHS","Sonoma","Partnership Health Plan of CA","112,271"], + ["COHS","Yolo","Partnership Health Plan of CA","52,674"], + ["COHS","Del Norte","Partnership Health Plan of CA","11,242"], + ["COHS","Humboldt","Partnership Health Plan of CA","49,911"], + ["COHS","Lake","Partnership Health Plan of CA","29,149"], + ["COHS","Lassen","Partnership Health Plan of CA","7,360"], + ["COHS","Modoc","Partnership Health Plan of CA","2,940"], + ["COHS","Shasta","Partnership Health Plan of CA","61,763"], + ["COHS","Siskiyou","Partnership Health Plan of CA","16,715"], + ["COHS","Trinity","Partnership Health Plan of CA","4,542"], + ["COHS","Merced","Central California Alliance for Health","123,907"], + ["COHS","Monterey","Central California Alliance for Health","147,397"], + ["COHS","Santa Cruz","Central California Alliance for Health","69,458"], + ["COHS","Santa Barbara","CenCal","117,609"], + ["COHS","San Luis Obispo","CenCal","55,761"], + ["COHS","Orange","CalOptima","783,079"], + ["COHS","San Mateo","Health Plan of San Mateo","113,202"], + ["COHS","Ventura","Gold Coast Health Plan","202,217"], + ["COHS","Total COHS Enrollment","","2,176,064"], + ["Subtotal for Two-Plan, Regional Model, GMC and COHS","","","10,132,022"], + ["PCCM","Los Angeles","AIDS Healthcare Foundation","828"], + ["PCCM","San Francisco","Family Mosaic","25"], + ["PCCM","Total PHP Enrollment","","853"], + ["All Models Total Enrollments","","","10,132,875"], + ["Source: Data Warehouse 12/14/15","","",""] +] \ No newline at end of file From c91a9bb36da64c8b686512707208490b1405b75f Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sun, 9 Sep 2018 05:36:07 +0530 Subject: [PATCH 35/39] Add future import --- camelot/image_processing.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/camelot/image_processing.py b/camelot/image_processing.py index bdd82fb..ec2b384 100644 --- a/camelot/image_processing.py +++ b/camelot/image_processing.py @@ -1,3 +1,4 @@ +from __future__ import division from itertools import groupby from operator import itemgetter @@ -75,9 +76,9 @@ def find_lines(threshold, direction='horizontal', line_size_scaling=15, iteratio x1, x2 = x, x + w y1, y2 = y, y + h if direction == 'vertical': - lines.append(((x1 + x2) / 2, y2, (x1 + x2) / 2, y1)) + lines.append(((x1 + x2) // 2, y2, (x1 + x2) // 2, y1)) elif direction == 'horizontal': - lines.append((x1, (y1 + y2) / 2, x2, (y1 + y2) / 2)) + lines.append((x1, (y1 + y2) // 2, x2, (y1 + y2) // 2)) return dmask, lines @@ -141,7 +142,7 @@ def find_table_joints(contours, vertical, horizontal): joint_coords = [] for j in jc: jx, jy, jw, jh = cv2.boundingRect(j) - c1, c2 = x + (2 * jx + jw) / 2, y + (2 * jy + jh) / 2 + c1, c2 = x + (2 * jx + jw) // 2, y + (2 * jy + jh) // 2 joint_coords.append((c1, c2)) tables[(x, y + h, x + w, y)] = joint_coords @@ -204,5 +205,5 @@ def find_cuts(threshold, char_size_scaling=200): contours = [cv2.boundingRect(c) for c in contours] y_cuts = [(c[1], c[1] + c[3]) for c in contours] y_cuts = list(merge_tuples(sorted(y_cuts))) - y_cuts = [(y_cuts[i][0] + y_cuts[i - 1][1]) / 2 for i in range(1, len(y_cuts))] + y_cuts = [(y_cuts[i][0] + y_cuts[i - 1][1]) // 2 for i in range(1, len(y_cuts))] return sorted(y_cuts, reverse=True) \ No newline at end of file From e75045053ac34c9eb219bbf11d1235e44150cbd5 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sun, 9 Sep 2018 05:36:45 +0530 Subject: [PATCH 36/39] Remove Makefile --- Makefile | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index f4183af..0000000 --- a/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -PYTHON ?= python -NOSETESTS ?= nosetests - -help: - @echo "Please use \`make ' where is one of" - @echo " clean" - @echo " dev to install in develop mode" - @echo " undev to uninstall develop mode" - @echo " install to install for all users" - @echo " test to run tests" - @echo " test-coverage to run tests with coverage report" - -clean: - $(PYTHON) setup.py clean - rm -rf dist - -dev: - $(PYTHON) setup.py develop - -undev: - $(PYTHON) setup.py develop --uninstall - -install: - $(PYTHON) setup.py install - -test: - $(NOSETESTS) -s -v - -test-coverage: - rm -rf coverage .coverage - $(NOSETESTS) -s -v --with-coverage From 16c6b8d45d62cf31b24eee19ef34d333f3993a09 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sun, 9 Sep 2018 05:41:42 +0530 Subject: [PATCH 37/39] Add setup.cfg --- setup.cfg | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..730f976 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,6 @@ +[aliases] +test=pytest + +[tool:pytest] +addopts = --verbose +python_files = tests/test_*.py From 9878de4dfc6eb35eef8ad6bf0717c41713bd1742 Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sun, 9 Sep 2018 10:00:22 +0530 Subject: [PATCH 38/39] Add docstrings and update docs --- .gitignore | 2 + README.md | 65 ++----- camelot/core.py | 186 ++++++++++++------- camelot/handlers.py | 69 +++++-- camelot/image_processing.py | 112 ++++++++--- camelot/io.py | 85 ++++++++- camelot/parsers/base.py | 3 +- camelot/parsers/lattice.py | 117 ++++++++++-- camelot/parsers/stream.py | 146 +++++++++++++-- camelot/plotting.py | 98 +++++++++- camelot/utils.py | 360 +++++++++++++++++++++++------------- docs/api.rst | 38 +++- docs/index.rst | 100 ++++------ requirements-dev.txt | 11 ++ requirements.txt | 10 +- setup.py | 16 +- 16 files changed, 997 insertions(+), 421 deletions(-) create mode 100644 requirements-dev.txt diff --git a/.gitignore b/.gitignore index 5351894..4fd453c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ dist/ .coverage .pytest_cache/ +_build/ +_static/ diff --git a/README.md b/README.md index 3dbaa79..372cc09 100644 --- a/README.md +++ b/README.md @@ -23,50 +23,9 @@ Camelot is a Python 2.7 library and command-line tool for extracting tabular dat >>> df = tables[0].df -Camelot comes with a CLI where you can specify page numbers, output format, output directory etc. By default, the output files are placed in the same directory as the PDF. - -
-Camelot: PDF parsing made simpler!
-
-usage:
- camelot [options] <method> [<args>...]
-
-options:
- -h, --help                Show this screen.
- -v, --version             Show version.
- -V, --verbose             Verbose.
- -p, --pages <pageno>      Comma-separated list of page numbers.
-                           Example: -p 1,3-6,10  [default: 1]
- -P, --parallel            Parallelize the parsing process.
- -f, --format <format>     Output format. (csv,tsv,html,json,xlsx) [default: csv]
- -l, --log                 Log to file.
- -o, --output <directory>  Output directory.
- -M, --cmargin <cmargin>   Char margin. Chars closer than cmargin are
-                           grouped together to form a word. [default: 2.0]
- -L, --lmargin <lmargin>   Line margin. Lines closer than lmargin are
-                           grouped together to form a textbox. [default: 0.5]
- -W, --wmargin <wmargin>   Word margin. Insert blank spaces between chars
-                           if distance between words is greater than word
-                           margin. [default: 0.1]
- -J, --split_text          Split text lines if they span across multiple cells.
- -K, --flag_size           Flag substring if its size differs from the whole string.
-                           Useful for super and subscripts.
- -X, --print-stats         List stats on the parsing process.
- -Y, --save-stats          Save stats to a file.
- -Z, --plot <dist>         Plot distributions. (page,all,rc)
-
-camelot methods:
- lattice  Looks for lines between data.
- stream   Looks for spaces between data.
-
-See 'camelot <method> -h' for more information on a specific method.
-
- ## Dependencies -Currently, camelot works under Python 2.7. - -The required dependencies include [numpy](http://www.numpy.org/), [OpenCV](http://opencv.org/) and [ghostscript](https://www.ghostscript.com/). +The dependencies include [tk](https://wiki.tcl.tk/3743) and [ghostscript](https://www.ghostscript.com/). ## Installation @@ -78,22 +37,22 @@ pip install -U pip setuptools ### Installing dependencies -numpy can be install using `pip`. OpenCV and ghostscript can be installed using your system's default package manager. +tk and ghostscript can be installed using your system's default package manager. #### Linux -* Arch Linux - -
-sudo pacman -S opencv tk ghostscript
-
- * Ubuntu
 sudo apt-get install python-opencv python-tk ghostscript
 
+* Arch Linux + +
+sudo pacman -S opencv tk ghostscript
+
+ #### OS X
@@ -103,7 +62,7 @@ brew install homebrew/science/opencv ghostscript
 Finally, `cd` into the project directory and install by
 
 
-make install
+python setup.py install
 
## Development @@ -118,14 +77,14 @@ git clone https://github.com/socialcopsdev/camelot.git ### Contributing -See [Contributing doc](). +See [Contributing guidelines](). ### Testing
-make test
+python setup.py test
 
## License -BSD License +BSD License \ No newline at end of file diff --git a/camelot/core.py b/camelot/core.py index 2417291..f400fe8 100644 --- a/camelot/core.py +++ b/camelot/core.py @@ -8,9 +8,48 @@ import pandas as pd class Cell(object): - """ + """Defines a cell in a table with coordinates relative to a + left-bottom origin. (pdf coordinate space) + + Parameters + ---------- + x1 : float + x-coordinate of left-bottom point. + y1 : float + y-coordinate of left-bottom point. + x2 : float + x-coordinate of right-top point. + y2 : float + y-coordinate of right-top point. + + Attributes + ---------- + lb : tuple + Tuple representing left-bottom coordinates. + lt : tuple + Tuple representing left-top coordinates. + rb : tuple + Tuple representing right-bottom coordinates. + rt : tuple + Tuple representing right-top coordinates. + left : bool + Whether or not cell is bounded on the left. + right : bool + Whether or not cell is bounded on the right. + top : bool + Whether or not cell is bounded on the top. + bottom : bool + Whether or not cell is bounded on the bottom. + hspan : bool + Whether or not cell spans horizontally. + vspan : bool + Whether or not cell spans vertically. + text : string + Text assigned to cell. + bound """ + def __init__(self, x1, y1, x2, y2): self.x1 = x1 self.y1 = y1 @@ -34,37 +73,48 @@ class Cell(object): @property def text(self): - """ - - Returns - ------- - - """ return self._text @text.setter def text(self, t): - """ - - Parameters - ---------- - t - """ self._text = ''.join([self._text, t]) @property def bound(self): - """ - - Returns - ------- - + """The number of sides on which the cell is bounded. """ return self.top + self.bottom + self.left + self.right class Table(object): - """ + """Defines a table with coordinates relative to a left-bottom + origin. (pdf coordinate space) + + Parameters + ---------- + cols : list + List of tuples representing column x-coordinates in increasing + order. + rows : list + List of tuples representing row y-coordinates in decreasing + order. + + Attributes + ---------- + df : object + pandas.DataFrame + shape : tuple + Shape of the table. + accuracy : float + Accuracy with which text was assigned to the cell. + whitespace : float + Percentage of whitespace in the table. + order : int + Table number on pdf page. + page : int + Pdf page number. + data + parsing_report """ def __init__(self, cols, rows): @@ -84,11 +134,7 @@ class Table(object): @property def data(self): - """ - - Returns - ------- - + """Returns two-dimensional list of strings in table. """ d = [] for row in self.cells: @@ -97,11 +143,8 @@ class Table(object): @property def parsing_report(self): - """ - - Returns - ------- - + """Returns a parsing report with accuracy, %whitespace, + table number on page and page number. """ # pretty? report = { @@ -112,27 +155,8 @@ class Table(object): } return report - def set_border(self): - """ - - Returns - ------- - - """ - for r in range(len(self.rows)): - self.cells[r][0].left = True - self.cells[r][len(self.cols) - 1].right = True - for c in range(len(self.cols)): - self.cells[0][c].top = True - self.cells[len(self.rows) - 1][c].bottom = True - return self - def set_all_edges(self): - """ - - Returns - ------- - + """Sets all table edges to True. """ for row in self.cells: for cell in row: @@ -140,16 +164,16 @@ class Table(object): return self def set_edges(self, vertical, horizontal, joint_close_tol=2): - """ + """Sets a cell's edges to True depending on whether the cell's + coordinates overlap with the line's coordinates within a + tolerance. Parameters ---------- - vertical - horizontal - joint_close_tol - - Returns - ------- + vertical : list + List of detected vertical lines. + horizontal : list + List of detected horizontal lines. """ for v in vertical: @@ -256,12 +280,20 @@ class Table(object): return self - def set_span(self): + def set_border(self): + """Sets table border edges to True. """ + for r in range(len(self.rows)): + self.cells[r][0].left = True + self.cells[r][len(self.cols) - 1].right = True + for c in range(len(self.cols)): + self.cells[0][c].top = True + self.cells[len(self.rows) - 1][c].bottom = True + return self - Returns - ------- - + def set_span(self): + """Sets a cell's hspan or vspan attribute to True depending + on whether the cell spans horizontally or vertically. """ for row in self.cells: for cell in row: @@ -288,6 +320,8 @@ class Table(object): return self def to_csv(self, path, **kwargs): + """Write Table to a comma-separated values (csv) file. + """ kw = { 'encoding': 'utf-8', 'index': False, @@ -297,6 +331,8 @@ class Table(object): self.df.to_csv(path, **kw) def to_json(self, path, **kwargs): + """Write Table to a JSON file. + """ kw = { 'orient': 'records' } @@ -306,6 +342,8 @@ class Table(object): f.write(json_string) def to_excel(self, path, **kwargs): + """Write Table to an Excel file. + """ kw = { 'sheet_name': 'page-{}-table-{}'.format(self.page, self.order), 'encoding': 'utf-8' @@ -316,13 +354,21 @@ class Table(object): writer.save() def to_html(self, path, **kwargs): + """Write Table to an HTML file. + """ html_string = self.df.to_html(**kwargs) with open(path, 'w') as f: f.write(html_string) class TableList(object): - """ + """Defines a list of camelot.core.Table objects. Each table can + be accessed using its index. + + Attributes + ---------- + n : int + Number of tables in the list. """ def __init__(self, tables): @@ -371,6 +417,18 @@ class TableList(object): z.write(filepath, os.path.basename(filepath)) def export(self, path, f='csv', compress=False): + """Exports the list of tables to specified file format. + + Parameters + ---------- + path : str + Filepath + f : str + File format. Can be csv, json, excel and html. + compress : bool + Whether or not to add files to a ZIP archive. + + """ dirname = os.path.dirname(path) basename = os.path.basename(path) root, ext = os.path.splitext(basename) @@ -402,9 +460,6 @@ class TableList(object): class Geometry(object): - """ - - """ def __init__(self): self.text = [] self.images = () @@ -421,9 +476,6 @@ class Geometry(object): class GeometryList(object): - """ - - """ def __init__(self, geometry): self.text = [g.text for g in geometry] self.images = [g.images for g in geometry] diff --git a/camelot/handlers.py b/camelot/handlers.py index af4db00..8585432 100644 --- a/camelot/handlers.py +++ b/camelot/handlers.py @@ -9,18 +9,43 @@ from .utils import get_page_layout, get_text_objects, get_rotation class PDFHandler(object): - """ + """Handles all operations like temp directory creation, splitting + file into single page pdfs, parsing each pdf and then removing the + temp directory. + + Parameter + --------- + filename : str + Path to pdf file. + pages : str + Comma-separated page numbers to parse. + Example: 1,3,4 or 1,4-end """ def __init__(self, filename, pages='1'): self.filename = filename if not self.filename.endswith('.pdf'): raise TypeError("File format not supported.") - self.pages = self.__get_pages(self.filename, pages) + self.pages = self._get_pages(self.filename, pages) self.tempdir = tempfile.mkdtemp() - def __get_pages(self, filename, pages): - # refactor + def _get_pages(self, filename, pages): + """Converts pages string to list of ints. + + Parameters + ---------- + filename : str + Path to pdf file. + pages : str + Comma-separated page numbers to parse. + Example: 1,3,4 or 1,4-end + + Returns + ------- + P : list + List of int page numbers. + + """ page_numbers = [] if pages == '1': page_numbers.append({'start': 1, 'end': 1}) @@ -42,8 +67,19 @@ class PDFHandler(object): P.extend(range(p['start'], p['end'] + 1)) return sorted(set(P)) - def __save_page(self, filename, page, temp): - # refactor + def _save_page(self, filename, page, temp): + """Saves specified page from pdf into a temporary directory. + + Parameters + ---------- + filename : str + Path to pdf file. + page : int + Page number + temp : str + Tmp directory + + """ with open(filename, 'rb') as fileobj: infile = PdfFileReader(fileobj, strict=False) fpath = os.path.join(temp, 'page-{0}.pdf'.format(page)) @@ -65,28 +101,37 @@ class PDFHandler(object): infile = PdfFileReader(open(fpath_new, 'rb'), strict=False) outfile = PdfFileWriter() p = infile.getPage(0) - if rotation == 'left': + if rotation == 'anticlockwise': p.rotateClockwise(90) - elif rotation == 'right': + elif rotation == 'clockwise': p.rotateCounterClockwise(90) outfile.addPage(p) with open(fpath, 'wb') as f: outfile.write(f) def parse(self, mesh=False, **kwargs): - """ + """Extracts tables by calling parser.get_tables on all single + page pdfs. Parameters ---------- - mesh - kwargs + mesh : bool (default: False) + Whether or not to use Lattice method of parsing. Stream + is used by default. + kwargs : dict + See camelot.read_pdf kwargs. Returns ------- + tables : camelot.core.TableList + List of tables found in pdf. + geometry : camelot.core.GeometryList + List of geometry objects (contours, lines, joints) + found in pdf. """ for p in self.pages: - self.__save_page(self.filename, p, self.tempdir) + self._save_page(self.filename, p, self.tempdir) pages = [os.path.join(self.tempdir, 'page-{0}.pdf'.format(p)) for p in self.pages] tables = [] diff --git a/camelot/image_processing.py b/camelot/image_processing.py index ec2b384..23923b2 100644 --- a/camelot/image_processing.py +++ b/camelot/image_processing.py @@ -9,17 +9,31 @@ from .utils import merge_tuples def adaptive_threshold(imagename, process_background=False, blocksize=15, c=-2): - """ + """Thresholds an image using OpenCV's adaptiveThreshold. Parameters ---------- - imagename - process_background - blocksize - c + imagename : string + Path to image file. + process_background : bool, optional (default: False) + Whether or not to process lines that are in background. + blocksize : int, optional (default: 15) + Size of a pixel neighborhood that is used to calculate a + threshold value for the pixel: 3, 5, 7, and so on. + + For more information, refer `OpenCV's adaptiveThreshold `_. + c : int, optional (default: -2) + Constant subtracted from the mean or weighted mean. + Normally, it is positive but may be zero or negative as well. + + For more information, refer `OpenCV's adaptiveThreshold `_. Returns ------- + img : object + numpy.ndarray representing the original image. + threshold : object + numpy.ndarray representing the thresholded image. """ img = cv2.imread(imagename) @@ -35,17 +49,35 @@ def adaptive_threshold(imagename, process_background=False, blocksize=15, c=-2): def find_lines(threshold, direction='horizontal', line_size_scaling=15, iterations=0): - """ + """Finds horizontal and vertical lines by applying morphological + transformations on an image. Parameters ---------- - threshold - direction - line_size_scaling - iterations + threshold : object + numpy.ndarray representing the thresholded image. + direction : string, optional (default: 'horizontal') + Specifies whether to find vertical or horizontal lines. + line_size_scaling : int, optional (default: 15) + Factor by which the page dimensions will be divided to get + smallest length of lines that should be detected. + + The larger this value, smaller the detected lines. Making it + too large will lead to text being detected as lines. + iterations : int, optional (default: 0) + Number of times for erosion/dilation is applied. + + For more information, refer `OpenCV's dilate `_. Returns ------- + dmask : object + numpy.ndarray representing pixels where vertical/horizontal + lines lie. + lines : list + List of tuples representing vertical/horizontal lines with + coordinates relative to a left-top origin in + image coordinate space. """ lines = [] @@ -84,15 +116,21 @@ def find_lines(threshold, direction='horizontal', line_size_scaling=15, iteratio def find_table_contours(vertical, horizontal): - """ + """Finds table boundaries using OpenCV's findContours. Parameters ---------- - vertical - horizontal + vertical : object + numpy.ndarray representing pixels where vertical lines lie. + horizontal : object + numpy.ndarray representing pixels where horizontal lines lie. Returns ------- + cont : list + List of tuples representing table boundaries. Each tuple is of + the form (x, y, w, h) where (x, y) -> left-top, w -> width and + h -> height in image coordinate space. """ mask = vertical + horizontal @@ -114,16 +152,26 @@ def find_table_contours(vertical, horizontal): def find_table_joints(contours, vertical, horizontal): - """ + """Finds joints/intersections present inside each table boundary. Parameters ---------- - contours - vertical - horizontal + contours : list + List of tuples representing table boundaries. Each tuple is of + the form (x, y, w, h) where (x, y) -> left-top, w -> width and + h -> height in image coordinate space. + vertical : object + numpy.ndarray representing pixels where vertical lines lie. + horizontal : object + numpy.ndarray representing pixels where horizontal lines lie. Returns ------- + tables : dict + Dict with table boundaries as keys and list of intersections + in that boundary as their value. + Keys are of the form (x1, y1, x2, y2) where (x1, y1) -> lb + and (x2, y2) -> rt in image coordinate space. """ joints = np.bitwise_and(vertical, horizontal) @@ -150,15 +198,24 @@ def find_table_joints(contours, vertical, horizontal): def remove_lines(threshold, line_size_scaling=15): - """ + """Removes lines from a thresholded image. Parameters ---------- - threshold - line_size_scaling + threshold : object + numpy.ndarray representing the thresholded image. + line_size_scaling : int, optional (default: 15) + Factor by which the page dimensions will be divided to get + smallest length of lines that should be detected. + + The larger this value, smaller the detected lines. Making it + too large will lead to text being detected as lines. Returns ------- + threshold : object + numpy.ndarray representing the thresholded image + with horizontal and vertical lines removed. """ size = threshold.shape[0] // line_size_scaling @@ -178,16 +235,23 @@ def remove_lines(threshold, line_size_scaling=15): def find_cuts(threshold, char_size_scaling=200): - """ + """Finds cuts made by text projections on y-axis. Parameters ---------- - threshold - char_size_scaling + threshold : object + numpy.ndarray representing the thresholded image. + line_size_scaling : int, optional (default: 200) + Factor by which the page dimensions will be divided to get + smallest length of lines that should be detected. + + The larger this value, smaller the detected lines. Making it + too large will lead to text being detected as lines. Returns ------- - + y_cuts : list + List of cuts on y-axis. """ size = threshold.shape[0] // char_size_scaling char_el = cv2.getStructuringElement(cv2.MORPH_RECT, (1, size)) diff --git a/camelot/io.py b/camelot/io.py index 54f8ef5..33007d4 100644 --- a/camelot/io.py +++ b/camelot/io.py @@ -2,20 +2,93 @@ from .handlers import PDFHandler def read_pdf(filepath, pages='1', mesh=False, **kwargs): - """ + """Read PDF and return parsed data tables. + + Note: kwargs annotated with ^ can only be used with mesh=False + and kwargs annotated with * can only be used with mesh=True. Parameters ---------- - filepath - pages - mesh - kwargs + filepath : str + Path to pdf file. + pages : str + Comma-separated page numbers to parse. + Example: 1,3,4 or 1,4-end + mesh : bool (default: False) + Whether or not to use Lattice method of parsing. Stream + is used by default. + table_area : list, optional (default: None) + List of table areas to analyze as strings of the form + x1,y1,x2,y2 where (x1, y1) -> left-top and + (x2, y2) -> right-bottom in pdf coordinate space. + columns^ : list, optional (default: None) + List of column x-coordinates as strings where the coordinates + are comma-separated. + split_text : bool, optional (default: False) + Whether or not to split a text line if it spans across + multiple cells. + flag_size : bool, optional (default: False) + Whether or not to highlight a substring using + if its size is different from rest of the string, useful for + super and subscripts. + row_close_tol^ : int, optional (default: 2) + Rows will be formed by combining text vertically + within this tolerance. + col_close_tol^ : int, optional (default: 0) + Columns will be formed by combining text horizontally + within this tolerance. + process_background* : bool, optional (default: False) + Whether or not to process lines that are in background. + line_size_scaling* : int, optional (default: 15) + Factor by which the page dimensions will be divided to get + smallest length of lines that should be detected. + + The larger this value, smaller the detected lines. Making it + too large will lead to text being detected as lines. + copy_text* : list, optional (default: None) + {'h', 'v'} + Select one or more strings from above and pass them as a list + to specify the direction in which text should be copied over + when a cell spans multiple rows or columns. + shift_text* : list, optional (default: ['l', 't']) + {'l', 'r', 't', 'b'} + Select one or more strings from above and pass them as a list + to specify where the text in a spanning cell should flow. + line_close_tol* : int, optional (default: 2) + Tolerance parameter used to merge vertical and horizontal + detected lines which lie close to each other. + joint_close_tol* : int, optional (default: 2) + Tolerance parameter used to decide whether the detected lines + and points lie close to each other. + threshold_blocksize : int, optional (default: 15) + Size of a pixel neighborhood that is used to calculate a + threshold value for the pixel: 3, 5, 7, and so on. + + For more information, refer `OpenCV's adaptiveThreshold `_. + threshold_constant : int, optional (default: -2) + Constant subtracted from the mean or weighted mean. + Normally, it is positive but may be zero or negative as well. + + For more information, refer `OpenCV's adaptiveThreshold `_. + iterations : int, optional (default: 0) + Number of times for erosion/dilation is applied. + + For more information, refer `OpenCV's dilate `_. + margins : tuple + PDFMiner margins. (char_margin, line_margin, word_margin) + + For for information, refer `PDFMiner docs `_. + debug : bool, optional (default: False) + Whether or not to return all text objects on the page + which can be used to generate a matplotlib plot, to get + values for table_area(s) and debugging. Returns ------- + tables : camelot.core.TableList """ - # explicit type conversion + # validate kwargs? p = PDFHandler(filepath, pages) tables, __ = p.parse(mesh=mesh, **kwargs) return tables \ No newline at end of file diff --git a/camelot/parsers/base.py b/camelot/parsers/base.py index 79cb986..3ffe146 100644 --- a/camelot/parsers/base.py +++ b/camelot/parsers/base.py @@ -5,8 +5,7 @@ from ..utils import get_page_layout, get_text_objects class BaseParser(object): - """ - + """Defines a base parser. """ def _generate_layout(self, filename): self.filename = filename diff --git a/camelot/parsers/lattice.py b/camelot/parsers/lattice.py index 15663dc..40a9040 100644 --- a/camelot/parsers/lattice.py +++ b/camelot/parsers/lattice.py @@ -11,7 +11,7 @@ from .base import BaseParser from ..core import Table from ..utils import (scale_image, scale_pdf, segments_in_bbox, text_in_bbox, merge_close_lines, get_table_index, compute_accuracy, - count_empty_strings, encode_, setup_logging) + compute_whitespace, setup_logging, encode_) from ..image_processing import (adaptive_threshold, find_lines, find_table_contours, find_table_joints) @@ -20,14 +20,74 @@ logger = setup_logging(__name__) class Lattice(BaseParser): - """ + """Lattice method of parsing looks for lines between text + to form a table. + + Parameters + ---------- + table_area : list, optional (default: None) + List of table areas to analyze as 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) + Whether or not to process lines that are in background. + line_size_scaling : int, optional (default: 15) + Factor by which the page dimensions will be divided to get + smallest length of lines that should be detected. + + The larger this value, smaller the detected lines. Making it + too large will lead to text being detected as lines. + copy_text : list, optional (default: None) + {'h', 'v'} + Select one or more strings from above and pass them as a list + to specify the direction in which text should be copied over + when a cell spans multiple rows or columns. + shift_text : list, optional (default: ['l', 't']) + {'l', 'r', 't', 'b'} + Select one or more strings from above and pass them as a list + to specify where the text in a spanning cell should flow. + split_text : bool, optional (default: False) + Whether or not to split a text line if it spans across + multiple cells. + flag_size : bool, optional (default: False) + Whether or not to highlight a substring using + if its size is different from rest of the string, useful for + super and subscripts. + line_close_tol : int, optional (default: 2) + Tolerance parameter used to merge vertical and horizontal + detected lines which lie close to each other. + joint_close_tol : int, optional (default: 2) + Tolerance parameter used to decide whether the detected lines + and points lie close to each other. + threshold_blocksize : int, optional (default: 15) + Size of a pixel neighborhood that is used to calculate a + threshold value for the pixel: 3, 5, 7, and so on. + + For more information, refer `OpenCV's adaptiveThreshold `_. + threshold_constant : int, optional (default: -2) + Constant subtracted from the mean or weighted mean. + Normally, it is positive but may be zero or negative as well. + + For more information, refer `OpenCV's adaptiveThreshold `_. + iterations : int, optional (default: 0) + Number of times for erosion/dilation is applied. + + For more information, refer `OpenCV's dilate `_. + margins : tuple + PDFMiner margins. (char_margin, line_margin, word_margin) + + For for information, refer `PDFMiner docs `_. + debug : bool, optional (default: False) + Whether or not to return all text objects on the page + which can be used to generate a matplotlib plot, to get + values for table_area(s) and debugging. """ def __init__(self, table_area=None, process_background=False, line_size_scaling=15, copy_text=None, shift_text=['l', 't'], split_text=False, flag_size=False, line_close_tol=2, joint_close_tol=2, threshold_blocksize=15, threshold_constant=-2, - iterations=0, margins=(1.0, 0.5, 0.1), debug=None): + iterations=0, margins=(1.0, 0.5, 0.1), debug=False): self.table_area = table_area self.process_background = process_background self.line_size_scaling = line_size_scaling @@ -45,6 +105,27 @@ class Lattice(BaseParser): @staticmethod def _reduce_index(t, idx, shift_text): + """Reduces index of a text object if it lies within a spanning + cell. + + Parameters + ---------- + table : camelot.core.Table + idx : list + List of tuples of the form (r_idx, c_idx, text). + shift_text : list + {'l', 'r', 't', 'b'} + Select one or more strings from above and pass them as a + list to specify where the text in a spanning cell should + flow. + + Returns + ------- + indices : list + List of tuples of the form (r_idx, c_idx, text) where + r_idx and c_idx are new row and column indices for text. + + """ indices = [] for r_idx, c_idx, text in idx: for d in shift_text: @@ -69,6 +150,22 @@ class Lattice(BaseParser): @staticmethod def _copy_spanning_text(t, copy_text=None): + """Copies over text in empty spanning cells. + + Parameters + ---------- + t : camelot.core.Table + copy_text : list, optional (default: None) + {'h', 'v'} + Select one or more strings from above and pass them as a list + to specify the direction in which text should be copied over + when a cell spans multiple rows or columns. + + Returns + ------- + t : camelot.core.Table + + """ for f in copy_text: if f == "h": for i in range(len(t.cells)): @@ -199,7 +296,7 @@ class Lattice(BaseParser): table.df = pd.DataFrame(data) table.shape = table.df.shape - whitespace, __, __ = count_empty_strings(data) + whitespace = compute_whitespace(data) table.accuracy = accuracy table.whitespace = whitespace table.order = table_idx + 1 @@ -208,16 +305,6 @@ class Lattice(BaseParser): return table def extract_tables(self, filename): - """ - - Parameters - ---------- - filename - - Returns - ------- - - """ logger.info('Processing {}'.format(os.path.basename(filename))) self._generate_layout(filename) @@ -237,7 +324,7 @@ class Lattice(BaseParser): table = self._generate_table(table_idx, cols, rows, v_s=v_s, h_s=h_s) _tables.append(table) - if self.debug is not None: + if self.debug: text = [] text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) diff --git a/camelot/parsers/stream.py b/camelot/parsers/stream.py index e1a4980..f547bf0 100644 --- a/camelot/parsers/stream.py +++ b/camelot/parsers/stream.py @@ -8,19 +8,54 @@ import pandas as pd from .base import BaseParser from ..core import Table from ..utils import (text_in_bbox, get_table_index, compute_accuracy, - count_empty_strings, encode_, setup_logging) + compute_whitespace, setup_logging, encode_) logger = setup_logging(__name__) class Stream(BaseParser): - """ + """Stream method of parsing looks for spaces between text + to form a table. + + If you want to specify columns when specifying multiple table + areas, make sure that the length of both lists are equal. + + Parameters + ---------- + table_area : list, optional (default: None) + List of table areas to analyze as strings of the form + x1,y1,x2,y2 where (x1, y1) -> left-top and + (x2, y2) -> right-bottom in pdf coordinate space. + columns : list, optional (default: None) + List of column x-coordinates as strings where the coordinates + are comma-separated. + split_text : bool, optional (default: False) + Whether or not to split a text line if it spans across + multiple cells. + flag_size : bool, optional (default: False) + Whether or not to highlight a substring using + if its size is different from rest of the string, useful for + super and subscripts. + row_close_tol : int, optional (default: 2) + Rows will be formed by combining text vertically + within this tolerance. + col_close_tol : int, optional (default: 0) + Columns will be formed by combining text horizontally + within this tolerance. + margins : tuple, optional (default: (1.0, 0.5, 0.1)) + PDFMiner margins. (char_margin, line_margin, word_margin) + + For for information, refer `PDFMiner docs `_. + debug : bool, optional (default: False) + Whether or not to return all text objects on the page + which can be used to generate a matplotlib plot, to get + values for table_area(s), columns and debugging. """ def __init__(self, table_area=None, columns=None, split_text=False, flag_size=False, row_close_tol=2, col_close_tol=0, - margins=(1.0, 0.5, 0.1), debug=None): + margins=(1.0, 0.5, 0.1), debug=False): self.table_area = table_area self.columns = columns self._validate_columns() @@ -33,6 +68,20 @@ class Stream(BaseParser): @staticmethod def _text_bbox(t_bbox): + """Returns bounding box for the text present on a page. + + Parameters + ---------- + t_bbox : dict + Dict with two keys 'horizontal' and 'vertical' with lists of + LTTextLineHorizontals and LTTextLineVerticals respectively. + + Returns + ------- + text_bbox : tuple + Tuple (x0, y0, x1, y1) in pdf coordinate space. + + """ xmin = min([t.x0 for direction in t_bbox for t in t_bbox[direction]]) ymin = min([t.y0 for direction in t_bbox for t in t_bbox[direction]]) xmax = max([t.x1 for direction in t_bbox for t in t_bbox[direction]]) @@ -42,6 +91,21 @@ class Stream(BaseParser): @staticmethod def _group_rows(text, row_close_tol=2): + """Groups PDFMiner text objects into rows vertically + within a tolerance. + + Parameters + ---------- + text : list + List of PDFMiner text objects. + row_close_tol : int, optional (default: 2) + + Returns + ------- + rows : list + Two-dimensional list of text objects grouped into rows. + + """ row_y = 0 rows = [] temp = [] @@ -61,6 +125,21 @@ class Stream(BaseParser): @staticmethod def _merge_columns(l, col_close_tol=0): + """Merges column boundaries horizontally if they overlap + or lie within a tolerance. + + Parameters + ---------- + l : list + List of column x-coordinate tuples. + col_close_tol : int, optional (default: 0) + + Returns + ------- + merged : list + List of merged column x-coordinate tuples. + + """ merged = [] for higher in l: if not merged: @@ -89,6 +168,21 @@ class Stream(BaseParser): @staticmethod def _join_rows(rows_grouped, text_y_max, text_y_min): + """Makes row coordinates continuous. + + Parameters + ---------- + rows_grouped : list + Two-dimensional list of text objects grouped into rows. + text_y_max : int + text_y_min : int + + Returns + ------- + rows : list + List of continuous row y-coordinate tuples. + + """ row_mids = [sum([(t.y0 + t.y1) / 2 for t in r]) / len(r) if len(r) > 0 else 0 for r in rows_grouped] rows = [(row_mids[i] + row_mids[i - 1]) / 2 for i in range(1, len(row_mids))] @@ -100,6 +194,23 @@ class Stream(BaseParser): @staticmethod def _add_columns(cols, text, row_close_tol): + """Adds columns to existing list by taking into account + the text that lies outside the current column x-coordinates. + + Parameters + ---------- + cols : list + List of column x-coordinate tuples. + text : list + List of PDFMiner text objects. + ytol : int + + Returns + ------- + cols : list + Updated list of column x-coordinate tuples. + + """ if text: text = Stream._group_rows(text, row_close_tol=row_close_tol) elements = [len(r) for r in text] @@ -110,6 +221,21 @@ class Stream(BaseParser): @staticmethod def _join_columns(cols, text_x_min, text_x_max): + """Makes column coordinates continuous. + + Parameters + ---------- + cols : list + List of column x-coordinate tuples. + text_x_min : int + text_y_max : int + + Returns + ------- + cols : list + Updated list of column x-coordinate tuples. + + """ cols = sorted(cols) cols = [(cols[i][0] + cols[i - 1][1]) / 2 for i in range(1, len(cols))] cols.insert(0, text_x_min) @@ -207,7 +333,7 @@ class Stream(BaseParser): table.df = pd.DataFrame(data) table.shape = table.df.shape - whitespace, __, __ = count_empty_strings(data) + whitespace = compute_whitespace(data) table.accuracy = accuracy table.whitespace = whitespace table.order = table_idx + 1 @@ -216,16 +342,6 @@ class Stream(BaseParser): return table def extract_tables(self, filename): - """ - - Parameters - ---------- - filename - - Returns - ------- - - """ logger.info('Processing {}'.format(os.path.basename(filename))) self._generate_layout(filename) @@ -244,7 +360,7 @@ class Stream(BaseParser): table = self._generate_table(table_idx, cols, rows) _tables.append(table) - if self.debug is not None: + if self.debug: text = [] text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.horizontal_text]) text.extend([(t.x0, t.y0, t.x1, t.y1) for t in self.vertical_text]) diff --git a/camelot/plotting.py b/camelot/plotting.py index 7d4e4d3..2d0bb3c 100644 --- a/camelot/plotting.py +++ b/camelot/plotting.py @@ -6,19 +6,101 @@ from .handlers import PDFHandler def plot_geometry(filepath, pages='1', mesh=False, geometry_type='text', **kwargs): - """ + """Plot geometry found on pdf page based on type specified, + useful for debugging and playing with different parameters to get + the best output. + + Note: kwargs annotated with ^ can only be used with mesh=False + and kwargs annotated with * can only be used with mesh=True. Parameters ---------- - filepath - pages - mesh - geometry_type - kwargs + filepath : str + Path to pdf file. + pages : str + Comma-separated page numbers to parse. + Example: 1,3,4 or 1,4-end + mesh : bool (default: False) + Whether or not to use Lattice method of parsing. Stream + is used by default. + geometry_type : str, optional (default: 'text') + 'text' : Plot text objects found on page, useful to get + table_area and columns coordinates. + 'table' : Plot parsed table. + 'contour'* : Plot detected rectangles. + 'joint'* : Plot detected line intersections. + 'line'* : Plot detected lines. + table_area : list, optional (default: None) + List of table areas to analyze as strings of the form + x1,y1,x2,y2 where (x1, y1) -> left-top and + (x2, y2) -> right-bottom in pdf coordinate space. + columns^ : list, optional (default: None) + List of column x-coordinates as strings where the coordinates + are comma-separated. + split_text : bool, optional (default: False) + Whether or not to split a text line if it spans across + multiple cells. + flag_size : bool, optional (default: False) + Whether or not to highlight a substring using + if its size is different from rest of the string, useful for + super and subscripts. + row_close_tol^ : int, optional (default: 2) + Rows will be formed by combining text vertically + within this tolerance. + col_close_tol^ : int, optional (default: 0) + Columns will be formed by combining text horizontally + within this tolerance. + process_background* : bool, optional (default: False) + Whether or not to process lines that are in background. + line_size_scaling* : int, optional (default: 15) + Factor by which the page dimensions will be divided to get + smallest length of lines that should be detected. + + The larger this value, smaller the detected lines. Making it + too large will lead to text being detected as lines. + copy_text* : list, optional (default: None) + {'h', 'v'} + Select one or more strings from above and pass them as a list + to specify the direction in which text should be copied over + when a cell spans multiple rows or columns. + shift_text* : list, optional (default: ['l', 't']) + {'l', 'r', 't', 'b'} + Select one or more strings from above and pass them as a list + to specify where the text in a spanning cell should flow. + line_close_tol* : int, optional (default: 2) + Tolerance parameter used to merge vertical and horizontal + detected lines which lie close to each other. + joint_close_tol* : int, optional (default: 2) + Tolerance parameter used to decide whether the detected lines + and points lie close to each other. + threshold_blocksize : int, optional (default: 15) + Size of a pixel neighborhood that is used to calculate a + threshold value for the pixel: 3, 5, 7, and so on. + + For more information, refer `OpenCV's adaptiveThreshold `_. + threshold_constant : int, optional (default: -2) + Constant subtracted from the mean or weighted mean. + Normally, it is positive but may be zero or negative as well. + + For more information, refer `OpenCV's adaptiveThreshold `_. + iterations : int, optional (default: 0) + Number of times for erosion/dilation is applied. + + For more information, refer `OpenCV's dilate `_. + margins : tuple + PDFMiner margins. (char_margin, line_margin, word_margin) + + For for information, refer `PDFMiner docs `_. + debug : bool, optional (default: False) + Whether or not to return all text objects on the page + which can be used to generate a matplotlib plot, to get + values for table_area(s) and debugging. + """ - # explicit type conversion + # validate kwargs? p = PDFHandler(filepath, pages) - kwargs.update({'debug': geometry_type}) + debug = True if geometry_type else False + kwargs.update({'debug': debug}) __, geometry = p.parse(mesh=mesh, **kwargs) if geometry_type == 'text': diff --git a/camelot/utils.py b/camelot/utils.py index d132b5a..075c0df 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -19,14 +19,15 @@ from pdfminer.layout import (LAParams, LTAnno, LTChar, LTTextLineHorizontal, def setup_logging(name): - """ + """Sets up a logger with StreamHandler. Parameters ---------- - name + name : str Returns ------- + logger : logging.Logger """ logger = logging.getLogger(name) @@ -47,15 +48,16 @@ logger = setup_logging(__name__) def translate(x1, x2): - """ + """Translates x2 by x1. Parameters ---------- - x1 - x2 + x1 : float + x2 : float Returns ------- + x2 : float """ x2 += x1 @@ -63,15 +65,16 @@ def translate(x1, x2): def scale(x, s): - """ + """Scales x by scaling factor s. Parameters ---------- - x - s + x : float + s : float Returns ------- + x : float """ x *= s @@ -79,18 +82,21 @@ def scale(x, s): def rotate(x1, y1, x2, y2, angle): - """ + """Rotates point x2, y2 about point x1, y1 by angle. Parameters ---------- - x1 - y1 - x2 - y2 - angle + x1 : float + y1 : float + x2 : float + y2 : float + angle : float + Angle in radians. Returns ------- + xnew : float + ynew : float """ s = np.sin(angle) @@ -105,15 +111,26 @@ def rotate(x1, y1, x2, y2, angle): def scale_pdf(k, factors): - """ + """Translates and scales pdf coordinate space to image + coordinate space. Parameters ---------- - k - factors + k : tuple + Tuple (x1, y1, x2, y2) representing table bounding box where + (x1, y1) -> lt and (x2, y2) -> rb in PDFMiner coordinate + space. + factors : tuple + Tuple (scaling_factor_x, scaling_factor_y, pdf_y) where the + first two elements are scaling factors and pdf_y is height of + pdf. Returns ------- + knew : tuple + Tuple (x1, y1, x2, y2) representing table bounding box where + (x1, y1) -> lt and (x2, y2) -> rb in OpenCV coordinate + space. """ x1, y1, x2, y2 = k @@ -127,17 +144,28 @@ def scale_pdf(k, factors): def scale_image(tables, v_segments, h_segments, factors): - """ + """Translates and scales image coordinate space to pdf + coordinate space. Parameters ---------- - tables - v_segments - h_segments - factors + tables : dict + Dict with table boundaries as keys and list of intersections + in that boundary as value. + v_segments : list + List of vertical line segments. + h_segments : list + List of horizontal line segments. + factors : tuple + Tuple (scaling_factor_x, scaling_factor_y, img_y) where the + first two elements are scaling factors and img_y is height of + image. Returns ------- + tables_new : dict + v_segments_new : dict + h_segments_new : dict """ scaling_factor_x, scaling_factor_y, img_y = factors @@ -172,16 +200,23 @@ def scale_image(tables, v_segments, h_segments, factors): def get_rotation(lttextlh, lttextlv, ltchar): - """ + """Detects if text in table is rotated or not using the current + transformation matrix (CTM) and returns its orientation. Parameters ---------- - lttextlh - lttextlv - ltchar + lttextlh : list + List of PDFMiner LTTextLineHorizontal objects. + lttextlv : list + List of PDFMiner LTTextLineVertical objects. + ltchar : list + List of PDFMiner LTChar objects. Returns ------- + rotation : string + '' if text in table is upright, 'left' if rotated 90 degree + anticlockwise and 'right' if rotated 90 degree clockwise. """ rotation = '' @@ -190,21 +225,30 @@ def get_rotation(lttextlh, lttextlv, ltchar): if hlen < vlen: clockwise = sum(t.matrix[1] < 0 and t.matrix[2] > 0 for t in ltchar) anticlockwise = sum(t.matrix[1] > 0 and t.matrix[2] < 0 for t in ltchar) - rotation = 'left' if clockwise < anticlockwise else 'right' + rotation = 'clockwise' if clockwise < anticlockwise else 'anticlockwise' return rotation def segments_in_bbox(bbox, v_segments, h_segments): - """ + """Returns all line segments present inside a bounding box. Parameters ---------- - bbox - v_segments - h_segments + bbox : tuple + Tuple (x1, y1, x2, y2) representing a bounding box where + (x1, y1) -> lb and (x2, y2) -> rt in PDFMiner coordinate + space. + v_segments : list + List of vertical line segments. + h_segments : list + List of vertical horizontal segments. Returns ------- + v_s : list + List of vertical line segments that lie inside table. + h_s : list + List of horizontal line segments that lie inside table. """ lb = (bbox[0], bbox[1]) @@ -217,35 +261,42 @@ def segments_in_bbox(bbox, v_segments, h_segments): def text_in_bbox(bbox, text): - """ + """Returns all text objects present inside a bounding box. Parameters ---------- - bbox - text + bbox : tuple + Tuple (x1, y1, x2, y2) representing a bounding box where + (x1, y1) -> lb and (x2, y2) -> rt in PDFMiner coordinate + space. + text : List of PDFMiner text objects. Returns ------- + t_bbox : list + List of PDFMiner text objects that lie inside table. """ lb = (bbox[0], bbox[1]) rt = (bbox[2], bbox[3]) t_bbox = [t for t in text if lb[0] - 2 <= (t.x0 + t.x1) / 2.0 - <= rt[0] + 2 and lb[1] - 2 <= (t.y0 + t.y1) / 2.0 - <= rt[1] + 2] + <= rt[0] + 2 and lb[1] - 2 <= (t.y0 + t.y1) / 2.0 + <= rt[1] + 2] return t_bbox def remove_close_lines(ar, line_close_tol=2): - """ + """Removes lines which are within a tolerance, based on their x or + y axis projections. Parameters ---------- - ar - line_close_tol + ar : list + line_close_tol : int, optional (default: 2) Returns ------- + ret : list """ ret = [] @@ -262,15 +313,17 @@ def remove_close_lines(ar, line_close_tol=2): def merge_close_lines(ar, line_close_tol=2): - """ + """Merges lines which are within a tolerance by calculating a + moving mean, based on their x or y axis projections. Parameters ---------- - ar - line_close_tol + ar : list + line_close_tol : int, optional (default: 2) Returns ------- + ret : list """ ret = [] @@ -288,15 +341,19 @@ def merge_close_lines(ar, line_close_tol=2): def flag_font_size(textline, direction): - """ + """Flags super/subscripts in text by enclosing them with . + May give false positives. Parameters ---------- - textline - direction + textline : list + List of PDFMiner LTChar objects. + direction : string + Direction of the PDFMiner LTTextLine object. Returns ------- + fstring : string """ if direction == 'horizontal': @@ -324,18 +381,27 @@ def flag_font_size(textline, direction): return fstring -def split_textline(table, textline, direction, flag_size=True): - """ +def split_textline(table, textline, direction, flag_size=False): + """Splits PDFMiner LTTextLine into substrings if it spans across + multiple rows/columns. Parameters ---------- - table - textline - direction - flag_size + table : camelot.core.Table + textline : object + PDFMiner LTTextLine object. + direction : string + Direction of the PDFMiner LTTextLine object. + flag_size : bool, optional (default: False) + Whether or not to highlight a substring using + if its size is different from rest of the string, useful for + super and subscripts. Returns ------- + grouped_chars : list + List of tuples of the form (idx, text) where idx is the index + of row/column and text is the an lttextline substring. """ idx = 0 @@ -388,19 +454,38 @@ def split_textline(table, textline, direction, flag_size=True): return grouped_chars -def get_table_index(table, t, direction, split_text=False, flag_size=True): - """ +def get_table_index(table, t, direction, split_text=False, flag_size=False): + """Gets indices of the table cell where given text object lies by + comparing their y and x-coordinates. Parameters ---------- - table - t - direction - split_text - flag_size + table : camelot.core.Table + t : object + PDFMiner LTTextLine object. + direction : string + Direction of the PDFMiner LTTextLine object. + split_text : bool, optional (default: False) + Whether or not to split a text line if it spans across + multiple cells. + flag_size : bool, optional (default: False) + Whether or not to highlight a substring using + if its size is different from rest of the string, useful for + super and subscripts. Returns ------- + indices : list + List of tuples of the form (r_idx, c_idx, text) where r_idx + and c_idx are row and column indices. + error : float + Assignment error, percentage of text area that lies outside + a cell. + +-------+ + | | + | [Text bounding box] + | | + +-------+ """ r_idx, c_idx = [-1] * 2 @@ -450,14 +535,19 @@ def get_table_index(table, t, direction, split_text=False, flag_size=True): def compute_accuracy(error_weights): - """ + """Calculates a score based on weights assigned to various + parameters and their error percentages. Parameters ---------- - error_weights + error_weights : list + Two-dimensional list of the form [[p1, e1], [p2, e2], ...] + where pn is the weight assigned to list of errors en. + Sum of pn should be equal to 100. Returns ------- + score : float """ SCORE_VAL = 100 @@ -474,50 +564,40 @@ def compute_accuracy(error_weights): return score -def count_empty_strings(d): - """ +def compute_whitespace(d): + """Calculates the percentage of empty strings in a + two-dimensional list. Parameters ---------- - d + d : list Returns ------- + whitespace : float + Percentage of empty cells. """ - empty_p = 0 + whitespace = 0 r_nempty_cells, c_nempty_cells = [], [] for i in d: for j in i: if j.strip() == '': - empty_p += 1 - empty_p = 100 * (empty_p / float(len(d) * len(d[0]))) - for row in d: - r_nempty_c = 0 - for r in row: - if r.strip() != '': - r_nempty_c += 1 - r_nempty_cells.append(r_nempty_c) - d = zip(*d) - d = [list(col) for col in d] - for col in d: - c_nempty_c = 0 - for c in col: - if c.strip() != '': - c_nempty_c += 1 - c_nempty_cells.append(c_nempty_c) - return empty_p, r_nempty_cells, c_nempty_cells + whitespace += 1 + whitespace = 100 * (whitespace / float(len(d) * len(d[0]))) + return whitespace -def remove_empty_strings(d): - """ +def remove_empty(d): + """Removes empty rows and columns from a two-dimensional list. Parameters ---------- - d + d : list Returns ------- + d : list """ for i, row in enumerate(d): @@ -530,70 +610,46 @@ def remove_empty_strings(d): def encode_(ar): - """ + """Encodes two-dimensional list into unicode. Parameters ---------- - ar + ar : list Returns ------- + ar : list """ ar = [[r.encode('utf-8') for r in row] for row in ar] return ar -def get_text_objects(layout, ltype="char", t=None): - """ - - Parameters - ---------- - layout - ltype - t - - Returns - ------- - - """ - if ltype == "char": - LTObject = LTChar - elif ltype == "lh": - LTObject = LTTextLineHorizontal - elif ltype == "lv": - LTObject = LTTextLineVertical - if t is None: - t = [] - try: - for obj in layout._objs: - if isinstance(obj, LTObject): - t.append(obj) - else: - t += get_text_objects(obj, ltype=ltype) - except AttributeError: - pass - return t - - -def get_page_layout(pname, char_margin=1.0, line_margin=0.5, word_margin=0.1, +def get_page_layout(filename, char_margin=1.0, line_margin=0.5, word_margin=0.1, detect_vertical=True, all_texts=True): - """ + """Returns a PDFMiner LTPage object and page dimension of a single + page pdf. See https://euske.github.io/pdfminer/ to get definitions + of kwargs. Parameters ---------- - pname - char_margin - line_margin - word_margin - detect_vertical - all_texts + filename : string + Path to pdf file. + char_margin : float + line_margin : float + word_margin : float + detect_vertical : bool + all_texts : bool Returns ------- + layout : object + PDFMiner LTPage object. + dim : tuple + Dimension of pdf page in the form (width, height). """ - with open(pname, 'r') as f: + with open(filename, 'r') as f: parser = PDFParser(f) document = PDFDocument(parser) if not document.is_extractable: @@ -615,12 +671,56 @@ def get_page_layout(pname, char_margin=1.0, line_margin=0.5, word_margin=0.1, return layout, dim -def merge_tuples(tuples): - """ +def get_text_objects(layout, ltype="char", t=None): + """Recursively parses pdf layout to get a list of + PDFMiner text objects. Parameters ---------- - tuples + layout : object + PDFMiner LTPage object. + ltype : string + Specify 'char', 'lh', 'lv' to get LTChar, LTTextLineHorizontal, + and LTTextLineVertical objects respectively. + t : list + + Returns + ------- + t : list + List of PDFMiner text objects. + + """ + if ltype == "char": + LTObject = LTChar + elif ltype == "lh": + LTObject = LTTextLineHorizontal + elif ltype == "lv": + LTObject = LTTextLineVertical + if t is None: + t = [] + try: + for obj in layout._objs: + if isinstance(obj, LTObject): + t.append(obj) + else: + t += get_text_objects(obj, ltype=ltype) + except AttributeError: + pass + return t + + +def merge_tuples(tuples): + """Merges a list of overlapping tuples. + + Parameters + ---------- + tuples : list + List of tuples where a tuple is a single axis coordinate pair. + + Yields + ------ + tuple + """ merged = list(tuples[0]) for s, e in tuples: diff --git a/docs/api.rst b/docs/api.rst index 99a9e7f..3bd0f3d 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,17 +4,37 @@ API Reference ============= -Pdf -=== -.. automodule:: camelot.pdf +camelot.read_pdf +================ +.. automodule:: camelot.read_pdf :members: -Lattice -======= -.. automodule:: camelot.lattice +camelot.handlers.PDFHandler +=========================== +.. automodule:: camelot.handlers.PDFHandler :members: -Stream -====== -.. automodule:: camelot.stream +camelot.parsers.Stream +====================== +.. automodule:: camelot.parsers.Stream + :members: + +camelot.parsers.Lattice +======================= +.. automodule:: camelot.parsers.Lattice + :members: + +camelot.core.Cell +================= +.. automodule:: camelot.core.Cell + :members: + +camelot.core.Table +================== +.. automodule:: camelot.core.Table + :members: + +camelot.core.TableList +====================== +.. automodule:: camelot.core.TableList :members: \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index b186ad7..4b91c69 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,11 +3,11 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -================================== -Camelot: pdf parsing made simpler! -================================== +===================================== +Camelot: PDF Table Parsing for Humans +===================================== -Camelot is a Python 2.7 library and command-line tool for getting tables out of pdf files. +Camelot is a Python 2.7 library and command-line tool for extracting tabular data from PDF files. Why another pdf table parsing library? ====================================== @@ -32,12 +32,22 @@ Usage :: - >>> from camelot.pdf import Pdf - >>> from camelot.lattice import Lattice - - >>> manager = Pdf(Lattice(), 'us-030.pdf') - >>> tables = manager.extract() - >>> print tables['page-1']['table-1']['data'] + >>> import camelot + >>> tables = camelot.read_pdf("foo.pdf") + >>> tables + + >>> tables.export("foo.csv", f="csv", compress=True) # json, excel, html + >>> tables[0] + + >>> tables[0].to_csv("foo.csv") # to_json, to_excel, to_html + >>> tables[0].parsing_report + { + "accuracy": 96, + "whitespace": 80, + "order": 1, + "page": 1 + } + >>> df = tables[0].df .. csv-table:: :header: "Cycle Name","KI (1/km)","Distance (mi)","Percent Fuel Savings","","","" @@ -49,45 +59,6 @@ Usage "2032_2","0.17","57.8","21.7%","0.3%","2.7%","1.2%" "4171_1","0.07","173.9","58.1%","1.6%","2.1%","0.5%" -Camelot comes with a CLI where you can specify page numbers, output format, output directory etc. By default, the output files are placed in the same directory as the PDF. - -:: - - Camelot: PDF parsing made simpler! - - usage: - camelot [options] [...] - - options: - -h, --help Show this screen. - -v, --version Show version. - -V, --verbose Verbose. - -p, --pages Comma-separated list of page numbers. - Example: -p 1,3-6,10 [default: 1] - -P, --parallel Parallelize the parsing process. - -f, --format Output format. (csv,tsv,html,json,xlsx) [default: csv] - -l, --log Log to file. - -o, --output Output directory. - -M, --cmargin Char margin. Chars closer than cmargin are - grouped together to form a word. [default: 1.0] - -L, --lmargin Line margin. Lines closer than lmargin are - grouped together to form a textbox. [default: 0.5] - -W, --wmargin Word margin. Insert blank spaces between chars - if distance between words is greater than word - margin. [default: 0.1] - -J, --split_text Split text lines if they span across multiple cells. - -K, --flag_size Flag substring if its size differs from the whole string. - Useful for super and subscripts. - -X, --print-stats List stats on the parsing process. - -Y, --save-stats Save stats to a file. - -Z, --plot Plot distributions. (page,all,rc) - - camelot methods: - lattice Looks for lines between data. - stream Looks for spaces between data. - - See 'camelot -h' for more information on a specific method. - Installation ============ @@ -95,42 +66,41 @@ Make sure you have the most updated versions for `pip` and `setuptools`. You can pip install -U pip setuptools -The required dependencies include `numpy`_, `OpenCV`_ and `ImageMagick`_. +The dependencies include `tk`_ and `ghostscript`_. -.. _numpy: http://www.numpy.org/ -.. _OpenCV: http://opencv.org/ -.. _ImageMagick: http://www.imagemagick.org/script/index.php +.. _tk: https://wiki.tcl.tk/3743 +.. _ghostscript: https://www.ghostscript.com/ Installing dependencies ----------------------- -numpy can be install using `pip`. OpenCV and imagemagick can be installed using your system's default package manager. +tk and ghostscript can be installed using your system's default package manager. Linux ^^^^^ -* Arch Linux - -:: - - sudo pacman -S opencv imagemagick - * Ubuntu :: - sudo apt-get install libopencv-dev python-opencv imagemagick + sudo apt-get install python-opencv python-tk ghostscript + +* Arch Linux + +:: + + sudo pacman -S opencv tk ghostscript OS X ^^^^ :: - brew install homebrew/science/opencv imagemagick + brew install homebrew/science/opencv ghostscript Finally, `cd` into the project directory and install by:: - make install + python setup.py install API Reference ============= @@ -150,14 +120,14 @@ You can check the latest sources with the command:: Contributing ------------ -See :doc:`Contributing doc `. +See :doc:`Contributing guidelines `. Testing ------- :: - make test + python setup.py test License ======= diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..d907a0b --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,11 @@ +click==6.7 +matplotlib==2.2.3 +numpy==1.13.3 +opencv-python==3.4.2.17 +pandas==0.23.4 +pdfminer==20140328 +Pillow==5.2.0 +PyPDF2==1.26.0 +pytest==3.8.0 +pytest-runner==4.2 +Sphinx==1.8.0b1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 0535f0c..d1a33b7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ -docopt==0.6.2 +click==6.7 matplotlib==2.2.3 -nose==1.3.7 +numpy==1.13.3 +opencv-python==3.4.2.17 +pandas==0.23.4 pdfminer==20140328 -pyexcel-xlsx==0.5.6 Pillow==5.2.0 -PyPDF2==1.26.0 -Sphinx==1.8.0b1 \ No newline at end of file +PyPDF2==1.26.0 \ No newline at end of file diff --git a/setup.py b/setup.py index b496b51..14c0516 100644 --- a/setup.py +++ b/setup.py @@ -4,12 +4,12 @@ import camelot NAME = 'camelot' VERSION = camelot.__version__ -DESCRIPTION = 'camelot parses tables from PDFs!' +DESCRIPTION = 'PDF Table Parsing for Humans' with open('README.md') as f: LONG_DESCRIPTION = f.read() URL = 'https://github.com/socialcopsdev/camelot' AUTHOR = 'Vinayak Mehta' -AUTHOR_EMAIL = 'vinayak@socialcops.com' +AUTHOR_EMAIL = 'vmehta94@gmail.com' LICENSE = 'BSD License' opencv_min_version = '2.4.8' @@ -58,18 +58,14 @@ def setup_package(): opencv_status = get_opencv_status() opencv_req_str = "camelot requires OpenCV >= {0}.\n".format(opencv_min_version) - instructions = ("Installation instructions are available in the README at " - "https://github.com/socialcopsdev/camelot") if opencv_status['up_to_date'] is False: if opencv_status['version']: - raise ImportError("Your installation of OpenCV " - "{0} is out-of-date.\n{1}{2}" - .format(opencv_status['version'], - opencv_req_str, instructions)) + raise ImportError("Your installation of OpenCV {} is out-of-date.\n{}" + .format(opencv_status['version'], opencv_req_str)) else: - raise ImportError("OpenCV is not installed.\n{0}{1}" - .format(opencv_req_str, instructions)) + raise ImportError("OpenCV is not installed.\n{}" + .format(opencv_req_str)) setup(**metadata) From 9a6ed555c804681cc343d080f89c8d0f275a116c Mon Sep 17 00:00:00 2001 From: Vinayak Mehta Date: Sun, 9 Sep 2018 10:04:54 +0530 Subject: [PATCH 39/39] Fix get_rotation --- camelot/utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/camelot/utils.py b/camelot/utils.py index 075c0df..3e87fe5 100644 --- a/camelot/utils.py +++ b/camelot/utils.py @@ -215,8 +215,9 @@ def get_rotation(lttextlh, lttextlv, ltchar): Returns ------- rotation : string - '' if text in table is upright, 'left' if rotated 90 degree - anticlockwise and 'right' if rotated 90 degree clockwise. + '' if text in table is upright, 'anticlockwise' if + rotated 90 degree anticlockwise and 'clockwise' if + rotated 90 degree clockwise. """ rotation = '' @@ -225,7 +226,7 @@ def get_rotation(lttextlh, lttextlv, ltchar): if hlen < vlen: clockwise = sum(t.matrix[1] < 0 and t.matrix[2] > 0 for t in ltchar) anticlockwise = sum(t.matrix[1] > 0 and t.matrix[2] < 0 for t in ltchar) - rotation = 'clockwise' if clockwise < anticlockwise else 'anticlockwise' + rotation = 'anticlockwise' if clockwise < anticlockwise else 'clockwise' return rotation