Ë
    =}žjx>  ã                  ó„  — d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	 ddl
mZ ddlmZ ddlmZ ddlZddlZddlmZ dZd	Zd
ZdZdZ ej8                  d«      Z e	d¬«       G d„ d«      «       Zd#d„Zd$d„Z d%d„Z!d&d„Z"d&d„Z#d'd„Z$d(d„Z%d)d„Z&d*d„Z'd+d,d„Z(d-d„Z)d.d„Z*d-d„Z+d/d„Z,d0d „Z-d1d!„Z.e/d"k(  r e.«        yy)2aß  Build and preview the AC28 supervised CAD-to-scan dataset.

Each manifest record uses the following contract:

* ``inputs``: the shared CATPart design file and one production Excel file;
* ``target``: the corresponding merged point-cloud PLY and its six scan views;
* ``label``: defect coordinates from the CSV, or ``null`` for an OK unit.

The source directory is deliberately kept external to the Pixi project so the
manifest contains portable paths relative to the data root.
é    )ÚannotationsN)ÚasdictÚ	dataclass)ÚPath)ÚAny)ÚFancyBboxPatchu   CATIA File (ì„¤ê³„ ë�°ì�´í„°)u   Excel File (ì„±í˜•ì •ë³´)u   CSV File (ë¶ˆëŸ‰ ì¢Œí‘œê°’)u   PLY File (ì¸¡ì • ë�°ì�´í„°)zAC28_RR DT UPR LHCUR.CATPartuF   _(?P<date>\d{8}) (?P<time>\d+ì‹œ(?:\d+ë¶„)?) ìƒ�ì‚°_(?P<status>NG|OK)$T)Úfrozenc                  ó>   — e Zd ZU ded<   ded<   ded<   edd„«       Zy)ÚProductionKeyÚstrÚdateÚtimeÚstatusc                óT   — d| j                   › d| j                  › d| j                  › �S )NÚAC28_Ú_)r   r   r   )Úselfs    ú'src/moltex_experiments/matching_data.pyÚ	sample_idzProductionKey.sample_id-   s'   € à�t—y‘y�k  4§9¡9 +¨Q¨t¯{©{¨mÐ<Ð<ó    N)Úreturnr   )Ú__name__Ú
__module__Ú__qualname__Ú__annotations__Úpropertyr   © r   r   r   r   '   s#   … à
ƒIØ
ƒIØƒKàò=ó ñ=r   r   c                ó¤   — t         j                  t        | «      j                  «      }|st	        d| ›�«      ‚t        di |j                  «       ¤ŽS )zGExtract the timestamp/status portion shared across Excel, PLY, and CSV.z,Could not parse production date/status from r   )ÚPRODUCTION_REÚsearchr   ÚstemÚ
ValueErrorr   Ú	groupdict)ÚnameÚmatchs     r   Úproduction_keyr&   2   sE   € ä× Ñ ¤ d£§¡Ó1€EÙÜÐGÈÀxÐPÓQÐQÜÑ-˜5Ÿ?™?Ó,Ñ-Ð-r   c                ó@   — | j                  |«      j                  «       S )N)Úrelative_toÚas_posix)ÚpathÚroots     r   Úrelativer,   :   s   € Ø×Ñ˜DÓ!×*Ñ*Ó,Ð,r   c                ó°   — t        j                  d| «      }|s| S t        |j                  d«      «      d›dt        |j                  d«      xs d«      d›�S )z>Convert Korean filename time text to an ASCII-safe plot label.u   (\d+)ì‹œ(?:(\d+)ë¶„)?é   Ú02dÚ:é   r   )ÚreÚ	fullmatchÚintÚgroup)Úvaluer%   s     r   Údisplay_timer7   >   sQ   € ä�L‰LÐ1°5Ó9€EÙØˆÜ�%—+‘+˜a“.Ó! #Ð& a¬¨E¯K©K¸«NÒ,?¸aÓ(@ÀÐ'EÐFÐFr   c                ó  — | j                  d«      5 }g }	 |j                  «       }|st        d| › �«      ‚|j                  |«       |j	                  «       dk(  rnŒF|j                  «       }ddd«       dj                  «      j                  dd¬«      }t        j                  d	|t        j                  ¬
«      }|st        d| › �«      ‚d|vrt        d| › �«      ‚dt        |j                  d«      «      dœS # 1 sw Y   Œ‘xY w)zDRead only the binary PLY header, never its multi-million-point body.ÚrbzPLY header is incomplete: s
   end_headerNr   ÚasciiÚstrict)Úerrorsz^element vertex (\d+)$)ÚflagszPLY has no vertex count: zformat binary_little_endian 1.0z#Expected binary little-endian PLY: Úbinary_little_endianr.   )ÚformatÚvertex_countÚheader_bytes)ÚopenÚreadliner"   ÚappendÚstripÚtellÚjoinÚdecoder2   r    Ú	MULTILINEr4   r5   )r*   ÚhandleÚheader_linesÚlineÚbyte_offsetÚheaderÚvertex_matchs          r   Úread_ply_headerrP   F   s  € à	�‰�4Œ˜FØ$&ˆØØ—?‘?Ó$ˆDÙÜ Ð#=¸d¸VÐ!DÓEÐEØ×Ñ Ô%Ø�z‰z‹|˜}Ò,Øð ð —k‘k“mˆ÷ 
