MCPcopy Create free account
hub / github.com/917Dhj/DeepPaperNote / _grow_table_region

Function _grow_table_region

scripts/extract_pdf_assets.py:839–915  ·  view source on GitHub ↗

Walk away from the caption in ``direction`` ('up' or 'down') and collect logical rows that look like part of a tabular layout. Returns the list of accepted row bboxes (caption excluded) and the number of rows confirmed as table body rows. The caller decides which direction wins.

(
    page,
    caption_anchor: dict,
    rows: list[dict],
    paragraph_blocks: list[tuple[float, float, float, float, str]],
    *,
    direction: str,
    upper_bound: float,
    lower_bound: float,
)

Source from the content-addressed store, hash-verified

837
838
839def _grow_table_region(
840 page,
841 caption_anchor: dict,
842 rows: list[dict],
843 paragraph_blocks: list[tuple[float, float, float, float, str]],
844 *,
845 direction: str,
846 upper_bound: float,
847 lower_bound: float,
848) -> tuple[list[tuple[float, float, float, float]], int]:
849 """Walk away from the caption in ``direction`` ('up' or 'down') and collect
850 logical rows that look like part of a tabular layout.
851
852 Returns the list of accepted row bboxes (caption excluded) and the number
853 of rows confirmed as table body rows. The caller decides which direction
854 wins.
855 """
856 caption_y0 = caption_anchor["bbox"][1]
857 caption_y1 = caption_anchor["bbox"][3]
858
859 accepted: list[tuple[float, float, float, float]] = []
860 data_row_count = 0
861 consecutive_non_data = 0
862 seen_data = False
863 last_accepted_edge = caption_y1 if direction == "down" else caption_y0
864
865 if direction == "down":
866 candidates = [r for r in rows if r["bbox"][1] > caption_y1 + 0.5]
867 candidates.sort(key=lambda r: r["bbox"][1])
868 boundary_check = lambda ly0, ly1: ly1 >= lower_bound
869 else:
870 candidates = [r for r in rows if r["bbox"][3] < caption_y0 - 0.5]
871 candidates.sort(key=lambda r: r["bbox"][3], reverse=True)
872 boundary_check = lambda ly0, ly1: ly0 <= upper_bound
873
874 for row in candidates:
875 restricted_row = _restrict_row_to_caption_column(row, caption_anchor["bbox"], page.rect)
876 if restricted_row is None:
877 continue
878 row = restricted_row
879 rx0, ry0, rx1, ry1 = row["bbox"]
880 if boundary_check(ry0, ry1):
881 break
882 text = row["text"]
883 is_table_row = _row_is_table_like(row)
884 in_paragraph_block = _line_is_inside_any_block(row["bbox"], paragraph_blocks)
885 row_gap = ry0 - last_accepted_edge if direction == "down" else last_accepted_edge - ry1
886 row_height = max(ry1 - ry0, 1.0)
887 if seen_data and row_gap > max(12.0, row_height * 1.8) and not is_table_row:
888 break
889 if (
890 seen_data
891 and len(row.get("members", []) or []) <= 1
892 and in_paragraph_block
893 and not _looks_like_data_row(text)
894 ):
895 break
896 # If this row sits entirely inside a real prose paragraph and does not

Calls 4

_row_is_table_likeFunction · 0.85
_looks_like_data_rowFunction · 0.85