ó
    5ûoj  ã                  óä   • S r SSKJr  SSKrSSKrSSKJr  SSKJr  SSK	J
r
  Sr " S S	\
5      r " S
 S\
5      r " S S\
5      rSSS jjr  S         SS jjr  S         SS jjrg)a  OCR grounding well: page text read from a rendered image, with provenance.

A scanned page or an image-bound figure has no native text layer, so a value
extracted from it has nothing to ground against. The well fills that gap. It
runs RapidOCR over a rendered page image and keeps every recognized fragment
with its bounding box and confidence. For a render of an original PDF page the
box is stored in PDF points, so a fragment grounds a value from a scanned
region the same way a native text cell grounds a table cell.

The well is evidence, never a correction target. Fragments are stored exactly
as the engine read them; anything that interprets or repairs them happens in
the consumer, against the fragment ids, so the trace from a value back to the
pixels survives every downstream step.
é    )ÚannotationsN)ÚPath)ÚAny)Ú	BaseModelg      R@c                  óL   • \ rS rSr% SrS\S'   S\S'   S\S'   S\S	'   S
\S'   Srg)ÚOcrFragmenté   z;One recognized text fragment and where it sits on the page.ÚstrÚidÚintÚpageÚtextú!tuple[float, float, float, float]ÚbboxÚfloatÚ
confidence© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__Ú__static_attributes__r   ó    Ú1/home/mande/repo/quber/src/quber/core/ocr/well.pyr   r      s"   ‡ ÙEàƒGØ
ƒIØ
ƒIð ,Ó+ØÖr   r   c                  óp   • \ rS rSr% SrS\S'   S\S'   S\S'   S	\S
'   S	\S'   S\S'    S     SS jjrSrg)ÚPageWellé(   z(Every fragment read from one page image.r   r   r
   Úimageú