ð �X‰X�lÓ#×*Ñ*¨7¸8Ð*ÓD€FÜ—9‘9Ð6¸ÄbÇlÁlÔS€LÙÜÐ4°T°FÐ;Ó<Ð<Ø(°Ñ6ÜÐ>¸t¸fÐEÓFÐFð )Ü˜L×.Ñ.¨qÓ1Ó2Ø#ñð ÷% 
ˆús   ’AC<Ã<Dc                ó  — t        j                  | d¬«      }|j                  d   }t        j                  | |ddd¬«      }|j	                  t        j
                  |«      d«      j                  j                  «       }|j                  |dœS )zLCapture a small, JSON-safe preview without putting sheet contents in labels.Úxlrd)Úenginer   Né   )Ú
sheet_namerN   ÚnrowsrS   )ÚsheetsÚpreview_rows)ÚpdÚ	ExcelFileÚsheet_namesÚ
read_excelÚwhereÚnotnaÚvaluesÚtolist)r*   ÚworkbookÚfirst_sheetÚpreviewr_   s        r   Úread_excel_metadatard   a   sr   € ä�|‰|˜D¨Ô0€HØ×&Ñ& qÑ)€KÜ�m‰m˜D¨[ÀÈQÐW]Ô^€GØ�]‰]œ2Ÿ8™8 GÓ,¨dÓ3×:Ñ:×AÑAÓC€FØ×*Ñ*¸FÑCÐCr   c                óÀ  — | j                  ddd¬«      5 }t        t        j                  |«      «      }d d d «       g }D ]�  }|j	                  t        |d   «      t        |d   «      t        |d   «      |j                  d«      rt        |d   «      nd |j                  d	«      rt        |d	   «      nd |j                  d
«      xs d dœ«       Œ‘ |S # 1 sw Y   Œ¡xY w)NÚrz	utf-8-sigÚ )ÚencodingÚnewlineÚNoÚXÚYÚWÚHÚError)ÚidÚxÚyÚwidthÚheightÚerror)rB   ÚlistÚcsvÚ
DictReaderrD   r4   Úget)r*   rJ   ÚrowsÚlabelsÚrows        r   Ú
read_labelr}   j   s¾   € Ø	�‰�3 °bˆÔ	9¸VÜ”C—N‘N 6Ó*Ó+ˆ÷ 
:à#%€FÛˆØ�‰ä˜#˜d™)“nÜ˜˜S™“]Ü˜˜S™“]Ø*-¯'©'°#¬,œ˜S ™Xœ¸DØ+.¯7©7°3¬<œ#˜c #™hœ-¸TØŸ™ Ó)Ò1¨Tñõ		
ð ð €M÷ 
:Ð	9ús   •CÃCc           
     óÀ   — i }t        | t        z  j                  d«      «      D ]7  }t        |j                  «      }||v rt        d|› d|› d||   › �«      ‚|||<   Œ9 |S )Nz*.csvzDuplicate CSV label for ú: z and )ÚsortedÚCSV_DIRÚglobr&   r$   r"   )r+   Úresultr*   Úkeys       r   Ú
