@@ -194,6 +194,88 @@ def fake_load_phase_extractor():
194194 assert extractor_loads ["count" ] == 1
195195
196196
197+ def test_main_skips_rows_with_existing_totalseg_phase_when_not_forced (
198+ tmp_path , monkeypatch
199+ ):
200+ nifti = tmp_path / "valid.nii.gz"
201+ nifti .write_text ("nifti" )
202+ csv_path = tmp_path / "nifti_index.csv"
203+ pd .DataFrame (
204+ [{"nifti_path" : str (nifti ), "totalseg_phase" : "portal" }]
205+ ).to_csv (csv_path , index = False )
206+
207+ calls = {"count" : 0 }
208+ monkeypatch .setattr (phase_module .nib , "load" , lambda _ : object ())
209+ monkeypatch .setattr (
210+ phase_module ,
211+ "_load_phase_extractor" ,
212+ lambda : (lambda _ , quiet = True : {"phase" : "arterial" }),
213+ )
214+
215+ def fake_process_single_volume (idx , row , * , phase_extractor , verbose = False ):
216+ calls ["count" ] += 1
217+ return idx , {"totalseg_phase" : "arterial" }, None
218+
219+ monkeypatch .setattr (phase_module , "process_single_volume" , fake_process_single_volume )
220+
221+ args = argparse .Namespace (
222+ csv_path = str (csv_path ),
223+ csv_path_out = str (tmp_path / "out.csv" ),
224+ error_csv_path = str (tmp_path / "errors.csv" ),
225+ verbose = False ,
226+ force = False ,
227+ checkpoint_every_rows = 1 ,
228+ checkpoint_every_sec = 3600 ,
229+ resume = False ,
230+ strict_resume = False ,
231+ )
232+ phase_module .main (args )
233+
234+ assert calls ["count" ] == 0
235+ out_df = pd .read_csv (args .csv_path_out )
236+ assert out_df .loc [0 , "totalseg_phase" ] == "portal"
237+
238+
239+ def test_main_force_recomputes_existing_totalseg_phase (tmp_path , monkeypatch ):
240+ nifti = tmp_path / "valid.nii.gz"
241+ nifti .write_text ("nifti" )
242+ csv_path = tmp_path / "nifti_index.csv"
243+ pd .DataFrame (
244+ [{"nifti_path" : str (nifti ), "totalseg_phase" : "portal" }]
245+ ).to_csv (csv_path , index = False )
246+
247+ calls = {"count" : 0 }
248+ monkeypatch .setattr (phase_module .nib , "load" , lambda _ : object ())
249+ monkeypatch .setattr (
250+ phase_module ,
251+ "_load_phase_extractor" ,
252+ lambda : (lambda _ , quiet = True : {"phase" : "arterial" }),
253+ )
254+
255+ def fake_process_single_volume (idx , row , * , phase_extractor , verbose = False ):
256+ calls ["count" ] += 1
257+ return idx , {"totalseg_phase" : "arterial" }, None
258+
259+ monkeypatch .setattr (phase_module , "process_single_volume" , fake_process_single_volume )
260+
261+ args = argparse .Namespace (
262+ csv_path = str (csv_path ),
263+ csv_path_out = str (tmp_path / "out.csv" ),
264+ error_csv_path = str (tmp_path / "errors.csv" ),
265+ verbose = False ,
266+ force = True ,
267+ checkpoint_every_rows = 1 ,
268+ checkpoint_every_sec = 3600 ,
269+ resume = False ,
270+ strict_resume = False ,
271+ )
272+ phase_module .main (args )
273+
274+ assert calls ["count" ] == 1
275+ out_df = pd .read_csv (args .csv_path_out )
276+ assert out_df .loc [0 , "totalseg_phase" ] == "arterial"
277+
278+
197279def test_main_preserves_foreign_columns_from_existing_output (tmp_path , monkeypatch ):
198280 nifti = tmp_path / "valid.nii.gz"
199281 nifti .write_text ("nifti" )
0 commit comments