Skip to content

Commit 70a6698

Browse files
committed
ENH: Restore CIFTI-2 generation
1 parent ea239d3 commit 70a6698

File tree

3 files changed

+145
-136
lines changed

3 files changed

+145
-136
lines changed

fmriprep/workflows/base.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ def init_single_subject_wf(subject_id: str):
147147
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
148148
from niworkflows.interfaces.bids import BIDSDataGrabber, BIDSInfo
149149
from niworkflows.interfaces.nilearn import NILEARN_VERSION
150+
from niworkflows.interfaces.utility import KeySelect
150151
from niworkflows.utils.bids import collect_data
151152
from niworkflows.utils.misc import fix_multi_T1w_source_name
152153
from niworkflows.utils.spaces import Reference
@@ -333,7 +334,7 @@ def init_single_subject_wf(subject_id: str):
333334

334335
# Set up the template iterator once, if used
335336
if config.workflow.level == "full":
336-
if spaces.get_spaces(nonstandard=False, dim=(3,)):
337+
if spaces.cached.get_spaces(nonstandard=False, dim=(3,)):
337338
template_iterator_wf = init_template_iterator_wf(spaces=spaces)
338339
workflow.connect([
339340
(anat_fit_wf, template_iterator_wf, [
@@ -342,6 +343,34 @@ def init_single_subject_wf(subject_id: str):
342343
]),
343344
]) # fmt:skip
344345

346+
# Thread MNI152NLin6Asym standard outputs to CIFTI subworkflow, skipping
347+
# the iterator, which targets only output spaces.
348+
# This can lead to duplication in the working directory if people actually
349+
# want MNI152NLin6Asym outputs, but we'll live with it.
350+
if config.workflow.cifti_output:
351+
from smriprep.interfaces.templateflow import TemplateFlowSelect
352+
353+
ref = Reference(
354+
"MNI152NLin6Asym",
355+
{"res": 2 if config.workflow.cifti_output == "91k" else 1},
356+
)
357+
358+
select_MNI6_xfm = pe.Node(
359+
KeySelect(fields=["anat2std_xfm"], key=ref.fullname),
360+
name="select_MNI6",
361+
run_without_submitting=True,
362+
)
363+
select_MNI6_tpl = pe.Node(
364+
TemplateFlowSelect(template=ref.fullname, resolution=ref.spec['res']),
365+
name="select_MNI6_tpl",
366+
)
367+
workflow.connect([
368+
(anat_fit_wf, select_MNI6_xfm, [
369+
("outputnode.anat2std_xfm", "anat2std_xfm"),
370+
("outputnode.template", "keys"),
371+
]),
372+
]) # fmt:skip
373+
345374
if config.workflow.anat_only:
346375
return clean_datasinks(workflow)
347376

@@ -362,7 +391,6 @@ def init_single_subject_wf(subject_id: str):
362391
f"{[e.method for e in fmap_estimators]}."
363392
)
364393

365-
from niworkflows.interfaces.utility import KeySelect
366394
from sdcflows import fieldmaps as fm
367395
from sdcflows.workflows.base import init_fmap_preproc_wf
368396

@@ -539,6 +567,16 @@ def init_single_subject_wf(subject_id: str):
539567
]),
540568
]) # fmt:skip
541569

570+
# Thread MNI152NLin6Asym standard outputs to CIFTI subworkflow, skipping
571+
# the iterator, which targets only output spaces.
572+
# This can lead to duplication in the working directory if people actually
573+
# want MNI152NLin6Asym outputs, but we'll live with it.
574+
if config.workflow.cifti_output:
575+
workflow.connect([
576+
(select_MNI6_xfm, bold_wf, [("anat2std_xfm", "inputnode.anat2mni6_xfm")]),
577+
(select_MNI6_tpl, bold_wf, [("brain_mask", "inputnode.mni6_mask")]),
578+
]) # fmt:skip
579+
542580
return clean_datasinks(workflow)
543581

544582

fmriprep/workflows/bold/base.py

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ def init_bold_wf(
213213
"std_cohort",
214214
"std_t1w",
215215
"std_mask",
216+
# MNI152NLin6Asym warp, for CIFTI use
217+
"anat2mni6_xfm",
218+
"mni6_mask",
216219
],
217220
),
218221
name="inputnode",
@@ -469,6 +472,68 @@ def init_bold_wf(
469472
(bold_anat_wf, bold_surf_wf, [("outputnode.bold_file", "inputnode.bold_t1w")]),
470473
]) # fmt:skip
471474

