@@ -481,6 +481,7 @@ def segment_volume(
481481) -> List [str ]:
482482 """Run segmentation tasks and optional post‐processing."""
483483 warnings : List [str ] = []
484+ ran_any_task = False
484485 tasks = tasks_config .get ("tasks" , [])
485486 if not tasks :
486487 raise ValueError ("No tasks provided in config" )
@@ -524,6 +525,7 @@ def segment_volume(
524525 task = task_name ,
525526 ** extra ,
526527 )
528+ ran_any_task = True
527529 except Exception as exc :
528530 logger .error (
529531 "Segmentation failed on %s (%s): %s" , nifti_path , task_name , exc
@@ -553,6 +555,13 @@ def segment_volume(
553555 merged_output = str (postprocess .get ("output" , "merged" )).strip () or "merged"
554556 merged_name = _output_to_filename (merged_output )
555557 dst = output_dir / merged_name
558+ if dst .exists () and not force and not ran_any_task :
559+ if verbose :
560+ logger .info (
561+ "Skip postprocess – output exists and row already has task outputs: %s" ,
562+ dst ,
563+ )
564+ return warnings
556565 if dst .exists ():
557566 warnings .append (
558567 f"Postprocess output will overwrite existing file and continue: { dst } "
@@ -800,12 +809,6 @@ def normalize_segment_args(args: argparse.Namespace) -> argparse.Namespace:
800809
801810def main (args : argparse .Namespace ) -> None :
802811 setup_logging (verbose = getattr (args , "verbose" , False ))
803- tasks_config = load_segmentation_config (
804- getattr (args , "manifest" , None ),
805- base_path = Path (__file__ ).resolve ().parents [1 ],
806- )
807- prefetch_totalsegmentator_models (tasks_config )
808-
809812 output_path = Path (args .csv_path_out )
810813 error_path = Path (args .error_csv_path )
811814
@@ -830,8 +833,21 @@ def main(args: argparse.Namespace) -> None:
830833 paths = resume_ctx ["paths" ]
831834 state = resume_ctx ["state" ]
832835 can_resume = resume_ctx ["can_resume" ]
836+ already_finished = resume_ctx ["already_finished" ]
833837 ckpt = CheckpointManager (paths = paths , config = resume_ctx ["config" ])
834838
839+ if already_finished :
840+ logger .info (
841+ "Resume enabled and matching segment run already finished; skipping execution."
842+ )
843+ return
844+
845+ tasks_config = load_segmentation_config (
846+ getattr (args , "manifest" , None ),
847+ base_path = Path (__file__ ).resolve ().parents [1 ],
848+ )
849+ prefetch_totalsegmentator_models (tasks_config )
850+
835851 from imperandi .utils .multiprocessing import (
836852 apply_strategy_env ,
837853 strategy_to_log_dict ,
0 commit comments