csv_by_keyr…   |   sn   € Ø(*€FÜ˜œw™×,Ñ,¨WÓ5Ö6ˆÜ˜TŸY™YÓ'ˆØ�&‰=ÜÐ7¸°u¸B¸t¸fÀEÈ&ÐQTÉ+ÈÐWÓXÐXØˆˆsŠð	 7ð
 €Mr   c                ó  — | t         z  t        z  }|j                  «       st        |«      ‚t	        | «      }g }t        | t        z  j                  d«      «      D �]¥  }t        |j                  «      }| t        z  |j                  z  }|j                  «       st        d|j                  › d|› �«      ‚t        |j                  d«      «      }|dz  }|j                  «       st        d|› �«      ‚|j                  |«      }	|j                  dk(  r|	€t        d|j                  › �«      ‚|j                  d	k(  r|	�t        d
|j                  › �«      ‚|j!                  |j"                  t%        |«      t'        || «      t'        || «      t)        |«      dœt'        || «      t'        || «      t+        |«      |D �
cg c]  }
t'        |
| «      t+        |
«      dœ‘Œ c}
dœ|	rt'        |	| «      t-        |	«      ddœnd dœ«       �Œ¨ |S c c}
w )Nz*.XlszNo PLY folder matching r   z*.plyzall_merge_pointcloud_full.plyzMissing primary merged PLY: ÚNGz(NG record has no defect-coordinate CSV: ÚOKz)OK record unexpectedly has a defect CSV: )ÚcatpartÚexcelÚexcel_metadata)r*   rN   )Úply_directoryÚprimary_plyÚprimary_ply_headerÚ	scan_plyszCsource inspection-image pixels; registration to PLY is not supplied)rw   ÚdefectsÚcoordinate_system)r   Ú
productionÚinputsÚtargetÚlabel)Ú	CATIA_DIRÚCATPART_NAMEÚis_fileÚFileNotFoundErrorr…   r€   Ú	EXCEL_DIRr‚   r&   r$   ÚPLY_DIRr!   Úis_dirry   r   r"   rD   r   r   r,   rd   rP   r}   )r+   r‰   r{   ÚrecordsÚ
excel_pathr„   Ú
ply_folderÚ	ply_pathsr�   Ú
label_pathr*   s              r   Úbuild_recordsr¢   †   s  € Ø”YÑ¤Ñ-€GØ�?‰?ÔÜ Ó(Ð(ä˜Ó€FØ$&€GÜ˜d¤YÑ.×4Ñ4°WÓ=×>ˆ
Ü˜ZŸ_™_Ó-ˆØœG‘^ j§o¡oÑ5ˆ
Ø× Ñ Ô"Ü#Ð&=¸j¿o¹oÐ=NÈbÐQ[ÐP\Ð$]Ó^Ð^ä˜:Ÿ?™?¨7Ó3Ó4ˆ	Ø Ð#BÑBˆØ×"Ñ"Ô$Ü#Ð&BÀ;À-Ð$PÓQÐQà—Z‘Z “_ˆ
Ø�:‰:˜Ò *Ð"4ÜÐGÈ
ÏÉÐGXÐYÓZÐZØ�:‰:˜Ò *Ð"8ÜÐHÈÏÉÐHYÐZÓ[Ð[à�‰à Ÿ]™]Ü$ S›kä'¨°Ó6Ü% j°$Ó7Ü&9¸*Ó&Eñô &.¨j¸$Ó%?Ü#+¨K¸Ó#>Ü*9¸+Ó*Fñ %.ó"á$-˜Dô "*¨$°Ó!5ÄÐQUÓAVÓWØ$-ñ"ñ	ñ "ô	  (¨
°DÓ9Ü#-¨jÓ#9Ø-ròð ñ1ö	
ð# ?ð\ €Nùò!"s   Æ:Hc                ó.  — |j                  dd¬«       |dz  }|j                  dd¬«      5 }| D ]+  }|j                  t        j                  |d¬«      d	z   «       Œ- 	 d d d «       d
dgdddœt        | «      t        d„ | D «       «      t        d„ | D «       «      | d   d   d   | D �cg c]%  }|d   |d   d   |d   d   |d   r|d   d   nd dœ‘Œ' c}dœ}|dz  j                  t        j                  |dd¬«      d	z   d¬«       y # 1 sw Y   Œ©xY wc c}w )NT©ÚparentsÚexist_okúac28_matching_dataset.jsonlÚwzutf-8)rh   F)Úensure_asciiÚ
ÚCATPartÚExcelÚPLYÚCSV)r“   r”   r•   c              3  ó2   K  — | ]  }|d    d   dk(  –— Œ y­w)r’   r   r‡   Nr   ©Ú.0Úrecords     r   Ú	<genexpr>z!write_manifest.<locals>.<genexpr>È   ó    è ø€ ÐUÉWÀ6˜˜|Ñ,¨XÑ6¸$Õ>ÉWùó   ‚c              3  ó2   K  — | ]  }|d    d   dk(  –— Œ y­w)r’   r   rˆ   Nr   r°   s     r   r³   z!write_manifest.<locals>.<genexpr>É   r´   rµ   r   r“   r‰   r   rŠ   r”   r�   r•   rw   )r   rŠ   r�   Ú	label_csv)ÚschemaÚrecord_countÚng_countÚok_countÚshared_catpartr�   z"ac28_matching_dataset_summary.jsonr1   )r©   Úindent)ÚmkdirrB   ÚwriteÚjsonÚdumpsÚlenÚsumÚ
write_text)r�   Ú
output_dirÚmanifestrJ   r²   Úsummarys         r   Úwrite_manifestrÈ   ¾   sB  € Ø×Ñ˜T¨DÐÔ1ØÐ9Ñ9€HØ	�‰�s WˆÔ	-°ÛˆFØ�L‰LœŸ™ F¸Ô?À$ÑFÕGñ ÷ 
.ð
 (¨Ð1¸UÈUÑSÜ˜G›ÜÑUÉWÓUÓUÜÑUÉWÓUÓUØ! !™* XÑ.¨yÑ9ñ "ó
ñ "�ð $ KÑ0Ø Ñ)¨'Ñ2Ø% hÑ/°Ñ>Ø7=¸g²˜V G™_¨UÒ3ÈDó	ð "ñ
ñ€Gð  Ð6Ñ6×BÑBÜ�
‰
�7¨°qÔ9¸DÑ@È7ð Cõ ÷) 
.Ð	-üò
s   ¬1DÂ'*DÄDc                ó
  — t        j                  g d¢«      }|d   }t        j                  d|dz
  t        ||«      t         j                  ¬«      }t        j
                  | |d|d   |f¬«      }||   j                  «       }~|S )	zIUniformly sample RGB points from a large binary PLY through a memory map.))rq   ú<f4)rr   rÊ   )ÚzrÊ   )rf   Úu1)ÚgrÌ   )ÚbrÌ   r@   r   r.   )Údtyperf   rA   )rÏ   ÚmodeÚoffsetÚshape)ÚnprÏ   ÚlinspaceÚminÚint64ÚmemmapÚcopy)r*   rN   Úmaximum_pointsrÏ   ÚcountÚindicesÚpointsÚsampleds           r   Úsample_point_cloudrÞ   Ú   s{   € ä�H‰HÚYó€Eð �>Ñ"€EÜ�k‰k˜!˜U Q™Y¬¨E°>Ó(BÌ"Ï(É(ÔS€GÜ�Y‰Y�t 5¨s¸6À.Ñ;QÐZ_ÐYaÔb€FØ�W‰o×"Ñ"Ó$€GØØ€Nr   c           
     ó~  — |j                  dd¬«       t        j                  dddd¬«      \  }}t        |j                  | d¬«      D �]0  \  }}|d   d   }t        ||d   d	   z  |«      }t        j                  |d
   |d   |d   f«      dz  }	|j                  |d   |d   |	ddd¬«       |j                  dd¬«       |j                  d«       |j                  d«       |d   d   }
