From 70e753333f6b5bd0b1eb98d5837b8dc38eced99c Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Mon, 24 Nov 2025 19:26:20 -0300 Subject: [PATCH] [Added][ConsolidateMetrics] Resume consolidation --- example_workflows/Compare_Masks_Dataset7.json | 1 + src/nodes/nodes_img.py | 120 +++++++++++++++--- 2 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 example_workflows/Compare_Masks_Dataset7.json diff --git a/example_workflows/Compare_Masks_Dataset7.json b/example_workflows/Compare_Masks_Dataset7.json new file mode 100644 index 0000000..02d25dc --- /dev/null +++ b/example_workflows/Compare_Masks_Dataset7.json @@ -0,0 +1 @@ +{"id":"e3e0b5c0-c671-4586-ad36-5ed9911d0f3b","revision":0,"last_node_id":128,"last_link_id":275,"nodes":[{"id":14,"type":"PreviewImage","pos":[2375,2100],"size":[660,420],"flags":{},"order":10,"mode":0,"inputs":[{"localized_name":"images","name":"images","type":"IMAGE","link":17}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.59","Node name for S&R":"PreviewImage","ue_properties":{"version":"7.0.1","widget_ue_connectable":{}},"widget_ue_connectable":{}},"widgets_values":[],"color":"#232","bgcolor":"#353"},{"id":13,"type":"SET_MaskDifference","pos":[2050,2100],"size":[270,78],"flags":{},"order":8,"mode":0,"inputs":[{"localized_name":"result","name":"result","type":"MASK","link":15},{"localized_name":"reference","name":"reference","type":"MASK","link":65},{"localized_name":"mode","name":"mode","type":"COMBO","widget":{"name":"mode"},"link":null}],"outputs":[{"localized_name":"IMAGE","name":"IMAGE","type":"IMAGE","links":[17]}],"properties":{"cnr_id":"image-misc","ver":"64eafc6402dab88363d4529b10ced54eb8a60eb2","Node name for S&R":"SET_MaskDifference","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"mode":true}},"widget_ue_connectable":{"mode":true}},"widgets_values":["Simple (Red/Green)"],"color":"#2a363b","bgcolor":"#3f5159"},{"id":11,"type":"SET_MaskLoad","pos":[1450,2600],"size":[410,450],"flags":{"collapsed":false},"order":6,"mode":0,"inputs":[{"localized_name":"file_name","name":"file_name","type":"STRING","widget":{"name":"file_name"},"link":73},{"localized_name":"batch_size","name":"batch_size","type":"INT","widget":{"name":"batch_size"},"link":null},{"localized_name":"channel","name":"channel","shape":7,"type":"COMBO","widget":{"name":"channel"},"link":null},{"localized_name":"show_preview","name":"show_preview","shape":7,"type":"BOOLEAN","widget":{"name":"show_preview"},"link":null}],"outputs":[{"localized_name":"mask","name":"mask","shape":6,"type":"MASK","links":[10,65]},{"localized_name":"file_name","name":"file_name","shape":6,"type":"STRING","links":null}],"properties":{"cnr_id":"image-misc","ver":"64eafc6402dab88363d4529b10ced54eb8a60eb2","Node name for S&R":"SET_MaskLoad","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"file_name":true,"batch_size":true,"channel":true,"show_preview":true}},"widget_ue_connectable":{"file_name":true,"batch_size":true,"channel":true,"show_preview":true}},"widgets_values":["SOD/gt/Dataset_1/im005.png",1,"red",true],"color":"#2a363b","bgcolor":"#3f5159"},{"id":50,"type":"SET_ConsolidateMetrics","pos":[2450,2725],"size":[270,126],"flags":{"collapsed":false},"order":9,"mode":0,"inputs":[{"localized_name":"metrics","name":"metrics","type":"DICT","link":81},{"localized_name":"img_name","name":"img_name","type":"STRING","link":82},{"localized_name":"destination","name":"destination","type":"STRING","widget":{"name":"destination"},"link":262},{"localized_name":"metric_ids","name":"metric_ids","shape":7,"type":"STRING","widget":{"name":"metric_ids"},"link":273},{"localized_name":"res_destination","name":"res_destination","shape":7,"type":"STRING","widget":{"name":"res_destination"},"link":274}],"outputs":[{"localized_name":"consolidated","name":"consolidated","shape":6,"type":"DICT","links":[218]}],"properties":{"cnr_id":"image-misc","ver":"4cb9bf3d81bc1778546ceb399d2b31dd65950a68","Node name for S&R":"SET_ConsolidateMetrics","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"destination":true}},"widget_ue_connectable":{"destination":true}},"widgets_values":["./result","",""],"color":"#2a363b","bgcolor":"#3f5159"},{"id":12,"type":"SET_MaskLoad","pos":[1450,2100],"size":[400,440],"flags":{"collapsed":false},"order":5,"mode":0,"inputs":[{"localized_name":"file_name","name":"file_name","type":"STRING","widget":{"name":"file_name"},"link":159},{"localized_name":"batch_size","name":"batch_size","type":"INT","widget":{"name":"batch_size"},"link":null},{"localized_name":"channel","name":"channel","shape":7,"type":"COMBO","widget":{"name":"channel"},"link":null},{"localized_name":"show_preview","name":"show_preview","shape":7,"type":"BOOLEAN","widget":{"name":"show_preview"},"link":null}],"outputs":[{"localized_name":"mask","name":"mask","shape":6,"type":"MASK","links":[12,15]},{"localized_name":"file_name","name":"file_name","shape":6,"type":"STRING","links":[]}],"properties":{"cnr_id":"image-misc","ver":"64eafc6402dab88363d4529b10ced54eb8a60eb2","Node name for S&R":"SET_MaskLoad","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"file_name":true,"batch_size":true,"channel":true,"show_preview":true}},"widget_ue_connectable":{"file_name":true,"batch_size":true,"channel":true,"show_preview":true}},"widgets_values":["",1,"red",true],"color":"#2a363b","bgcolor":"#3f5159"},{"id":92,"type":"SET_PlotMetricCurvesPIL","pos":[3175,2725],"size":[270,174],"flags":{},"order":11,"mode":0,"inputs":[{"localized_name":"metrics","name":"metrics","type":"DICT","link":218},{"localized_name":"legend_labels","name":"legend_labels","shape":7,"type":"STRING","link":275},{"localized_name":"plot_title","name":"plot_title","type":"STRING","widget":{"name":"plot_title"},"link":238},{"localized_name":"curve_color","name":"curve_color","type":"STRING","widget":{"name":"curve_color"},"link":null},{"localized_name":"width","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"height","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"auto_scale","name":"auto_scale","type":"BOOLEAN","widget":{"name":"auto_scale"},"link":null}],"outputs":[{"localized_name":"pr_curve_plot","name":"pr_curve_plot","type":"IMAGE","links":[167]},{"localized_name":"fm_curve_plot","name":"fm_curve_plot","type":"IMAGE","links":[171]}],"properties":{"cnr_id":"image-misc","ver":"4cb9bf3d81bc1778546ceb399d2b31dd65950a68","Node name for S&R":"SET_PlotMetricCurvesPIL","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"plot_title":true,"curve_color":true,"width":true,"height":true}},"widget_ue_connectable":{"plot_title":true,"curve_color":true,"width":true,"height":true,"auto_scale":true}},"widgets_values":["Dataset_1","red blue",1600,1200,true],"color":"#2a363b","bgcolor":"#3f5159"},{"id":95,"type":"PreviewImage","pos":[3500,2750],"size":[1150,600],"flags":{},"order":13,"mode":0,"inputs":[{"localized_name":"images","name":"images","type":"IMAGE","link":171}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.59","Node name for S&R":"PreviewImage","ue_properties":{"version":"7.0.1","widget_ue_connectable":{}},"widget_ue_connectable":{}},"widgets_values":[],"color":"#232","bgcolor":"#353"},{"id":93,"type":"PreviewImage","pos":[3500,2150],"size":[1150,525],"flags":{},"order":12,"mode":0,"inputs":[{"localized_name":"images","name":"images","type":"IMAGE","link":167}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.59","Node name for S&R":"PreviewImage","ue_properties":{"version":"7.0.1","widget_ue_connectable":{}},"widget_ue_connectable":{}},"widgets_values":[],"color":"#232","bgcolor":"#353"},{"id":120,"type":"Basic data handling: DataListCreate","pos":[375,2725],"size":[210,106],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"item_0","name":"item_0","shape":7,"type":"*","widget":{"name":"item_0"},"link":null},{"name":"item_1","shape":7,"type":"*","widget":{"name":"item_1"},"link":null},{"name":"item_2","shape":7,"type":"*","widget":{"name":"item_2"},"link":null}],"outputs":[{"localized_name":"list","name":"list","shape":6,"type":"*","links":[238,254]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"34e0ef423b283ccb6d3b5aeb20f12535abc21774","Node name for S&R":"Basic data handling: DataListCreate","widget_ue_connectable":{}},"widgets_values":["Dataset_1","Dataset_2",""],"color":"#233","bgcolor":"#355"},{"id":121,"type":"Basic data handling: DataListCreate","pos":[375,2550],"size":[210,106],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"item_0","name":"item_0","shape":7,"type":"*","widget":{"name":"item_0"},"link":null},{"name":"item_1","shape":7,"type":"*","widget":{"name":"item_1"},"link":null},{"name":"item_2","shape":7,"type":"*","widget":{"name":"item_2"},"link":null}],"outputs":[{"localized_name":"list","name":"list","shape":6,"type":"*","links":[253]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"34e0ef423b283ccb6d3b5aeb20f12535abc21774","Node name for S&R":"Basic data handling: DataListCreate","widget_ue_connectable":{}},"widgets_values":["Method_1","Method_2",""],"color":"#233","bgcolor":"#355"},{"id":17,"type":"PrimitiveString","pos":[325,2900],"size":[270,58],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"value","name":"value","type":"STRING","widget":{"name":"value"},"link":null}],"outputs":[{"localized_name":"STRING","name":"STRING","type":"STRING","links":[252]}],"title":"Base path","properties":{"cnr_id":"comfy-core","ver":"0.3.59","Node name for S&R":"PrimitiveString","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"value":true}},"widget_ue_connectable":{"value":true}},"widgets_values":["SOD"],"color":"#232","bgcolor":"#353"},{"id":1,"type":"SET_SaliencyEvaluationMetrics","pos":[2000,2350],"size":[300,630],"flags":{"collapsed":false},"order":7,"mode":0,"inputs":[{"localized_name":"prediction","name":"prediction","type":"MASK","link":12},{"localized_name":"ground_truth","name":"ground_truth","type":"MASK","link":10},{"localized_name":"img_name","name":"img_name","shape":7,"type":"STRING","link":74},{"localized_name":"normalize","name":"normalize","shape":7,"type":"BOOLEAN","widget":{"name":"normalize"},"link":null},{"localized_name":"result_save","name":"result_save","shape":7,"type":"BOOLEAN","widget":{"name":"result_save"},"link":null},{"localized_name":"mae_enable","name":"mae_enable","shape":7,"type":"BOOLEAN","widget":{"name":"mae_enable"},"link":null},{"localized_name":"mae_save","name":"mae_save","shape":7,"type":"BOOLEAN","widget":{"name":"mae_save"},"link":null},{"localized_name":"max_f_mes_enable","name":"max_f_mes_enable","shape":7,"type":"BOOLEAN","widget":{"name":"max_f_mes_enable"},"link":null},{"localized_name":"max_f_mes_save","name":"max_f_mes_save","shape":7,"type":"BOOLEAN","widget":{"name":"max_f_mes_save"},"link":null},{"localized_name":"s_mes_enable","name":"s_mes_enable","shape":7,"type":"BOOLEAN","widget":{"name":"s_mes_enable"},"link":null},{"localized_name":"s_mes_save","name":"s_mes_save","shape":7,"type":"BOOLEAN","widget":{"name":"s_mes_save"},"link":null},{"localized_name":"e_mes_enable","name":"e_mes_enable","shape":7,"type":"BOOLEAN","widget":{"name":"e_mes_enable"},"link":null},{"localized_name":"e_mes_save","name":"e_mes_save","shape":7,"type":"BOOLEAN","widget":{"name":"e_mes_save"},"link":null},{"localized_name":"wf_mes_enable","name":"wf_mes_enable","shape":7,"type":"BOOLEAN","widget":{"name":"wf_mes_enable"},"link":null},{"localized_name":"wf_mes_save","name":"wf_mes_save","shape":7,"type":"BOOLEAN","widget":{"name":"wf_mes_save"},"link":null}],"outputs":[{"localized_name":"all","name":"all","shape":6,"type":"DICT","links":[81]},{"localized_name":"img_name","name":"img_name","shape":6,"type":"STRING","links":[82]},{"localized_name":"MAE","name":"MAE","type":"FLOAT","links":null},{"localized_name":"Max_F-measure","name":"Max_F-measure","type":"FLOAT","links":null},{"localized_name":"S-measure","name":"S-measure","type":"FLOAT","links":null},{"localized_name":"E-measure","name":"E-measure","type":"FLOAT","links":null},{"localized_name":"Weighted_F-measure","name":"Weighted_F-measure","type":"FLOAT","links":null}],"properties":{"cnr_id":"image-misc","ver":"64eafc6402dab88363d4529b10ced54eb8a60eb2","Node name for S&R":"SET_SaliencyEvaluationMetrics","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"result_save":true,"mae_enable":true,"mae_save":true,"max_f_mes_enable":true,"max_f_mes_save":true,"s_mes_enable":true,"s_mes_save":true,"e_mes_enable":true,"e_mes_save":true,"wf_mes_enable":true,"wf_mes_save":true}},"widget_ue_connectable":{"normalize":true,"result_save":true,"mae_enable":true,"mae_save":true,"max_f_mes_enable":true,"max_f_mes_save":true,"s_mes_enable":true,"s_mes_save":true,"e_mes_enable":true,"e_mes_save":true,"wf_mes_enable":true,"wf_mes_save":true}},"widgets_values":["
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
","
MAE0.0000
Fβmax0.0000
Sα0.0000
Eϕmean0.0000
Eϕmax0.0000
Eϕadp0.0000
Fβw0.0000
"],"color":"#2a363b","bgcolor":"#3f5159"},{"id":44,"type":"SET_ImageDataset","pos":[1075,2575],"size":[270,338],"flags":{"collapsed":false},"order":4,"mode":0,"inputs":[{"localized_name":"source","name":"source","type":"STRING","widget":{"name":"source"},"link":261},{"localized_name":"pattern","name":"pattern","type":"STRING","widget":{"name":"pattern"},"link":null},{"localized_name":"destination","name":"destination","type":"STRING","widget":{"name":"destination"},"link":263},{"localized_name":"dest_ext","name":"dest_ext","type":"STRING","widget":{"name":"dest_ext"},"link":null},{"localized_name":"reference","name":"reference","shape":7,"type":"STRING","widget":{"name":"reference"},"link":272},{"localized_name":"sort_method","name":"sort_method","shape":7,"type":"COMBO","widget":{"name":"sort_method"},"link":null},{"localized_name":"image_load_cap","name":"image_load_cap","shape":7,"type":"INT","widget":{"name":"image_load_cap"},"link":null},{"localized_name":"skip_first_images","name":"skip_first_images","shape":7,"type":"INT","widget":{"name":"skip_first_images"},"link":null},{"localized_name":"select_every_nth","name":"select_every_nth","shape":7,"type":"INT","widget":{"name":"select_every_nth"},"link":null},{"localized_name":"random_seed","name":"random_seed","shape":7,"type":"INT","widget":{"name":"random_seed"},"link":null},{"localized_name":"block_when_finished","name":"block_when_finished","shape":7,"type":"BOOLEAN","widget":{"name":"block_when_finished"},"link":null}],"outputs":[{"localized_name":"images","name":"images","shape":6,"type":"STRING","links":[159]},{"localized_name":"results","name":"results","shape":6,"type":"STRING","links":[74]},{"localized_name":"references","name":"references","shape":6,"type":"STRING","links":[73]}],"properties":{"cnr_id":"image-misc","ver":"a34689b27c842b792cb0fc8011ac5fe1d6ebe8d8","Node name for S&R":"SET_ImageDataset","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"source":true,"pattern":true,"destination":true,"dest_ext":true,"reference":true,"sort_method":true,"image_load_cap":true,"skip_first_images":true,"select_every_nth":true,"random_seed":true}},"widget_ue_connectable":{"source":true,"pattern":true,"destination":true,"dest_ext":true,"reference":true,"sort_method":true,"image_load_cap":true,"skip_first_images":true,"select_every_nth":true,"random_seed":true,"block_when_finished":true}},"widgets_values":["./dataset/im",".*","./result","csv","./dataset/gt","Alphabetical (ASC)",16,0,1,1,false],"color":"#2a363b","bgcolor":"#3f5159"},{"id":126,"type":"3ce0ebe0-ef07-4967-827e-9715b95b02c8","pos":[675,2625],"size":[210,158],"flags":{"collapsed":false},"order":3,"mode":0,"inputs":[{"label":"base_path","localized_name":"path2","name":"path2","type":"STRING","widget":{"name":"path2"},"link":252},{"label":"methods","localized_name":"list_A","name":"list_A","type":"*","link":253},{"label":"datasets","localized_name":"list_B","name":"list_B","type":"*","link":254}],"outputs":[{"label":"input","name":"path","type":"STRING","links":[261]},{"label":"output","name":"path_1","type":"STRING","links":[262,263]},{"label":"gt","name":"path_2","type":"STRING","links":[272]},{"label":"output_id","name":"STRING","type":"STRING","links":[273]},{"label":"output_base","name":"path_3","type":"STRING","links":[274]},{"label":"legend_labels","name":"B_out","type":"*","links":[275]}],"properties":{"proxyWidgets":[["-1","path2"]],"cnr_id":"comfy-core","ver":"0.3.66","widget_ue_connectable":{}},"widgets_values":["pred_maps"],"color":"#323","bgcolor":"#535"}],"links":[[10,11,0,1,1,"MASK"],[12,12,0,1,0,"MASK"],[15,12,0,13,0,"MASK"],[17,13,0,14,0,"IMAGE"],[65,11,0,13,1,"MASK"],[73,44,2,11,0,"STRING"],[74,44,1,1,2,"STRING"],[81,1,0,50,0,"DICT"],[82,1,1,50,1,"STRING"],[159,44,0,12,0,"STRING"],[167,92,0,93,0,"IMAGE"],[171,92,1,95,0,"IMAGE"],[218,50,0,92,0,"DICT"],[238,120,0,92,2,"STRING"],[252,17,0,126,0,"STRING"],[253,121,0,126,1,"*"],[254,120,0,126,2,"*"],[261,126,0,44,0,"STRING"],[262,126,1,50,2,"STRING"],[263,126,1,44,2,"STRING"],[272,126,2,44,4,"STRING"],[273,126,3,50,3,"STRING"],[274,126,4,50,4,"STRING"],[275,126,5,92,1,"STRING"]],"groups":[{"id":2,"title":"Load and compare","bounding":[1425,2000,1630,1060],"color":"#3f789e","font_size":24,"flags":{}},{"id":3,"title":"Compose the image and reference paths","bounding":[300,2475,625,500],"color":"#3f789e","font_size":24,"flags":{}},{"id":7,"title":"Plots","bounding":[3475,2075,1200,1300],"color":"#3f789e","font_size":24,"flags":{}}],"definitions":{"subgraphs":[{"id":"3ce0ebe0-ef07-4967-827e-9715b95b02c8","version":1,"state":{"lastGroupId":7,"lastNodeId":134,"lastLinkId":273,"lastRerouteId":43},"revision":0,"config":{},"name":"Path create","inputNode":{"id":-10,"bounding":[-1025,2600,120,100]},"outputNode":{"id":-20,"bounding":[1325,2575,120,160]},"inputs":[{"id":"e82411a8-2a90-4c0a-961d-696d838e42fb","name":"path2","type":"STRING","linkIds":[51,40],"localized_name":"path2","label":"base_path","shape":7,"pos":[-925,2620]},{"id":"20f0405f-75f4-4d8c-b335-e089a50b43a7","name":"list_A","type":"*","linkIds":[242],"localized_name":"list_A","label":"methods","pos":[-925,2640]},{"id":"0f95981f-d683-4610-937a-99d4ae13e780","name":"list_B","type":"*","linkIds":[243],"localized_name":"list_B","label":"datasets","pos":[-925,2660]}],"outputs":[{"id":"5e724299-38ef-44b0-8fd8-1c51456b0a2c","name":"path","type":"STRING","linkIds":[256],"label":"input","pos":[1345,2595]},{"id":"fedc5410-87c6-420d-834c-34ff490b4e06","name":"path_1","type":"STRING","linkIds":[257],"label":"output","pos":[1345,2615]},{"id":"ad59d7eb-ff25-4efe-a2fe-9bebda625ddb","name":"path_2","type":"STRING","linkIds":[269],"label":"gt","pos":[1345,2635]},{"id":"e6c90c5d-f65b-4763-a700-070a164ca1c9","name":"STRING","type":"STRING","linkIds":[270],"label":"output_id","pos":[1345,2655]},{"id":"0bc818df-af4b-4548-b352-acdd653a0444","name":"path_3","type":"STRING","linkIds":[271],"label":"output_base","pos":[1345,2675]},{"id":"8e895392-8db5-4d48-bc2f-dbe20a92218e","name":"B_out","type":"*","linkIds":[273],"label":"legend_labels","pos":[1345,2695]}],"widgets":[],"nodes":[{"id":36,"type":"Basic data handling: PathJoin","pos":[-625,2900],"size":[270,82],"flags":{},"order":11,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":87},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":51}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[53,268,271]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","pred_maps"],"color":"#233","bgcolor":"#355"},{"id":33,"type":"Basic data handling: PathJoin","pos":[-625,2475],"size":[270,82],"flags":{},"order":10,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":86},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":40}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[41,42]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","pred_maps"],"color":"#233","bgcolor":"#355"},{"id":18,"type":"Basic data handling: PathJoin","pos":[-275,3100],"size":[270,82],"flags":{},"order":6,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":42},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":null}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[24]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","gt"],"color":"#233","bgcolor":"#355"},{"id":125,"type":"SET_CartesianProduct","pos":[-275,2625],"size":[210,78],"flags":{},"order":14,"mode":0,"inputs":[{"localized_name":"list_A","name":"list_A","type":"*","link":242},{"localized_name":"list_B","name":"list_B","type":"*","link":243},{"localized_name":"order","name":"order","type":"COMBO","widget":{"name":"order"},"link":null}],"outputs":[{"localized_name":"A_out","name":"A_out","shape":6,"type":"*","links":[251,254,255,260,262,273]},{"localized_name":"B_out","name":"B_out","shape":6,"type":"*","links":[248,252,253,265]}],"properties":{"cnr_id":"image-misc","ver":"d02c46e15c1d744d8c95d9ea071dea63a35cfc3d","Node name for S&R":"SET_CartesianProduct","widget_ue_connectable":{}},"widgets_values":["A_fast (A1, A2, A1...)"],"color":"#2a363b","bgcolor":"#3f5159"},{"id":19,"type":"Basic data handling: PathJoin","pos":[75,2350],"size":[270,82],"flags":{},"order":7,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":20},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":254}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[21]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","Method_2"],"color":"#233","bgcolor":"#355"},{"id":38,"type":"Basic data handling: PathJoin","pos":[100,2900],"size":[270,82],"flags":{},"order":12,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":53},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":255}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[55]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","gt"],"color":"#233","bgcolor":"#355"},{"id":54,"type":"Basic data handling: PathOutputDir","pos":[-850,2925],"size":[140,26],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"localized_name":"output_path","name":"output_path","type":"STRING","links":[87]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.7.0","Node name for S&R":"Basic data handling: PathOutputDir","widget_ue_connectable":{},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{}}},"widgets_values":[],"color":"#233","bgcolor":"#355"},{"id":53,"type":"Basic data handling: PathInputDir","pos":[-875,2500],"size":[140,26],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"localized_name":"input_path","name":"input_path","type":"STRING","links":[86]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.7.0","Node name for S&R":"Basic data handling: PathInputDir","widget_ue_connectable":{},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{}}},"widgets_values":[],"color":"#233","bgcolor":"#355"},{"id":16,"type":"Basic data handling: PathJoin","pos":[-275,2375],"size":[270,82],"flags":{},"order":5,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":41},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":null}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[20]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","pred_maps"],"color":"#233","bgcolor":"#355"},{"id":126,"type":"Note","pos":[400,2175],"size":[275,88],"flags":{},"order":2,"mode":0,"inputs":[],"outputs":[],"properties":{},"widgets_values":["INPUT/BASE_PATH/pred_maps/METHOD/DATASET"],"color":"#432","bgcolor":"#653"},{"id":127,"type":"Note","pos":[475,2725],"size":[275,88],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[],"properties":{},"widgets_values":["OUTPUT/BASE_PATH/METHOD/DATASET"],"color":"#432","bgcolor":"#653"},{"id":20,"type":"Basic data handling: PathJoin","pos":[400,2325],"size":[270,82],"flags":{},"order":8,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":21},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":253}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[68,256]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","pred_maps"],"color":"#233","bgcolor":"#355"},{"id":39,"type":"Basic data handling: PathJoin","pos":[475,2875],"size":[270,82],"flags":{},"order":13,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":55},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":248}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[69,85,257]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","gt"],"color":"#233","bgcolor":"#355"},{"id":129,"type":"Basic data handling: StringConcat","pos":[425,2500],"size":[270,82],"flags":{},"order":15,"mode":0,"inputs":[{"localized_name":"string_a","name":"string_a","type":"STRING","widget":{"name":"string_a"},"link":262},{"localized_name":"string_b","name":"string_b","type":"STRING","widget":{"name":"string_b"},"link":null}],"outputs":[{"localized_name":"STRING","name":"STRING","type":"STRING","links":[266]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"34e0ef423b283ccb6d3b5aeb20f12535abc21774","Node name for S&R":"Basic data handling: StringConcat","widget_ue_connectable":{}},"widgets_values":["","/"],"color":"#233","bgcolor":"#355"},{"id":128,"type":"Note","pos":[450,3200],"size":[275,88],"flags":{},"order":4,"mode":0,"inputs":[],"outputs":[],"properties":{},"widgets_values":["INPUT/BASE_PATH/gt/DATASET"],"color":"#432","bgcolor":"#653"},{"id":23,"type":"Basic data handling: PathJoin","pos":[450,3075],"size":[270,82],"flags":{},"order":9,"mode":0,"inputs":[{"localized_name":"path1","name":"path1","type":"STRING","widget":{"name":"path1"},"link":24},{"localized_name":"path2","name":"path2","shape":7,"type":"STRING","widget":{"name":"path2"},"link":252}],"outputs":[{"localized_name":"path","name":"path","type":"STRING","links":[70,261,269]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"0.6.0","Node name for S&R":"Basic data handling: PathJoin","widget_ue_connectable":{"path1":true,"path2":true},"cnr_id":"basic_data_handling","ue_properties":{"version":"7.0.1","widget_ue_connectable":{"path1":true,"path2":true}}},"widgets_values":["","pred_maps"],"color":"#233","bgcolor":"#355"},{"id":130,"type":"Basic data handling: StringConcat","pos":[750,2550],"size":[270,82],"flags":{},"order":16,"mode":0,"inputs":[{"localized_name":"string_a","name":"string_a","type":"STRING","widget":{"name":"string_a"},"link":266},{"localized_name":"string_b","name":"string_b","type":"STRING","widget":{"name":"string_b"},"link":265}],"outputs":[{"localized_name":"STRING","name":"STRING","type":"STRING","links":[267,270]}],"properties":{"aux_id":"set-soft/ComfyUI-basic_data_handling","ver":"34e0ef423b283ccb6d3b5aeb20f12535abc21774","Node name for S&R":"Basic data handling: StringConcat","widget_ue_connectable":{}},"widgets_values":["",""],"color":"#233","bgcolor":"#355"}],"groups":[],"links":[{"id":87,"origin_id":54,"origin_slot":0,"target_id":36,"target_slot":0,"type":"STRING"},{"id":86,"origin_id":53,"origin_slot":0,"target_id":33,"target_slot":0,"type":"STRING"},{"id":41,"origin_id":33,"origin_slot":0,"target_id":16,"target_slot":0,"type":"STRING"},{"id":42,"origin_id":33,"origin_slot":0,"target_id":18,"target_slot":0,"type":"STRING"},{"id":20,"origin_id":16,"origin_slot":0,"target_id":19,"target_slot":0,"type":"STRING"},{"id":53,"origin_id":36,"origin_slot":0,"target_id":38,"target_slot":0,"type":"STRING","parentId":39},{"id":24,"origin_id":18,"origin_slot":0,"target_id":23,"target_slot":0,"type":"STRING"},{"id":55,"origin_id":38,"origin_slot":0,"target_id":39,"target_slot":0,"type":"STRING"},{"id":248,"origin_id":125,"origin_slot":1,"target_id":39,"target_slot":1,"type":"STRING","parentId":37},{"id":21,"origin_id":19,"origin_slot":0,"target_id":20,"target_slot":0,"type":"STRING"},{"id":51,"origin_id":-10,"origin_slot":0,"target_id":36,"target_slot":1,"type":"STRING"},{"id":40,"origin_id":-10,"origin_slot":0,"target_id":33,"target_slot":1,"type":"STRING"},{"id":242,"origin_id":-10,"origin_slot":1,"target_id":125,"target_slot":0,"type":"*"},{"id":243,"origin_id":-10,"origin_slot":2,"target_id":125,"target_slot":1,"type":"*"},{"id":252,"origin_id":125,"origin_slot":1,"target_id":23,"target_slot":1,"type":"STRING","parentId":37},{"id":253,"origin_id":125,"origin_slot":1,"target_id":20,"target_slot":1,"type":"STRING","parentId":37},{"id":254,"origin_id":125,"origin_slot":0,"target_id":19,"target_slot":1,"type":"STRING","parentId":38},{"id":255,"origin_id":125,"origin_slot":0,"target_id":38,"target_slot":1,"type":"STRING","parentId":38},{"id":256,"origin_id":20,"origin_slot":0,"target_id":-20,"target_slot":0,"type":"STRING"},{"id":257,"origin_id":39,"origin_slot":0,"target_id":-20,"target_slot":1,"type":"STRING"},{"id":262,"origin_id":125,"origin_slot":0,"target_id":129,"target_slot":0,"type":"STRING","parentId":38},{"id":265,"origin_id":125,"origin_slot":1,"target_id":130,"target_slot":1,"type":"STRING","parentId":37},{"id":266,"origin_id":129,"origin_slot":0,"target_id":130,"target_slot":0,"type":"STRING"},{"id":269,"origin_id":23,"origin_slot":0,"target_id":-20,"target_slot":2,"type":"STRING"},{"id":270,"origin_id":130,"origin_slot":0,"target_id":-20,"target_slot":3,"type":"STRING"},{"id":271,"origin_id":36,"origin_slot":0,"target_id":-20,"target_slot":4,"type":"STRING","parentId":43},{"id":273,"origin_id":125,"origin_slot":0,"target_id":-20,"target_slot":5,"type":"*","parentId":38}],"reroutes":[{"id":37,"pos":[375,2700],"linkIds":[248,252,253,265],"floating":{"slotType":"input"}},{"id":38,"pos":[50,2650],"linkIds":[254,255,262,273]},{"id":39,"pos":[-127,2925],"linkIds":[53,271]},{"id":42,"parentId":39,"pos":[241.71608954802457,3332.165553229266],"linkIds":[271]},{"id":43,"parentId":42,"pos":[888.4060220513168,3330.9938990753385],"linkIds":[271]}],"extra":{}}]},"config":{},"extra":{"ue_links":[],"links_added_by_ue":[],"reroutes":[{"id":1,"parentId":35,"pos":[1100,3075],"linkIds":[262]},{"id":2,"parentId":1,"pos":[2375,3075],"linkIds":[262]},{"id":5,"pos":[1950,2400],"linkIds":[10,65]},{"id":7,"pos":[1450,2550],"linkIds":[74]},{"id":8,"parentId":7,"pos":[1925,2550],"linkIds":[74]},{"id":30,"parentId":33,"pos":[3075,3175],"linkIds":[275]},{"id":31,"parentId":36,"pos":[650,3200],"linkIds":[238]},{"id":32,"parentId":31,"pos":[3125,3200],"linkIds":[238]},{"id":33,"parentId":37,"pos":[950,3175],"linkIds":[275]},{"id":35,"pos":[975,2675],"linkIds":[262,263]},{"id":36,"pos":[625,2950],"linkIds":[238]},{"id":37,"pos":[900,2950],"linkIds":[275]},{"id":38,"pos":[1087.6217415055216,3115.295948478345],"linkIds":[273]},{"id":39,"parentId":38,"pos":[2395.4860537109425,3105.7106167853835],"linkIds":[273]},{"id":40,"pos":[1024.7846226889699,3140.8568091578745],"linkIds":[274]},{"id":41,"parentId":40,"pos":[2418.9168486259355,3141.921806287586],"linkIds":[274]}],"ds":{"scale":0.5830049367450394,"offset":[-863.2333867404435,-1383.8613732137217]},"linkExtensions":[{"id":10,"parentId":5},{"id":65,"parentId":5},{"id":74,"parentId":8},{"id":238,"parentId":32},{"id":262,"parentId":2},{"id":263,"parentId":35},{"id":273,"parentId":39},{"id":274,"parentId":41},{"id":275,"parentId":30}]},"version":0.4} \ No newline at end of file diff --git a/src/nodes/nodes_img.py b/src/nodes/nodes_img.py index 2fbbe51..449502d 100644 --- a/src/nodes/nodes_img.py +++ b/src/nodes/nodes_img.py @@ -102,6 +102,8 @@ SOD_NAMES = {'mae': "MAE", 'max_f_mes': "Max F-measure", 'adp_f_mes': "Adp F-mea REVERSE_SOD_NAMES = {v: k for k, v in SOD_NAMES.items()} IS_VECT_NAME = re.compile(r"(F|FP|FR|E)\((\d+)\)") VECT_NAMES = {'e', 'f', 'fp', 'fr'} +DATASET_NAMES = ['Fmax dataset', 'Fmean dataset', 'Emax dataset', 'Emean dataset'] + # A dictionary to cache loaded fonts font_cache = {} @@ -160,7 +162,7 @@ def expand_header_keys(header): key = key.upper() h.extend([f"{key}({c})" for c in range(F_POINTS)]) else: - h.append(SOD_NAMES[key]) + h.append(SOD_NAMES.get(key, key)) return h @@ -990,6 +992,10 @@ class ConsolidateMetrics(ComfyNodeABC): "If this is a directory the file\nwill be named `consolidated.csv` inside it" }), }, + "optional": { + "metric_ids": (IO.STRING, ), + "res_destination": (IO.STRING, ), + }, } INPUT_IS_LIST = True @@ -1028,7 +1034,7 @@ class ConsolidateMetrics(ComfyNodeABC): # Read the single value from the current position. scalar_str_value = row_data[data_col_idx] # Convert to float and store it in the dictionary. - metric_values[key] = float(scalar_str_value) + metric_values[key] = float(scalar_str_value) if scalar_str_value else 0 # Advance the column index by one. data_col_idx += 1 return metric_values @@ -1037,6 +1043,7 @@ class ConsolidateMetrics(ComfyNodeABC): existing_data = {} header = [] metric_keys_ordered = [] + totals = {} if dest_path.is_file(): try: @@ -1057,7 +1064,7 @@ class ConsolidateMetrics(ComfyNodeABC): if index == "0": metric_keys_ordered.append(vect_name.lower()) else: - metric_keys_ordered.append(REVERSE_SOD_NAMES.get(h)) + metric_keys_ordered.append(REVERSE_SOD_NAMES.get(h, h)) # Load existing rows, stopping at any blank line (which precedes totals). for row in reader: @@ -1071,16 +1078,29 @@ class ConsolidateMetrics(ComfyNodeABC): metric_values = self.compact_row(row[1:], metric_keys_ordered) existing_data[filename] = metric_values + totals_row = next(reader, ['']) + if totals_row[0] == 'Total': + totals = self.compact_row(totals_row[1:], metric_keys_ordered) + + for row in reader: + if not row: + continue + if len(row) >= 2: + totals[row[0]] = row[1] + except (IOError, StopIteration, IndexError, ValueError) as e: logger.warning(f"Could not properly read existing file at {dest_path}. It will be overwritten. Error: {e}") + raise existing_data = {} # Reset on read error - return existing_data, header, metric_keys_ordered + return existing_data, header, metric_keys_ordered, totals - def execute(self, metrics, img_name, destination): + def execute(self, metrics, img_name, destination, metric_ids=None, res_destination=None): n_metrics = len(metrics) n_img_name = len(img_name) n_destination = len(destination) + n_res_destination = 0 if res_destination is None else len(res_destination) + n_metric_ids = 0 if metric_ids is None else len(metric_ids) logger.debug(f"metrics: {n_metrics}") logger.debug(f"img_name: {n_img_name} {img_name}") @@ -1093,13 +1113,24 @@ class ConsolidateMetrics(ComfyNodeABC): raise ValueError(f"Got {n_metrics} metrics and {n_img_name} file names. They must match.") if n_metrics % n_destination != 0: raise ValueError(f"Got {n_metrics} metrics and {n_destination} destinations. They must be multiples.") + if n_res_destination > 1: + raise ValueError(f"Only one resume destination currently supported, got {n_res_destination}") + if n_res_destination and n_metric_ids != n_metrics: + raise ValueError(f"Got {n_metrics} metrics and {n_metric_ids} metric IDs. They must match.") slice_size = n_metrics // n_destination res = [] + totals = {} for c, d in enumerate(destination): start = c * slice_size end = start + slice_size - res.append(self.consolidate(metrics[start:end], img_name[start:end], d)) + data, total = self.consolidate(metrics[start:end], img_name[start:end], d) + res.append(data) + if n_res_destination: + totals[metric_ids[c]] = total + + if totals: + self.update_resume(res_destination[0], totals) return (res, ) @@ -1108,7 +1139,7 @@ class ConsolidateMetrics(ComfyNodeABC): if destination is None: # We don't even know where to consolidate data - return [{}] + return [{}], {} # Resolve the final destination path for the CSV file. dest_path = Path(get_output_directory(), destination) @@ -1118,14 +1149,14 @@ class ConsolidateMetrics(ComfyNodeABC): if metrics[0] is None or img_name[0] is None: # This is normal when all images are processed and we aren't blocking # In this case return what we already have on disk - existing_data, header, metric_keys_ordered = self.load_current_data(dest_path) - return [v for v in existing_data.values()] + existing_data, header, metric_keys_ordered, totals = self.load_current_data(dest_path) + return [v for v in existing_data.values()], totals # Ensure the parent directory exists. dest_path.parent.mkdir(exist_ok=True) # --- 2. Load Existing Data from CSV (if it exists) --- - existing_data, header, metric_keys_ordered = self.load_current_data(dest_path) + existing_data, header, metric_keys_ordered, _ = self.load_current_data(dest_path) # --- 3. Consolidate New Metrics --- @@ -1136,7 +1167,7 @@ class ConsolidateMetrics(ComfyNodeABC): if not existing_data: logger.warning("[Warning] No metrics to consolidate. Aborting file write.") - return [{}] + return [{}], {} # --- 4. Prepare for Writing (Sort and Define Header if New) --- @@ -1191,25 +1222,80 @@ class ConsolidateMetrics(ComfyNodeABC): Fmax = averages.get('f').max() if 'f' in averages else 0.0 Emax = averages.get('e').max() if 'e' in averages else 0.0 - if Fmax or Fmax: + if Fmax or Emax: writer.writerow([]) if Fmax: # This is the maximum for the average F-measure # Is more representative for the dataset than the average of the maximums of each image - writer.writerow(['Fmax dataset', f"{Fmax:.4f}"]) + key = 'Fmax dataset' + val = f"{Fmax:.4f}" + writer.writerow([key, val]) + averages[key] = val Ftot = averages.get('f').sum() - writer.writerow(['Fmean dataset', f"{Ftot/F_POINTS:.4f}"]) + key = 'Fmean dataset' + val = f"{Ftot/F_POINTS:.4f}" + writer.writerow([key, val]) + averages[key] = val # Do we have E(th)? if Emax: - writer.writerow(['Emax dataset', f"{Emax:.4f}"]) + key = 'Emax dataset' + val = f"{Emax:.4f}" + writer.writerow([key, val]) + averages[key] = val Etot = averages.get('e').sum() - writer.writerow(['Emean dataset', f"{Etot/F_POINTS:.4f}"]) + key = 'Emean dataset' + val = f"{Etot/F_POINTS:.4f}" + writer.writerow([key, val]) + averages[key] = val logger.info(f"Metrics consolidated and saved to {dest_path}") - return [v for v in existing_data.values()] + return [v for v in existing_data.values()], averages + + def update_resume(self, destination, totals): + # Resolve the final destination path for the CSV file. + dest_path = Path(get_output_directory(), destination) + if dest_path.is_dir(): + dest_path = dest_path / 'consolidated.csv' + + # Ensure the parent directory exists. + dest_path.parent.mkdir(exist_ok=True) + + # Load Existing Data from CSV (if it exists) + existing_data, header, metric_keys_ordered, _ = self.load_current_data(dest_path) + + # Consolidate New Metrics + # Add or update the new metrics into our dictionary of existing data. + existing_data.update(totals) + if not existing_data: + return + + # Prepare for Writing (Sort and Define Header if New) + # If the file was new, define the header and key order now. + if not header: + metric_keys_ordered = list(SOD_NAMES.keys()) + DATASET_NAMES + list(VECT_NAMES) + header = ["ID"] + expand_header_keys(metric_keys_ordered) + + # Sort the consolidated data alphabetically by ID. + sorted_ids = sorted(existing_data.keys()) + + # Write Consolidated File + with open(dest_path, 'w', newline='') as f: + writer = csv.writer(f) + + # Write the header. + writer.writerow(expand_header(header)) + + # Write the sorted data rows. + for id in sorted_ids: + metric_dict = existing_data[id] + row_data = [id] + expand_data_row(metric_dict, metric_keys_ordered) + writer.writerow(row_data) + + logger.info(f"Resumed metrics consolidated and saved to {dest_path}") + return # Most code from Gemini 3 Pro