@@ -657,148 +657,7 @@ def _get_text_confidence_data(self, page) -> str:
657657 raise
658658 return ""
659659
660- def _convert_bbox_to_geometry (
661- self , bbox_coords : list [float ], page_num : int
662- ) -> dict [str , Any ]:
663- """
664- Convert [x1,y1,x2,y2] coordinates to geometry format.
665-
666- Args:
667- bbox_coords: list of 4 coordinates [x1, y1, x2, y2] in 0-1000 scale
668- page_num: Page number where the bounding box appears
669-
670- Returns:
671- dictionary in geometry format compatible with pattern-1 UI
672- """
673- if len (bbox_coords ) != 4 :
674- raise ValueError (f"Expected 4 coordinates, got { len (bbox_coords )} " )
675-
676- x1 , y1 , x2 , y2 = bbox_coords
677-
678- # Ensure coordinates are in correct order
679- x1 , x2 = min (x1 , x2 ), max (x1 , x2 )
680- y1 , y2 = min (y1 , y2 ), max (y1 , y2 )
681-
682- # Convert from normalized 0-1000 scale to 0-1
683- left = x1 / 1000.0
684- top = y1 / 1000.0
685- width = (x2 - x1 ) / 1000.0
686- height = (y2 - y1 ) / 1000.0
687-
688- return {
689- "boundingBox" : {"top" : top , "left" : left , "width" : width , "height" : height },
690- "page" : page_num ,
691- }
692-
693- def _process_single_assessment_geometry (
694- self , attr_assessment : dict [str , Any ], attr_name : str = ""
695- ) -> dict [str , Any ]:
696- """
697- Process geometry data for a single assessment (with confidence key).
698-
699- Args:
700- attr_assessment: Single assessment dictionary with confidence data
701- attr_name: Name of attribute for logging
702-
703- Returns:
704- Enhanced assessment with geometry converted to proper format
705- """
706- enhanced_attr = attr_assessment .copy ()
707-
708- # Check if this assessment includes bbox data
709- if "bbox" in attr_assessment or "page" in attr_assessment :
710- # Both bbox and page are required for valid geometry
711- if "bbox" in attr_assessment and "page" in attr_assessment :
712- try :
713- bbox_coords = attr_assessment ["bbox" ]
714- page_num = attr_assessment ["page" ]
715-
716- # Validate bbox coordinates
717- if isinstance (bbox_coords , list ) and len (bbox_coords ) == 4 :
718- # Convert to geometry format
719- geometry = self ._convert_bbox_to_geometry (bbox_coords , page_num )
720- enhanced_attr ["geometry" ] = [geometry ]
721-
722- logger .debug (
723- f"Converted bounding box for { attr_name } : { bbox_coords } -> geometry format"
724- )
725- else :
726- logger .warning (
727- f"Invalid bounding box format for { attr_name } : { bbox_coords } "
728- )
729- except Exception as e :
730- logger .warning (
731- f"Failed to process bounding box for { attr_name } : { str (e )} "
732- )
733- raise
734- else :
735- # If only one of bbox/page exists, log a warning about incomplete data
736- if "bbox" in attr_assessment and "page" not in attr_assessment :
737- logger .warning (
738- f"Found bbox without page for { attr_name } - removing incomplete bbox data"
739- )
740- elif "page" in attr_assessment and "bbox" not in attr_assessment :
741- logger .warning (
742- f"Found page without bbox for { attr_name } - removing incomplete page data"
743- )
744-
745- # Always remove raw bbox/page data from output (whether processed or incomplete)
746- enhanced_attr .pop ("bbox" , None )
747- enhanced_attr .pop ("page" , None )
748-
749- return enhanced_attr
750-
751- def _extract_geometry_from_assessment (
752- self , assessment_data : dict [str , Any ]
753- ) -> dict [str , Any ]:
754- """
755- Extract geometry data from assessment response and convert to proper format.
756- Now supports recursive processing of nested group attributes.
757-
758- Args:
759- assessment_data: Dictionary containing assessment results from LLM
760-
761- Returns:
762- Enhanced assessment data with geometry information converted to proper format
763- """
764- enhanced_assessment = {}
765-
766- for attr_name , attr_assessment in assessment_data .items ():
767- if isinstance (attr_assessment , dict ):
768- # Check if this is a direct confidence assessment
769- if "confidence" in attr_assessment :
770- # This is a direct assessment - process its geometry
771- enhanced_assessment [attr_name ] = (
772- self ._process_single_assessment_geometry (
773- attr_assessment , attr_name
774- )
775- )
776- else :
777- # This is a group attribute (no direct confidence) - recursively process nested attributes
778- logger .debug (f"Processing group attribute: { attr_name } " )
779- enhanced_assessment [attr_name ] = (
780- self ._extract_geometry_from_assessment (attr_assessment )
781- )
782-
783- elif isinstance (attr_assessment , list ):
784- # Handle list attributes - process each item recursively
785- enhanced_list = []
786- for i , item_assessment in enumerate (attr_assessment ):
787- if isinstance (item_assessment , dict ):
788- # Recursively process each list item
789- enhanced_item = self ._extract_geometry_from_assessment (
790- item_assessment
791- )
792- enhanced_list .append (enhanced_item )
793- else :
794- # Non-dict items pass through unchanged
795- enhanced_list .append (item_assessment )
796- enhanced_assessment [attr_name ] = enhanced_list
797- else :
798- # Other types pass through unchanged
799- enhanced_assessment [attr_name ] = attr_assessment
800-
801- return enhanced_assessment
660+ # Geometry processing uses shared utilities from geometry_utils module
802661
803662 def process_document_section (self , document : Document , section_id : str ) -> Document :
804663 """
0 commit comments