From 691dd54498d3c92e3ff4faacfc62b001bba53ffb Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 19 Nov 2023 12:34:30 -0500 Subject: [PATCH] RF: Reuse cortical mask ROI and downsampled midthickness --- fmriprep/workflows/base.py | 21 +++++++++- fmriprep/workflows/bold/base.py | 8 ++-- fmriprep/workflows/bold/resampling.py | 58 ++++++++------------------- 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/fmriprep/workflows/base.py b/fmriprep/workflows/base.py index 7a253e6fd..afd6f613b 100644 --- a/fmriprep/workflows/base.py +++ b/fmriprep/workflows/base.py @@ -162,6 +162,7 @@ def init_single_subject_wf(subject_id: str): init_gifti_morphometrics_wf, init_hcp_morphometrics_wf, init_morph_grayords_wf, + init_resample_midthickness_wf, ) from fmriprep.workflows.bold.base import init_bold_wf @@ -435,6 +436,9 @@ def init_single_subject_wf(subject_id: str): grayord_density=config.workflow.cifti_output, omp_nthreads=omp_nthreads, ) + resample_midthickness_wf = init_resample_midthickness_wf( + grayord_density=config.workflow.cifti_output, + ) ds_grayord_metrics_wf = init_ds_grayord_metrics_wf( bids_root=bids_root, output_dir=fmriprep_dir, @@ -456,6 +460,13 @@ def init_single_subject_wf(subject_id: str): (curv_wf, hcp_morphometrics_wf, [ ("outputnode.curv", "inputnode.curv"), ]), + (anat_fit_wf, resample_midthickness_wf, [ + ('outputnode.midthickness', 'inputnode.midthickness'), + ( + f"outputnode.sphere_reg_{'msm' if msm_sulc else 'fsLR'}", + "inputnode.sphere_reg_fsLR", + ), + ]), (anat_fit_wf, morph_grayords_wf, [ ("outputnode.midthickness", "inputnode.midthickness"), ( @@ -469,6 +480,9 @@ def init_single_subject_wf(subject_id: str): ("outputnode.sulc", "inputnode.sulc"), ("outputnode.roi", "inputnode.roi"), ]), + (resample_midthickness_wf, morph_grayords_wf, [ + ('outputnode.midthickness_fsLR', 'inputnode.midthickness_fsLR'), + ]), (anat_fit_wf, ds_grayord_metrics_wf, [ ('outputnode.t1w_valid_list', 'inputnode.source_files'), ]), @@ -648,7 +662,6 @@ def init_single_subject_wf(subject_id: str): ('outputnode.white', 'inputnode.white'), ('outputnode.pial', 'inputnode.pial'), ('outputnode.midthickness', 'inputnode.midthickness'), - ('outputnode.thickness', 'inputnode.thickness'), ('outputnode.anat_ribbon', 'inputnode.anat_ribbon'), ( f'outputnode.sphere_reg_{"msm" if msm_sulc else "fsLR"}', @@ -696,6 +709,12 @@ def init_single_subject_wf(subject_id: str): workflow.connect([ (select_MNI6_xfm, bold_wf, [("anat2std_xfm", "inputnode.anat2mni6_xfm")]), (select_MNI6_tpl, bold_wf, [("brain_mask", "inputnode.mni6_mask")]), + (hcp_morphometrics_wf, bold_wf, [ + ("outputnode.roi", "inputnode.cortex_mask"), + ]), + (resample_midthickness_wf, bold_wf, [ + ('outputnode.midthickness_fsLR', 'inputnode.midthickness_fsLR'), + ]), ]) # fmt:skip return clean_datasinks(workflow) diff --git a/fmriprep/workflows/bold/base.py b/fmriprep/workflows/bold/base.py index c0bcb9f00..34fba1754 100644 --- a/fmriprep/workflows/bold/base.py +++ b/fmriprep/workflows/bold/base.py @@ -113,8 +113,6 @@ def init_bold_wf( FreeSurfer pial surfaces, in T1w space, collated left, then right sphere_reg_fsLR Registration spheres from fsnative to fsLR space, collated left, then right - thickness - FreeSurfer thickness metrics, collated left, then right anat_ribbon Binary cortical ribbon mask in T1w space fmap_id @@ -235,7 +233,8 @@ def init_bold_wf( "midthickness", "pial", "sphere_reg_fsLR", - "thickness", + "midthickness_fsLR", + "cortex_mask", "anat_ribbon", # Fieldmap registration "fmap", @@ -580,8 +579,9 @@ def init_bold_wf( ("white", "inputnode.white"), ("pial", "inputnode.pial"), ("midthickness", "inputnode.midthickness"), - ("thickness", "inputnode.thickness"), + ("midthickness_fsLR", "inputnode.midthickness_fsLR"), ("sphere_reg_fsLR", "inputnode.sphere_reg_fsLR"), + ("cortex_mask", "inputnode.cortex_mask"), ("anat_ribbon", "inputnode.anat_ribbon"), ]), (bold_anat_wf, bold_fsLR_resampling_wf, [ diff --git a/fmriprep/workflows/bold/resampling.py b/fmriprep/workflows/bold/resampling.py index cabf895a2..9a3b612e0 100644 --- a/fmriprep/workflows/bold/resampling.py +++ b/fmriprep/workflows/bold/resampling.py @@ -587,27 +587,28 @@ def init_bold_fsLR_resampling_wf( niu.IdentityInterface( fields=[ 'bold_file', + 'anat_ribbon', 'white', 'pial', 'midthickness', - 'thickness', + 'midthickness_fsLR', 'sphere_reg_fsLR', - 'anat_ribbon', + 'cortex_mask', ] ), name='inputnode', ) - itersource = pe.Node( + hemisource = pe.Node( niu.IdentityInterface(fields=['hemi']), - name='itersource', + name='hemisource', iterables=[('hemi', ['L', 'R'])], ) joinnode = pe.JoinNode( niu.IdentityInterface(fields=['bold_fsLR']), name='joinnode', - joinsource='itersource', + joinsource='hemisource', ) outputnode = pe.Node( @@ -622,9 +623,10 @@ def init_bold_fsLR_resampling_wf( "white", "pial", "midthickness", - "thickness", - "sphere_reg", + 'midthickness_fsLR', + "sphere_reg_fsLR", "template_sphere", + 'cortex_mask', "template_roi", ], keys=["L", "R"], @@ -648,20 +650,6 @@ def init_bold_fsLR_resampling_wf( str(atlases / 'R.atlasroi.32k_fs_LR.shape.gii'), ] - # Reimplements lines 282-290 of FreeSurfer2CaretConvertAndRegisterNonlinear.sh - initial_roi = pe.Node(CreateROI(), name="initial_roi", mem_gb=DEFAULT_MEMORY_MIN_GB) - - # Lines 291-292 - fill_holes = pe.Node(MetricFillHoles(), name="fill_holes", mem_gb=DEFAULT_MEMORY_MIN_GB) - native_roi = pe.Node(MetricRemoveIslands(), name="native_roi", mem_gb=DEFAULT_MEMORY_MIN_GB) - - # Line 393 of FreeSurfer2CaretConvertAndRegisterNonlinear.sh - downsampled_midthickness = pe.Node( - SurfaceResample(method='BARYCENTRIC'), - name="downsampled_midthickness", - mem_gb=DEFAULT_MEMORY_MIN_GB, - ) - # RibbonVolumeToSurfaceMapping.sh # Line 85 thru ... volume_to_surface = pe.Node( @@ -689,23 +677,11 @@ def init_bold_fsLR_resampling_wf( ('white', 'white'), ('pial', 'pial'), ('midthickness', 'midthickness'), - ('thickness', 'thickness'), - ('sphere_reg_fsLR', 'sphere_reg'), - ]), - (itersource, select_surfaces, [('hemi', 'key')]), - # Native ROI file from thickness - (itersource, initial_roi, [('hemi', 'hemisphere')]), - (select_surfaces, initial_roi, [('thickness', 'thickness_file')]), - (select_surfaces, fill_holes, [('midthickness', 'surface_file')]), - (select_surfaces, native_roi, [('midthickness', 'surface_file')]), - (initial_roi, fill_holes, [('roi_file', 'metric_file')]), - (fill_holes, native_roi, [('out_file', 'metric_file')]), - # Downsample midthickness to fsLR density - (select_surfaces, downsampled_midthickness, [ - ('midthickness', 'surface_in'), - ('sphere_reg', 'current_sphere'), - ('template_sphere', 'new_sphere'), + ('midthickness_fsLR', 'midthickness_fsLR'), + ('sphere_reg_fsLR', 'sphere_reg_fsLR'), + ('cortex_mask', 'cortex_mask'), ]), + (hemisource, select_surfaces, [('hemi', 'key')]), # Resample BOLD to native surface, dilate and mask (inputnode, volume_to_surface, [ ('bold_file', 'volume_file'), @@ -716,17 +692,17 @@ def init_bold_fsLR_resampling_wf( ('pial', 'outer_surface'), ]), (select_surfaces, metric_dilate, [('midthickness', 'surf_file')]), + (select_surfaces, mask_native, [('cortex_mask', 'mask')]), (volume_to_surface, metric_dilate, [('out_file', 'in_file')]), - (native_roi, mask_native, [('out_file', 'mask')]), (metric_dilate, mask_native, [('out_file', 'in_file')]), # Resample BOLD to fsLR and mask (select_surfaces, resample_to_fsLR, [ - ('sphere_reg', 'current_sphere'), + ('sphere_reg_fsLR', 'current_sphere'), ('template_sphere', 'new_sphere'), ('midthickness', 'current_area'), + ('midthickness_fsLR', 'new_area'), + ('cortex_mask', 'roi_metric'), ]), - (downsampled_midthickness, resample_to_fsLR, [('surface_out', 'new_area')]), - (native_roi, resample_to_fsLR, [('out_file', 'roi_metric')]), (mask_native, resample_to_fsLR, [('out_file', 'in_file')]), (select_surfaces, mask_fsLR, [('template_roi', 'mask')]), (resample_to_fsLR, mask_fsLR, [('out_file', 'in_file')]),