|d   }d|d   › dt        |d   «      › d|
› d|d   d ›d!�	}|d"   r8|d"   d#   d   }|d$|d%   › d&|d   › d'|d   › d(�z  }|j                  |d)d*¬+«       n|d,z  }|j                  |d-d*¬+«       |j                  d.¬/«       �Œ3 |d0z  }|j                  d1d2¬3«       |j!                  |d4d5¬6«       t        j"                  |«       |S )7NTr¤   r1   ©é   é   ©ÚfigsizeÚconstrained_layout©r;   r”   rŽ   r�   rf   rÍ   rÎ   g     ào@rq   rr   ç333333Ó?r   )ÚcÚsÚ
linewidthsÚ
rasterizedÚequalÚbox©Ú
adjustableúPLY xzPLY yr’   r   úAC28 r   Ú r   rª   r@   Ú,z vertices (8,000 sampled)r•   r�   z
CSV defect #rp   z
 @ image (ú, Ú)Úcrimsoné
   ©ÚcolorÚfontsizez 
CSV label: none (OK production)Úseagreençš™™™™™É?©Úalphaz!ac28_pointcloud_label_preview.pngu7   AC28: CATPart + Excel â†’ PLY target; CSV defect labelsé   ©rú   é´   Útight©ÚdpiÚbbox_inches)r¾   ÚpltÚsubplotsÚzipÚflatrÞ   rÓ   Úcolumn_stackÚscatterÚ
set_aspectÚ
set_xlabelÚ
set_ylabelr7   Ú	set_titleÚgridÚsuptitleÚsavefigÚclose)r�   r+   rÅ   ÚfigureÚaxesÚaxisr²   rN   rÜ   Úcolorsr   r’   ÚtitleÚdefectrc   s                  r   Úrender_previewr  ç   s  € Ø×Ñ˜T¨DÐÔ1Ü—<‘<  1¨hÈ4ÔP�L€FˆDÜ˜DŸI™I w°t×<Ð<‰ˆˆfØ˜Ñ!Ð"6Ñ7ˆÜ# D¨6°(Ñ+;¸MÑ+JÑ$JÈFÓSˆÜ—‘ &¨¡+¨v°c©{¸FÀ3¹KÐ!HÓIÈEÑQˆØ�‰�V˜C‘[ &¨¡+°¸3È1ÐY]ˆÔ^Ø�‰˜¨EˆÔ2Ø�‰˜Ô Ø�‰˜Ô Ø˜Ñ% hÑ/ˆØ˜LÑ)ˆ
à�J˜vÑ&Ð' q¬°jÀÑ6HÓ)IÐ(JÈ!ÈFÈ8ÐSUØ�nÑ% aÐ(Ð(AðCð 	ð �'Š?Ø˜G‘_ YÑ/°Ñ2ˆFØ�~ f¨T¡l ^°:¸fÀS¹k¸]È"ÈVÐTWÉ[ÈMÐYZÐ[Ñ[ˆEØ�N‰N˜5¨	¸BˆNÕ?àÐ8Ñ8ˆEØ�N‰N˜5¨
¸RˆNÔ@Ø�	‰	˜ˆ	Öð+ =ð. Ð>Ñ>€GØ
‡O�OÐMÐXZ€OÔ[Ø
‡N�N�7 °€NÔ9Ü‡I�IˆfÔØ€Nr   c                óF   — | d   }d|d   › dt        |d   «      › d|d   › �S )Nr’   rñ   r   rò   r   r   )r7   )r²   r’   s     r   Úrecord_titler    s=   € Ø˜Ñ%€JØ�:˜fÑ%Ð& a¬°ZÀÑ5GÓ(HÐ'IÈÈ:ÐV^ÑK_ÐJ`ÐaÐar   c           
     óx  — |j                  dd¬«       t        j                  dddd¬«      \  }}t        |j                  | d¬«      D ]®  \  }}|d   d   }t        ||d   d	   z  |«      }|j                  |d
   |d   |d   dddd¬«       |j                  dd¬«       |j                  d«       |j                  d«       |j                  t        |«      |d   rdndd¬«       |j                  d¬«       Œ° |dz  }	|j                  dd¬«       |j                  |	d d!¬"«       t        j                  |«       |	S )#zCRender a complementary x-z projection; colour represents elevation.Tr¤   r1   rà   rã   ræ   r”   rŽ   r�   rq   rË   ÚviridisgÍÌÌÌÌÌÜ?r   )rè   Úcmapré   rê   rë   rì   rí   rî   rð   zPLY z / elevationr•   rö   rû   é   rø   rü   rý   z#ac28_pointcloud_profile_preview.pngzCAC28 merged point-cloud profile views (uniform 8,000-point samples)rÿ   r   r  r  r  )r¾   r  r  r  r	  rÞ   r  r  r  r  r  r  r  r  r  r  )
