drawing_tools.table package#
Submodules#
drawing_tools.table.candidate_preparation module#
Candidate preparation for table detection (Phase 1): which edges/texts to propose.
The TableCandidatePreparer turns a drawing view into candidate sets of
edges paired with the view’s text entities, ready for table generation. It collects
edge sources (CompositeEntities, background-view geometries with the grid reference
excluded), extracts the H/V line segments and peels densely-connected clusters with
the iterative connectivity filter.
- class drawing_tools.table.candidate_preparation.CandidatePreparationConfig(line_segment_tolerance: float = 0.5, connectivity_filter: ConnectivityFilterConfig = <factory>, max_filter_passes: int = 5)#
Bases:
objectConfiguration for candidate edge preparation (Phase 1).
- connectivity_filter: ConnectivityFilterConfig#
- __init__(line_segment_tolerance: float = 0.5, connectivity_filter: ConnectivityFilterConfig = <factory>, max_filter_passes: int = 5) None#
- class drawing_tools.table.candidate_preparation.TableCandidatePreparer(sheet_width: float, sheet_height: float, grid_reference_extractor: ReferenceFrameExtractor | None, config: CandidatePreparationConfig | None = None)#
Bases:
objectPrepares candidate edge/text sets for table detection in a view (Phase 1).
Owns the
ConnectivityDensityFilterand the grid-reference exclusion for the background view. The entry point iscreate_view_candidate_sets(); each candidate set it returns goes through the same pipeline: grid reference exclusion followed by iterative connectivity density filtering.- __init__(sheet_width: float, sheet_height: float, grid_reference_extractor: ReferenceFrameExtractor | None, config: CandidatePreparationConfig | None = None)#
Initialize the preparer.
- Parameters:
sheet_width – Width of the sheet, for the connectivity filter thresholds.
sheet_height – Height of the sheet, for the connectivity filter thresholds.
grid_reference_extractor – The sheet’s reference frame extractor, used to exclude the grid reference geometries from background-view candidates. May only be None when no view is ever processed with
is_background=True.config – Configuration for candidate edge preparation.
- create_view_candidate_sets(view: View, is_background: bool = False, _view_data: ViewDetectionData | None = None) list[tuple[list[Edge], list[Entity], str]]#
Create candidate sets of edges and annotations for table detection in a view.
For background views, the grid reference is identified via the sheet extractor’s
reference_frame_data.grid_reference_geometriesand excluded from both direct geometries and composite entity geometries.Every candidate set is paired with the leaf
Textentities of the whole view, collected only once the view is known to produce candidates: unpacking every annotation tree is not free, and most views yield no candidate at all.Each candidate set goes through the same pipeline: grid reference exclusion followed by connectivity density filtering.
- Parameters:
view – The view to process
is_background – True if this is the background view; requires a non-None
grid_reference_extractor_view_data – Optional data container for storing intermediate results
- Returns:
Filtered candidate sets.
drawing_tools.table.core module#
Table detection algorithm for detect tables in technical drawings.
This module provides methods to detect and extract table structures from technical drawings.
- class drawing_tools.table.core.TableLine(edge: Edge | None = None, start: Point2D | None = None, end: Point2D | None = None, tolerance: float = 0.5, span_ranges: list[tuple[float, float]] | None = None, name: str = '')#
Bases:
DessiaObjectRepresents a line segment for table detection, either from an Edge or virtual.
This class wraps line segments that are used in table structure detection, providing convenient properties for analyzing table grid patterns. Lines can be either extracted from Edge objects or created as virtual lines to complete table boundaries.
- __init__(edge: Edge | None = None, start: Point2D | None = None, end: Point2D | None = None, tolerance: float = 0.5, span_ranges: list[tuple[float, float]] | None = None, name: str = '')#
Initialize either from an Edge or from explicit coordinates.
- Parameters:
edge – Optional Edge object to extract line from
start – Start point (required if edge is None)
end – End point (required if edge is None)
tolerance – Tolerance for line classification (vertical/horizontal detection)
span_ranges – Optional custom span ranges (for merged lines with gaps)
- Raises:
ValueError – If edge is invalid or if start/end are missing when edge is None
- classmethod from_edge(edge: Edge, tolerance: float = 0.001) TableLine#
Create TableLine from an Edge object.
- Parameters:
edge – Edge containing a line segment
tolerance – Tolerance for line classification
- Returns:
TableLine instance
- classmethod virtual(start: Point2D, end: Point2D, tolerance: float = 0.001) TableLine#
Create a virtual TableLine without an associated Edge.
Virtual lines are used to complete table boundaries when detecting table structures that may have incomplete borders.
- Parameters:
start – Start point of the line
end – End point of the line
tolerance – Tolerance for line classification
- Returns:
TableLine instance marked as virtual
- property start: Point2D#
Get the start point of the line segment.
- property end: Point2D#
Get the end point of the line segment.
- property line_coordinate: float#
Get the coordinate value where this line is positioned.
For vertical lines, returns the x-coordinate. For horizontal lines, returns the y-coordinate.
- Returns:
The average coordinate along the line’s perpendicular axis
- property is_virtual: bool#
Check if this is a virtual line (no associated Edge).
Virtual lines are created to complete table boundaries and don’t correspond to actual geometry in the drawing.
- Returns:
True if this line has no associated Edge object
- merge_with(other: TableLine) TableLine#
Merge this line with another parallel line.
- Parameters:
other – Another TableLine that should be parallel to this one
- Returns:
New TableLine representing the merged result
- Raises:
ValueError – If lines are not parallel or compatible
- property gap_positions: list[tuple[float, float]]#
Get the positions of gaps in this line.
- Returns:
List of (start, end) positions where gaps exist
- property coverage_ratio: float#
Calculate the ratio of covered length to total possible length.
Useful for determining if a line is mostly continuous or has significant gaps.
- is_on_range(coord: float, tolerance: float = 0.0) bool#
Check if a coordinate falls on any span of this line.
- Parameters:
coord – y-coordinate for vertical lines, x-coordinate for horizontal
tolerance – Tolerance to extend span boundaries (handles floating-point imprecision)
- Returns:
True if the coordinate is within any span range
- class drawing_tools.table.core.TableCell(row_id: int, col_id: int, start: Point2D, end: Point2D, row_range: tuple[int, int], col_range: tuple[int, int], content: list[Entity] | None = None, name: str = '')#
Bases:
DessiaObjectRepresents a logical cell in a detected table with content.
TableCell represents the logical/semantic cells of a table, which may span multiple grid positions when merged. Each TableCell contains the actual content (text, annotations) and represents how the table appears to users.
- Example:
If a table cell spans positions (0,0) to (0,2) in the grid: - get_table_cell_at(0, 0), get_table_cell_at(0, 1), get_table_cell_at(0, 2) all return the same TableCell - This TableCell has row_range=(0,0), col_range=(0,2) and contains all content
- __init__(row_id: int, col_id: int, start: Point2D, end: Point2D, row_range: tuple[int, int], col_range: tuple[int, int], content: list[Entity] | None = None, name: str = '')#
Initialize a TableCell.
- Parameters:
row_id – Row index of the first grid position this cell occupies
col_id – Column index of the first grid position this cell occupies
start – Bottom-left corner point of the cell
end – Top-right corner point of the cell
row_range – Tuple of (start_row, end_row) indicating the cell’s row span
col_range – Tuple of (start_col, end_col) indicating the cell’s column span
content – Optional list of Entity objects (text, annotations) contained in this cell
name – Optional name for the cell
- property center: Point2D#
Get the center point of the cell.
- property bounding_rectangle: BoundingRectangle#
Convert cell to a BoundingRectangle.
- contains_entity(entity: Entity) bool#
Check if an entity belongs to this cell.
An entity belongs to a cell if its bounding rectangle center is inside the cell’s bounding rectangle.
- Parameters:
entity – The entity to check
- Returns:
True if the entity belongs to this cell
- add_content(entity: Entity) None#
Add an entity to this cell’s content.
- Parameters:
entity – The entity to add to the cell
- get_text_content(ordered: bool = True, line_tolerance: float = 2.0) list[str]#
Extract text content from all entities in this cell.
- Parameters:
ordered – If True, orders content in reading order (top-to-bottom, left-to-right)
line_tolerance – Tolerance for grouping items on the same line (in drawing units)
- Returns:
List of text strings from text-searchable entities
- get_ordered_content(line_tolerance: float = 2.0) list[Entity]#
Get cell content ordered in reading order (top-to-bottom, left-to-right).
Groups entities by line (similar Y coordinate) then sorts each line left-to-right.
- Parameters:
line_tolerance – Tolerance for grouping items on the same line
- Returns:
List of entities ordered for reading
- get_combined_text(ordered: bool = True, separator: str = ' ', line_tolerance: float = 2.0) str#
Get all text content combined into a single string.
- Parameters:
ordered – If True, orders content in reading order
separator – Separator between text elements
line_tolerance – Tolerance for grouping items on the same line
- Returns:
Combined text string
- contains_text(text: str, case_sensitive: bool = False, ordered: bool = True) bool#
Check if this cell contains the given text.
Searches through the cell’s combined text content and returns True if the specified text is found as a substring.
- Parameters:
text – The text to search for (e.g., “SAFETY CLASS”)
case_sensitive – If True, the search is case-sensitive (default: False)
ordered – If True, orders content in reading order before searching
- Returns:
True if the cell contains the text, False otherwise
- debug_content_order(line_tolerance: float = 2.0) str#
Debug method to visualize content ordering.
- Parameters:
line_tolerance – Tolerance for grouping items on the same line
- Returns:
String showing the ordering of content with positions
- plot_data_primitives(opacity: float = 0.4, detailed: bool = False, cell_color: Color | None = None) list[PlotDataObject]#
Get the plot data representation of the table cell.
- Parameters:
opacity – The opacity of the cell region.
detailed – If activated, add the cell information label (with the merge ranges when the cell spans several grid positions).
cell_color – When given, unified cell color: text content in this color, background in the same color lightened.
- class drawing_tools.table.core.GridCell(row: int, col: int, start: Point2D, end: Point2D, merge_origin_position: tuple[int, int] | None = None, name: str = '')#
Bases:
DessiaObjectRepresents a single position in the virtual grid structure.
GridCell represents a cell at a unique position in the table’s underlying grid structure. Each grid position has its own GridCell, even if it’s part of a merged logical cell. GridCell provides geometric information but does not contain content directly.
- Example:
If a TableCell spans positions (0,0) to (0,2) in the grid: - get_grid_cell_at(0, 0) returns GridCell at (0,0) with merge_origin_position=None - get_grid_cell_at(0, 1) returns GridCell at (0,1) with merge_origin_position=(0,0) - get_grid_cell_at(0, 2) returns GridCell at (0,2) with merge_origin_position=(0,0) - All three positions reference the same TableCell via get_table_cell_at()
- __init__(row: int, col: int, start: Point2D, end: Point2D, merge_origin_position: tuple[int, int] | None = None, name: str = '')#
Initialize a GridCell.
- Parameters:
row – Row index in the virtual grid (0-based)
col – Column index in the virtual grid (0-based)
start – Bottom-left corner point of this grid cell
end – Top-right corner point of this grid cell
merge_origin_position – (row, col) tuple of the first grid position if this cell is part of a merged TableCell. None if this is the first position of a logical cell.
name – Optional name for the grid cell
- property center: Point2D#
Get the center point of the grid cell.
- class drawing_tools.table.core.TableGrid(x_positions: list[float], y_positions: list[float], name: str = '')#
Bases:
DessiaObjectRepresents the virtual grid structure of a table.
- __init__(x_positions: list[float], y_positions: list[float], name: str = '') None#
Initialize the table grid.
- Parameters:
x_positions – List of x-coordinates for vertical lines
y_positions – List of y-coordinates for horizontal lines
- classmethod from_table_lines(v_lines: list[TableLine], h_lines: list[TableLine]) TableGrid#
Create a grid from a set of horizontal and vertical lines.
- plot_data_primitives(show_indices: bool = True, extra_primitives: list[PlotDataObject] | None = None) list[PlotDataObject]#
Generate plot data primitives for the virtual grid.
- Parameters:
extra_primitives – Optional plot data primitives to be integrated in the table plot
show_indices – Whether to show row/col indices
- Returns:
List of plot data primitives
- plot_data(show_indices: bool = True, extra_primitives: list[PlotDataObject] | None = None) None#
Generate plot data visualization for the virtual grid.
- Parameters:
extra_primitives – Optional plot data primitives to be integrated in the table plot
show_indices – Whether to show row/col indices
- Returns:
List of plot data primitives
- class drawing_tools.table.core.TableStructure(lines: list[TableLine], bounds: BoundingRectangle, tolerance: float = 0.001, name: str = '')#
Bases:
DessiaObjectRepresents the reverse-engineered structure of a table.
Contains organized lines, grid information, and methods to detect cells within the structure. Serves as the structural foundation for creating a DetectedTable.
- __init__(lines: list[TableLine], bounds: BoundingRectangle, tolerance: float = 0.001, name: str = '')#
Initialize by extracting structure from lines.
- Parameters:
lines – Collection of TableLine objects
bounds – Bounding rectangle of the structure
tolerance – Tolerance for line processing
- detect_cells(min_cell_size: float = 2.0, annotations: list[Entity] | None = None) list[TableCell]#
Detect TableCell objects by analyzing the grid structure and optionally populate with annotations.
- Parameters:
min_cell_size – Minimum dimension for a valid cell
annotations – Optional list of annotations to associate with cells
- Returns:
List of detected TableCell objects with their content
drawing_tools.table.detection module#
Table detection: the DetectedTable model, structure generation, and orchestration.
The pipeline’s other two phases live in their own modules:
candidate_preparation (Phase 1) and
validation (Phase 3). SheetTableDetector
instantiates and orchestrates the three phases.
- drawing_tools.table.detection.is_symbol_with_rectangle_frame(symbol_entity: Entity) bool#
Check if a Symbol entity has a rectangular frame with a valid bounding rectangle.
- Parameters:
symbol_entity – A Symbol entity to test.
- Returns:
True if the symbol has a frame with
entity_type == "RECTANGLE"and a valid bounding rectangle.
- class drawing_tools.table.detection.TableGenerationConfig(tolerance: float = 0.5, min_table_size: float = 10.0, min_cell_size: float = 2.0, min_edges_for_table: int = 4, min_lines_in_component: int = 4, intersection_tolerance: float = 0.5, min_lines_for_extent: int = 2)#
Bases:
objectConfiguration for table structure detection (Phase 2).
- class drawing_tools.table.detection.DetectedTable(structure: TableStructure, cells: list[TableCell], source: str = '', name: str = '')#
Bases:
DessiaObjectRepresents a detected table with its cells.
- __init__(structure: TableStructure, cells: list[TableCell], source: str = '', name: str = '')#
Initialize a DetectedTable.
- Parameters:
structure – The table structure containing lines and grid
cells – List of TableCell objects that make up the table
source – Origin of the table (e.g. candidate set name, “annotation”)
name – Optional name for the table
- property bounds: BoundingRectangle#
The structure’s bounding rectangle.
- property bounding_rectangle: BoundingRectangle#
Get the table’s BoundingRectangle.
- get_table_cell_at(row_index: int, column_index: int) TableCell | None#
Get the TableCell object at a specific grid position.
- get_grid_cell_at(row_index: int, column_index: int) GridCell | None#
Get the GridCell object at a specific grid position.
- find_table_cells_with_text(text: str, case_sensitive: bool = False) list[TableCell]#
Find all cells containing the given text.
Searches through all cells in the table and returns all cells that contain the specified text.
- Parameters:
text – The text to search for (e.g., “SAFETY CLASS”)
case_sensitive – If True, the search is case-sensitive (default: False)
- Returns:
List of TableCell objects containing the text
- plot_data_primitives(extra_primitives: list[PlotDataObject] | None = None, opacity: float = 0.4, detailed: bool = False) list[PlotDataObject]#
Get the plot data representation for the detected table.
Each cell gets its own color from a rotating palette (texts in the color, background in the same color lightened), showing which text was attached to which cell.
- Parameters:
extra_primitives – Optional plot data primitives to be integrated in the table plot
opacity – The opacity of the table regions.
detailed – If activated, add cells information texts (position and merge ranges).
- plot_data(extra_primitives: list[PlotDataObject] | None = None, detailed: bool = False, opacity: float = 0.4) None#
Visualize the final detected table with cells.
Each cell gets its own color from a rotating palette (texts in the color, background in the same color lightened), showing which text was attached to which cell.
- Parameters:
extra_primitives – Optional plot data primitives to be integrated in the table plot.
detailed – If activated, add cells information texts (position and merge ranges).
opacity – The opacity of the table regions.
- class drawing_tools.table.detection.TableGenerator(config: TableGenerationConfig | None = None)#
Bases:
DessiaObjectDetects tables in technical drawings by analyzing line segments.
Integrates connection analysis and orchestrates the detection process.
- __init__(config: TableGenerationConfig | None = None)#
Initialize the TableGenerator.
- Parameters:
config – Configuration for table generation
- structures: list[TableStructure]#
- detect_tables_from_edges(edges: list[Edge], annotations: list[Entity] | None = None, source: str = '') list[DetectedTable]#
Detect tables from a list of edge geometries and optionally populate with annotations.
- Parameters:
edges – List of edges that may form tables
annotations – Optional list of annotations to associate with table cells
source – Source identifier to tag on each detected table (e.g. “background_geometries”)
- Returns:
List of detected tables with populated content
- capture_generation_data(source: str, detected_tables: list[DetectedTable]) TableGenerationSetData#
Snapshot the current generator state into a
TableGenerationSetData.- Parameters:
source – Source identifier for this candidate set.
detected_tables – Tables detected from the current candidate set.
- Returns:
A data snapshot of the generation phase for this candidate set.
- class drawing_tools.table.detection.SheetTableDetector(sheet: Sheet, candidate_preparation_config: CandidatePreparationConfig | None = None, table_generation_config: TableGenerationConfig | None = None, table_selection_config: TableSelectionConfig | None = None, store_detection_data: bool = False)#
Bases:
DessiaObjectDetects and extracts table structures from technical drawing sheets.
- __init__(sheet: Sheet, candidate_preparation_config: CandidatePreparationConfig | None = None, table_generation_config: TableGenerationConfig | None = None, table_selection_config: TableSelectionConfig | None = None, store_detection_data: bool = False)#
Initialize the detector with a sheet.
- Parameters:
sheet – The sheet containing tables.
candidate_preparation_config – Configuration for candidate edge preparation (Phase 1)
table_generation_config – Configuration for table structure detection (Phase 2)
table_selection_config – Configuration for table validation and selection (Phase 3)
store_detection_data – If True, store all intermediate pipeline data for visualization/debugging. Access via
detection_dataproperty after detection.
- property tables: dict[int, list[Table | DetectedTable]]#
All detected tables (computed once on first access).
- Returns:
Dictionary mapping view index to list of detected tables.
- property detection_data: TableDetectionData#
Access stored detection data. Only available when
store_detection_data=True.
- get_title_block_annotations() list[Entity]#
Extract annotations that belong to the title block area.
Reads the content-side annotations of the memoized
reference_frame_data. Beyond-content annotations that are not validated grid labels — e.g. the drawing-number continuation strip — are available viareference_frame_data.other_beyond_content_annotationsshould title-block detection ever need to consider them.
- get_title_block_table() DetectedTable | None#
Detect the table that represents the title block in the drawing.
Reuses the memoized
tablesso that requesting the title block after (or before) the tables does not run the detection twice.
- detect_title_block() TitleBlock | None#
Detect the title block and extract structured information.
- detect_view_tables(view: View, is_background: bool = False, _view_index: int | None = None) list[Table | DetectedTable]#
Detect tables in a specific view.
This method finds tables in the view through three independent branches: 1. tables_from_tables — existing Table annotation instances 2. tables_from_notes — Symbol entities (TypeNote) with a rectangular frame 3. tables_from_geometries — edge-based detection from view geometries
- Parameters:
view – The view to search for tables in
is_background – Whether this is the background view (affects detection strategy)
_view_index – Optional view index for storing intermediate data
- Returns:
List of detected table objects (mix of Table annotations and DetectedTable instances)
- detect_tables_in_background_view() list[Table | DetectedTable]#
Detect tables specifically in the background view.
This is a convenience method that calls detect_view_tables with the background view and appropriate settings for background view processing.
- Returns:
List of detected table objects in the background view
- detect_all_tables() dict[int, list[Table | DetectedTable]]#
Detect all tables in the drawing across all views.
Every view goes through the three branches of
detect_view_tables()(Tableannotations, framedSymbolnotes, edge-based detection).The background view gets ONE extra candidate source: its own
geometries(the sheet frame layer, where the title block and the revision block live), minus the grid reference geometries. For the other views only the geometries carried byCompositeEntityannotations are candidates — their direct geometries draw the part, not tables.Edge-based tables are validated to ensure they have sufficient content before being included.
- Returns:
Dictionary mapping view index to list of validated detected tables
- get_tables_summary(include_validation_stats: bool = False) dict[str, Any]#
Get a summary of all detected tables in the drawing.
- Parameters:
include_validation_stats – If True, also include statistics about invalid tables
- Returns:
Dictionary with summary statistics and details
- collect_overlay_primitives() list[PlotDataObject]#
Build overlay primitives for all detected tables and the title block.
Thin delegate: the rendering lives with the other table visualizations in
collect_table_overlay_primitives().- Returns:
List of plot_data primitives.
drawing_tools.table.detection_data module#
Intermediate data storage for the table detection pipeline.
When SheetTableDetector is created with store_detection_data=True,
every pipeline stage populates a TableDetectionData instance so that
visualisation and debugging can happen after detection without re-running
the pipeline.
- class drawing_tools.table.detection_data.CandidatePreparationSetData(source: str = '', content_geometries: list[Edge] = <factory>, line_segments: list[Edge] = <factory>, filtered_edges: list[Edge] = <factory>, excluded_edges: list[Edge] = <factory>, connectivity_debug_info: dict[str, ~typing.Any] | None=None)#
Bases:
objectPhase 1 intermediate data for a single candidate set.
Stores content geometries extracted from a view source (background geometries or CompositeEntity), the H/V line segments found, and the results of connectivity density filtering.
- store_filtering_results(line_segments: list[Edge], filtered: list[Edge], debug_info: dict[str, Any] | None = None) None#
Populate filtering results from the connectivity density filter.
- Parameters:
line_segments – H/V line segments extracted from content geometries.
filtered – Edges that passed the connectivity filter.
debug_info – Optional debug info from the filter.
- class drawing_tools.table.detection_data.TableGenerationSetData(source: str = '', structural_lines: list[TableLine] = <factory>, excluded_lines: list[TableLine] = <factory>, structures: list[TableStructure] = <factory>, detected_tables: list[DetectedTable] = <factory>)#
Bases:
objectPhase 2 intermediate data for a single candidate set.
Stores the output of
TableGeneratorafter runningdetect_tables_from_edgeson one candidate set’s filtered edges.- structures: list[TableStructure]#
- detected_tables: list[DetectedTable]#
- class drawing_tools.table.detection_data.CandidatePreparationData(sets: list[CandidatePreparationSetData] = <factory>)#
Bases:
objectPhase 1: Candidate preparation data across all candidate sets of a view.
- sets: list[CandidatePreparationSetData]#
- __init__(sets: list[CandidatePreparationSetData] = <factory>) None#
- class drawing_tools.table.detection_data.GeneratedTablesData(sets: list[TableGenerationSetData] = <factory>)#
Bases:
objectPhase 2: Table generation results for a view.
- sets: list[TableGenerationSetData]#
- property all_structures: list[TableStructure]#
All TableStructures across candidate sets.
- __init__(sets: list[TableGenerationSetData] = <factory>) None#
- class drawing_tools.table.detection_data.ValidatedTablesData(tables: list[TableType] = <factory>)#
Bases:
objectPhase 3: Validated tables for a view.
- class drawing_tools.table.detection_data.ViewDetectionData(view_index: int = 0, is_background: bool = False, candidates: CandidatePreparationData = <factory>, generation: GeneratedTablesData = <factory>, tables_from_tables: list[TableType] = <factory>, tables_from_notes: list[DetectedTable] = <factory>, tables_from_geometries: list[DetectedTable] = <factory>, validation: ValidatedTablesData = <factory>)#
Bases:
objectAll intermediate data for a single view’s detection pass.
- candidates: CandidatePreparationData#
- generation: GeneratedTablesData#
- tables_from_notes: list[DetectedTable]#
- tables_from_geometries: list[DetectedTable]#
- validation: ValidatedTablesData#
- __init__(view_index: int = 0, is_background: bool = False, candidates: CandidatePreparationData = <factory>, generation: GeneratedTablesData = <factory>, tables_from_tables: list[TableType] = <factory>, tables_from_notes: list[DetectedTable] = <factory>, tables_from_geometries: list[DetectedTable] = <factory>, validation: ValidatedTablesData = <factory>) None#
- class drawing_tools.table.detection_data.TableSelectionData(title_block_table: DetectedTable | None = None)#
Bases:
objectCross-view selection results: title block identification.
- title_block_table: DetectedTable | None = None#
- __init__(title_block_table: DetectedTable | None = None) None#
- class drawing_tools.table.detection_data.TableDetectionData(views: dict[int, ~drawing_tools.table.detection_data.ViewDetectionData]=<factory>, selection: TableSelectionData = <factory>)#
Bases:
objectTop-level container for all pipeline intermediate data.
Populated by
SheetTableDetectorwhenstore_detection_data=True.- views: dict[int, ViewDetectionData]#
- selection: TableSelectionData#
- get_view_data(view_index: int) ViewDetectionData | None#
Get detection data for any view by index.
- __init__(views: dict[int, ~drawing_tools.table.detection_data.ViewDetectionData]=<factory>, selection: TableSelectionData = <factory>) None#
drawing_tools.table.title_block module#
Title block extraction from detected tables.
- class drawing_tools.table.title_block.TitleBlockExtractor(detected_table: DetectedTable, line_tolerance: float = 2.0)#
Bases:
objectExtracts title block information from a DetectedTable.
Uses pattern matching and keyword search to identify fields.
- MIN_TITLE_LENGTH = 5#
- __init__(detected_table: DetectedTable, line_tolerance: float = 2.0)#
Initialize the extractor with a detected table.
- Parameters:
detected_table – The table containing title block information
line_tolerance – Tolerance for grouping text items on the same line
- extract(debug: bool = False) TitleBlock#
Extract title block information from the table.
- Parameters:
debug – If True, print debug information about content ordering
- Returns:
TitleBlock instance with extracted information
drawing_tools.table.utils module#
Utility functions for table detection and text processing.
This module provides sophisticated filtering of line segments based on their spatial density and connectivity patterns, useful for isolating structured elements like tables from scattered individual lines.
- class drawing_tools.table.utils.ConnectivityFilterConfig(threshold_ratio: float = 0.2, use_elliptical: bool = True, std_deviation_factor: float = 1.2, debug_visualization: bool = False, output_path: str = 'connectivity_filter_debug.html')#
Bases:
objectConfiguration for connectivity density filtering.
- Parameters:
threshold_ratio – Base ratio for threshold calculation (0.2 = 20%)
use_elliptical – Use elliptical neighborhoods (True) or rectangular (False)
std_deviation_factor – Multiplier for standard deviation in threshold calculation. Higher values lower the min_neighbors threshold, making the filter more permissive. Formula: min_neighbors = max(1, int(avg - factor * std))
debug_visualization – Enable debug visualization output
output_path – Path for debug visualization file
- class drawing_tools.table.utils.ConnectivityDensityFilter(drawing_width: float, drawing_height: float, config: ConnectivityFilterConfig | None = None)#
Bases:
objectAdvanced connectivity density filter for isolating connected line structures.
This filter analyzes spatial relationships between lines and removes isolated or sparsely connected lines, keeping only densely connected clusters that likely represent structured elements like table grids.
Features: - Adaptive thresholds based on drawing aspect ratio - Elliptical or rectangular neighborhood analysis - Statistical filtering using standard deviation - Comprehensive debug visualization capabilities
- MIN_LINES_FOR_PROCESSING = 3#
- MIN_LINES_FOR_TABLE = 4#
- __init__(drawing_width: float, drawing_height: float, config: ConnectivityFilterConfig | None = None)#
Initialize the connectivity density filter.
- Parameters:
drawing_width – Width of the drawing for threshold calculation
drawing_height – Height of the drawing for threshold calculation
config – Configuration object with filtering parameters
- filter(lines: list[Edge], store_debug_info: bool = False) list[Edge]#
Apply connectivity density filtering to the provided lines.
- Parameters:
lines – List of line edges to filter
store_debug_info – If True, store debug info without generating visualization. Access via
debug_infoproperty after calling this method.
- Returns:
Filtered list of lines with sufficient connectivity density
drawing_tools.table.validation module#
Table validation and selection (Phase 3): which tables to keep and why.
The TableValidator runs the selection criteria over the raw tables produced
by the generation phase. TableValidator.validation_failure() is the single
source of truth for the criteria, their order and their config gates: both the
pass/fail verdict and the rejection reasons (logs, validation statistics) derive
from it.
- class drawing_tools.table.validation.TableSelectionConfig(min_content_ratio: float = 0.3, max_sheet_coverage_ratio: float = 0.8, min_nb_cells: int = 2, validate_has_cells: bool = True, validate_sheet_coverage: bool = True, validate_content_ratio: bool = True)#
Bases:
objectConfiguration for table validation and selection (Phase 3).
- class drawing_tools.table.validation.TableValidator(sheet_area: float, config: TableSelectionConfig | None = None)#
Bases:
objectValidates detected tables against the selection criteria of a sheet.
- __init__(sheet_area: float, config: TableSelectionConfig | None = None)#
Initialize the validator.
- Parameters:
sheet_area – Area of the sheet, for the coverage-ratio criterion.
config – Configuration for table validation and selection.
- validation_failure(table: DetectedTable) str | None#
Run the validation checks and name the first failing one.
Single source of truth for the criteria, their order and their config gates: both the pass/fail verdict (
is_valid_table()) and the rejection reasons (logs, validation statistics) derive from it.- Parameters:
table – The DetectedTable to validate
- Returns:
The failing check’s reason, or None when the table is valid.
- is_valid_table(table: DetectedTable) bool#
Validate if a detected table is actually a valid table.
- Parameters:
table – The DetectedTable to validate
- Returns:
True if the table is valid, False otherwise
- filter_valid_tables(raw_tables: list[DetectedTable]) list[DetectedTable]#
Silently keep the tables that pass validation (no logging: diagnostic paths).
- Parameters:
raw_tables – Unvalidated tables.
- Returns:
The tables that pass
is_valid_table().
- validate_raw_tables(raw_tables: list[DetectedTable]) list[DetectedTable]#
Filter raw tables through validation, keeping the losses observable.
Rejection is routine (the connectivity peeling deliberately produces candidate groups that are not tables), so each rejected table is logged at DEBUG and a single aggregated WARNING per call summarizes the counts and reasons. Rejections used to be completely silent, only visible by re-running with
SheetTableDetector(store_detection_data=True).- Parameters:
raw_tables – Unvalidated tables from the generation phase.
- Returns:
The tables that pass
is_valid_table().
Module contents#
Table extraction from dessia_drawing package.
- class drawing_tools.table.SheetTableDetector(sheet: Sheet, candidate_preparation_config: CandidatePreparationConfig | None = None, table_generation_config: TableGenerationConfig | None = None, table_selection_config: TableSelectionConfig | None = None, store_detection_data: bool = False)#
Bases:
DessiaObjectDetects and extracts table structures from technical drawing sheets.
- __init__(sheet: Sheet, candidate_preparation_config: CandidatePreparationConfig | None = None, table_generation_config: TableGenerationConfig | None = None, table_selection_config: TableSelectionConfig | None = None, store_detection_data: bool = False)#
Initialize the detector with a sheet.
- Parameters:
sheet – The sheet containing tables.
candidate_preparation_config – Configuration for candidate edge preparation (Phase 1)
table_generation_config – Configuration for table structure detection (Phase 2)
table_selection_config – Configuration for table validation and selection (Phase 3)
store_detection_data – If True, store all intermediate pipeline data for visualization/debugging. Access via
detection_dataproperty after detection.
- property tables: dict[int, list[Table | DetectedTable]]#
All detected tables (computed once on first access).
- Returns:
Dictionary mapping view index to list of detected tables.
- property detection_data: TableDetectionData#
Access stored detection data. Only available when
store_detection_data=True.
- get_title_block_annotations() list[Entity]#
Extract annotations that belong to the title block area.
Reads the content-side annotations of the memoized
reference_frame_data. Beyond-content annotations that are not validated grid labels — e.g. the drawing-number continuation strip — are available viareference_frame_data.other_beyond_content_annotationsshould title-block detection ever need to consider them.
- get_title_block_table() DetectedTable | None#
Detect the table that represents the title block in the drawing.
Reuses the memoized
tablesso that requesting the title block after (or before) the tables does not run the detection twice.
- detect_title_block() TitleBlock | None#
Detect the title block and extract structured information.
- detect_view_tables(view: View, is_background: bool = False, _view_index: int | None = None) list[Table | DetectedTable]#
Detect tables in a specific view.
This method finds tables in the view through three independent branches: 1. tables_from_tables — existing Table annotation instances 2. tables_from_notes — Symbol entities (TypeNote) with a rectangular frame 3. tables_from_geometries — edge-based detection from view geometries
- Parameters:
view – The view to search for tables in
is_background – Whether this is the background view (affects detection strategy)
_view_index – Optional view index for storing intermediate data
- Returns:
List of detected table objects (mix of Table annotations and DetectedTable instances)
- detect_tables_in_background_view() list[Table | DetectedTable]#
Detect tables specifically in the background view.
This is a convenience method that calls detect_view_tables with the background view and appropriate settings for background view processing.
- Returns:
List of detected table objects in the background view
- detect_all_tables() dict[int, list[Table | DetectedTable]]#
Detect all tables in the drawing across all views.
Every view goes through the three branches of
detect_view_tables()(Tableannotations, framedSymbolnotes, edge-based detection).The background view gets ONE extra candidate source: its own
geometries(the sheet frame layer, where the title block and the revision block live), minus the grid reference geometries. For the other views only the geometries carried byCompositeEntityannotations are candidates — their direct geometries draw the part, not tables.Edge-based tables are validated to ensure they have sufficient content before being included.
- Returns:
Dictionary mapping view index to list of validated detected tables
- get_tables_summary(include_validation_stats: bool = False) dict[str, Any]#
Get a summary of all detected tables in the drawing.
- Parameters:
include_validation_stats – If True, also include statistics about invalid tables
- Returns:
Dictionary with summary statistics and details
- collect_overlay_primitives() list[PlotDataObject]#
Build overlay primitives for all detected tables and the title block.
Thin delegate: the rendering lives with the other table visualizations in
collect_table_overlay_primitives().- Returns:
List of plot_data primitives.