ó
    À‘´j90  ã                  óp  • S r SSKJr  SSKrSSKJrJr  SSKJr  SSK	J
r
JrJrJrJrJr  \
(       a  SSKJr  SSKJr  SS	KJr  SS
KJrJr  SSKJr  SSKJrJr  \\\\\4   r " S S\5      r  " S S\5      r! " S S\5      r" " S S\5      r#\ " S S5      5       r$SS jr%SS jr&SS jr'SS jr(S S jr)g)!u‘  The output contract a `Parser` hands back: the document plus the signals
docling produces alongside it.

`result.document` is the DoclingDocument. Four more fields ride with it. The
fusion step reads only `pages` and `table_provenance`:

- `confidence` â€” docling's own confidence report, taken straight from
  `ConversionResult.confidence`. It is held in memory only. `save` does not
  write it and `load` leaves it `None`.
- `page_scores` â€” the per-page parse/layout/table/ocr scores copied out of that
  report. They are written to `<base>.confidence.json` and reloaded, but no code
  outside this module reads them.
- `pages` â€” the parsed-page cells (`text`, top-left box, `from_ocr`,
  `confidence`), one list per page. docling frees these after assembling the
  document unless `generate_parsed_pages=True`; capturing them is what makes the
  OCR-vs-native signal available downstream.
- `table_provenance` â€” derived once per table from the cells under its box: the
  fraction read by OCR, the mean OCR confidence, and a native/ocr/empty verdict.
  A table whose region carries no native text layer (verdict `ocr`, or `empty`
  when Camelot also finds nothing) is a table rendered as an image.

Parsed cells are stored top-left in PDF points. A table's box stays in the
DoclingDocument in docling's own coordinate origin. `_table_provenance` flips it
to top-left only while comparing it with the cells under it.
é    )ÚannotationsN)Ú	dataclassÚfield)ÚPath)ÚTYPE_CHECKINGÚDictÚListÚLiteralÚOptionalÚTuple)ÚConfidenceReport)ÚConversionResult)ÚCoordOrigin)ÚDoclingDocumentÚ	TableItem)ÚBoundingRectangle)Ú	BaseModelÚFieldc                  óh   • \ rS rSr% SrS\S'   \" SS9rS\S'   \" S	S9rS
\S'   \" SSS9r	S\S'   Sr
g)Ú
ParsedCellé3   z6One parsed-page text cell, box in top-left PDF points.ÚstrÚtextz-(x0, y0, x1, y1), top-left origin, PDF points©ÚdescriptionÚBoxÚboxz1True if docling read this cell off the page imageÚboolÚfrom_ocrç        z%docling's OCR confidence for the cell)Údefaultr   ÚfloatÚ
confidence© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__r   r   r   r#   Ú__static_attributes__r$   ó    Ú7/home/mande/repo/quber/src/quber/core/parsers/result.pyr   r   3   s<   ‡ Ù@à
ƒIÙÐ!PÑQ€CˆÓQÙÐ'ZÑ[€HˆdÓ[Ù cÐ7^Ñ_€J�Ö_r,   r   c                  óN   • \ rS rSr% SrS\S'   S\S'   S\S'   \" \S9rS	\S
'   Sr	g)Ú	PageParseé<   zEThe parsed-page cells for one page, with the page's point dimensions.ÚintÚpage_nor"   ÚwidthÚheight©Údefault_factoryzList[ParsedCell]Úcellsr$   N)
r%   r&   r'   r(   r)   r*   r   Úlistr7   r+   r$   r,   r-   r/   r/   <   s$   ‡ ÙOàƒLØƒLØƒMÙ#°DÑ9€EÐÖ9r,   r/   c                  óL   • \ rS rSr% SrS\S'   S\S'   S\S'   S\S'   S\S	'   S
rg)Ú	PageScoreéE   zGdocling's per-page confidence scores (NaN where docling did not score).r1   r2   r"   Úparse_scoreÚlayout_scoreÚtable_scoreÚ	ocr_scorer$   N)r%   r&   r'   r(   r)   r*   r+   r$   r,   r-   r:   r:   E   s"   ‡ ÙQàƒLØÓØÓØÓØÖr,   r:   c                  ó’   • \ rS rSr% Sr\" SS9rS\S'   S\S'   \" S	S9rS\S
'   \" SS9r	S\S'   \" SS9r
S\S'   \" SS9rS\S'   Srg)ÚTableProvenanceéO   zJOCR-vs-native verdict for one docling table, from the cells under its box.z0The TableItem.self_ref this provenance describesr   r   Úself_refr1   r2   z5Parsed-page cells whose center falls in the table boxÚ
cell_countz+Fraction of those cells docling read by OCRr"   Úfrom_ocr_fractionz'Mean confidence over the OCR-read cellsÚmean_ocr_confidencezœnative: the table box has a real text layer. ocr: docling read it off the page image (a table rendered as an image). empty: no cells fall in the box at all.z!Literal['native', 'ocr', 'empty']Úverdictr$   N)r%   r&   r'   r(   r)   r   rC   r*   rD   rE   rF   rG   r+   r$   r,   r-   rA   rA   O   sc   ‡ ÙTáÐ&XÑY€HˆcÓYØƒLÙÐ(_Ñ`€J�Ó`Ù$Ð1^Ñ_Ð�uÓ_Ù!&Ð3\Ñ!]Ð˜Ó]Ù16ðñ2€GÐ.ö r,   rA   c                  ó°   • \ rS rSr% SrS\S'   SrS\S'   \" \S9r	S	\S
'   \" \S9r
S\S'   \" \S9rS\S'   SS jrSS jr\SS j5       r\SS j5       rSrg)ÚParseResulté`   zýEverything one parse produced: the document and docling's side signals.

`document` is the canonical IR. The rest is docling's confidence report, the
per-page scores, the parsed-page cells, and the per-table OCR/native verdict
derived from those cells.
r   ÚdocumentNzOptional[ConfidenceReport]r#   r5   zList[PageScore]Úpage_scoresúList[PageParse]ÚpagesúList[TableProvenance]Útable_provenancec                óZ   • U R                    Vs0 s H  oR                  U_M     sn$ s  snf )z3Per-table provenance keyed by `TableItem.self_ref`.)rP   rC   )ÚselfÚps     r-   Úprovenance_by_refÚParseResult.provenance_by_refo   s(   € à'+×'<Ò'<Ó=Ò'< !—
‘
˜A’Ñ'<Ñ=Ð=ùÒ=s   �(c           
     ó@  • UR                  SSS9  X S3-  nX S3-  nX S3-  nU R                  R                  U5        UR                  [        R
                  " U R                   Vs/ s H  ofR                  5       PM     snU R                   Vs/ s H  owR                  5       PM     snS.S[        S9S	S
9  UR                  [        R
                  " U R                   Vs/ s H  owR                  5       PM     snS[        S9S	S
9  X4US.$ s  snf s  snf s  snf )u©  Write the parse artifacts under `directory`, named from `base`.

Three files form the document step's artifact contract â€” the seam the
fusion step (and a later cloud job) reloads:

- `<base>.docling.json` â€” the DoclingDocument.
- `<base>.confidence.json` â€” per-page scores + per-table provenance.
- `<base>.cells.json` â€” the parsed-page cells.

Returns the written paths keyed by `document` / `confidence` / `cells`.
T)ÚparentsÚexist_okú.docling.jsonú.confidence.jsonú.cells.json)rL   rP   é   )Úindentr!   zutf-8)Úencoding)rK   r#   r7   )ÚmkdirrK   Úsave_as_jsonÚ
write_textÚjsonÚdumpsrL   Ú
model_dumprP   r   rN   )rR   Ú	directoryÚbaseÚdocument_pathÚconfidence_pathÚ
cells_pathÚsrS   s           r-   ÚsaveÚParseResult.saves   s  € ð 	�‰ ¨tˆÑ4Ø! f¨MÐ$:Ñ:ˆØ#¨Ð.>Ð&?Ñ?ˆØ 6¨Ð!5Ñ5ˆ
à�‰×"Ñ" =Ô1Ø×"Ñ"Ü�JŠJà<@×<LÒ<LÓ#MÒ<L°q§L¡L¦NÑ<LÑ#MØAE×AVÒAVÓ(WÒAV¸A¯©®ÑAVÑ(Wñð Üñð ð 	#ñ 
	
ð 	×ÑÜ�JŠJ°·
²
Ó;²
¨1Ÿ™ž±
Ñ;ÀAÌsÑSØð 	ñ 	
ð *ÐS]Ñ^Ð^ùò $NùÚ(Wùò <s   Á*DÂDÃ%Dc                óð  • [         R                  " X S3-  5      n[        R                  " X S3-  R	                  5       5      nUR                  S/ 5       Vs/ s H  n[        S0 UD6PM     nnUR                  S/ 5       Vs/ s H  n[        S0 UD6PM     nn[        R                  " X S3-  R	                  5       5      n	U	 Vs/ s H  n[        S0 UD6PM     n
nU " USUU
US9$ s  snf s  snf s  snf )	a  Reconstruct a ParseResult from artifacts written by `save`.

The `confidence` object is not restored. The document, page scores, page
cells, and per-table provenance round-trip exactly. The fusion step reads
the document, the page cells, and the per-table provenance.
rY   rZ   rL   rP   r[   N©rK   r#   rL   rN   rP   r$   )	r   Úload_from_jsonrb   ÚloadsÚ	read_textÚgetr:   rA   r/   )Úclsre   rf   rK   Úconfidence_blobrj   rL   rS   rP   Ú
cells_blobrN   s              r-   ÚloadÚParseResult.load–   sû   € ô #×1Ò1°)ÀÀmÐ>TÑ2TÓUˆÜŸ*š* i°FÐ:JÐ2KÑ&K×%VÑ%VÓ%XÓYˆØ/>×/BÑ/BÀ=ÐRTÔ/UÓVÒ/U¨!”y‘~ 1”~Ñ/UˆÐVØ:I×:MÑ:MÐN`ÐbdÔ:eÓfÒ:e°QœOÑ0¨aÔ0Ñ:eÐÐfÜ—Z’Z ¨v°[Ð-AÑ!A× LÑ LÓ NÓOˆ
Ù)3Ó4ª A”‘˜Q”©ˆÐ4ÙØØØ#ØØ-ñ
ð 	
ùò	 WùÚfùâ4s   ÁC)ÂC.ÃC3c                óJ  • UR                   n/ nUR                  bz  [        UR                  R                  R	                  5       5       HI  u  pEUR                  [        UUR                  UR                  UR                  UR                  S95        MK     / nUR                   HÙ  nUR                  (       a  UR                  R                  OSnUR                  (       a  UR                  R                  OSn	UR                   V
s/ s HI  n
[        U
R                   [#        U
R$                  5      U
R&                  U
R                  =(       d    SS9PMK     nn
UR                  [)        UR*                  X‰US95        MÛ     [-        X&5      nU " UUR                  UUUS9$ s  sn
f )aV  Build a ParseResult from a docling ConversionResult.

Reads the per-page scores and the parsed-page cells off the result, then
derives the per-table provenance from the cells under each table box.
Requires the converter to have run with `generate_parsed_pages=True`;
without it `result.pages[i].cells` is empty and every table reads `empty`.
)r2   r<   r=   r>   r?   r    )r   r   r   r#   )r2   r3   r4   r7   rn   )rK   r#   ÚsortedrN   ÚitemsÚappendr:   r<   r=   r>   r?   Úsizer3   r4   r7   r   r   Ú_cell_box_top_leftÚrectr   r/   r2   Úderive_table_provenance)rs   ÚresultrK   rL   r2   ÚscoresrN   Úpager3   r4   Úcellr7   Ú
provenances                r-   Úfrom_conversionÚParseResult.from_conversion¬   sg  € ð —?‘?ˆà')ˆØ×ÑÑ(Ü#)¨&×*;Ñ*;×*AÑ*A×*GÑ*GÓ*IÖ#J‘�Ø×"Ñ"ÜØ 'Ø$*×$6Ñ$6Ø%+×%8Ñ%8Ø$*×$6Ñ$6Ø"(×"2Ñ"2ñöñ $Kð "$ˆØ—L”LˆDØ'+§y§y�D—I‘I—O’O°cˆEØ)-¯¯�T—Y‘Y×%Ò%¸ˆFð !ŸJšJóò '�Dô ØŸ™Ü*¨4¯9©9Ó5Ø!Ÿ]™]Ø#Ÿ™×5°#ô	ñ 'ð ð ð �L‰Lœ¨4¯<©<¸uÐ[`ÑaÖbñ !ô -¨XÓ=ˆ
áØØ×(Ñ(Ø#ØØ'ñ
ð 	
ùòs   ÄAF r$   )ÚreturnzDict[str, TableProvenance])re   r   rf   r   r‡   zDict[str, Path])re   r   rf   r   r‡   ú'ParseResult')r€   r   r‡   rˆ   )r%   r&   r'   r(   r)   r*   r#   r   r8   rL   rN   rP   rT   rk   Úclassmethodrv   r…   r+   r$   r,   r-   rI   rI   `   s}   ‡ ñð ÓØ-1€JÐ*Ó1Ù#(¸Ñ#>€K�Ó>Ù"°4Ñ8€Eˆ?Ó8Ù.3ÀDÑ.IÐÐ+ÓIô>ô!_ðF ó
ó ð
ð* ó.
ó ó.
r,   rI   c                ó¾   • U Vs0 s H  o"R                   U_M     nnU R                   Vs/ s H   oDR                  (       d  M  [        XC5      PM"     sn$ s  snf s  snf )aV  The OCR-versus-native verdict for every table in `document`.