r�   r+   rÅ   r  r  r  r²   rN   rÜ   rc   s
             r   Úrender_profile_previewr!    sA  € à×Ñ˜T¨DÐÔ1Ü—<‘<  1¨hÈ4ÔP�L€FˆDÜ˜DŸI™I w°t×<‰ˆˆfØ˜Ñ!Ð"6Ñ7ˆÜ# D¨6°(Ñ+;¸MÑ+JÑ$JÈFÓSˆØ�‰Ø�3‰KØ�3‰KØ�S‰kØØØØð 	ô 	
ð 	�‰˜¨EˆÔ2Ø�‰˜Ô Ø�‰Ð+Ô,Ø�‰”| FÓ+ÀÀwÂ±9ÐU_ÐjlˆÔmØ�	‰	˜ˆ	Õð! =ð$ Ð@Ñ@€GØ
‡O�OÐYÐdf€OÔgØ
‡N�N�7 °€NÔ9Ü‡I�IˆfÔØ€Nr   c                óX  — |j                  dd¬«       t        j                  dd¬«      \  }}| D ��cg c]  }|d   r|d   d   D ]  }||f‘Œ Œ }}}t        d„ |D «       «      }t        d„ |D «       «      }|j	                  d	t        d
|dz   «      «       |j                  t        d|dz   «      d	«       g d¢}	g d¢}
t        |	|
|d¬«      D ]b  \  }}\  }}|j                  |d   |d   d|dd¬«       |j                  t        |«      › d|d   › d|d   › d|d   › d�|d   |d   f|dd¬«       Œd |j                  d«       |j                  d «       |j                  d!«       |j                  d"¬#«       |d$z  }|j                  |d%d&¬'«       t        j                  |«       |S c c}}w )(zGShow the CSV labels in their native inspection-image coordinate system.Tr¤   )r÷   é   rã   r•   r�   c              3  ó,   K  — | ]  \  }}|d    –— Œ y­w)rq   Nr   ©r±   r   r  s      r   r³   z'render_label_preview.<locals>.<genexpr>4  ó   è ø€ Ð4©V¡	  6��s•©Vùó   ‚c              3  ó,   K  — | ]  \  }}|d    –— Œ y­w)rr   Nr   r%  s      r   r³   z'render_label_preview.<locals>.<genexpr>5  r&  r'  r   i   i,  i (  i¼  )z#d62728z#ff7f0ez#9467bd))râ   iÞÿÿÿ)râ   iîÿÿÿ)râ   é&   ræ   rq   rr   éª   Úblacké   )ré   rù   Ú
edgecolorsÚzorderz	
defect #rp   z (rô   rõ   zoffset pointsé	   )ÚxytextÚ
textcoordsrú   z0NG defect labels in inspection-image coordinateszCSV X (pixels)z$CSV Y (pixels; origin at upper-left)rç   rý   zac28_csv_label_coordinates.pngr  r  r  )r¾   r  r  ÚmaxÚset_xlimÚset_ylimr  r  Úannotater  r  r  r  r  r  r  )r�   rÅ   r  r  r²   r  r{   Úmax_xÚmax_yÚcoloursÚoffsetsÚcolourrÑ   rc   s                 r   Úrender_label_previewr;  *  sÕ  € à×Ñ˜T¨DÐÔ1Ü—<‘<¨ÀDÔI�L€FˆDñ ôáˆFØ�'Š?Ø˜W‘o iÔ0ˆFð 
�Òð 1ð 	Øð ñ ô Ñ4©VÓ4Ó4€EÜÑ4©VÓ4Ó4€EØ‡M�M�!”S˜˜u s™{Ó+Ô,Ø‡M�M”#�e˜U S™[Ó)¨1Ô-Ú/€GÚ.€GÜ,/°¸À&ÐQU×,VÑ(ˆ�Ñ(˜ Ø�‰�V˜C‘[ &¨¡+°¸FÈwÐ_`ˆÔaØ�‰Ü˜FÓ#Ð$ J¨v°d©|¨n¸B¸vÀc¹{¸mÈ2ÈfÐUXÉkÈ]ÐZ[Ð\Ø�C‰[˜& ™+Ð&ØØ&Øð 	õ 	
ð -Wð 	‡N�NÐEÔFØ‡O�OÐ$Ô%Ø‡O�OÐ:Ô;Ø‡I�I�C€IÔØÐ;Ñ;€GØ
‡N�N�7 °€NÔ9Ü‡I�IˆfÔØ€Nùó9s   ³F&c           
     ój  — | j                  dd¬«       t        j                  dd¬«      \  }}|j                  «        g d¢}|D ]h  \  }}}}}t	        |df|dd|d	d
