@@ -313,13 +313,19 @@ def init_single_subject_wf(subject_id):
313
313
fmap_estimators = find_estimators (
314
314
layout = config .execution .layout ,
315
315
subject = subject_id ,
316
- fmapless = False ,
316
+ fmapless = config .workflow .use_syn ,
317
+ force_fmapless = config .workflow .force_syn ,
317
318
)
318
319
319
- # Add fieldmap-less estimators
320
- if not fmap_estimators and config .workflow .use_syn :
321
- # estimators = [fm.FieldmapEstimation()]
322
- raise NotImplementedError
320
+ if (
321
+ any (f .method == fm .EstimatorType .ANAT for f in fmap_estimators )
322
+ and "MNI152NLin2009cAsym" not in spaces .get_spaces (nonstandard = False , dim = (3 ,))
323
+ ):
324
+ # Although this check would go better within parser, allow datasets with fieldmaps
325
+ # not to require spatial standardization of the T1w.
326
+ raise RuntimeError ("""\
327
+ Argument '--use-sdc-syn' requires having 'MNI152NLin2009cAsym' as one output standard space. \
328
+ Please add the 'MNI152NLin2009cAsym' keyword to the '--output-spaces' argument""" )
323
329
324
330
# Nuts and bolts: initialize individual run's pipeline
325
331
dwi_preproc_list = []
@@ -354,6 +360,10 @@ def init_single_subject_wf(subject_id):
354
360
dwi_preproc_list .append (dwi_preproc_wf )
355
361
356
362
if not fmap_estimators :
363
+ config .loggers .workflow .warning (
364
+ "Data for fieldmap estimation not present. Please note that these data "
365
+ "will not be corrected for susceptibility distortions."
366
+ )
357
367
return workflow
358
368
359
369
# SDC Step 2: Manually add further estimators (e.g., fieldmap-less)
@@ -371,7 +381,6 @@ def init_single_subject_wf(subject_id):
371
381
BIDS structure for this particular subject.
372
382
"""
373
383
374
- # TODO: Requires nipreps/sdcflows#147
375
384
for dwi_preproc_wf in dwi_preproc_list :
376
385
# fmt: off
377
386
workflow .connect ([
@@ -392,38 +401,75 @@ def init_single_subject_wf(subject_id):
392
401
393
402
# Step 3: Manually connect PEPOLAR
394
403
for estimator in fmap_estimators :
395
- if estimator .method != fm .EstimatorType .PEPOLAR :
404
+ config .loggers .workflow .info (f"""\
405
+ Setting-up fieldmap "{ estimator .bids_id } " ({ estimator .method } ) with \
406
+ <{ ', ' .join (s .path .name for s in estimator .sources )} >""" )
407
+ if estimator .method in (fm .EstimatorType .MAPPED , fm .EstimatorType .PHASEDIFF ):
396
408
continue
397
409
398
410
suffices = set (s .suffix for s in estimator .sources )
399
411
400
- if sorted (suffices ) == ["epi" ]:
412
+ if estimator . method == fm . EstimatorType . PEPOLAR and sorted (suffices ) == ["epi" ]:
401
413
getattr (fmap_wf .inputs , f"in_{ estimator .bids_id } " ).in_data = [
402
414
str (s .path ) for s in estimator .sources
403
415
]
404
416
getattr (fmap_wf .inputs , f"in_{ estimator .bids_id } " ).metadata = [
405
417
s .metadata for s in estimator .sources
406
418
]
407
- else :
408
- raise NotImplementedError
409
- # from niworkflows.interfaces.utility import KeySelect
410
- # est_id = estimator.bids_id
411
- # estim_select = pe.MapNode(
412
- # KeySelect(fields=["metadata", "dwi_reference", "dwi_mask", "gradients_rasb",]),
413
- # name=f"fmap_select_{est_id}",
414
- # run_without_submitting=True,
415
- # iterfields=["key"]
416
- # )
417
- # estim_select.inputs.key = [
418
- # str(s.path) for s in estimator.sources if s.suffix in ("epi", "dwi", "sbref")
419
- # ]
420
- # # fmt:off
421
- # workflow.connect([
422
- # (referencenode, estim_select, [("dwi_file", "keys"),
423
- # ("metadata", "metadata"),
424
- # ("dwi_reference", "dwi_reference"),
425
- # ("gradients_rasb", "gradients_rasb")]),
426
- # ])
427
- # # fmt:on
419
+ continue
420
+
421
+ if estimator .method == fm .EstimatorType .PEPOLAR :
422
+ raise NotImplementedError (
423
+ "Sophisticated PEPOLAR schemes (e.g., using DWI+EPI) are unsupported."
424
+ )
425
+
426
+ if estimator .method == fm .EstimatorType .ANAT :
427
+ from sdcflows .interfaces .brainmask import BrainExtraction
428
+ from sdcflows .workflows .fit .syn import init_syn_preprocessing_wf
429
+ from ...interfaces .vectors import CheckGradientTable
430
+
431
+ sources = [str (s .path ) for s in estimator .sources ]
432
+ layout = config .execution .layout
433
+ syn_preprocessing_wf = init_syn_preprocessing_wf (
434
+ omp_nthreads = config .nipype .omp_nthreads ,
435
+ auto_bold_nss = False ,
436
+ )
437
+ syn_preprocessing_wf .inputs .in_epis = sources
438
+ syn_preprocessing_wf .inputs .in_meta = [
439
+ layout .get_metadata (s ) for s in sources
440
+ ]
441
+
442
+ b0_masks = pe .MapNode (CheckGradientTable (), name = "b0_masks" ,
443
+ iterfield = ("dwi_file" , "in_bvec" , "in_bval" ))
444
+ b0_masks .inputs .dwi_file = sources
445
+ b0_masks .inputs .in_bvec = [str (layout .get_bvec (s )) for s in sources ]
446
+ b0_masks .inputs .in_bval = [str (layout .get_bval (s )) for s in sources ]
447
+
448
+ epi_brain = pe .Node (BrainExtraction (), name = "epi_brain" )
449
+
450
+ # fmt:off
451
+ workflow .connect ([
452
+ (anat_preproc_wf , syn_preprocessing_wf , [
453
+ ("outputnode.t1w_preproc" , "inputnode.in_anat" ),
454
+ ("outputnode.t1w_mask" , "inputnode.mask_anat" ),
455
+ ]),
456
+ (b0_masks , syn_preprocessing_wf , [("b0_mask" , "inputnode.t_masks" )]),
457
+ (syn_preprocessing_wf , fmap_wf , [
458
+ ("outputnode.epi_ref" , "inputnode.epi_ref" ),
459
+ ("outputnode.anat_ref" , "inputnode.anat_ref" ),
460
+ ("outputnode.anat_mask" , "inputnode.anat_mask" ),
461
+ ("outputnode.anat2epi_xfm" , "inputnode.anat2epi_xfm" ),
462
+ ]),
463
+ (syn_preprocessing_wf , epi_brain , [("outputnode.epi_ref" , "in_file" )]),
464
+ (anat_preproc_wf , fmap_wf , [
465
+ ("outputnode.std2anat_xfm" , "inputnode.std2anat_xfm" ),
466
+ ]),
467
+ (epi_brain , fmap_wf , [("out_mask" , "inputnode.epi_mask" )]),
468
+ ])
469
+ # fmt:on
470
+
471
+ raise RuntimeError (
472
+ f"Unknown fieldmap estimation strategy <{ estimator } >."
473
+ )
428
474
429
475
return workflow
0 commit comments