Ë
    ÙSºjE(  ã                  ó  — d Z ddlmZ ddlZddlZddlZddlmZ ddlZ ej                  d«       ddl
mZ ddlZ ee«      j!                  «       j"                  d   Zedz  Zedz  Zdd	„Zdd
„Zdd„Zdd„Zdd„Zedk(  r e«        yy)zDCompare saved CAD-mapped weak-risk fits across AC28 and ME1a models.é    )ÚannotationsN)ÚPathÚAggé   z(results/ME1a_DT_comparison/model_rankingzresults/ME1a_DT_comparisonc                óL   — t        j                  | j                  d¬«      «      S )Núutf-8©Úencoding)ÚjsonÚloadsÚ	read_text)Úpaths    õ$   ì „ì²˜ë¦¬/compare_all_models_risk.pyÚloadr      s   € Ü�:‰:�d—n‘n¨g�nÓ6Ó7Ð7ó    c                ó0   ‡‡— t        ˆˆfd„| D «       «      S )Nc              3  óf   •K  — | ](  }|d    dk(  sŒ|d   dk(  sŒ|d   ‰k(  r|d   ‰k(  r|–— Œ* y­w)Úbudgetéà.  ÚkindÚresidual_geoÚeval_runÚsetupN© )Ú.0ÚrowÚrunr   s     €€r   Ú	<genexpr>zresidual_row.<locals>.<genexpr>   sF   øè ø€ ð F™t˜ s¨8¡}¸Ó'=À#ÀfÁ+ÐQ_ÓB_Ø˜
‘O sÒ*¨s°7©|¸uÒ/Dô ™tùs   ƒ1‘1š1)Únext)Úrowsr   r   s    ``r   Úresidual_rowr!      s    ù€ Üô F™tó Fó Fð Fr   c                 ó  — t        t        dz  «      } t        t        dz  «      }t        t        dz  «      }| d   dk7  s|d   dk7  rt        d«      ‚g }| d   j	                  «       D ]  \  }}|d   |   }|j                  i d	|“d
d“dd“d|d   “d|d   “d|d   “d|d   “d|d   “d|dk(  rdnd“d|d   “d|d   “d|d   “d|d   “d |d   “d!d"“d#|d$   “d%d&|d$   z   “«       Œ� d'D ]›  \  }}t        |d(   d)|d*k(  rd+nd,«      }t        |d(   d-|d*k(  rd.nd,«      }|j                  i d	|“d
d/“dd0“d|d1   “d|d2   “d|d3   “dd4“d|d5   “d|d6   “d|d1   “d|d2   “d|d3   “dd4“d |d5   “d!|d6   “d#|d$   “d%|d$   “«       Œ� |S )7Nz*results/models/cad_predictions/report.jsonz>experiments/ME1a_DT/results/models/cad_predictions/report.jsonzgnn_joint_hard/report.jsonr   Ú18h01Ú14h06zUnexpected comparison runÚmodelsÚmodelÚfamilyzprior baselineÚgraph_nodes_requestedÚ Úac28_apÚaverage_precisionÚac28_iouÚthreshold_iouÚ	ac28_diceÚthreshold_diceÚac28_coverageÚdisplay_coverageÚac28_epochsÚepochsÚac28_training_runsúRisk GNNzAC28 16h + 18h01ú
AC28 18h01Úme1a_apÚme1a_iouÚ	me1a_diceÚme1a_coverageÚme1a_epochsÚme1a_training_runsú
ME1a 14h06Úac28_checkpointÚ
checkpointÚme1a_checkpointzexperiments/ME1a_DT/))zResidual Geo GNN (individual)Úsingle)zResidual Geo GNN (joint)Újointr    Ú
AC28_18h01rA   Úsingle_AC28_18h01rB   Ú
ME1a_14h06Úsingle_ME1a_14h06zoptimized risk-only GNNr   Ú	mapped_apÚ
mapped_iouÚmapped_diceg      ð?Úepochs_per_fitÚ
train_runs)r   ÚPROJECTÚBASEÚ
ValueErrorÚitemsÚappendr!   )	ÚacÚmeÚhardr    ÚnameÚaÚmÚtitler   s	            r   ÚrecordsrX      s.  € Ü	ŒgÐDÑDÓ	E€BÜ	ŒgÐXÑXÓ	Y€BÜ”Ð3Ñ3Ó4€DØ	ˆ%�y�GÒ˜r %™y¨GÒ3ÜÐ4Ó5Ð5Ø€DØ�h‘<×%Ñ%Ö'‰ˆˆaØˆx‰L˜ÑˆØ�‰ð 	R�W˜dð 	R HÐ.>ð 	RÐ@WÐY[ð 	RØ Ð"5Ñ 6ð	RØ8BÀAÀoÑDVð	Rà  !Ð$4Ñ"5ð	Rà7FÈÐJ\ÑH]ð	Rð # A h¡Kð	Rð *ÀÈÒASÑ+=ÐYeð		Rð
  Ð"5Ñ 6ð	Rð
 9CÀAÀoÑDVð	Rð ! !Ð$4Ñ"5ð	Rð 8GÈÐJ\ÑH]ð	Rð # A h¡Kð	Rð 2FÀ|ð	Rð '¨¨,©ð	Rð 'Ð(>ÀÀ<ÁÑ(Pð	Rõ 		Sð (ó@‰ˆˆuä˜˜f™ |ÈEÐU]ÒL]Ñ5HÐcjÓkˆÜ˜˜f™ |ÈEÐU]ÒL]Ñ5HÐcjÓkˆØ�‰ð ]�W˜eð ] XÐ/Hð ]ÐJaÐchð ]Ø  +¡ð]Ø0:¸A¸l¹Oð]à  ! MÑ"2ð]à4CÀSð]ð # DÐ)9Ñ$:ð]ð =QÐRSÐT`ÑRað]ð   +¡ð	]ð 1;¸A¸l¹Oð	]ð
 ! ! MÑ"2ð]ð
 5DÀSð]ð # DÐ)9Ñ$:ð]ð =QÐRSÐT`ÑRað]ð '¨¨,©ð]ð :KÈAÈlÉOð]õ 	^ð	@ð €Kr   c                ó:  ‡— t        j                  dddd¬«      \  }}t        d«      D �]ž  \  }\  }}t        d«      D �]†  \  }\  }}|› d|› �Št        | ˆfd„¬	«      }	|	D �
cg c]$  }
|
d
   dk(  rdn|
d   j	                  d«      rdnd‘Œ& }}
|||f   }t        j                  t        |	«      «      }|j                  ||	D �
cg c]  }
|
‰   ‘Œ	 c}
|¬«       |j                  ||	D �
cg c]  }
|
d
   ‘Œ	 c}
d¬«       |j                  dt        dt        ˆfd„|	D «       «      dz  «      «       |j                  |dk(  r|j                  «       nd«       |j                  |› d|› �«       |j                  dd¬«       t        |	«      D ]:  \  }}
|j!                  |
‰   |j#                  «       d   dz  z   ||
‰   d ›d!d"¬#«       Œ< �Œ‰ �Œ¡ |j%                  d$d%¬«       |j'                  t(        d&z  d'¬(«       t        j*                  |«       y c c}
w c c}
w c c}
w ))Né   )é   é   T)ÚfigsizeÚconstrained_layout))Úac28r6   )Úme1ar=   ))ÚapzAverage precision)Úiouz
IoU at 0.5Ú_c                ó   •— | ‰   S ©Nr   )r   Úkeys    €r   Ú<lambda>zfigure.<locals>.<lambda>D   s	   ø€ °3°s²8r   ©rf   r&   r5   z#cf6d28r'   Ú	optimizedz#126c9az#8998aa)Úcoloré   )Úfontsizer   gš™™™™™©?c              3  ó(   •K  — | ]	  }|‰   –— Œ y ­wre   r   )r   r   rf   s     €r   r   zfigure.<locals>.<genexpr>K   s   øè ø€ Ð'D¹G°S¨¨C­¹Gùs   ƒg=
×£p=ò?ra   ÚIoUú: Úxgš™™™™™É?)ÚaxisÚalphar   gü©ñÒMb€?ú.3fÚcenteré   )Úvarl   zIWeak-label same-run fit; training setups and native output domains differr[   zmodel_comparison.pngéª   )Údpi)ÚpltÚsubplotsÚ	enumerateÚsortedÚ
startswithÚnpÚarangeÚlenÚbarhÚ
set_yticksÚset_xlimÚmaxÚ
set_xlabelÚupperÚ	set_titleÚgridÚtextÚget_xlimÚsuptitleÚsavefigÚOUTÚclose)r    ÚfigÚaxesÚiÚpartÚlabelÚjÚmetricrW   Úorderedr   ÚcolorsÚaxÚyÚkrf   s                  @r   Úfigurer›   ?   s  ø€ Ü—‘˜Q ¨8ÈÔM�I€CˆÜ%Ð&V×WÑˆ‰=ˆD�%Ü"+Ð,`×"aÑˆA‰�˜Ø�F˜!˜F˜8Ð$ˆCÜ˜TÓ';Ô<ˆGáelónÙelÐ^að %(¨¡L°JÒ$>‘yØ$'¨¡M×$<Ñ$<¸[Ô$I‘yÈyñYØelð ð nà�a˜�d‘ˆBÜ—	‘	œ#˜g›,Ó'ˆAØ�G‰G�A©GÓ4©G S˜˜C›¨GÑ4¸FˆGÔCØ�M‰M˜!±gÓ>±g¨s˜c '›l°gÑ>ÈˆMÔKØ�K‰K˜œ3˜s¤CÓ'D¹GÓ'DÓ$DÀtÑ$KÓLÔMØ�M‰M¨F°dªN˜&Ÿ,™,œ.ÀÔFØ�L‰L˜E˜7 " U GÐ,Ô-Ø�G‰G˜ BˆGÔ'Ü# GÖ,‘��3Ø—‘˜˜C™ 2§;¡;£=°Ñ#3°dÑ#:Ñ:¸AÀ#ÀcÁ(È3ÀÐU]Ðhi�Õjò -ò #bð Xð  ‡L�LÐ\Ðgi€LÔjØ‡K�K”Ð,Ñ,°#€KÔ6Ü‡I�Iˆc…Nùònùò 5ùÚ>s   Á#)HÃHÃ(Hc                 ó  — t         j                  dd¬«       t        «       } t         dz  j                  ddd¬«      5 }t	        j
                  |t        | d   «      ¬	«      }|j                  «        |j                  | «       d d d «       d