Purely geometric: each table's box is compared against the parsed-page cells
it encloses. It runs once, in `ParseResult.from_conversion`, on the document
docling just produced. Fusion looks the stored verdicts up by each table's
parse-time `self_ref` through `provenance_by_ref`.
)r2   ÚtablesÚprovÚ_table_provenance)rK   rN   rS   Úpages_by_noÚtables        r-   r   r   Þ   sN   € ñ */Ó/ª A—9‘9˜a’<©€KÐ/Ø?G¿ºÓ]º°e×R\ÕR\Ó1Ô˜eÖ1¹Ñ]Ð]ùò 0ùÚ]s   …A«AÁAc                ó  • U R                   U R                  U R                  U R                  /nU R                  U R
                  U R                  U R                  /n[        U5      [        U5      [        U5      [        U5      4$ )zMA parsed-cell rectangle (four corner points) -> a top-left (x0,y0,x1,y1) box.)
Úr_x0Úr_x1Úr_x2Úr_x3Úr_y0Úr_y1Úr_y2Úr_y3ÚminÚmax)r~   ÚxsÚyss      r-   r}   r}   ê   s]   € à
�)‰)�T—Y‘Y §	¡	¨4¯9©9Ð	5€BØ
�)‰)�T—Y‘Y §	¡	¨4¯9©9Ð	5€BÜ�‹G”S˜“Wœc "›g¤s¨2£wÐ/Ð/r,   c                ó0  • U R                   S   R                  nUR                  [        R                  :X  a.  UR
                  UR                  UR                  UR                  4$ UR
                  XR                  -
  UR                  XR                  -
  4$ )zÅA table's provenance bbox -> a top-left (x0,y0,x1,y1) box in PDF points.

