47
47
BOLD_PATH = "ds054/sub-100185/func/sub-100185_task-machinegame_run-01_bold.nii.gz"
48
48
49
49
50
+ def make_prep_and_save (
51
+ prep_interface ,
52
+ base_directory ,
53
+ out_path_base = None ,
54
+ ** kwargs ,
55
+ ):
56
+ if prep_interface is bintfs .DerivativesDataSink :
57
+ kwargs .update (out_path_base = out_path_base , base_directory = base_directory )
58
+
59
+ prep = save = prep_interface (** kwargs )
60
+
61
+ if prep_interface is not bintfs .DerivativesDataSink :
62
+ save = bintfs .SaveDerivative (base_directory = base_directory )
63
+
64
+ return prep , save
65
+
66
+
67
+ def connect_and_run_save (prep_result , save ):
68
+ if prep_result .interface is bintfs .DerivativesDataSink :
69
+ return prep_result
70
+
71
+ save .inputs .in_file = prep_result .outputs .out_file
72
+ save .inputs .relative_path = prep_result .outputs .out_path
73
+ save .inputs .metadata = prep_result .outputs .out_meta
74
+
75
+ return save .run ()
76
+
77
+
50
78
@pytest .mark .parametrize ("interface" , [bintfs .DerivativesDataSink , bintfs .PrepareDerivative ])
51
79
@pytest .mark .parametrize ("out_path_base" , [None , "fmriprep" ])
52
80
@pytest .mark .parametrize (
@@ -296,36 +324,26 @@ def test_DerivativesDataSink_build_path(
296
324
ds_inputs .append (str (fname ))
297
325
298
326
base_directory = tmp_path / "output"
299
- work_dir = tmp_path / "work"
300
327
base_directory .mkdir ()
301
- work_dir .mkdir ()
302
328
303
- prep = save = interface (
329
+ prep , save = make_prep_and_save (
330
+ interface ,
331
+ base_directory = str (base_directory ),
332
+ out_path_base = out_path_base ,
304
333
in_file = ds_inputs ,
305
334
source_file = source ,
306
335
dismiss_entities = dismiss_entities ,
307
336
** entities ,
308
- ** ({"out_path_base" : out_path_base } if interface == bintfs .DerivativesDataSink else {}),
309
337
)
310
- if interface == bintfs .DerivativesDataSink :
311
- prep .inputs .base_directory = str (base_directory )
312
- else :
313
- save = bintfs .SaveDerivative (base_directory = str (base_directory ))
314
-
315
338
if isinstance (expectation , type ):
316
339
with pytest .raises (expectation ):
317
340
prep .run ()
318
341
return
319
342
320
- prep_outputs = save_outputs = prep .run ().outputs
321
-
322
- if save is not prep :
323
- save .inputs .in_file = prep_outputs .out_file
324
- save .inputs .relative_path = prep_outputs .out_path
325
- save .inputs .metadata = prep_outputs .out_meta
326
- save_outputs = save .run ().outputs
343
+ prep_result = prep .run ()
344
+ save_result = connect_and_run_save (prep_result , save )
327
345
328
- output = save_outputs .out_file
346
+ output = save_result . outputs .out_file
329
347
if isinstance (expectation , str ):
330
348
expectation = [expectation ]
331
349
output = [output ]
@@ -363,7 +381,8 @@ def test_DerivativesDataSink_build_path(
363
381
assert sha1 (Path (out ).read_bytes ()).hexdigest () == chksum
364
382
365
383
366
- def test_DerivativesDataSink_dtseries_json (tmp_path ):
384
+ @pytest .mark .parametrize ("interface" , [bintfs .DerivativesDataSink , bintfs .PrepareDerivative ])
385
+ def test_DerivativesDataSink_dtseries_json (tmp_path , interface ):
367
386
cifti_fname = str (tmp_path / "test.dtseries.nii" )
368
387
369
388
axes = (nb .cifti2 .SeriesAxis (start = 0 , step = 2 , size = 20 ),
@@ -378,20 +397,22 @@ def test_DerivativesDataSink_dtseries_json(tmp_path):
378
397
source_file .parent .mkdir (parents = True )
379
398
source_file .touch ()
380
399
381
- dds = bintfs . DerivativesDataSink (
382
- in_file = cifti_fname ,
400
+ prep , save = make_prep_and_save (
401
+ interface ,
383
402
base_directory = str (tmp_path ),
403
+ out_path_base = "" ,
404
+ in_file = cifti_fname ,
384
405
source_file = str (source_file ),
385
406
compress = False ,
386
- out_path_base = "" ,
387
407
space = "fsLR" ,
388
408
grayordinates = "91k" ,
389
409
RepetitionTime = 2.0 ,
390
410
)
391
411
392
- res = dds .run ()
412
+ prep_result = prep .run ()
413
+ save_result = connect_and_run_save (prep_result , save )
393
414
394
- out_path = Path (res .outputs .out_file )
415
+ out_path = Path (save_result .outputs .out_file )
395
416
396
417
assert out_path .name == "sub-01_task-rest_space-fsLR_bold.dtseries.nii"
397
418
old_sidecar = out_path .with_name ("sub-01_task-rest_space-fsLR_bold.dtseries.json" )
@@ -402,6 +423,7 @@ def test_DerivativesDataSink_dtseries_json(tmp_path):
402
423
assert "RepetitionTime" in json .loads (new_sidecar .read_text ())
403
424
404
425
426
+ @pytest .mark .parametrize ("interface" , [bintfs .DerivativesDataSink , bintfs .PrepareDerivative ])
405
427
@pytest .mark .parametrize (
406
428
"space, size, units, xcodes, zipped, fixed, data_dtype" ,
407
429
[
@@ -427,7 +449,7 @@ def test_DerivativesDataSink_dtseries_json(tmp_path):
427
449
],
428
450
)
429
451
def test_DerivativesDataSink_bold (
430
- tmp_path , space , size , units , xcodes , zipped , fixed , data_dtype
452
+ tmp_path , interface , space , size , units , xcodes , zipped , fixed , data_dtype
431
453
):
432
454
fname = str (tmp_path / "source.nii" ) + (".gz" if zipped else "" )
433
455
@@ -438,25 +460,29 @@ def test_DerivativesDataSink_bold(
438
460
nb .Nifti1Image (np .zeros (size ), np .eye (4 ), hdr ).to_filename (fname )
439
461
440
462
# BOLD derivative in T1w space
441
- dds = bintfs .DerivativesDataSink (
463
+ prep , _ = make_prep_and_save (
464
+ interface ,
442
465
base_directory = str (tmp_path ),
443
466
keep_dtype = True ,
444
467
data_dtype = data_dtype or Undefined ,
445
468
desc = "preproc" ,
446
469
source_file = BOLD_PATH ,
447
470
space = space or Undefined ,
448
471
in_file = fname ,
449
- ).run ()
472
+ )
473
+
474
+ prep_result = prep .run ()
450
475
451
- nii = nb .load (dds .outputs .out_file )
452
- assert dds .outputs .fixed_hdr == fixed
476
+ nii = nb .load (prep_result .outputs .out_file )
477
+ assert prep_result .outputs .fixed_hdr == fixed
453
478
if data_dtype :
454
479
assert nii .get_data_dtype () == np .dtype (data_dtype )
455
480
assert int (nii .header ["qform_code" ]) == XFORM_CODES [space ]
456
481
assert int (nii .header ["sform_code" ]) == XFORM_CODES [space ]
457
482
assert nii .header .get_xyzt_units () == ("mm" , "sec" )
458
483
459
484
485
+ @pytest .mark .parametrize ("interface" , [bintfs .DerivativesDataSink , bintfs .PrepareDerivative ])
460
486
@pytest .mark .parametrize (
461
487
"space, size, units, xcodes, fixed" ,
462
488
[
@@ -480,7 +506,7 @@ def test_DerivativesDataSink_bold(
480
506
(None , (30 , 30 , 30 ), (None , "sec" ), (0 , 0 ), [True ]),
481
507
],
482
508
)
483
- def test_DerivativesDataSink_t1w (tmp_path , space , size , units , xcodes , fixed ):
509
+ def test_DerivativesDataSink_t1w (tmp_path , interface , space , size , units , xcodes , fixed ):
484
510
fname = str (tmp_path / "source.nii.gz" )
485
511
486
512
hdr = nb .Nifti1Header ()
@@ -490,22 +516,26 @@ def test_DerivativesDataSink_t1w(tmp_path, space, size, units, xcodes, fixed):
490
516
nb .Nifti1Image (np .zeros (size ), np .eye (4 ), hdr ).to_filename (fname )
491
517
492
518
# BOLD derivative in T1w space
493
- dds = bintfs .DerivativesDataSink (
519
+ prep , _ = make_prep_and_save (
520
+ interface ,
494
521
base_directory = str (tmp_path ),
495
522
keep_dtype = True ,
496
523
desc = "preproc" ,
497
524
source_file = T1W_PATH ,
498
525
space = space or Undefined ,
499
526
in_file = fname ,
500
- ). run ()
527
+ )
501
528
502
- nii = nb .load (dds .outputs .out_file )
503
- assert dds .outputs .fixed_hdr == fixed
529
+ prep_result = prep .run ()
530
+
531
+ nii = nb .load (prep_result .outputs .out_file )
532
+ assert prep_result .outputs .fixed_hdr == fixed
504
533
assert int (nii .header ["qform_code" ]) == XFORM_CODES [space ]
505
534
assert int (nii .header ["sform_code" ]) == XFORM_CODES [space ]
506
535
assert nii .header .get_xyzt_units () == ("mm" , "unknown" )
507
536
508
537
538
+ @pytest .mark .parametrize ("interface" , [bintfs .DerivativesDataSink , bintfs .PrepareDerivative ])
509
539
@pytest .mark .parametrize (
510
540
"source_file" ,
511
541
[
@@ -517,7 +547,7 @@ def test_DerivativesDataSink_t1w(tmp_path, space, size, units, xcodes, fixed):
517
547
@pytest .mark .parametrize ("source_dtype" , ["<i4" , "<f4" ])
518
548
@pytest .mark .parametrize ("in_dtype" , ["<i4" , "<f4" ])
519
549
def test_DerivativesDataSink_data_dtype_source (
520
- tmp_path , source_file , source_dtype , in_dtype
550
+ tmp_path , interface , source_file , source_dtype , in_dtype
521
551
):
522
552
523
553
def make_empty_nii_with_dtype (fname , dtype ):
@@ -539,19 +569,23 @@ def make_empty_nii_with_dtype(fname, dtype):
539
569
for s in source_file :
540
570
make_empty_nii_with_dtype (s , source_dtype )
541
571
542
- dds = bintfs .DerivativesDataSink (
572
+ prep , save = make_prep_and_save (
573
+ interface ,
543
574
base_directory = str (tmp_path ),
544
575
data_dtype = "source" ,
545
576
desc = "preproc" ,
546
577
source_file = source_file ,
547
578
in_file = in_file ,
548
- ).run ()
579
+ )
580
+
581
+ prep_result = prep .run ()
549
582
550
- nii = nb .load (dds .outputs .out_file )
583
+ nii = nb .load (prep_result .outputs .out_file )
551
584
assert nii .get_data_dtype () == np .dtype (source_dtype )
552
585
553
586
554
- def test_DerivativesDataSink_fmapid (tmp_path ):
587
+ @pytest .mark .parametrize ("interface" , [bintfs .DerivativesDataSink , bintfs .PrepareDerivative ])
588
+ def test_DerivativesDataSink_fmapid (tmp_path , interface ):
555
589
"""Ascertain #637 is not regressing."""
556
590
source_file = [
557
591
(tmp_path / s )
@@ -569,7 +603,8 @@ def test_DerivativesDataSink_fmapid(tmp_path):
569
603
in_file = tmp_path / "report.svg"
570
604
in_file .write_text ("" )
571
605
572
- dds = bintfs .DerivativesDataSink (
606
+ prep , save = make_prep_and_save (
607
+ interface ,
573
608
base_directory = str (tmp_path ),
574
609
datatype = "figures" ,
575
610
suffix = "fieldmap" ,
@@ -579,12 +614,19 @@ def test_DerivativesDataSink_fmapid(tmp_path):
579
614
fmapid = "auto00000" ,
580
615
source_file = [str (s .absolute ()) for s in source_file ],
581
616
in_file = str (in_file ),
582
- ).run ()
583
- assert dds .outputs .out_file .endswith ("sub-36_fmapid-auto00000_desc-pepolar_fieldmap.svg" )
617
+ )
584
618
619
+ prep_result = prep .run ()
620
+ save_result = connect_and_run_save (prep_result , save )
585
621
622
+ assert save_result .outputs .out_file .endswith (
623
+ "sub-36_fmapid-auto00000_desc-pepolar_fieldmap.svg"
624
+ )
625
+
626
+
627
+ @pytest .mark .parametrize ("interface" , [bintfs .DerivativesDataSink , bintfs .PrepareDerivative ])
586
628
@pytest .mark .parametrize ("dtype" , ("i2" , "u2" , "f4" ))
587
- def test_DerivativesDataSink_values (tmp_path , dtype ):
629
+ def test_DerivativesDataSink_values (tmp_path , interface , dtype ):
588
630
# We use static checksums above, which ensures we don't break things, but
589
631
# pins the tests to specific values.
590
632
# Here we use random values, check that the values are preserved, and then
@@ -599,16 +641,19 @@ def test_DerivativesDataSink_values(tmp_path, dtype):
599
641
orig_data = np .asanyarray (nb .load (fname ).dataobj )
600
642
expected = np .rint (orig_data ) if dtype [0 ] in "iu" else orig_data
601
643
602
- dds = bintfs .DerivativesDataSink (
644
+ prep , _ = make_prep_and_save (
645
+ interface ,
603
646
base_directory = str (tmp_path ),
604
647
keep_dtype = True ,
605
648
data_dtype = dtype ,
606
649
desc = "preproc" ,
607
650
source_file = T1W_PATH ,
608
651
in_file = fname ,
609
- ).run ()
652
+ )
653
+
654
+ prep_result = prep .run ()
610
655
611
- out_file = Path (dds .outputs .out_file )
656
+ out_file = Path (prep_result .outputs .out_file )
612
657
613
658
nii = nb .load (out_file )
614
659
assert np .allclose (nii .dataobj , expected )
@@ -617,14 +662,17 @@ def test_DerivativesDataSink_values(tmp_path, dtype):
617
662
out_file .unlink ()
618
663
619
664
# Rerun to ensure determinism with non-zero data
620
- dds = bintfs .DerivativesDataSink (
665
+ prep , _ = make_prep_and_save (
666
+ interface ,
621
667
base_directory = str (tmp_path ),
622
668
keep_dtype = True ,
623
669
data_dtype = dtype ,
624
670
desc = "preproc" ,
625
671
source_file = T1W_PATH ,
626
672
in_file = fname ,
627
- ).run ()
673
+ )
674
+
675
+ prep_result = prep .run ()
628
676
629
677
assert sha1 (out_file .read_bytes ()).hexdigest () == checksum
630
678
0 commit comments