int | NoneÚdpir   ÚwidthÚheightúlist[OcrFragment]Ú	fragmentsc           	     ó>  • Uu  p4pV/ nU R                    H…  nUR                  u  pšp¼[        S[        Xµ5      [        X“5      -
  5      n[        S[        XÆ5      [        X¤5      -
  5      n[        X¹-
  XÊ-
  -  S5      nXÞ-  U-  U:¼  d  Mt  UR	                  U5        M‡     U$ )zAFragments whose area overlaps the region by at least min_overlap.g        g�íµ ÷Æ°>)r&   r   ÚmaxÚminÚappend)Úselfr   Úmin_overlapÚleftÚtopÚrightÚbottomÚhitsÚfragÚflÚftÚfrÚfbÚinter_wÚinter_hÚareas                   r   Úfragments_in_boxÚPageWell.fragments_in_box2   s˜   € ð $(Ñ ˆ�5ØˆØ—N”NˆDØ!ŸY™Y‰NˆB�BÜ˜#œs 2›~´°B³Ñ=Ó>ˆGÜ˜#œs 2›´°R³Ñ=Ó>ˆGÜ˜™ B¡GÑ,¨dÓ3ˆDØÑ! TÑ)¨[Õ8Ø—‘˜DÖ!ñ #ð ˆr   r   N)g      à?)r   r   r,   r   Úreturnr%   )r   r   r   r   r   r   r:   r   r   r   r   r   r   (   sO   ‡ Ù2à
ƒIØƒJØ	ƒOØƒLØƒMØ Ó ð
 !ðà/ðð ðð 
÷	ð r   r   c                  óB   • \ rS rSr% SrS\S'   S\S'   S\S'   SS jrS	rg
)ÚDocumentWelléD   z7The wells for every page read from one source document.r
   ÚsourceÚenginezlist[PageWell]Úpagesc                ól   • U R                    H  nUR                  U:X  d  M  Us  $    [        SU 35      e)Nzno well for page )rB   r   ÚKeyError)r+   Úpage_noÚwells      r   r   ÚDocumentWell.pageK   s6   € Ø—J”JˆDØ�y‰y˜GÕ#Ø’ñ ô Ð*¨7¨)Ð4Ó5Ð5r   r   N)rE   r   r<   r   )r   r   r   r   r   r   r   r   r   r   r   r>   r>   D   s   ‡ ÙAàƒKØƒKØÓ÷6r   r>   c                ó    • SSK Jn  U" SU S.S9$ )a  RapidOCR configured the way the tuned-financial preset runs it.

docling propagates the CUDA device to RapidOCR's paddle and torch engines
but not the default onnxruntime engine, so the CUDA execution provider is
named explicitly here, matching TunedFinancialParser.
r   )ÚRapidOCRT)z!EngineConfig.onnxruntime.use_cudaz.EngineConfig.onnxruntime.cuda_ep_cfg.device_id)Úparams)ÚrapidocrrI   )Ú	device_idrI   s     r   Úmake_enginerM   R   s   € õ "áà15Ø>Gñ
ñð r   c                ó8  • SSK Jn  Uc
  [        5       nUR                  U 5       nUR                  u  pgSSS5        U" [        U 5      5      nU(       a	  [        U-  OSn	/ n
[        USS5      n[        USS5      =(       d    / n[        USS5      =(       d    / nUbÆ  [        [        X¼USS	95       H®  u  nu  nnnU Vs/ s H  n[        US   5      PM     nnU Vs/ s H  n[        US
   5      PM     nnU
R                  [        SU SU 3U[        U5      [        U5      U	-  [        U5      U	-  [        U5      U	-  [        U5      U	-  4[        U5      S95        M°     [        U[        U 5      UWU	-  WU	-  U
S9$ ! , (       d  f       GNS= fs  snf s  snf )z«Read one page image into a well.

When dpi is given the fragment boxes are converted from pixels to PDF
points, so they land in the coordinate frame of the original page.
r   )ÚImageNg      ð?ÚboxesÚtxtsÚscoresF)Ústricté   Úpz.f)r   r   r   r   r   )r   r    r"   r#   r$   r&   )ÚPILrO   rM   ÚopenÚsizer
   ÚPOINTS_PER_INCHÚgetattrÚ	enumerateÚzipr   r*   r   r)   r(   r   )Ú
image_pathrE   r"   rA   rO   ÚimgÚwidth_pxÚ	height_pxÚresultÚscaler&   rP   rQ   rR   ÚiÚboxr   ÚscorerU   ÚxsÚyss                        r   Ú
read_imagerh   c   s“  € õ à�~Ü“ˆØ	�‰�JÔ	 3Ø!Ÿh™hÑˆ÷ 
 á”C˜
“OÓ$€FÞ%(ŒO˜cÒ!¨c€Eà#%€IÜ�F˜G TÓ*€EÜ�6˜6 4Ó(×.¨B€DÜ�V˜X tÓ,×2°€FØÑÜ%.¬s°5ÀÈuÑ/UÖ%VÑ!ˆAÑ!��T˜5Ù'*Ó+¢s !”%˜˜!™–+¡sˆBÐ+Ù'*Ó+¢s !”%˜˜!™–+¡sˆBÐ+Ø×ÑÜØ˜7˜) 2 a SÐ)Ø Ü˜T›ä˜B› %™Ü˜B› %™Ü˜B› %™Ü˜B› %™ð	ô  % U›|ñöñ &Wô" ØÜ�*‹oØØ˜ÑØ˜5Ñ Øñð ÷7 
 Ö	üò ,ùÚ+s   ¥F Â?FÃFÆ 
Fc                ó*  • Uc
  [        5       n/ n[        R                  " 5        nU H¼  n[        U5      SUS 3-  n[        R
                  " SS[        U5      SS[        U5      S[        U5      [        U 5      [        U5      /
S	S	S
9  [        [        U5      R                  SUS S35      5      nU(       d  [        SU 35      eUR                  [        US   XbUS95        M¾     SSS5        [        [        U 5      SUS9$ ! , (       d  f       N"= f)z:Render the named pages of a PDF and read each into a well.Nr   Ú04dÚpdftoppmz-rz-pngz-fz-lT)ÚcheckÚcapture_outputz*.pngz$pdftoppm produced no image for page r   )r"   rA   rK   )r@   rA   rB   )rM   ÚtempfileÚTemporaryDirectoryr   Ú
subprocessÚrunr
   ÚsortedÚglobÚFileNotFoundErrorr*   rh   r>   )	ÚpdfrB   r"   rA   Ú
page_wellsÚtmprE   ÚprefixÚrendereds	            r   Ú
build_wellrz   —   s  € ð �~Ü“ˆØ!#€JÜ	×	$Ò	$Ô	&¨#ÛˆGÜ˜#“Y 4¨° }Ð!5Ñ5ˆFÜ�NŠNàØÜ˜“HØØÜ˜“LØÜ˜“LÜ˜“HÜ˜“Kðð Ø#òô  œd 3›iŸn™n¨t°G¸C°=ÀÐ-FÓGÓHˆHÞÜ'Ð*NÈwÈiÐ(XÓYÐYØ×Ñœj¨°!©°gÈvÑVÖWñ+ ÷ 
'ô. œs 3›x°
À*ÑMÐM÷/ 
'Õ	&ús   ¥CDÄ
D)r   )rL   r   r<   r   )NN)
r]   r   rE   r   r"   r!   rA   r   r<   r   )i,  N)
ru   r   rB   z	list[int]r"   r   rA   r   r<   r>   )r   Ú
__future__r   rp   rn   Úpathlibr   Útypingr   Úpydanticr   rY   r   r   r>   rM   rh   rz   r   r   r   Ú<module>r      sÉ   ðñõ #ã Û Ý Ý å à€ô	�)ô 	ôˆyô ô86�9ô 6öð( Øð	1Øð1àð1ð 
ð1ð ð	1ð
 õ1ðn Øð	!NØ	ð!Nàð!Nð 
ð!Nð ð	!Nð
 ö!Nr   