ddddœddg d¢| dœ}t         dz  j                  t        j                  |d¬«      d¬«       t        | «       t        d„ | D «       «      }t        d„ | D «       «      }t        | d„ ¬«      }t        | d„ ¬«      }t        | d„ ¬«      }t        | d„ ¬«      }	dj                  d„ t!        | d„ d¬«      D «       «      }
dj                  d„ | D «       «      }dj                  g d ‘t#        j$                  |d!   «      › ‘d"‘|d#   d$›‘d%‘t#        j$                  |d!   «      › ‘d"‘|d&   d$›‘d'‘t#        j$                  |d!   «      › ‘d"‘|d(   d$›‘d)‘t#        j$                  |	d!   «      › ‘d"‘|	d*   d$›‘d+‘|d#   d$›‘d,‘|d&   d$›‘d-‘|d(   d$›‘d,‘|d*   d$›‘d.‘|d#   |d#   z
  d$›‘d/‘|
› ‘d0‘|› ‘d1‘«      }t         d2z  j                  |d¬«       t'        t         d2z  «       y # 1 sw Y   �ŒùxY w)3NT)ÚparentsÚexist_okz
report.csvÚwr)   r   )Únewliner
   r   )Ú
fieldnamesÚ)saved_same_run_weak_label_risk_comparisonFrZ   r   )ÚAC28ÚME1a_DTzUCAD-mapped 10 mm CSV-seeded weak risk mask on AC28 18h01 and ME1a 14h06 training runs)z7Unvalidated CAD-to-scan registration and defect extentszADifferent training epochs, source domains and CAD mapping supportzIRisk GNN was trained on two AC28 runs; other prior AC28 models used 18h01zMOptimized residual GNN predicts risk only; Risk GNN also predicts deformation)ÚstatusÚproduction_validÚpart_run_countÚ
evaluationÚheld_out_baselines_availableÚlimitationsr    zreport.json)Úindentr	   c              3  ó2   K  — | ]  }|d    dk(  sŒ|–— Œ y­w)r&   r5   Nr   ©r   Úrs     r   r   zwrite.<locals>.<genexpr>g   ó   è ø€ Ð<™4�a 1 W¡:°Ó#;”™4ùó   ‚�c              3  ó2   K  — | ]  }|d    dk(  sŒ|–— Œ y­w)r&   zMesh GNNNr   r­   s     r   r   zwrite.<locals>.<genexpr>h   r¯   r°   c                ó   — | d   S )Nr*   r   ©r®   s    r   rg   zwrite.<locals>.<lambda>i   ó   €  A i¢Lr   rh   c                ó   — | d   S )Nr,   r   r³   s    r   rg   zwrite.<locals>.<lambda>j   ó   €  Q z¢]r   c                ó   — | d   S ©Nr7   r   r³   s    r   rg   zwrite.<locals>.<lambda>k   r´   r   c                ó   — | d   S )Nr8   r   r³   s    r   rg   zwrite.<locals>.<lambda>l   r¶   r   c              3  óÀ   K  — | ]V  }d t        j                  |d   «      › d|d   d›d|d   d›d|d   d›d|d   d›d|d	   d›d|d
   d›d|d   › d|d   › d�–— ŒX y­w)ú<tr><th>r&   ú	</th><td>r*   rs   ú	</td><td>r,   r7   r8   r0   r:   r2   r;   ú