475+
if config.workflow.cifti_output:
476+
from .resampling import init_bold_fsLR_resampling_wf, init_bold_grayords_wf
477+
478+
bold_MNI6_wf = init_bold_volumetric_resample_wf(
479+
metadata=all_metadata[0],
480+
fieldmap_id=fieldmap_id if not multiecho else None,
481+
omp_nthreads=omp_nthreads,
482+
name='bold_MNI6_wf',
483+
)
484+
485+
bold_fsLR_resampling_wf = init_bold_fsLR_resampling_wf(
486+
estimate_goodvoxels=config.workflow.project_goodvoxels,
487+
grayord_density=config.workflow.cifti_output,
488+
omp_nthreads=omp_nthreads,
489+
mem_gb=mem_gb["resampled"],
490+
)
491+
492+
bold_grayords_wf = init_bold_grayords_wf(
493+
grayord_density=config.workflow.cifti_output,
494+
mem_gb=mem_gb["resampled"],
495+
repetition_time=all_metadata[0]["RepetitionTime"],
496+
)
497+
498+
workflow.connect([
499+
# Resample BOLD to MNI152NLin6Asym, may duplicate bold_std_wf above
500+
(inputnode, bold_MNI6_wf, [
501+
("mni6_mask", "inputnode.target_ref_file"),
502+
("mni6_mask", "inputnode.target_mask"),
503+
("anat2mni6_xfm", "inputnode.anat2std_xfm"),
504+
("fmap_ref", "inputnode.fmap_ref"),
505+
("fmap_coeff", "inputnode.fmap_coeff"),
506+
("fmap_id", "inputnode.fmap_id"),
507+
]),
508+
(bold_fit_wf, bold_MNI6_wf, [
509+
("outputnode.coreg_boldref", "inputnode.bold_ref_file"),
510+
("outputnode.boldref2fmap_xfm", "inputnode.boldref2fmap_xfm"),
511+
("outputnode.boldref2anat_xfm", "inputnode.boldref2anat_xfm"),
512+
]),
513+
(bold_native_wf, bold_MNI6_wf, [
514+
("outputnode.bold_minimal", "inputnode.bold_file"),
515+
("outputnode.motion_xfm", "inputnode.motion_xfm"),
516+
]),
517+
# Resample T1w-space BOLD to fsLR surfaces
518+
(inputnode, bold_fsLR_resampling_wf, [
519+
("white", "inputnode.white"),
520+
("pial", "inputnode.pial"),
521+
("midthickness", "inputnode.midthickness"),
522+
("thickness", "inputnode.thickness"),
523+
("sphere_reg_fsLR", "inputnode.sphere_reg_fsLR"),
524+
("anat_ribbon", "inputnode.anat_ribbon"),
525+
]),
526+
(bold_anat_wf, bold_fsLR_resampling_wf, [
527+
("outputnode.bold_file", "inputnode.bold_file"),
528+
]),
529+
(bold_MNI6_wf, bold_grayords_wf, [
530+
("outputnode.bold_file", "inputnode.bold_std"),
531+
]),
532+
(bold_fsLR_resampling_wf, bold_grayords_wf, [
533+
("outputnode.bold_fsLR", "inputnode.bold_fsLR"),
534+
]),
535+
]) # fmt:skip
536+
472537
bold_confounds_wf = init_bold_confs_wf(
473538
mem_gb=mem_gb["largemem"],
474539
metadata=all_metadata[0],
@@ -664,7 +729,6 @@ def init_func_preproc_wf(bold_file, has_fieldmap=False):
664729
spaces = config.workflow.spaces
665730
fmriprep_dir = str(config.execution.fmriprep_dir)
666731
freesurfer_spaces = spaces.get_fs_spaces()
667-
project_goodvoxels = config.workflow.project_goodvoxels and config.workflow.cifti_output
668732

669733
ref_file = bold_file
670734
wf_name = _get_wf_name(ref_file, "func_preproc")
@@ -752,52 +816,6 @@ def init_func_preproc_wf(bold_file, has_fieldmap=False):
752816
# SURFACES ##################################################################################
753817

754818
# CIFTI output
755-
if config.workflow.cifti_output:
756-
from .resampling import init_bold_fsLR_resampling_wf, init_bold_grayords_wf
757-
758-
bold_fsLR_resampling_wf = init_bold_fsLR_resampling_wf(
759-
estimate_goodvoxels=project_goodvoxels,
760-
grayord_density=config.workflow.cifti_output,
761-
omp_nthreads=omp_nthreads,
762-
mem_gb=mem_gb["resampled"],
763-
)
764-
765-
bold_grayords_wf = init_bold_grayords_wf(
766-
grayord_density=config.workflow.cifti_output,
767-
mem_gb=mem_gb["resampled"],
768-
repetition_time=metadata["RepetitionTime"],
769-
)
770-
771-
# fmt:off
772-
workflow.connect([
773-
(inputnode, bold_fsLR_resampling_wf, [
774-
("surfaces", "inputnode.surfaces"),
775-
("morphometrics", "inputnode.morphometrics"),
776-
("sphere_reg_fsLR", "inputnode.sphere_reg_fsLR"),
777-
("anat_ribbon", "inputnode.anat_ribbon"),
778-
]),
779-
(bold_t1_trans_wf, bold_fsLR_resampling_wf, [
780-
("outputnode.bold_t1", "inputnode.bold_file"),
781-
]),
782-
(bold_std_trans_wf, bold_grayords_wf, [
783-
("outputnode.bold_std", "inputnode.bold_std"),
784-
("outputnode.spatial_reference", "inputnode.spatial_reference"),
785-
]),
786-
(bold_fsLR_resampling_wf, bold_grayords_wf, [
787-
("outputnode.bold_fsLR", "inputnode.bold_fsLR"),
788-
]),
789-
(bold_fsLR_resampling_wf, func_derivatives_wf, [
790-
("outputnode.goodvoxels_mask", "inputnode.goodvoxels_mask"),
791-
]),
792-
(bold_fsLR_resampling_wf, outputnode, [
793-
("outputnode.weights_text", "weights_text"),
794-
]),
795-
(bold_grayords_wf, outputnode, [
796-
("outputnode.cifti_bold", "bold_cifti"),
797-
("outputnode.cifti_metadata", "cifti_metadata"),
798-
]),
799-
])
800-
# fmt:on
801819

802820
if spaces.get_spaces(nonstandard=False, dim=(3,)):
803821
carpetplot_wf = init_carpetplot_wf(

0 commit comments

Comments
 (0)