docling table boxes are bottom-left origin; flip y against the page height so
they share the parsed cells' top-left frame.
r   )	rŒ   ÚbboxÚcoord_originr   ÚTOPLEFTÚlÚtÚrÚb)r�   Úpage_heightrž   s      r-   Ú_table_box_top_leftr¦   ñ   so   € ð �:‰:�a‰=×Ñ€DØ×ÑœK×/Ñ/Ó/Ø—‘˜Ÿ™ §¡¨¯©Ð/Ð/Ø�F‰F�K§&¡&Ñ(¨$¯&©&°+ÇÁÑ2FÐGÐGr,   c                ó(  • U S   U S   -   S-  U S   U S   -   S-  p2[        US   US   5      [        US   US   5      [        US   US   5      [        US   US   5      4u  pEpgXBs=:*  =(       a    U:*  Os  =(       a    XSs=:*  =(       a    U:*  $ s  $ )Nr   r\   é   é   )r™   rš   )r   ÚregionÚcxÚcyÚx0Úy0Úx1Úy1s           r-   Ú
_center_inr±   ý   s    € Ø�!‰f�s˜1‘v‰o Ñ" S¨¡V¨c°!©f¡_¸Ñ$9ˆäˆF�1‰I�v˜a‘yÓ!ÜˆF�1‰I�v˜a‘yÓ!ÜˆF�1‰I�v˜a‘yÓ!ÜˆF�1‰I�v˜a‘yÓ!ð	�N€BˆBð �>‹>�rŒ>×,˜bŸn›n¨"™nÐ,™nÐ,r,   c           	     óp  • U R                   S   R                  nUR                  U5      nU R                  nUc  [	        UUSSSSS9$ [        XR                  5      nUR                   Vs/ s H"  n[        UR                  U5      (       d  M   UPM$     nnU(       d  [	        UUSSSSS9$ U Vs/ s H  ofR                  (       d  M  UPM     nn[        U5      [        U5      -  n	U(       a  [        S U 5       5      [        U5      -  OSn
U	S:”  a  SOSn[	        UU[        U5      U	U
US9$ s  snf s  snf )	zIDerive the OCR/native verdict for one table from the cells under its box.r   r    Úempty)rC   r2   rD   rE   rF   rG   c              3  ó8   #   • U  H  oR                   v •  M     g 7f)N)r#   )Ú.0Úcs     r-   Ú	<genexpr>Ú$_table_provenance.<locals>.<genexpr>&  s   é € Ð5ª9 a—\–\ª9ùs   ‚g      à?ÚocrÚnative)rŒ   r2   rr   rC   rA   r¦   r4   r7   r±   r   r   ÚlenÚsum)r�   rŽ   r2   r‚   rC   rª   r¶   ÚunderÚ	ocr_cellsrE   Ú	mean_confrG   s               r-   r�   r�     s/  € à�j‰j˜‰m×#Ñ#€GØ�?‰?˜7Ó#€DØ�~‰~€Hà�|ÜØØØØ!Ø #Øñ
ð 	
ô ! ¯©Ó4€FØŸ
š
Ó@š
�1¤j°·±¸×&?�Q™
€EÐ@ÞÜØØØØ!Ø #Øñ
ð 	
ñ "Ó0šE�q§Z¥Z—™E€IÐ0Ü˜I›¬¨U«Ñ3ÐÞKT”Ñ5©9Ó5Ó5¼¸I»ÒFÐZ]€IØ:KÈcÓ:Q±ÐW_€GÜØØÜ�u“:Ø+Ø%Øñð ùò Aùò 1s   Á+D.ÂD.Â/D3ÃD3)rK   r   rN   rM   r‡   rO   )r~   r   r‡   r   )r�   r   r¥   r"   r‡   r   )r   r   rª   r   r‡   r   )r�   r   rŽ   zDict[int, PageParse]r‡   rA   )*r)   Ú
__future__r   rb   Údataclassesr   r   Úpathlibr   Útypingr   r   r	   r
   r   r   Údocling.datamodel.base_modelsr   Údocling.datamodel.documentr   Údocling_core.types.doc.baser   Údocling_core.types.doc.documentr   r   Údocling_core.types.doc.pager   Úpydanticr   r   r"   r   r   r/   r:   rA   rI   r   r}   r¦   r±   r�   r$   r,   r-   Ú<module>rÊ      s³   ðñõ4 #ã ß (Ý ÷ G× FæÝ>Ý;å 3ß FÝ 9ß %àˆE�5˜% Ð&Ñ'€ô`�ô `ô:�	ô :ô�	ô ô�iô ð" ÷z
ð z
ó ðz
ôz	^ô0ô	Hô-õ'r,   