</td></tr>N©ÚhtmlÚescaper­   s     r   r   zwrite.<locals>.<genexpr>m   s±   è ø€ ð Iñ HˆAð ”4—;‘;˜q ™zÓ*Ð+¨9°Q°y±\À#Ð4FÀiÐPQÐR\ÑP]Ð^aÐObð cØ�‰|˜CÐ  	¨!¨J©-¸Ð)<¸IÀaÈÑFXÐY\ÐE]ð ^Ø�Ñ! #Ð& i°°-Ñ0@Ð/AÀÈ1È]ÑK[ÐJ\Ð\fô	hñ Hùs   ‚AAc                ó   — | d   S r¸   r   r³   s    r   rg   zwrite.<locals>.<lambda>q   s   € ¨A¨iªLr   )rf   Úreversec           
   3  ó¸   K  — | ]R  }d t        j                  |d   «      › dt        j                  |d   «      › dt        j                  |d   «      › d�–— ŒT y­w)r»   r&   r¼   r4   r½   r<   r¾   Nr¿   r­   s     r   r   zwrite.<locals>.<genexpr>r   se   è ø€ ð \ÙVZÐQRð  ¤§¡¨A¨g©JÓ 7Ð8¸	Ä$Ç+Á+ÈaÐPdÑNeÓBfÐAgð hÜ ŸK™K¨Ð*>Ñ(?Ó@ÐAÀôMÙVZùs   ‚AAa  <!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>AC28 and ME1a: all risk models compared</title>
<style>body{font:15px/1.5 system-ui,sans-serif;max-width:1400px;margin:auto;padding:24px;background:#f4f7fb;color:#1c2b3a}section{background:white;border:1px solid #dbe3ec;border-radius:10px;padding:18px;margin:17px 0}.warning{background:#fff0cc;border-left:5px solid #b98109;padding:14px}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(270px,1fr));gap:10px}.grid div{background:#eaf2f8;border-radius:8px;padding:12px}table{border-collapse:collapse;width:100%;min-width:850px}th,td{border-bottom:1px solid #dce3eb;padding:7px;text-align:right;white-space:nowrap}th:first-child,td:first-child{text-align:left}.scroll{overflow:auto}img{max-width:100%}a{color:#125d91}</style>
<h1>Is Risk GNN the best risk model?</h1><p class="warning">These are fits to provisional masks on the training runs, with unvalidated scan registration. Output resolutions, CAD mapping coverage, loss functions and epoch counts differ. The table can compare saved diagnostics; it cannot identify the best production predictor. Other model families have no held-out run scores.</p>
<section><div class="grid"><div><b>AC28 highest AP</b><br>r&   ro   r*   rs   z&</div><div><b>AC28 highest IoU</b><br>r,   z%</div><div><b>ME1a highest AP</b><br>r7   z&</div><div><b>ME1a highest IoU</b><br>r8   z2</div></div><p><strong>Risk GNN:</strong> AC28 AP z, IoU z
; ME1a AP z$. Its AC28 AP lead over Mesh GNN is a´  . It does not lead AC28 IoU or either ME1a metric. The optimized residual GNN predicts risk only; Risk GNN also emits a deformation field.</p></section>
<section><h2>All saved model results on common CAD nodes</h2><div class="scroll"><table><thead><tr><th>Model</th><th>AC28 AP</th><th>AC28 IoU</th><th>ME1a AP</th><th>ME1a IoU</th><th>AC28 coverage</th><th>ME1a coverage</th><th>AC28 epochs</th><th>ME1a epochs</th></tr></thead><tbody>a3  </tbody></table></div><img src="model_comparison.png" alt="AP and IoU of all models on AC28 and ME1a"></section>
<section><h2>Training scope</h2><p>The Risk GNN used both AC28 runs for its AC28 entry. Other original models used AC28 18h01. The residual GNN individual entry uses one run of each part; its joint entry uses both AC28 runs and ME1a. Every displayed score evaluates a run included in that model's training. Only the residual GNN has a separate leave-one-run-out experiment, and its held-out IoU was zero for all three runs. The five conditional diffusion variants generate outputs on different native domains; their diagnostic risk scores are in the main report and are not ranked here.</p><div class="scroll"><table><thead><tr><th>Model</th><th>AC28 training</th><th>ME1a training</th></tr></thead><tbody>uÌ  </tbody></table></div><p><a href="../gnn_joint_hard/index.html">Residual GNN held-out experiment</a> Â· <a href="../../models/cad_predictions/index.html">AC28 model gallery</a> Â· <a href="../../../experiments/ME1a_DT/results/models/cad_predictions/index.html">ME1a model gallery</a></p></section>
<p><a href="report.csv">All metrics CSV</a> Â· <a href="report.json">Machine-readable results</a> Â· <a href="../index.html">Main comparison report</a></p></html>z
index.html)r�   ÚmkdirrX   ÚopenÚcsvÚ
DictWriterÚlistÚwriteheaderÚ	writerowsÚ
write_textr   Údumpsr›   r   r„   Újoinr|   rÀ   rÁ   Úprint)r    ÚfhÚwriterÚresultÚriskÚmeshÚac_apÚac_iouÚme_apÚme_iouÚ
table_rowsÚscopesÚpages                r   ÚwriterÜ   V   sè  € Ü‡I�I�d T€IÔ*Ü‹9€DÜ
�Ñ
×	"Ñ	" 3°¸WÐ	"Ô	EÈÜ—‘ ¬t°D¸±G«}Ô=ˆØ×ÑÔ˜f×.Ñ.¨tÔ4÷ 
Fð DÐY^Ø)*°qÑ 9ØsØ.3òoð ñ€Fô 	ˆ=Ñ×$Ñ$¤T§Z¡Z°¸qÔ%AÈGÐ$ÔTÜ
ˆ4„LÜÑ<™4Ó<Ó<€DÜÑ<™4Ó<Ó<€DÜ�Ñ0Ô1€EÜ�Ñ2Ô3€FÜ�Ñ0Ô1€EÜ�Ñ2Ô3€FØ—‘ñ Iô ˜Ñ"8À$ÕGó	Ió I€Jð
 �W‰Wñ \ÙVZó\ó \€F÷fó fð ;ð fô <@¿;¹;ÀuÈWÁ~Ó;VÐ:Wðfð XZðfð [`Ð`iÑZjÐknÐYoðfð pVðfô W[÷  Wbñ  Wbð  cið  jqñ  cró  Wsð  Vtðfð tvðfð w}ð  ~Hñ  wIð  JMð  vNðfð Nsðfô tx÷  tñ  tð  @Eð  FMñ  @Nó  tOð  sPðfð PRðfð SXð  Ybñ  Scð  dgð  Rhðfð hNðfô OS÷  OZñ  OZð  [að  biñ  [jó  Okð  Nlðfð lnðfð ouð  v@ñ  oAð  BEð  nFðfð Fxðfð y}ð  ~Gñ  yHð  ILð  xMðfð MSðfð TXð  Ycñ  Tdð  ehð  Siðfð isðfð txð  yBñ  tCð  DGð  sHðfð HNðfð OSð  T^ñ  O_ð  `cð  Ndðfð dH	ðfð I	M	ð  N	W	ñ  I	X	ð  Y	]	ð  ^	g	ñ  Y	h	ñ  I	h	ð  i	l	ð  H	m	ðfðm	\ðfð ]gð  \hð	fðhCð	fð
 DJð  CKðfð
Kcôf€Dô 	ˆ<Ñ×#Ñ# D°7Ð#Ô;Ü	Œ#�Ñ
Õ÷G 
FÑ	Eús   ½AI9É9JÚ__main__)r   r   ÚreturnÚdict)r    ú
list[dict]r   Ústrr   rá   rÞ   rß   )rÞ   rà   )r    rà   rÞ   ÚNone)rÞ   râ   )Ú__doc__Ú
__future__r   rÇ   rÀ   r   Úpathlibr   Ú
matplotlibÚuseÚmatplotlib.pyplotÚpyplotry   Únumpyr~   Ú__file__Úresolver�   rL   r�   rM   r   r!   rX   r›   rÜ   Ú__name__r   r   r   Ú<module>rî      sŽ   ðá JÝ "ã 
Û Û Ý ã Ø €
‡�ˆuÔ Ý Û á
ˆx‹.×
 Ñ
 Ó
"×
*Ñ
*¨1Ñ
-€ØÐ:Ñ:€ØÐ-Ñ-€ó8óFó
óDó.&ðR ˆzÒ™5�7Ðr   