@@ -287,6 +287,7 @@ def init_single_subject_wf(subject_id):
287
287
return workflow
288
288
289
289
from .dwi .base import init_dwi_preproc_wf
290
+
290
291
# Append the dMRI section to the existing anatomical excerpt
291
292
# That way we do not need to stream down the number of DWI datasets
292
293
anat_preproc_wf .__postdesc__ = (
@@ -300,77 +301,87 @@ def init_single_subject_wf(subject_id):
300
301
and a *b=0* average for reference to the subsequent steps of preprocessing was calculated.
301
302
"""
302
303
)
303
- dwi_preproc_list = []
304
- for dwi_file in subject_data ["dwi" ]:
305
- dwi_preproc_wf = init_dwi_preproc_wf (dwi_file )
306
- dwi_preproc_list .append (dwi_preproc_wf )
307
304
308
- dwi_preproc_list_wf = pe .Node (niu .IdentityInterface (fields = ["dwi_workflows" ]),
309
- name = "dwi_preproc_list_wf" )
310
- dwi_preproc_list_wf .iterables = [("dwi_workflows" , dwi_preproc_list )]
305
+ # SDC Step 0: Determine whether fieldmaps can/should be estimated
306
+ fmap_estimators = None
307
+ if "fieldmap" not in config .workflow .ignore :
308
+ from sdcflows import fieldmaps as fm
309
+ from sdcflows .utils .wrangler import find_estimators
310
+ from sdcflows .workflows .base import init_fmap_preproc_wf
311
311
312
- # fmt: off
313
- workflow .connect ([
314
- (anat_preproc_wf , dwi_preproc_list_wf , [
315
- ("outputnode.t1w_preproc" , "inputnode.t1w_preproc" ),
316
- ("outputnode.t1w_mask" , "inputnode.t1w_mask" ),
317
- ("outputnode.t1w_dseg" , "inputnode.t1w_dseg" ),
318
- ("outputnode.t1w_aseg" , "inputnode.t1w_aseg" ),
319
- ("outputnode.t1w_aparc" , "inputnode.t1w_aparc" ),
320
- ("outputnode.t1w_tpms" , "inputnode.t1w_tpms" ),
321
- ("outputnode.template" , "inputnode.template" ),
322
- ("outputnode.anat2std_xfm" , "inputnode.anat2std_xfm" ),
323
- ("outputnode.std2anat_xfm" , "inputnode.std2anat_xfm" ),
324
- # Undefined if --fs-no-reconall, but this is safe
325
- ("outputnode.subjects_dir" , "inputnode.subjects_dir" ),
326
- ("outputnode.t1w2fsnative_xfm" , "inputnode.t1w2fsnative_xfm" ),
327
- ("outputnode.fsnative2t1w_xfm" , "inputnode.fsnative2t1w_xfm" ),
328
- ]),
329
- (bids_info , dwi_preproc_list_wf , [("subject" , "inputnode.subject_id" )]),
330
- ])
331
- # fmt: on
312
+ # SDC Step 1: Run basic heuristics to identify available data for fieldmap estimation
313
+ fmap_estimators = find_estimators (config .execution .layout )
332
314
333
- if "fieldmap" in config .workflow .ignore :
334
- return workflow
315
+ # Add fieldmap-less estimators
316
+ if not fmap_estimators and config .workflow .use_syn :
317
+ # estimators = [fm.FieldmapEstimation()]
318
+ raise NotImplementedError
335
319
336
- from sdcflows import fieldmaps as fm
337
- from sdcflows .utils .wrangler import find_estimators
338
- from sdcflows .workflows .base import init_fmap_preproc_wf
320
+ # Nuts and bolts: initialize individual run's pipeline
321
+ dwi_preproc_list = []
322
+ for dwi_file in subject_data ["dwi" ]:
323
+ dwi_preproc_wf = init_dwi_preproc_wf (
324
+ dwi_file ,
325
+ has_fieldmap = bool (fmap_estimators ),
326
+ )
339
327
340
- # SDCFlows connection
341
- # Step 1: Run basic heuristics to identify available data for fieldmap estimation
342
- estimators = find_estimators (config .execution .layout )
328
+ # fmt: off
329
+ workflow .connect ([
330
+ (anat_preproc_wf , dwi_preproc_wf , [
331
+ ("outputnode.t1w_preproc" , "inputnode.t1w_preproc" ),
332
+ ("outputnode.t1w_mask" , "inputnode.t1w_mask" ),
333
+ ("outputnode.t1w_dseg" , "inputnode.t1w_dseg" ),
334
+ ("outputnode.t1w_aseg" , "inputnode.t1w_aseg" ),
335
+ ("outputnode.t1w_aparc" , "inputnode.t1w_aparc" ),
336
+ ("outputnode.t1w_tpms" , "inputnode.t1w_tpms" ),
337
+ ("outputnode.template" , "inputnode.template" ),
338
+ ("outputnode.anat2std_xfm" , "inputnode.anat2std_xfm" ),
339
+ ("outputnode.std2anat_xfm" , "inputnode.std2anat_xfm" ),
340
+ # Undefined if --fs-no-reconall, but this is safe
341
+ ("outputnode.subjects_dir" , "inputnode.subjects_dir" ),
342
+ ("outputnode.t1w2fsnative_xfm" , "inputnode.t1w2fsnative_xfm" ),
343
+ ("outputnode.fsnative2t1w_xfm" , "inputnode.fsnative2t1w_xfm" ),
344
+ ]),
345
+ (bids_info , dwi_preproc_wf , [("subject" , "inputnode.subject_id" )]),
346
+ ])
347
+ # fmt: on
348
+
349
+ # Keep a handle to each workflow
350
+ dwi_preproc_list .append (dwi_preproc_wf )
343
351
344
- if not estimators and config .workflow .use_syn : # Add fieldmap-less estimators
345
- # estimators = [fm.FieldmapEstimation()]
346
- raise NotImplementedError
352
+ if not fmap_estimators :
353
+ return workflow
347
354
348
- # Step 2: Manually add further estimators (e.g., fieldmap-less)
355
+ # SDC Step 2: Manually add further estimators (e.g., fieldmap-less)
349
356
fmap_wf = init_fmap_preproc_wf (
350
357
debug = config .execution .debug ,
351
- estimators = estimators ,
358
+ estimators = fmap_estimators ,
352
359
omp_nthreads = config .nipype .omp_nthreads ,
353
360
output_dir = str (output_dir ),
354
361
subject = subject_id ,
355
362
)
356
- # fmt: off
357
- workflow .connect ([
358
- (fmap_wf , dwi_preproc_list_wf , [
359
- ("outputnode.fmap" , "inputnode.fmap" ),
360
- ("outputnode.fmap_ref" , "inputnode.fmap_ref" ),
361
- ("outputnode.fmap_coeff" , "inputnode.fmap_coeff" ),
362
- ("outputnode.fmap_mask" , "inputnode.fmap_mask" ),
363
- ]),
364
- ])
365
- # fmt: on
363
+
364
+ # TODO: Requires nipreps/sdcflows#147
365
+ for dwi_preproc_wf in dwi_preproc_list :
366
+ # fmt: off
367
+ workflow .connect ([
368
+ (fmap_wf , dwi_preproc_wf , [
369
+ ("outputnode.fmap" , "inputnode.fmap" ),
370
+ ("outputnode.fmap_ref" , "inputnode.fmap_ref" ),
371
+ ("outputnode.fmap_coeff" , "inputnode.fmap_coeff" ),
372
+ ("outputnode.fmap_mask" , "inputnode.fmap_mask" ),
373
+ ("outputnode.fmap_id" , "inputnode.fmap_id" ),
374
+ ]),
375
+ ])
376
+ # fmt: on
377
+
366
378
# Overwrite ``out_path_base`` of sdcflows's DataSinks
367
379
for node in fmap_wf .list_node_names ():
368
380
if node .split ("." )[- 1 ].startswith ("ds_" ):
369
381
fmap_wf .get_node (node ).interface .out_path_base = "dmriprep"
370
- workflow .add_nodes ([fmap_wf ])
371
382
372
383
# Step 3: Manually connect PEPOLAR
373
- for estimator in estimators :
384
+ for estimator in fmap_estimators :
374
385
if estimator .method != fm .EstimatorType .PEPOLAR :
375
386
continue
376
387
@@ -387,18 +398,18 @@ def init_single_subject_wf(subject_id):
387
398
raise NotImplementedError
388
399
# from niworkflows.interfaces.utility import KeySelect
389
400
# est_id = estimator.bids_id
390
- # fmap_select = pe.MapNode(
401
+ # estim_select = pe.MapNode(
391
402
# KeySelect(fields=["metadata", "dwi_reference", "dwi_mask", "gradients_rasb",]),
392
403
# name=f"fmap_select_{est_id}",
393
404
# run_without_submitting=True,
394
405
# iterfields=["key"]
395
406
# )
396
- # fmap_select .inputs.key = [
407
+ # estim_select .inputs.key = [
397
408
# str(s.path) for s in estimator.sources if s.suffix in ("epi", "dwi", "sbref")
398
409
# ]
399
410
# # fmt:off
400
411
# workflow.connect([
401
- # (referencenode, fmap_select , [("dwi_file", "keys"),
412
+ # (referencenode, estim_select , [("dwi_file", "keys"),
402
413
# ("metadata", "metadata"),
403
414
# ("dwi_reference", "dwi_reference"),
404
415
# ("gradients_rasb", "gradients_rasb")]),
0 commit comments