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":["
| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.0000 |
","| MAE | 0.0000 |
| Fβmax | 0.0000 |
| Sα | 0.0000 |
| Eϕmean | 0.0000 |
| Eϕmax | 0.0000 |
| Eϕadp | 0.0000 |
| Fβw | 0.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