Skip to content

Commit 2e1a8c8

Browse files
authored
ENH: Restore confound generation (#3120)
Builds on #3116. Just check the last two commits.
2 parents ce7c65f + 3d541d5 commit 2e1a8c8

File tree

6 files changed

+89
-47
lines changed

6 files changed

+89
-47
lines changed

fmriprep/workflows/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ def init_single_subject_wf(subject_id: str):
503503
('outputnode.t1w_preproc', 'inputnode.t1w_preproc'),
504504
('outputnode.t1w_mask', 'inputnode.t1w_mask'),
505505
('outputnode.t1w_dseg', 'inputnode.t1w_dseg'),
506+
('outputnode.t1w_tpms', 'inputnode.t1w_tpms'),
506507
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
507508
('outputnode.subject_id', 'inputnode.subject_id'),
508509
('outputnode.fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),

fmriprep/workflows/bold/base.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ def init_bold_wf(
188188
"t1w_preproc",
189189
"t1w_mask",
190190
"t1w_dseg",
191+
"t1w_tpms",
191192
"subjects_dir",
192193
"subject_id",
193194
"fsnative2t1w_xfm",
@@ -441,6 +442,50 @@ def init_bold_wf(
441442
(bold_std_wf, ds_bold_std_wf, [('outputnode.bold_file', 'inputnode.bold')]),
442443
]) # fmt:skip
443444

445+
bold_confounds_wf = init_bold_confs_wf(
446+
mem_gb=mem_gb["largemem"],
447+
metadata=all_metadata[0],
448+
freesurfer=config.workflow.run_reconall,
449+
regressors_all_comps=config.workflow.regressors_all_comps,
450+
regressors_fd_th=config.workflow.regressors_fd_th,
451+
regressors_dvars_th=config.workflow.regressors_dvars_th,
452+
name="bold_confounds_wf",
453+
)
454+
455+
ds_confounds = pe.Node(
456+
DerivativesDataSink(
457+
base_directory=fmriprep_dir,
458+
desc='confounds',
459+
suffix='timeseries',
460+
dismiss_entities=("echo",),
461+
),
462+
name="ds_confounds",
463+
run_without_submitting=True,
464+
mem_gb=config.DEFAULT_MEMORY_MIN_GB,
465+
)
466+
ds_confounds.inputs.source_file = bold_file
467+
468+
workflow.connect([
469+
(inputnode, bold_confounds_wf, [
470+
('t1w_tpms', 'inputnode.t1w_tpms'),
471+
('t1w_mask', 'inputnode.t1w_mask'),
472+
]),
473+
(bold_fit_wf, bold_confounds_wf, [
474+
('outputnode.bold_mask', 'inputnode.bold_mask'),
475+
('outputnode.movpar_file', 'inputnode.movpar_file'),
476+
('outputnode.rmsd_file', 'inputnode.rmsd_file'),
477+
('outputnode.boldref2anat_xfm', 'inputnode.boldref2anat_xfm'),
478+
('outputnode.dummy_scans', 'inputnode.skip_vols'),
479+
]),
480+
(bold_native_wf, bold_confounds_wf, [
481+
('outputnode.bold_native', 'inputnode.bold'),
482+
]),
483+
(bold_confounds_wf, ds_confounds, [
484+
('outputnode.confounds_file', 'in_file'),
485+
('outputnode.confounds_metadata', 'meta_dict'),
486+
]),
487+
]) # fmt:skip
488+
444489
# Fill-in datasinks of reportlets seen so far
445490
for node in workflow.list_node_names():
446491
if node.split(".")[-1].startswith("ds_report"):
@@ -677,18 +722,6 @@ def init_func_preproc_wf(bold_file, has_fieldmap=False):
677722
name="outputnode",
678723
)
679724

680-
# get confounds
681-
bold_confounds_wf = init_bold_confs_wf(
682-
mem_gb=mem_gb["largemem"],
683-
metadata=metadata,
684-
freesurfer=freesurfer,
685-
regressors_all_comps=config.workflow.regressors_all_comps,
686-
regressors_fd_th=config.workflow.regressors_fd_th,
687-
regressors_dvars_th=config.workflow.regressors_dvars_th,
688-
name="bold_confounds_wf",
689-
)
690-
bold_confounds_wf.get_node("inputnode").inputs.t1_transform_flags = [False]
691-
692725
# SURFACES ##################################################################################
693726
# Freesurfer
694727
if freesurfer and freesurfer_spaces:

fmriprep/workflows/bold/confounds.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,16 @@ def init_bold_confs_wf(
121121
movpar_file
122122
SPM-formatted motion parameters file
123123
rmsd_file
124-
Framewise displacement as measured by ``fsl_motion_outliers``.
124+
Root mean squared deviation as measured by ``fsl_motion_outliers`` [Jenkinson2002]_.
125125
skip_vols
126126
number of non steady state volumes
127127
t1w_mask
128128
Mask of the skull-stripped template image
129129
t1w_tpms
130130
List of tissue probability maps in T1w space
131-
t1_bold_xform
132-
Affine matrix that maps the T1w space into alignment with
133-
the native BOLD space
131+
boldref2anat_xfm
132+
Affine matrix that maps the BOLD reference space into alignment with
133+
the anatomical (T1w) space
134134
135135
Outputs
136136
-------
@@ -224,7 +224,7 @@ def init_bold_confs_wf(
224224
"skip_vols",
225225
"t1w_mask",
226226
"t1w_tpms",
227-
"t1_bold_xform",
227+
"boldref2anat_xfm",
228228
]
229229
),
230230
name="inputnode",
@@ -244,7 +244,7 @@ def init_bold_confs_wf(
244244

245245
# Project T1w mask into BOLD space and merge with BOLD brainmask
246246
t1w_mask_tfm = pe.Node(
247-
ApplyTransforms(interpolation="MultiLabel"),
247+
ApplyTransforms(interpolation="MultiLabel", invert_transform_flags=[True]),
248248
name="t1w_mask_tfm",
249249
)
250250
union_mask = pe.Node(niu.Function(function=_binary_union), name="union_mask")
@@ -266,9 +266,9 @@ def init_bold_confs_wf(
266266
# Generate aCompCor probseg maps
267267
acc_masks = pe.Node(aCompCorMasks(is_aseg=freesurfer), name="acc_masks")
268268

269-
# Resample probseg maps in BOLD space via T1w-to-BOLD transform
269+
# Resample probseg maps in BOLD space via BOLD-to-T1w transform
270270
acc_msk_tfm = pe.MapNode(
271-
ApplyTransforms(interpolation="Gaussian"),
271+
ApplyTransforms(interpolation="Gaussian", invert_transform_flags=[True]),
272272
iterfield=["input_image"],
273273
name="acc_msk_tfm",
274274
mem_gb=0.1,
@@ -500,7 +500,7 @@ def _select_cols(table):
500500
# Brain mask
501501
(inputnode, t1w_mask_tfm, [("t1w_mask", "input_image"),
502502
("bold_mask", "reference_image"),
503-
("t1_bold_xform", "transforms")]),
503+
("boldref2anat_xfm", "transforms")]),
504504
(inputnode, union_mask, [("bold_mask", "mask1")]),
505505
(t1w_mask_tfm, union_mask, [("output_image", "mask2")]),
506506
(union_mask, dilated_mask, [("out", "in_mask")]),
@@ -512,7 +512,7 @@ def _select_cols(table):
512512
("skip_vols", "ignore_initial_volumes")]),
513513
(inputnode, acc_masks, [("t1w_tpms", "in_vfs"),
514514
(("bold", _get_zooms), "bold_zooms")]),
515-
(inputnode, acc_msk_tfm, [("t1_bold_xform", "transforms"),
515+
(inputnode, acc_msk_tfm, [("boldref2anat_xfm", "transforms"),
516516
("bold_mask", "reference_image")]),
517517
(inputnode, acc_msk_brain, [("bold_mask", "in_mask")]),
518518
(acc_masks, acc_msk_tfm, [("out_masks", "input_image")]),
@@ -624,9 +624,9 @@ def init_carpetplot_wf(
624624
BOLD series mask
625625
confounds_file
626626
TSV of all aggregated confounds
627-
t1_bold_xform
628-
Affine matrix that maps the T1w space into alignment with
629-
the native BOLD space
627+
boldref2anat_xfm
628+
Affine matrix that maps the BOLD reference space into alignment with
629+
the anatomical (T1w) space
630630
std2anat_xfm
631631
ANTs-compatible affine-and-warp transform file
632632
cifti_bold
@@ -653,7 +653,7 @@ def init_carpetplot_wf(
653653
"bold",
654654
"bold_mask",
655655
"confounds_file",
656-
"t1_bold_xform",
656+
"boldref2anat_xfm",
657657
"std2anat_xfm",
658658
"cifti_bold",
659659
"crown_mask",
@@ -708,6 +708,7 @@ def init_carpetplot_wf(
708708
extension=[".nii", ".nii.gz"],
709709
)
710710
),
711+
invert_transform_flags=[True, False],
711712
interpolation="MultiLabel",
712713
args="-u int",
713714
),
@@ -720,7 +721,7 @@ def init_carpetplot_wf(
720721

721722
# fmt:off
722723
workflow.connect([
723-
(inputnode, mrg_xfms, [("t1_bold_xform", "in1"),
724+
(inputnode, mrg_xfms, [("boldref2anat_xfm", "in1"),
724725
("std2anat_xfm", "in2")]),
725726
(inputnode, resample_parc, [("bold_mask", "reference_image")]),
726727
(inputnode, parcels, [("crown_mask", "crown_mask")]),

fmriprep/workflows/bold/fit.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ def init_bold_fit_wf(
177177
boldref2fmap_xfm
178178
Affine transform mapping from BOLD reference space to the fieldmap
179179
space, if applicable.
180+
movpar_file
181+
MCFLIRT motion parameters, normalized to SPM format (X, Y, Z, Rx, Ry, Rz)
182+
rmsd_file
183+
Root mean squared deviation as measured by ``fsl_motion_outliers`` [Jenkinson2002]_.
184+
dummy_scans
185+
The number of dummy scans declared or detected at the beginning of the series.
180186
181187
See Also
182188
--------
@@ -267,6 +273,8 @@ def init_bold_fit_wf(
267273
"motion_xfm",
268274
"boldref2anat_xfm",
269275
"boldref2fmap_xfm",
276+
"movpar_file",
277+
"rmsd_file",
270278
],
271279
),
272280
name="outputnode",
@@ -276,7 +284,8 @@ def init_bold_fit_wf(
276284
workflow.add_nodes([inputnode])
277285

278286
hmcref_buffer = pe.Node(
279-
niu.IdentityInterface(fields=["boldref", "bold_file"]), name="hmcref_buffer"
287+
niu.IdentityInterface(fields=["boldref", "bold_file", "dummy_scans"]),
288+
name="hmcref_buffer",
280289
)
281290
fmapref_buffer = pe.Node(niu.Function(function=_select_ref), name="fmapref_buffer")
282291
hmc_buffer = pe.Node(niu.IdentityInterface(fields=["hmc_xforms"]), name="hmc_buffer")
@@ -313,13 +322,20 @@ def init_bold_fit_wf(
313322

314323
# fmt:off
315324
workflow.connect([
316-
(hmcref_buffer, outputnode, [("boldref", "hmc_boldref")]),
325+
(hmcref_buffer, outputnode, [
326+
("boldref", "hmc_boldref"),
327+
("dummy_scans", "dummy_scans"),
328+
]),
317329
(regref_buffer, outputnode, [
318330
("boldref", "coreg_boldref"),
319331
("boldmask", "bold_mask"),
320332
]),
321333
(fmapreg_buffer, outputnode, [("boldref2fmap_xfm", "boldref2fmap_xfm")]),
322-
(hmc_buffer, outputnode, [("hmc_xforms", "motion_xfm")]),
334+
(hmc_buffer, outputnode, [
335+
("hmc_xforms", "motion_xfm"),
336+
("movpar_file", "movpar_file"),
337+
("rmsd_file", "rmsd_file"),
338+
]),
323339
(inputnode, func_fit_reports_wf, [
324340
("bold_file", "inputnode.source_file"),
325341
("t1w_preproc", "inputnode.t1w_preproc"),
@@ -360,6 +376,7 @@ def init_bold_fit_wf(
360376
(hmc_boldref_wf, hmcref_buffer, [
361377
("outputnode.bold_file", "bold_file"),
362378
("outputnode.boldref", "boldref"),
379+
("outputnode.skip_vols", "dummy_scans"),
363380
]),
364381
(hmcref_buffer, ds_hmc_boldref_wf, [("boldref", "inputnode.boldref")]),
365382
(hmc_boldref_wf, summary, [("outputnode.algo_dummy_scans", "algo_dummy_scans")]),
@@ -403,7 +420,11 @@ def init_bold_fit_wf(
403420
("bold_file", "inputnode.bold_file"),
404421
]),
405422
(bold_hmc_wf, ds_hmc_wf, [("outputnode.xforms", "inputnode.xforms")]),
406-
(ds_hmc_wf, hmc_buffer, [("outputnode.xforms", "hmc_xforms")]),
423+
(bold_hmc_wf, hmc_buffer, [
424+
("outputnode.xforms", "hmc_xforms"),
425+
("outputnode.movpar_file", "movpar_file"),
426+
("outputnode.rmsd_file", "rmsd_file"),
427+
]),
407428
])
408429
# fmt:on
409430
else:

fmriprep/workflows/bold/hmc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ def init_bold_hmc_wf(mem_gb: float, omp_nthreads: int, name: str = 'bold_hmc_wf'
7575
ITKTransform file aligning each volume to ``ref_image``
7676
movpar_file
7777
MCFLIRT motion parameters, normalized to SPM format (X, Y, Z, Rx, Ry, Rz)
78-
rms_file
79-
Framewise displacement as measured by ``fsl_motion_outliers`` [Jenkinson2002]_.
78+
rmsd_file
79+
Root mean squared deviation as measured by ``fsl_motion_outliers`` [Jenkinson2002]_.
8080
8181
"""
8282
from niworkflows.engine.workflows import LiterateWorkflow as Workflow

fmriprep/workflows/bold/outputs.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -961,17 +961,6 @@ def init_func_derivatives_wf(
961961
raw_sources = pe.Node(niu.Function(function=_bids_relative), name='raw_sources')
962962
raw_sources.inputs.bids_root = bids_root
963963

964-
ds_confounds = pe.Node(
965-
DerivativesDataSink(
966-
base_directory=output_dir,
967-
desc='confounds',
968-
suffix='timeseries',
969-
dismiss_entities=("echo",),
970-
),
971-
name="ds_confounds",
972-
run_without_submitting=True,
973-
mem_gb=DEFAULT_MEMORY_MIN_GB,
974-
)
975964
ds_ref_t1w_xfm = pe.Node(
976965
DerivativesDataSink(
977966
base_directory=output_dir,
@@ -1001,9 +990,6 @@ def init_func_derivatives_wf(
1001990
# fmt:off
1002991
workflow.connect([
1003992
(inputnode, raw_sources, [('all_source_files', 'in_files')]),
1004-
(inputnode, ds_confounds, [('source_file', 'source_file'),
1005-
('confounds', 'in_file'),
1006-
('confounds_metadata', 'meta_dict')]),
1007993
(inputnode, ds_ref_t1w_xfm, [('source_file', 'source_file'),
1008994
('bold2anat_xfm', 'in_file')]),
1009995
(inputnode, ds_ref_t1w_inv_xfm, [('source_file', 'source_file'),

0 commit comments

Comments
 (0)