¬«      }	|j                  |	«       |j                  ||dz  z   d|dddd¬«       |j                  ||dz  z   d|ddd¬«       Œj dD ]!  \  }
}|j                  d|df|
dfdddœ¬«       Œ# |j                  ddddddd¬«       |j                  ddddddd ¬!«       | d"z  }|j                  |d#d$¬%«       t        j                  |«       |S )&zCRender the model-ready data contract as a simple data-flow diagram.Tr¤   )é   rT   rã   ))g¸…ëQ¸ž?ç)\�Âõ(Ì?zInput Xz#CATPart (shared)
+ Excel (per unit)z#dbeafe)rç   gáz®GáÊ?z	Match keyzdate + time +
production statusz#fef3c7)ç=
×£p=â?r>  zTarget Yzmerged PLY +
6 scan-view PLYsz#dcfce7)çáz®Gáê?gìQ¸…ëÁ?ÚLabelzCSV defect pixels
(NG only)z#fee2e2gìQ¸…ëÑ?g)\�Âõ(Ü?zround,pad=0.02z#334155g      ø?)ÚboxstyleÚ	facecolorÚ	edgecolorÚ	linewidthr1   g333333ã?Úcenterrâ   Úbold)ÚhaÚvarú   Ú
fontweightgáz®GáÚ?r÷   )rH  rI  rú   ))g      Ð?rç   )g¤p=
×£à?r?  )gš™™™™™é?r@  rg   g      à?z->)Ú
arrowstyleÚlw)Úxyr0  Ú
arrowpropsgq=
×£pí?z AC28 supervised matching dataseté   g{®Gáz´?znCSV coordinates are inspection-image pixels; a camera-to-PLY registration is required for vertex-level labels.z#475569)rH  rI  rú   rù   zac28_dataset_contract.pngr  r  r  )
r¾   r  r  Úset_axis_offr   Ú	add_patchÚtextr5  r  r  )rÅ   r  r  Úboxesrq   rs   ÚheadingÚbodyr:  ÚpatchÚstartÚendrc   s                r   Úrender_contract_previewrY  M  sn  € à×Ñ˜T¨DÐÔ1Ü—<‘<¨ÀDÔI�L€FˆDØ×ÑÔò€Eó ,1Ñ'ˆˆ5�'˜4 ÜØ�ˆI�u˜dÐ-=ÈÐ[dÐpsô
ˆð 	�‰�uÔØ�	‰	�!�e˜a‘i‘-  w°8ÀÐSUÐbhˆ	ÔiØ�	‰	�!�e˜a‘i‘-  t°¸XÐPRˆ	ÕSð ,1ó A‰
ˆˆsØ�‰�b˜c 3˜Z°¸°ÐX\ÐdeÑIfˆÕgð Aà‡I�Iˆc�4Ð;ÀÈXÐ`bÐou€IÔvØ‡I�IØØØxØØØØð ô ð Ð6Ñ6€GØ
‡N�N�7 °€NÔ9Ü‡I�IˆfÔØ€Nr   c                 ó¾  — t        j                  t        ¬«      } | j                  dt        t	        d«      ¬«       | j                  dt        t	        d«      ¬«       | j                  dd¬	«       | j                  «       }t        |j                  «      }t        ||j                  «       |j                  s€t        ||j                  |j                  «      t        ||j                  |j                  «      t        ||j                  «      t        |j                  «      g}|D ]  }t        d
|› �«       Œ t        dt!        |«      › d|j                  dz  › �«       y )N)Údescriptionz--data-rootz/workspace/moltex-sample)ÚtypeÚdefaultz--output-dirÚ	artifactsz--skip-previewÚ
store_true)ÚactionzWrote preview: zWrote z matched records to r§   )ÚargparseÚArgumentParserÚ__doc__Úadd_argumentr   Ú
parse_argsr¢   Ú	data_rootrÈ   rÅ   Úskip_previewr  r!  r;  rY  ÚprintrÂ   )ÚparserÚargsr�   Úpreviewsrc   s        r   Úmainrl  q  s  € Ü×$Ñ$´Ô9€FØ
×Ñ˜¬D¼$Ð?YÓ:ZÐÔ[Ø
×Ñ˜¬T¼4ÀÓ;LÐÔMØ
×ÑÐ(°ÐÔ>Ø×ÑÓ€Dä˜DŸN™NÓ+€GÜ�7˜DŸO™OÔ,Ø×Òä˜7 D§N¡N°D·O±OÓDÜ" 7¨D¯N©N¸D¿O¹OÓLÜ  ¨$¯/©/Ó:Ü# D§O¡OÓ4ð	
ˆó  ˆGÜ�O G 9Ð-Õ.ð  ä	ˆF”3�w“<�.Ð 4°T·_±_ÐGdÑ5dÐ4eÐ
fÕgr   Ú__main__)r$   r   r   r   )r*   r   r+   r   r   r   )r6   r   r   r   )r*   r   r   údict[str, Any])r*   r   r   úlist[dict[str, Any]])r+   r   r   zdict[ProductionKey, Path])r+   r   r   ro  )r�   ro  rÅ   r   r   ÚNone)i@  )r*   r   rN   rn  rÙ   r4   r   z
np.ndarray)r�   ro  r+   r   rÅ   r   r   r   )r²   rn  r   r   )r�   ro  rÅ   r   r   r   )rÅ   r   r   r   )r   rp  )0rc  Ú
__future__r   ra  rw   rÀ   r2   Údataclassesr   r   Úpathlibr   Útypingr   Úmatplotlib.pyplotÚpyplotr  ÚnumpyrÓ   ÚpandasrY   Úmatplotlib.patchesr   r–   rš   r�   r›   r—   Úcompiler   r   r&   r,   r7   rP   rd   r}   r…   r¢   rÈ   rÞ   r  r  r!  r;  rY  rl  r   r   r   r   Ú<module>r{     sè   ðñ
õ #ã Û 
Û Û 	ß )Ý Ý å Û Û Ý -ð ,€	Ø'€	Ø
'€Ø
'€Ø-€Ø�—
‘
ØMó€ñ
 �$Ô÷=ð =ó ð=ó.ó-óGóó6Dóó$ó5ópô8
óóBbó
ó: óF!óHhð* ˆzÒÙ…Fð r   