From 23bc03b9454296538b55e54ea5cc4bae71150da5 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Fri, 22 Aug 2025 16:07:36 -0400 Subject: [PATCH 01/17] changing ref from brain to whole head --- CPAC/func_preproc/func_preproc.py | 37 ++++++-------- CPAC/pipeline/cpac_pipeline.py | 16 +++--- CPAC/registration/registration.py | 82 +++++++------------------------ 3 files changed, 44 insertions(+), 91 deletions(-) diff --git a/CPAC/func_preproc/func_preproc.py b/CPAC/func_preproc/func_preproc.py index d098b6186..c787b06f3 100644 --- a/CPAC/func_preproc/func_preproc.py +++ b/CPAC/func_preproc/func_preproc.py @@ -1559,12 +1559,12 @@ def anat_brain_to_bold_res(wf_name, cfg, pipe_num): inputNode = pe.Node( util.IdentityInterface( - fields=["T1w-template-funcreg", "space-template_desc-preproc_T1w"] + fields=["T1w-template-funcreg", "space-template_desc-head_T1w"] ), name="inputspec", ) outputNode = pe.Node( - util.IdentityInterface(fields=["space-template_res-bold_desc-brain_T1w"]), + util.IdentityInterface(fields=["space-template_res-bold_desc-head_T1w"]), name="outputspec", ) @@ -1579,7 +1579,7 @@ def anat_brain_to_bold_res(wf_name, cfg, pipe_num): ]["registration"]["FSL-FNIRT"]["identity_matrix"] wf.connect( - inputNode, "space-template_desc-preproc_T1w", anat_brain_to_func_res, "in_file" + inputNode, "space-template_desc-head_T1w", anat_brain_to_func_res, "in_file" ) wf.connect(inputNode, "T1w-template-funcreg", anat_brain_to_func_res, "ref_file") @@ -1587,7 +1587,7 @@ def anat_brain_to_bold_res(wf_name, cfg, pipe_num): anat_brain_to_func_res, "out_file", outputNode, - "space-template_res-bold_desc-brain_T1w", + "space-template_res-bold_desc-head_T1w", ) return wf @@ -1598,7 +1598,7 @@ def anat_brain_mask_to_bold_res(wf_name, cfg, pipe_num): wf = pe.Workflow(name=f"{wf_name}_{pipe_num}") inputNode = pe.Node( util.IdentityInterface( - fields=["space-template_desc-brain_mask", "space-template_desc-preproc_T1w"] + fields=["space-template_desc-brain_mask", "space-template_desc-head_T1w"] ), name="inputspec", ) @@ -1625,7 +1625,7 @@ def anat_brain_mask_to_bold_res(wf_name, cfg, pipe_num): ) wf.connect( inputNode, - "space-template_desc-preproc_T1w", + "space-template_desc-head_T1w", anat_brain_mask_to_func_res, "ref_file", ) @@ -1649,11 +1649,11 @@ def anat_brain_mask_to_bold_res(wf_name, cfg, pipe_num): option_val="Anatomical_Resampled", inputs=[ "T1w-template-funcreg", - "space-template_desc-preproc_T1w", + "space-template_desc-head_T1w", "space-template_desc-brain_mask", ], outputs=[ - "space-template_res-bold_desc-brain_T1w", + "space-template_res-bold_desc-head_T1w", "space-template_desc-bold_mask", ], ) @@ -1666,9 +1666,9 @@ def bold_mask_anatomical_resampled(wf, cfg, strat_pool, pipe_num, opt=None): wf_name="anat_brain_to_bold_res", cfg=cfg, pipe_num=pipe_num ) - node, out = strat_pool.get_data("space-template_desc-preproc_T1w") + node, out = strat_pool.get_data("space-template_desc-head_T1w") wf.connect( - node, out, anat_brain_to_func_res, "inputspec.space-template_desc-preproc_T1w" + node, out, anat_brain_to_func_res, "inputspec.space-template_desc-head_T1w" ) node, out = strat_pool.get_data("T1w-template-funcreg") @@ -1690,15 +1690,15 @@ def bold_mask_anatomical_resampled(wf, cfg, strat_pool, pipe_num, opt=None): wf.connect( anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", + "outputspec.space-template_res-bold_desc-head_T1w", anat_brain_mask_to_func_res, - "inputspec.space-template_desc-preproc_T1w", + "inputspec.space-template_desc-head_T1w", ) outputs = { - "space-template_res-bold_desc-brain_T1w": ( + "space-template_res-bold_desc-head_T1w": ( anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", + "outputspec.space-template_res-bold_desc-head_T1w", ), "space-template_desc-bold_mask": ( anat_brain_mask_to_func_res, @@ -1897,7 +1897,7 @@ def bold_masking(wf, cfg, strat_pool, pipe_num, opt=None): ["functional_preproc", "template_space_func_masking", "run"], ], inputs=[ - ("space-template_desc-preproc_bold", "space-template_desc-bold_mask"), + ("space-template_desc-head_bold", "space-template_desc-bold_mask"), ], outputs={ "space-template_desc-preproc_bold": { @@ -1908,10 +1908,6 @@ def bold_masking(wf, cfg, strat_pool, pipe_num, opt=None): "Description": "The skull-stripped BOLD time-series.", "SkullStripped": True, }, - "space-template_desc-head_bold": { - "Description": "The non skull-stripped BOLD time-series.", - "SkullStripped": False, - }, }, ) def template_space_bold_masking( @@ -1931,7 +1927,7 @@ def template_space_bold_masking( func_apply_mask.inputs.outputtype = "NIFTI_GZ" node_head_bold, out_head_bold = strat_pool.get_data( - "space-template_desc-preproc_bold" + "space-template_desc-head_bold" ) wf.connect(node_head_bold, out_head_bold, func_apply_mask, "in_file_a") @@ -1941,7 +1937,6 @@ def template_space_bold_masking( outputs: POOL_RESOURCE_DICT = { "space-template_desc-preproc_bold": (func_apply_mask, "out_file"), "space-template_desc-brain_bold": (func_apply_mask, "out_file"), - "space-template_desc-head_bold": (node_head_bold, out_head_bold), } return wf, outputs diff --git a/CPAC/pipeline/cpac_pipeline.py b/CPAC/pipeline/cpac_pipeline.py index c2ffa9640..6546a1324 100644 --- a/CPAC/pipeline/cpac_pipeline.py +++ b/CPAC/pipeline/cpac_pipeline.py @@ -1291,6 +1291,13 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None): mask_sbref, ] + # Template space functional mask + if cfg.functional_preproc["template_space_func_masking"]["run"]: + if not rpool.check_rpool("space-template_desc-bold_mask"): + pipeline_blocks += [ + bold_mask_anatomical_resampled, + ] + # Distortion/Susceptibility Correction distcor_blocks = [] if "fmap" in sub_dict: @@ -1472,17 +1479,12 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None): warp_deriv_mask_to_EPItemplate, ] - # Template space functional masking + # Apply mask in template space if cfg.functional_preproc["template_space_func_masking"]["run"]: - if not rpool.check_rpool("space-template_desc-bold_mask"): - pipeline_blocks += [ - bold_mask_anatomical_resampled, - ] - pipeline_blocks += [ template_space_bold_masking, ] - + # Template-space nuisance regression nuisance_template = ( cfg["nuisance_corrections", "2-nuisance_regression", "space"] == "template" diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index efb8645df..9bdda851b 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -2901,6 +2901,7 @@ def register_ANTs_EPI_to_template(wf, cfg, strat_pool, pipe_num, opt=None): inputs=[ ( "desc-restore-brain_T1w", + "desc-head_T1w", ["desc-preproc_T1w", "space-longitudinal_desc-brain_T1w"], ["desc-restore_T1w", "desc-preproc_T1w", "desc-reorient_T1w", "T1w"], ["desc-preproc_T1w", "desc-reorient_T1w", "T1w"], @@ -3081,7 +3082,7 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None wf.connect(node, out, match_fovs_T1w, "reference") wf.connect(node, out, fsl_apply_warp_t1_to_template, "ref_file") - node, out = strat_pool.get_data(["desc-restore_T1w", "desc-preproc_T1w"]) + node, out = strat_pool.get_data(["desc-restore_T1w", "desc-head_T1w"]) wf.connect(node, out, match_fovs_T1w, "in_file") wf.connect(match_fovs_T1w, "out_file", fsl_apply_warp_t1_to_template, "in_file") @@ -4169,7 +4170,8 @@ def warp_timeseries_to_T1template_deriv(wf, cfg, strat_pool, pipe_num, opt=None) "from-bold_to-template_mode-image_xfm", "fsl-blip-warp", "desc-preproc_T1w", - "space-template_res-bold_desc-brain_T1w", + "desc-head_T1w", + "space-template_res-bold_desc-head_T1w", "space-template_desc-bold_mask", "T1w-brain-template-funcreg", "T1w-template-funcreg", @@ -4199,7 +4201,7 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): convert_func_to_anat_linear_warp.inputs.out_relwarp = True convert_func_to_anat_linear_warp.inputs.relwarp = True - node, out = strat_pool.get_data("desc-preproc_T1w") + node, out = strat_pool.get_data("desc-head_T1w") wf.connect(node, out, convert_func_to_anat_linear_warp, "reference") if strat_pool.check_rpool("fsl-blip-warp"): @@ -4231,24 +4233,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("from-T1w_to-template_mode-image_xfm") wf.connect(node, out, convert_func_to_standard_warp, "warp2") - from CPAC.func_preproc.func_preproc import ( - anat_brain_mask_to_bold_res, - anat_brain_to_bold_res, - ) - - anat_brain_to_func_res = anat_brain_to_bold_res(wf, cfg, pipe_num) - - node, out = strat_pool.get_data("space-template_desc-preproc_T1w") - wf.connect( - node, out, anat_brain_to_func_res, "inputspec.space-template_desc-preproc_T1w" - ) - - node, out = strat_pool.get_data("T1w-template-funcreg") - wf.connect(node, out, anat_brain_to_func_res, "inputspec.T1w-template-funcreg") - + node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", + node, out, convert_func_to_standard_warp, "reference", ) @@ -4314,11 +4301,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): convert_registration_warp.inputs.out_relwarp = True convert_registration_warp.inputs.relwarp = True + node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", - convert_registration_warp, - "reference", + node, out, convert_registration_warp, "reference", ) wf.connect( @@ -4356,11 +4341,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): convert_registration_warp, "out_file", applywarp_func_to_standard, "field_file" ) + node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", - applywarp_func_to_standard, - "ref_file", + node, out, applywarp_func_to_standard, "ref_file", ) # applywarp --rel --interp=nn --in=${WD}/prevols/vol${vnum}_mask.nii.gz --warp=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_all_warp.nii.gz --ref=${WD}/${T1wImageFile}.${FinalfMRIResolution} --out=${WD}/postvols/vol${vnum}_mask.nii.gz @@ -4384,11 +4367,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): "field_file", ) + node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", - applywarp_func_mask_to_standard, - "ref_file", + node, out, applywarp_func_mask_to_standard, "ref_file", ) ### Loop ends! ### @@ -4436,11 +4417,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): convert_dc_warp.inputs.out_relwarp = True convert_dc_warp.inputs.relwarp = True + node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", - convert_dc_warp, - "reference", + node, out, convert_dc_warp, "reference", ) wf.connect(multiply_func_roi_by_zero, "out_file", convert_dc_warp, "warp1") @@ -4458,11 +4437,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("motion-basefile") wf.connect(node, out, applywarp_scout, "in_file") + node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", - applywarp_scout, - "ref_file", + node, out, applywarp_scout, "ref_file", ) wf.connect(convert_dc_warp, "out_file", applywarp_scout, "field_file") @@ -4471,30 +4448,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): # fslmaths ${InputfMRI} -mas ${BrainMask} -mas ${InputfMRI}_mask -thr 0 -ing 10000 ${OutputfMRI} -odt float merge_func_mask = pe.Node(util.Merge(2), name=f"merge_func_mask_{pipe_num}") - anat_brain_mask_to_func_res = anat_brain_mask_to_bold_res( - wf_name="anat_brain_mask_to_bold_res", cfg=cfg, pipe_num=pipe_num - ) - - node, out = strat_pool.get_data("space-template_desc-brain_mask") + node, out = strat_pool.get_data("space-template_desc-bold_mask") wf.connect( - node, - out, - anat_brain_mask_to_func_res, - "inputspec.space-template_desc-brain_mask", - ) - - wf.connect( - anat_brain_to_func_res, - "outputspec.space-template_res-bold_desc-brain_T1w", - anat_brain_mask_to_func_res, - "inputspec.space-template_desc-preproc_T1w", - ) - - wf.connect( - anat_brain_mask_to_func_res, - "outputspec.space-template_desc-bold_mask", - merge_func_mask, - "in1", + node, out, merge_func_mask, "in1", ) wf.connect(find_min_mask, "out_file", merge_func_mask, "in2") From 9d89c6f93b202574781419a91449d94b71fe8477 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Tue, 26 Aug 2025 12:13:52 -0400 Subject: [PATCH 02/17] removing unnecessary nodes --- CPAC/registration/registration.py | 132 ++++++++++++++++++------------ 1 file changed, 81 insertions(+), 51 deletions(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index 9bdda851b..c2bdb6d60 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -22,6 +22,7 @@ from voluptuous import RequiredFieldInvalid from nipype.interfaces import afni, ants, c3, fsl, utility as util from nipype.interfaces.afni import utils as afni_utils +from pathlib import Path from CPAC.anat_preproc.lesion_preproc import create_lesion_preproc from CPAC.func_preproc.func_preproc import fsl_afni_subworkflow @@ -4194,6 +4195,21 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): https://github.com/DCAN-Labs/DCAN-HCP/blob/a8d495a/fMRIVolume/scripts/DistortionCorrectionAndEPIToT1wReg_FLIRTBBRAndFreeSurferBBRbased.sh#L548 convertwarp --relout --rel -m ${WD}/fMRI2str.mat --ref=${T1wImage} --out=${WD}/fMRI2str.nii.gz """ + # Identity matrix node needed for matching FOV + identity_node = pe.Node( + Function( + imports=["from pathlib import Path", "import numpy as np"], + input_names=["workdir"], + output_names=["identity_file"], + function=lambda workdir: ( + np.savetxt(Path(workdir) / "identity.mat", np.eye(4), fmt="%.6f") or + str(Path(workdir) / "identity.mat") + ) + ), + name=f"create_identity_matrix_{pipe_num}" + ) + identity_node.inputs.workdir = str(Path.cwd()) + convert_func_to_anat_linear_warp = pe.Node( interface=fsl.ConvertWarp(), name=f"convert_func_to_anat_linear_warp_{pipe_num}" ) @@ -4204,15 +4220,12 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("desc-head_T1w") wf.connect(node, out, convert_func_to_anat_linear_warp, "reference") - if strat_pool.check_rpool("fsl-blip-warp"): - node, out = strat_pool.get_data("from-bold_to-T1w_mode-image_desc-linear_xfm") - wf.connect(node, out, convert_func_to_anat_linear_warp, "postmat") + node, out = strat_pool.get_data("from-bold_to-T1w_mode-image_desc-linear_xfm") + wf.connect(node, out, convert_func_to_anat_linear_warp, "premat") + if strat_pool.check_rpool("fsl-blip-warp"): node, out = strat_pool.get_data("fsl-blip-warp") wf.connect(node, out, convert_func_to_anat_linear_warp, "warp1") - else: - node, out = strat_pool.get_data("from-bold_to-T1w_mode-image_desc-linear_xfm") - wf.connect(node, out, convert_func_to_anat_linear_warp, "premat") # https://github.com/DCAN-Labs/DCAN-HCP/blob/1d90814/fMRIVolume/scripts/OneStepResampling.sh#L140 # convertwarp --relout --rel --warp1=${fMRIToStructuralInput} --warp2=${StructuralToStandard} --ref=${WD}/${T1wImageFile}.${FinalfMRIResolution} --out=${OutputTransform} @@ -4253,15 +4266,6 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("desc-reorient_bold") wf.connect(node, out, extract_func_roi, "in_file") - # fslmaths "$fMRIFolder"/"$NameOffMRI"_gdc_warp -mul 0 "$fMRIFolder"/"$NameOffMRI"_gdc_warp - multiply_func_roi_by_zero = pe.Node( - interface=fsl.maths.MathsCommand(), name=f"multiply_func_roi_by_zero_{pipe_num}" - ) - - multiply_func_roi_by_zero.inputs.args = "-mul 0" - - wf.connect(extract_func_roi, "roi_file", multiply_func_roi_by_zero, "in_file") - # https://github.com/DCAN-Labs/DCAN-HCP/blob/1d90814/fMRIVolume/scripts/OneStepResampling.sh#L168-L193 # fslsplit ${InputfMRI} ${WD}/prevols/vol -t split_func = pe.Node(interface=fsl.Split(), name=f"split_func_{pipe_num}") @@ -4272,6 +4276,16 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): wf.connect(node, out, split_func, "in_file") ### Loop starts! ### + # Match FOV func_to_standard + match_fov_func = pe.MapNode( + interface=fsl.FLIRT(apply_xfm=True, interp="spline"), name=f"match_fov_func_{pipe_num}", iterfield=["in_file"] + ) + wf.connect(identity_node, "identity_file", match_fov_func, "in_matrix_file") + wf.connect(split_func, "out_files", match_fov_func, "in_file") + + node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") + wf.connect(node, out, match_fov_func, "reference") + # convertwarp --relout --rel --ref=${WD}/prevols/vol${vnum}.nii.gz --warp1=${GradientDistortionField} --postmat=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum} --out=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_gdc_warp.nii.gz convert_motion_distortion_warp = pe.MapNode( interface=fsl.ConvertWarp(), @@ -4282,15 +4296,15 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): convert_motion_distortion_warp.inputs.out_relwarp = True convert_motion_distortion_warp.inputs.relwarp = True - wf.connect( - multiply_func_roi_by_zero, "out_file", convert_motion_distortion_warp, "warp1" - ) - - wf.connect(split_func, "out_files", convert_motion_distortion_warp, "reference") + wf.connect(match_fov_func, "out_file", convert_motion_distortion_warp, "reference") node, out = strat_pool.get_data("coordinate-transformation") wf.connect(node, out, convert_motion_distortion_warp, "postmat") + if strat_pool.check_rpool("gradient-distortion-field"): + node, out = strat_pool.get_data("gradient-distortion-field") + wf.connect(node, out, convert_motion_distortion_warp, "warp1") + # convertwarp --relout --rel --ref=${WD}/${T1wImageFile}.${FinalfMRIResolution} --warp1=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_gdc_warp.nii.gz --warp2=${OutputTransform} --out=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_all_warp.nii.gz convert_registration_warp = pe.MapNode( interface=fsl.ConvertWarp(), @@ -4314,17 +4328,6 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): convert_func_to_standard_warp, "out_file", convert_registration_warp, "warp2" ) - # fslmaths ${WD}/prevols/vol${vnum}.nii.gz -mul 0 -add 1 ${WD}/prevols/vol${vnum}_mask.nii.gz - generate_vol_mask = pe.MapNode( - interface=fsl.maths.MathsCommand(), - name=f"generate_mask_{pipe_num}", - iterfield=["in_file"], - ) - - generate_vol_mask.inputs.args = "-mul 0 -add 1" - - wf.connect(split_func, "out_files", generate_vol_mask, "in_file") - # applywarp --rel --interp=spline --in=${WD}/prevols/vol${vnum}.nii.gz --warp=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_all_warp.nii.gz --ref=${WD}/${T1wImageFile}.${FinalfMRIResolution} --out=${WD}/postvols/vol${vnum}.nii.gz applywarp_func_to_standard = pe.MapNode( interface=fsl.ApplyWarp(), @@ -4332,10 +4335,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): iterfield=["in_file", "field_file"], ) - applywarp_func_to_standard.inputs.relwarp = True applywarp_func_to_standard.inputs.interp = "spline" - wf.connect(split_func, "out_files", applywarp_func_to_standard, "in_file") + wf.connect(match_fov_func, "out_file", applywarp_func_to_standard, "in_file") wf.connect( convert_registration_warp, "out_file", applywarp_func_to_standard, "field_file" @@ -4353,11 +4355,11 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): iterfield=["in_file", "field_file"], ) - applywarp_func_mask_to_standard.inputs.relwarp = True applywarp_func_mask_to_standard.inputs.interp = "nn" + node, out = strat_pool.get_data("space-template_desc-bold_mask") wf.connect( - generate_vol_mask, "out_file", applywarp_func_mask_to_standard, "in_file" + node, out, applywarp_func_mask_to_standard, "in_file" ) wf.connect( @@ -4408,41 +4410,35 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): wf.connect(merge_func_mask_to_standard, "merged_file", find_min_mask, "in_file") - # Combine transformations: gradient non-linearity distortion + fMRI_dc to standard - # convertwarp --relout --rel --ref=${WD}/${T1wImageFile}.${FinalfMRIResolution} --warp1=${GradientDistortionField} --warp2=${OutputTransform} --out=${WD}/Scout_gdc_MNI_warp.nii.gz - convert_dc_warp = pe.Node( - interface=fsl.ConvertWarp(), name=f"convert_dc_warp_{pipe_num}" + # Match FOV scout_to_standard + match_fov_scout_to_standard = pe.MapNode( + interface=fsl.FLIRT(apply_xfm=True, interp="spline"), name=f"match_fov_scout_to_standard_{pipe_num}", iterfield=["in_file"] ) - - convert_dc_warp.inputs.out_relwarp = True - convert_dc_warp.inputs.relwarp = True + wf.connect(identity_node, "identity_file", match_fov_scout_to_standard, "in_matrix_file") + node, out = strat_pool.get_data("motion-basefile") + wf.connect(node, out, match_fov_scout_to_standard, "in_file") node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - node, out, convert_dc_warp, "reference", + node, out, match_fov_scout_to_standard, "reference" ) - wf.connect(multiply_func_roi_by_zero, "out_file", convert_dc_warp, "warp1") - - wf.connect(convert_func_to_standard_warp, "out_file", convert_dc_warp, "warp2") - # applywarp --rel --interp=spline --in=${ScoutInput} -w ${WD}/Scout_gdc_MNI_warp.nii.gz -r ${WD}/${T1wImageFile}.${FinalfMRIResolution} -o ${ScoutOutput} applywarp_scout = pe.Node( interface=fsl.ApplyWarp(), name=f"applywarp_scout_input_{pipe_num}" ) - applywarp_scout.inputs.relwarp = True applywarp_scout.inputs.interp = "spline" - node, out = strat_pool.get_data("motion-basefile") - wf.connect(node, out, applywarp_scout, "in_file") + wf.connect(match_fov_scout_to_standard, "out_file", applywarp_scout, "in_file") node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( node, out, applywarp_scout, "ref_file", ) - wf.connect(convert_dc_warp, "out_file", applywarp_scout, "field_file") + # warp field is just fMRI->standard (skip GDC) + wf.connect(convert_func_to_standard_warp, "out_file", applywarp_scout, "field_file") # https://github.com/DCAN-Labs/DCAN-HCP/blob/1214767/fMRIVolume/scripts/IntensityNormalization.sh#L124-L127 # fslmaths ${InputfMRI} -mas ${BrainMask} -mas ${InputfMRI}_mask -thr 0 -ing 10000 ${OutputfMRI} -odt float @@ -5597,3 +5593,37 @@ def _warp_return( if apply_xfm is None: return wf, {} return wf, outputs + + +def create_identity_matrix(workdir): + """Create an identity matrix for FLIRT.""" + identity_file = Path(workdir) / "identity.mat" + np.savetxt(identity_file, np.eye(4), fmt="%.6f") + return str(identity_file) + +def build_match_fov_wf(name, workdir, pipe_num): + """ + Workflow to match Field-of-View for T1w or functional images + using an identity matrix. + """ + wf = Workflow(name=name) + + identity_node = Node( + Function( + input_names=["workdir"], + output_names=["identity_file"], + function=create_identity_matrix + ), + name=f"create_identity_matrix_{pipe_num}" + ) + identity_node.inputs.workdir = workdir + + match_fov_node = MapNode( + interface=fsl.FLIRT(apply_xfm=True, interp="spline"), + name=f"match_fov_{pipe_num}", + iterfield=["in_file"] + ) + + wf.connect(identity_node, "identity_file", match_fov_node, "in_matrix_file") + + return wf, match_fov_node \ No newline at end of file From 262c2fc528b07cb8e70426de8fee0790cc80b150 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 16:14:21 +0000 Subject: [PATCH 03/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CPAC/func_preproc/func_preproc.py | 4 +- CPAC/pipeline/cpac_pipeline.py | 2 +- CPAC/registration/registration.py | 73 +++++++++++++++++++------------ 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/CPAC/func_preproc/func_preproc.py b/CPAC/func_preproc/func_preproc.py index c787b06f3..43658bbec 100644 --- a/CPAC/func_preproc/func_preproc.py +++ b/CPAC/func_preproc/func_preproc.py @@ -1926,9 +1926,7 @@ def template_space_bold_masking( func_apply_mask.inputs.expr = "a*b" func_apply_mask.inputs.outputtype = "NIFTI_GZ" - node_head_bold, out_head_bold = strat_pool.get_data( - "space-template_desc-head_bold" - ) + node_head_bold, out_head_bold = strat_pool.get_data("space-template_desc-head_bold") wf.connect(node_head_bold, out_head_bold, func_apply_mask, "in_file_a") node, out = strat_pool.get_data("space-template_desc-bold_mask") diff --git a/CPAC/pipeline/cpac_pipeline.py b/CPAC/pipeline/cpac_pipeline.py index 6546a1324..b9e686593 100644 --- a/CPAC/pipeline/cpac_pipeline.py +++ b/CPAC/pipeline/cpac_pipeline.py @@ -1484,7 +1484,7 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None): pipeline_blocks += [ template_space_bold_masking, ] - + # Template-space nuisance regression nuisance_template = ( cfg["nuisance_corrections", "2-nuisance_regression", "space"] == "template" diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index c2bdb6d60..d42f66095 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -22,7 +22,7 @@ from voluptuous import RequiredFieldInvalid from nipype.interfaces import afni, ants, c3, fsl, utility as util from nipype.interfaces.afni import utils as afni_utils -from pathlib import Path +from pathlib import Path from CPAC.anat_preproc.lesion_preproc import create_lesion_preproc from CPAC.func_preproc.func_preproc import fsl_afni_subworkflow @@ -4202,14 +4202,14 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): input_names=["workdir"], output_names=["identity_file"], function=lambda workdir: ( - np.savetxt(Path(workdir) / "identity.mat", np.eye(4), fmt="%.6f") or - str(Path(workdir) / "identity.mat") - ) + np.savetxt(Path(workdir) / "identity.mat", np.eye(4), fmt="%.6f") + or str(Path(workdir) / "identity.mat") + ), ), - name=f"create_identity_matrix_{pipe_num}" + name=f"create_identity_matrix_{pipe_num}", ) identity_node.inputs.workdir = str(Path.cwd()) - + convert_func_to_anat_linear_warp = pe.Node( interface=fsl.ConvertWarp(), name=f"convert_func_to_anat_linear_warp_{pipe_num}" ) @@ -4248,7 +4248,8 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - node, out, + node, + out, convert_func_to_standard_warp, "reference", ) @@ -4278,7 +4279,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): ### Loop starts! ### # Match FOV func_to_standard match_fov_func = pe.MapNode( - interface=fsl.FLIRT(apply_xfm=True, interp="spline"), name=f"match_fov_func_{pipe_num}", iterfield=["in_file"] + interface=fsl.FLIRT(apply_xfm=True, interp="spline"), + name=f"match_fov_func_{pipe_num}", + iterfield=["in_file"], ) wf.connect(identity_node, "identity_file", match_fov_func, "in_matrix_file") wf.connect(split_func, "out_files", match_fov_func, "in_file") @@ -4317,7 +4320,10 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - node, out, convert_registration_warp, "reference", + node, + out, + convert_registration_warp, + "reference", ) wf.connect( @@ -4345,7 +4351,10 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - node, out, applywarp_func_to_standard, "ref_file", + node, + out, + applywarp_func_to_standard, + "ref_file", ) # applywarp --rel --interp=nn --in=${WD}/prevols/vol${vnum}_mask.nii.gz --warp=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_all_warp.nii.gz --ref=${WD}/${T1wImageFile}.${FinalfMRIResolution} --out=${WD}/postvols/vol${vnum}_mask.nii.gz @@ -4358,9 +4367,7 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): applywarp_func_mask_to_standard.inputs.interp = "nn" node, out = strat_pool.get_data("space-template_desc-bold_mask") - wf.connect( - node, out, applywarp_func_mask_to_standard, "in_file" - ) + wf.connect(node, out, applywarp_func_mask_to_standard, "in_file") wf.connect( convert_registration_warp, @@ -4371,7 +4378,10 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - node, out, applywarp_func_mask_to_standard, "ref_file", + node, + out, + applywarp_func_mask_to_standard, + "ref_file", ) ### Loop ends! ### @@ -4412,16 +4422,18 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): # Match FOV scout_to_standard match_fov_scout_to_standard = pe.MapNode( - interface=fsl.FLIRT(apply_xfm=True, interp="spline"), name=f"match_fov_scout_to_standard_{pipe_num}", iterfield=["in_file"] + interface=fsl.FLIRT(apply_xfm=True, interp="spline"), + name=f"match_fov_scout_to_standard_{pipe_num}", + iterfield=["in_file"], + ) + wf.connect( + identity_node, "identity_file", match_fov_scout_to_standard, "in_matrix_file" ) - wf.connect(identity_node, "identity_file", match_fov_scout_to_standard, "in_matrix_file") node, out = strat_pool.get_data("motion-basefile") wf.connect(node, out, match_fov_scout_to_standard, "in_file") node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") - wf.connect( - node, out, match_fov_scout_to_standard, "reference" - ) + wf.connect(node, out, match_fov_scout_to_standard, "reference") # applywarp --rel --interp=spline --in=${ScoutInput} -w ${WD}/Scout_gdc_MNI_warp.nii.gz -r ${WD}/${T1wImageFile}.${FinalfMRIResolution} -o ${ScoutOutput} applywarp_scout = pe.Node( @@ -4434,7 +4446,10 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( - node, out, applywarp_scout, "ref_file", + node, + out, + applywarp_scout, + "ref_file", ) # warp field is just fMRI->standard (skip GDC) @@ -4446,7 +4461,10 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("space-template_desc-bold_mask") wf.connect( - node, out, merge_func_mask, "in1", + node, + out, + merge_func_mask, + "in1", ) wf.connect(find_min_mask, "out_file", merge_func_mask, "in2") @@ -5601,29 +5619,30 @@ def create_identity_matrix(workdir): np.savetxt(identity_file, np.eye(4), fmt="%.6f") return str(identity_file) + def build_match_fov_wf(name, workdir, pipe_num): """ Workflow to match Field-of-View for T1w or functional images using an identity matrix. """ wf = Workflow(name=name) - + identity_node = Node( Function( input_names=["workdir"], output_names=["identity_file"], - function=create_identity_matrix + function=create_identity_matrix, ), - name=f"create_identity_matrix_{pipe_num}" + name=f"create_identity_matrix_{pipe_num}", ) identity_node.inputs.workdir = workdir match_fov_node = MapNode( interface=fsl.FLIRT(apply_xfm=True, interp="spline"), name=f"match_fov_{pipe_num}", - iterfield=["in_file"] + iterfield=["in_file"], ) - + wf.connect(identity_node, "identity_file", match_fov_node, "in_matrix_file") - return wf, match_fov_node \ No newline at end of file + return wf, match_fov_node From 713f451b597daba3e39f4ae290a41811dccf599d Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Wed, 27 Aug 2025 15:08:46 -0400 Subject: [PATCH 04/17] moving the reference flag from inside of bbreg to coregistration --- CPAC/pipeline/schema.py | 2 +- CPAC/registration/registration.py | 138 ++++++------------ .../configs/pipeline_config_abcd-options.yml | 5 +- .../configs/pipeline_config_blank.yml | 10 +- .../configs/pipeline_config_default.yml | 10 +- .../pipeline_config_fmriprep-options.yml | 7 +- 6 files changed, 59 insertions(+), 113 deletions(-) diff --git a/CPAC/pipeline/schema.py b/CPAC/pipeline/schema.py index 2785f6d8a..abfb7a3c4 100644 --- a/CPAC/pipeline/schema.py +++ b/CPAC/pipeline/schema.py @@ -843,12 +843,12 @@ def sanitize(filename): }, "mask_sbref": bool1_1, }, + "reference": In({"whole-head", "brain"}), "boundary_based_registration": { "run": forkable, "bbr_schedule": str, "bbr_wm_map": In({"probability_map", "partial_volume_map"}), "bbr_wm_mask_args": str, - "reference": In({"whole-head", "brain"}), }, }, "EPI_registration": { diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index d42f66095..a8da814e9 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -22,7 +22,6 @@ from voluptuous import RequiredFieldInvalid from nipype.interfaces import afni, ants, c3, fsl, utility as util from nipype.interfaces.afni import utils as afni_utils -from pathlib import Path from CPAC.anat_preproc.lesion_preproc import create_lesion_preproc from CPAC.func_preproc.func_preproc import fsl_afni_subworkflow @@ -3068,7 +3067,9 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None wf.connect(merge_inv_xfms_to_list, "out", merge_inv_xfms, "in_files") # Match FOVs using flirt -in infile -ref MNI152_T1_1mm_resample.nii.gz -out my_T1w_resampled.nii.gz -applyxfm -usesqform - match_fovs_T1w = pe.Node(interface=fsl.FLIRT(), name=f"match_fovs_T1w_{pipe_num}") + match_fovs_T1w = pe.Node( + interface=fsl.FLIRT(), name=f"match_fovs_T1w_{pipe_num}" + ) match_fovs_T1w.inputs.apply_xfm = True match_fovs_T1w.inputs.uses_qform = True @@ -3091,7 +3092,9 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None merge_xfms, "merged_file", fsl_apply_warp_t1_to_template, "field_file" ) - match_fovs_T1w_brain = pe.Node(interface=fsl.FLIRT(), name=f"match_fovs_T1w_brain_{pipe_num}") + match_fovs_T1w_brain = pe.Node( + interface=fsl.FLIRT(), name=f"match_fovs_T1w_brain_{pipe_num}" + ) match_fovs_T1w_brain.inputs.apply_xfm = True match_fovs_T1w_brain.inputs.uses_qform = True @@ -3105,7 +3108,12 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # TODO connect T1wRestoreBrain, check T1wRestoreBrain quality node, out = strat_pool.get_data(["desc-restore-brain_T1w", "desc-preproc_T1w"]) wf.connect(node, out, match_fovs_T1w_brain, "in_file") - wf.connect(match_fovs_T1w_brain, "out_file", fsl_apply_warp_t1_brain_to_template, "in_file") + wf.connect( + match_fovs_T1w_brain, + "out_file", + fsl_apply_warp_t1_brain_to_template, + "in_file", + ) node, out = strat_pool.get_data("T1w-brain-template") wf.connect(node, out, match_fovs_T1w_brain, "reference") @@ -3115,7 +3123,9 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None merge_xfms, "merged_file", fsl_apply_warp_t1_brain_to_template, "field_file" ) - match_fovs_T1w_brain_mask = pe.Node(interface=fsl.FLIRT(), name=f"match_fovs_T1w_brain_mask_{pipe_num}") + match_fovs_T1w_brain_mask = pe.Node( + interface=fsl.FLIRT(), name=f"match_fovs_T1w_brain_mask_{pipe_num}" + ) match_fovs_T1w_brain_mask.inputs.apply_xfm = True match_fovs_T1w_brain_mask.inputs.uses_qform = True @@ -3128,7 +3138,12 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None node, out = strat_pool.get_data("space-T1w_desc-brain_mask") wf.connect(node, out, match_fovs_T1w_brain_mask, "in_file") - wf.connect(match_fovs_T1w_brain_mask, "out_file", fsl_apply_warp_t1_brain_mask_to_template, "in_file") + wf.connect( + match_fovs_T1w_brain_mask, + "out_file", + fsl_apply_warp_t1_brain_mask_to_template, + "in_file", + ) node, out = strat_pool.get_data("T1w-brain-template-mask") wf.connect(node, out, match_fovs_T1w_brain_mask, "reference") @@ -3335,6 +3350,7 @@ def coregistration_prep_fmriprep(wf, cfg, strat_pool, pipe_num, opt=None): ( "desc-preproc_T1w", ["desc-restore-brain_T1w", "desc-preproc_T1w"], + ["desc-restore_T1w", "desc-head_T1w"], "desc-preproc_T2w", "desc-preproc_T2w", "T2w", @@ -3405,7 +3421,18 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("sbref") wf.connect(node, out, func_to_anat, "inputspec.func") - node, out = strat_pool.get_data(["desc-restore-brain_T1w", "desc-preproc_T1w"]) + if ( + cfg.registration_workflows["functional_registration"]["coregistration"][ + "reference" + ] + == "whole-head" + ): + node, out = strat_pool.get_data(["desc-restore_T1w", "desc-head_T1w"]) + else: + node, out = strat_pool.get_data( + ["desc-restore-brain_T1w", "desc-preproc_T1w"] + ) + wf.connect(node, out, func_to_anat, "inputspec.anat") if diff_complete: @@ -3466,8 +3493,8 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): if ( cfg.registration_workflows["functional_registration"]["coregistration"][ - "boundary_based_registration" - ]["reference"] + "reference" + ] == "whole-head" ): node, out = strat_pool.get_data("desc-head_T1w") @@ -3475,8 +3502,8 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): elif ( cfg.registration_workflows["functional_registration"]["coregistration"][ - "boundary_based_registration" - ]["reference"] + "reference" + ] == "brain" ): node, out = strat_pool.get_data("desc-preproc_T1w") @@ -4195,21 +4222,6 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): https://github.com/DCAN-Labs/DCAN-HCP/blob/a8d495a/fMRIVolume/scripts/DistortionCorrectionAndEPIToT1wReg_FLIRTBBRAndFreeSurferBBRbased.sh#L548 convertwarp --relout --rel -m ${WD}/fMRI2str.mat --ref=${T1wImage} --out=${WD}/fMRI2str.nii.gz """ - # Identity matrix node needed for matching FOV - identity_node = pe.Node( - Function( - imports=["from pathlib import Path", "import numpy as np"], - input_names=["workdir"], - output_names=["identity_file"], - function=lambda workdir: ( - np.savetxt(Path(workdir) / "identity.mat", np.eye(4), fmt="%.6f") - or str(Path(workdir) / "identity.mat") - ), - ), - name=f"create_identity_matrix_{pipe_num}", - ) - identity_node.inputs.workdir = str(Path.cwd()) - convert_func_to_anat_linear_warp = pe.Node( interface=fsl.ConvertWarp(), name=f"convert_func_to_anat_linear_warp_{pipe_num}" ) @@ -4277,18 +4289,6 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): wf.connect(node, out, split_func, "in_file") ### Loop starts! ### - # Match FOV func_to_standard - match_fov_func = pe.MapNode( - interface=fsl.FLIRT(apply_xfm=True, interp="spline"), - name=f"match_fov_func_{pipe_num}", - iterfield=["in_file"], - ) - wf.connect(identity_node, "identity_file", match_fov_func, "in_matrix_file") - wf.connect(split_func, "out_files", match_fov_func, "in_file") - - node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") - wf.connect(node, out, match_fov_func, "reference") - # convertwarp --relout --rel --ref=${WD}/prevols/vol${vnum}.nii.gz --warp1=${GradientDistortionField} --postmat=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum} --out=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_gdc_warp.nii.gz convert_motion_distortion_warp = pe.MapNode( interface=fsl.ConvertWarp(), @@ -4299,7 +4299,7 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): convert_motion_distortion_warp.inputs.out_relwarp = True convert_motion_distortion_warp.inputs.relwarp = True - wf.connect(match_fov_func, "out_file", convert_motion_distortion_warp, "reference") + wf.connect(split_func, "out_files", convert_motion_distortion_warp, "reference") node, out = strat_pool.get_data("coordinate-transformation") wf.connect(node, out, convert_motion_distortion_warp, "postmat") @@ -4341,9 +4341,10 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): iterfield=["in_file", "field_file"], ) + applywarp_func_to_standard.inputs.relwarp = True applywarp_func_to_standard.inputs.interp = "spline" - wf.connect(match_fov_func, "out_file", applywarp_func_to_standard, "in_file") + wf.connect(split_func, "out_files", applywarp_func_to_standard, "in_file") wf.connect( convert_registration_warp, "out_file", applywarp_func_to_standard, "field_file" @@ -4364,9 +4365,10 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): iterfield=["in_file", "field_file"], ) + applywarp_func_mask_to_standard.inputs.relwarp = True applywarp_func_mask_to_standard.inputs.interp = "nn" - node, out = strat_pool.get_data("space-template_desc-bold_mask") + node, out = strat_pool.get_data("space-template_desc-brain_mask") wf.connect(node, out, applywarp_func_mask_to_standard, "in_file") wf.connect( @@ -4420,29 +4422,16 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): wf.connect(merge_func_mask_to_standard, "merged_file", find_min_mask, "in_file") - # Match FOV scout_to_standard - match_fov_scout_to_standard = pe.MapNode( - interface=fsl.FLIRT(apply_xfm=True, interp="spline"), - name=f"match_fov_scout_to_standard_{pipe_num}", - iterfield=["in_file"], - ) - wf.connect( - identity_node, "identity_file", match_fov_scout_to_standard, "in_matrix_file" - ) - node, out = strat_pool.get_data("motion-basefile") - wf.connect(node, out, match_fov_scout_to_standard, "in_file") - - node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") - wf.connect(node, out, match_fov_scout_to_standard, "reference") - # applywarp --rel --interp=spline --in=${ScoutInput} -w ${WD}/Scout_gdc_MNI_warp.nii.gz -r ${WD}/${T1wImageFile}.${FinalfMRIResolution} -o ${ScoutOutput} applywarp_scout = pe.Node( interface=fsl.ApplyWarp(), name=f"applywarp_scout_input_{pipe_num}" ) + applywarp_scout.inputs.relwarp = True applywarp_scout.inputs.interp = "spline" - wf.connect(match_fov_scout_to_standard, "out_file", applywarp_scout, "in_file") + node, out = strat_pool.get_data("motion-basefile") + wf.connect(node, out, applywarp_scout, "in_file") node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") wf.connect( @@ -5611,38 +5600,3 @@ def _warp_return( if apply_xfm is None: return wf, {} return wf, outputs - - -def create_identity_matrix(workdir): - """Create an identity matrix for FLIRT.""" - identity_file = Path(workdir) / "identity.mat" - np.savetxt(identity_file, np.eye(4), fmt="%.6f") - return str(identity_file) - - -def build_match_fov_wf(name, workdir, pipe_num): - """ - Workflow to match Field-of-View for T1w or functional images - using an identity matrix. - """ - wf = Workflow(name=name) - - identity_node = Node( - Function( - input_names=["workdir"], - output_names=["identity_file"], - function=create_identity_matrix, - ), - name=f"create_identity_matrix_{pipe_num}", - ) - identity_node.inputs.workdir = workdir - - match_fov_node = MapNode( - interface=fsl.FLIRT(apply_xfm=True, interp="spline"), - name=f"match_fov_{pipe_num}", - iterfield=["in_file"], - ) - - wf.connect(identity_node, "identity_file", match_fov_node, "in_matrix_file") - - return wf, match_fov_node diff --git a/CPAC/resources/configs/pipeline_config_abcd-options.yml b/CPAC/resources/configs/pipeline_config_abcd-options.yml index 844def45a..ee961a7ff 100644 --- a/CPAC/resources/configs/pipeline_config_abcd-options.yml +++ b/CPAC/resources/configs/pipeline_config_abcd-options.yml @@ -217,14 +217,15 @@ registration_workflows: # Mask the sbref created by coregistration input prep nodeblocks above before registration mask_sbref: Off + # options: 'whole-head' or 'brain' + reference: whole-head + # Choose coregistration interpolation interpolation: spline # Choose coregistration degree of freedom dof: 12 - - func_registration_to_template: # these options modify the application (to the functional data), not the calculation, of the diff --git a/CPAC/resources/configs/pipeline_config_blank.yml b/CPAC/resources/configs/pipeline_config_blank.yml index fd1686a21..008090280 100644 --- a/CPAC/resources/configs/pipeline_config_blank.yml +++ b/CPAC/resources/configs/pipeline_config_blank.yml @@ -738,16 +738,15 @@ registration_workflows: # Mask the sbref created by coregistration input prep nodeblocks above before registration mask_sbref: On + # options: 'whole-head' or 'brain' + reference: whole-head + boundary_based_registration: # this is a fork point # run: [On, Off] - this will run both and fork the pipeline run: [Off] - # reference for boundary based registration - # options: 'whole-head' or 'brain' - reference: whole-head - # choose which FAST map to generate BBR WM mask # options: 'probability_map', 'partial_volume_map' bbr_wm_map: probability_map @@ -759,9 +758,6 @@ registration_workflows: # It is not necessary to change this path unless you intend to use non-standard MNI registration. bbr_schedule: $FSLDIR/etc/flirtsch/bbr.sch - # Choose FSL or ABCD as coregistration method - using: FSL - # Choose coregistration interpolation interpolation: trilinear diff --git a/CPAC/resources/configs/pipeline_config_default.yml b/CPAC/resources/configs/pipeline_config_default.yml index cba22d6a0..c69cc8d4b 100644 --- a/CPAC/resources/configs/pipeline_config_default.yml +++ b/CPAC/resources/configs/pipeline_config_default.yml @@ -775,9 +775,6 @@ registration_workflows: run: On - # Choose FSL or ABCD as coregistration method - using: FSL - # Choose coregistration interpolation interpolation: trilinear @@ -811,6 +808,9 @@ registration_workflows: # Mask the sbref created by coregistration input prep nodeblocks above before registration mask_sbref: On + # options: 'whole-head' or 'brain' + reference: whole-head + boundary_based_registration: # this is a fork point # run: [On, Off] - this will run both and fork the pipeline @@ -820,10 +820,6 @@ registration_workflows: # It is not necessary to change this path unless you intend to use non-standard MNI registration. bbr_schedule: $FSLDIR/etc/flirtsch/bbr.sch - # reference for boundary based registration - # options: 'whole-head' or 'brain' - reference: whole-head - # choose which FAST map to generate BBR WM mask # options: 'probability_map', 'partial_volume_map' bbr_wm_map: 'probability_map' diff --git a/CPAC/resources/configs/pipeline_config_fmriprep-options.yml b/CPAC/resources/configs/pipeline_config_fmriprep-options.yml index 5453144af..2b268930a 100644 --- a/CPAC/resources/configs/pipeline_config_fmriprep-options.yml +++ b/CPAC/resources/configs/pipeline_config_fmriprep-options.yml @@ -251,16 +251,15 @@ registration_workflows: # input: ['Mean_Functional', 'Selected_Functional_Volume', 'fmriprep_reference'] input: [fmriprep_reference] + # options: 'whole-head' or 'brain' + reference: brain + boundary_based_registration: # this is a fork point # run: [On, Off] - this will run both and fork the pipeline run: [On] - # reference for boundary based registration - # options: 'whole-head' or 'brain' - reference: brain - # choose which FAST map to generate BBR WM mask # options: 'probability_map', 'partial_volume_map' bbr_wm_map: partial_volume_map From e9ba975098b09382ed976f2964caca4dab7245f2 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Wed, 27 Aug 2025 16:25:52 -0400 Subject: [PATCH 05/17] adding ref_weight in FLIRT whole head registration --- CPAC/registration/registration.py | 33 ++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index a8da814e9..c3d63f43c 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -711,6 +711,12 @@ def create_register_func_to_anat( inputspec.interp : string Type of interpolation to use ('trilinear' or 'nearestneighbour' or 'sinc') + inputspec.ref_weight : string (nifti file) + Reference weight image for registration + inputspec.fieldmap : string (nifti file) + Field map image for registration + inputspec.fieldmapmask : string (nifti file) + Field map mask image for registration Workflow Outputs:: @@ -723,7 +729,15 @@ def create_register_func_to_anat( inputspec = pe.Node( util.IdentityInterface( - fields=["func", "anat", "dof", "interp", "fieldmap", "fieldmapmask"] + fields=[ + "func", + "anat", + "dof", + "interp", + "fieldmap", + "fieldmapmask", + "ref_weight", + ] ), name="inputspec", ) @@ -754,6 +768,15 @@ def create_register_func_to_anat( linear_reg.inputs.dof = config.registration_workflows["functional_registration"][ "coregistration" ]["dof"] + + if ( + config.registration_workflows["functional_registration"]["coregistration"][ + "reference" + ] + == "whole_head" + ): + register_func_to_anat.connect(inputspec, "ref_weight", linear_reg, "ref_weight") + if ( config.registration_workflows["functional_registration"]["coregistration"][ "arguments" @@ -3349,6 +3372,7 @@ def coregistration_prep_fmriprep(wf, cfg, strat_pool, pipe_num, opt=None): ), ( "desc-preproc_T1w", + "space-T1w_desc-brain_mask", ["desc-restore-brain_T1w", "desc-preproc_T1w"], ["desc-restore_T1w", "desc-head_T1w"], "desc-preproc_T2w", @@ -3428,12 +3452,15 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): == "whole-head" ): node, out = strat_pool.get_data(["desc-restore_T1w", "desc-head_T1w"]) + wf.connect(node, out, func_to_anat, "inputspec.anat") + + node, out = strat_pool.get_data("space-T1w_desc-brain_mask") + wf.connect(node, out, func_to_anat, "inputspec.ref_weight") else: node, out = strat_pool.get_data( ["desc-restore-brain_T1w", "desc-preproc_T1w"] ) - - wf.connect(node, out, func_to_anat, "inputspec.anat") + wf.connect(node, out, func_to_anat, "inputspec.anat") if diff_complete: node, out = strat_pool.get_data("effectiveEchoSpacing") From 4e47f2dbb588b487a2bf5116aca6df0f68eda0ac Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Thu, 28 Aug 2025 13:14:33 -0400 Subject: [PATCH 06/17] adding reference whole head --- CPAC/registration/registration.py | 2 +- .../configs/pipeline_config_abcd-options.yml | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index c3d63f43c..65a6f00a8 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -773,7 +773,7 @@ def create_register_func_to_anat( config.registration_workflows["functional_registration"]["coregistration"][ "reference" ] - == "whole_head" + == "whole-head" ): register_func_to_anat.connect(inputspec, "ref_weight", linear_reg, "ref_weight") diff --git a/CPAC/resources/configs/pipeline_config_abcd-options.yml b/CPAC/resources/configs/pipeline_config_abcd-options.yml index ee961a7ff..de7d04a47 100644 --- a/CPAC/resources/configs/pipeline_config_abcd-options.yml +++ b/CPAC/resources/configs/pipeline_config_abcd-options.yml @@ -225,6 +225,11 @@ registration_workflows: # Choose coregistration degree of freedom dof: 12 + boundary_based_registration: + + # this is a fork point + # run: [On, Off] - this will run both and fork the pipeline + run: [On] func_registration_to_template: @@ -263,7 +268,13 @@ registration_workflows: # Interpolation method for writing out transformed functional images. # Possible values: Linear, BSpline, LanczosWindowedSinc interpolation: Linear + EPI_registration: + # directly register the mean functional to an EPI template + # instead of applying the anatomical T1-to-template transform to the functional data that has been + # coregistered to anatomical/T1 space + run: on + functional_preproc: run: On motion_estimates_and_correction: From 25453fcf656fa14696002da1c3adaf494d3388e1 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Fri, 29 Aug 2025 18:56:51 -0400 Subject: [PATCH 07/17] concating match_fov to the xfm --- CPAC/registration/registration.py | 145 ++++++------------------------ 1 file changed, 28 insertions(+), 117 deletions(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index 65a6f00a8..a39d4b3a3 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -3095,6 +3095,7 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None ) match_fovs_T1w.inputs.apply_xfm = True match_fovs_T1w.inputs.uses_qform = True + match_fovs_T1w.inputs.out_matrix_file = "match_fov.mat" # applywarp --rel --interp=spline -i ${T1wRestore} -r ${Reference} -w ${OutputTransform} -o ${OutputT1wImageRestore} fsl_apply_warp_t1_to_template = pe.Node( @@ -3115,11 +3116,25 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None merge_xfms, "merged_file", fsl_apply_warp_t1_to_template, "field_file" ) - match_fovs_T1w_brain = pe.Node( - interface=fsl.FLIRT(), name=f"match_fovs_T1w_brain_{pipe_num}" + concat_match_fov = pe.Node(interface=fsl.ConvertWarp(), name=f"concat_match_fov_{pipe_num}") + concat_match_fov.inputs.relwarp = True + + wf.connect(match_fovs_T1w, "out_matrix_file", concat_match_fov, "premat") + wf.connect(merge_xfms, "merged_file", concat_match_fov, "warp1") + node, out = strat_pool.get_data("T1w-template") + wf.connect(node, out, concat_match_fov, "reference") + + # Node to concatenate the inverse warp with the FOV matrix + concat_match_fov_inv = pe.Node( + interface=fsl.ConvertWarp(), + name=f"concat_match_fov_inv_{pipe_num}" ) - match_fovs_T1w_brain.inputs.apply_xfm = True - match_fovs_T1w_brain.inputs.uses_qform = True + concat_match_fov_inv.inputs.relwarp = True + + wf.connect(merge_inv_xfms, "merged_file", concat_match_fov_inv, "warp1") + wf.connect(match_fovs_T1w, "out_matrix_file", concat_match_fov_inv, "premat") + node, out = strat_pool.get_data(["desc-restore_T1w", "desc-head_T1w"]) + wf.connect(node, out, concat_match_fov_inv, "reference") # applywarp --rel --interp=nn -i ${T1wRestoreBrain} -r ${Reference} -w ${OutputTransform} -o ${OutputT1wImageRestoreBrain} fsl_apply_warp_t1_brain_to_template = pe.Node( @@ -3130,28 +3145,17 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # TODO connect T1wRestoreBrain, check T1wRestoreBrain quality node, out = strat_pool.get_data(["desc-restore-brain_T1w", "desc-preproc_T1w"]) - wf.connect(node, out, match_fovs_T1w_brain, "in_file") wf.connect( - match_fovs_T1w_brain, - "out_file", - fsl_apply_warp_t1_brain_to_template, - "in_file", + node, out, fsl_apply_warp_t1_brain_to_template, "in_file" ) node, out = strat_pool.get_data("T1w-brain-template") - wf.connect(node, out, match_fovs_T1w_brain, "reference") wf.connect(node, out, fsl_apply_warp_t1_brain_to_template, "ref_file") wf.connect( - merge_xfms, "merged_file", fsl_apply_warp_t1_brain_to_template, "field_file" + concat_match_fov, "out_file", fsl_apply_warp_t1_brain_to_template, "field_file" ) - match_fovs_T1w_brain_mask = pe.Node( - interface=fsl.FLIRT(), name=f"match_fovs_T1w_brain_mask_{pipe_num}" - ) - match_fovs_T1w_brain_mask.inputs.apply_xfm = True - match_fovs_T1w_brain_mask.inputs.uses_qform = True - fsl_apply_warp_t1_brain_mask_to_template = pe.Node( interface=fsl.ApplyWarp(), name=f"FSL-ABCD_T1_brain_mask_to_template_{pipe_num}", @@ -3160,21 +3164,16 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None fsl_apply_warp_t1_brain_mask_to_template.inputs.interp = "nn" node, out = strat_pool.get_data("space-T1w_desc-brain_mask") - wf.connect(node, out, match_fovs_T1w_brain_mask, "in_file") wf.connect( - match_fovs_T1w_brain_mask, - "out_file", - fsl_apply_warp_t1_brain_mask_to_template, - "in_file", + node, out, fsl_apply_warp_t1_brain_mask_to_template, "in_file" ) node, out = strat_pool.get_data("T1w-brain-template-mask") - wf.connect(node, out, match_fovs_T1w_brain_mask, "reference") wf.connect(node, out, fsl_apply_warp_t1_brain_mask_to_template, "ref_file") wf.connect( - merge_xfms, - "merged_file", + concat_match_fov, + "out_file", fsl_apply_warp_t1_brain_mask_to_template, "field_file", ) @@ -3193,8 +3192,8 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None outputs = { "space-template_desc-preproc_T1w": (apply_mask, "out_file"), "space-template_desc-head_T1w": (fsl_apply_warp_t1_to_template, "out_file"), - "from-T1w_to-template_mode-image_xfm": (merge_xfms, "merged_file"), - "from-template_to-T1w_mode-image_xfm": (merge_inv_xfms, "merged_file"), + "from-T1w_to-template_mode-image_xfm": (concat_match_fov, "out_file"), + "from-template_to-T1w_mode-image_xfm": (concat_match_fov_inv, "out_file"), } else: @@ -4385,34 +4384,6 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): "ref_file", ) - # applywarp --rel --interp=nn --in=${WD}/prevols/vol${vnum}_mask.nii.gz --warp=${MotionMatrixFolder}/${MotionMatrixPrefix}${vnum}_all_warp.nii.gz --ref=${WD}/${T1wImageFile}.${FinalfMRIResolution} --out=${WD}/postvols/vol${vnum}_mask.nii.gz - applywarp_func_mask_to_standard = pe.MapNode( - interface=fsl.ApplyWarp(), - name=f"applywarp_func_mask_to_standard_{pipe_num}", - iterfield=["in_file", "field_file"], - ) - - applywarp_func_mask_to_standard.inputs.relwarp = True - applywarp_func_mask_to_standard.inputs.interp = "nn" - - node, out = strat_pool.get_data("space-template_desc-brain_mask") - wf.connect(node, out, applywarp_func_mask_to_standard, "in_file") - - wf.connect( - convert_registration_warp, - "out_file", - applywarp_func_mask_to_standard, - "field_file", - ) - - node, out = strat_pool.get_data("space-template_res-bold_desc-head_T1w") - wf.connect( - node, - out, - applywarp_func_mask_to_standard, - "ref_file", - ) - ### Loop ends! ### # fslmerge -tr ${OutputfMRI} $FrameMergeSTRING $TR_vol @@ -4426,29 +4397,6 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): applywarp_func_to_standard, "out_file", merge_func_to_standard, "in_files" ) - # fslmerge -tr ${OutputfMRI}_mask $FrameMergeSTRINGII $TR_vol - merge_func_mask_to_standard = pe.Node( - interface=fslMerge(), name=f"merge_func_mask_to_standard_{pipe_num}" - ) - - merge_func_mask_to_standard.inputs.dimension = "t" - - wf.connect( - applywarp_func_mask_to_standard, - "out_file", - merge_func_mask_to_standard, - "in_files", - ) - - # fslmaths ${OutputfMRI}_mask -Tmin ${OutputfMRI}_mask - find_min_mask = pe.Node( - interface=fsl.maths.MathsCommand(), name=f"find_min_mask_{pipe_num}" - ) - - find_min_mask.inputs.args = "-Tmin" - - wf.connect(merge_func_mask_to_standard, "merged_file", find_min_mask, "in_file") - # applywarp --rel --interp=spline --in=${ScoutInput} -w ${WD}/Scout_gdc_MNI_warp.nii.gz -r ${WD}/${T1wImageFile}.${FinalfMRIResolution} -o ${ScoutOutput} applywarp_scout = pe.Node( interface=fsl.ApplyWarp(), name=f"applywarp_scout_input_{pipe_num}" @@ -4471,46 +4419,9 @@ def warp_timeseries_to_T1template_abcd(wf, cfg, strat_pool, pipe_num, opt=None): # warp field is just fMRI->standard (skip GDC) wf.connect(convert_func_to_standard_warp, "out_file", applywarp_scout, "field_file") - # https://github.com/DCAN-Labs/DCAN-HCP/blob/1214767/fMRIVolume/scripts/IntensityNormalization.sh#L124-L127 - # fslmaths ${InputfMRI} -mas ${BrainMask} -mas ${InputfMRI}_mask -thr 0 -ing 10000 ${OutputfMRI} -odt float - merge_func_mask = pe.Node(util.Merge(2), name=f"merge_func_mask_{pipe_num}") - - node, out = strat_pool.get_data("space-template_desc-bold_mask") - wf.connect( - node, - out, - merge_func_mask, - "in1", - ) - - wf.connect(find_min_mask, "out_file", merge_func_mask, "in2") - - extract_func_brain = pe.Node( - interface=fsl.MultiImageMaths(), name=f"extract_func_brain_{pipe_num}" - ) - - extract_func_brain.inputs.op_string = "-mas %s -mas %s -thr 0 -ing 10000" - extract_func_brain.inputs.output_datatype = "float" - - wf.connect(merge_func_to_standard, "merged_file", extract_func_brain, "in_file") - - wf.connect(merge_func_mask, "out", extract_func_brain, "operand_files") - - # fslmaths ${ScoutInput} -mas ${BrainMask} -mas ${InputfMRI}_mask -thr 0 -ing 10000 ${ScoutOutput} -odt float - extract_scout_brain = pe.Node( - interface=fsl.MultiImageMaths(), name=f"extract_scout_brain_{pipe_num}" - ) - - extract_scout_brain.inputs.op_string = "-mas %s -mas %s -thr 0 -ing 10000" - extract_scout_brain.inputs.output_datatype = "float" - - wf.connect(applywarp_scout, "out_file", extract_scout_brain, "in_file") - - wf.connect(merge_func_mask, "out", extract_scout_brain, "operand_files") - outputs = { - "space-template_desc-preproc_bold": (extract_func_brain, "out_file"), - "space-template_desc-scout_bold": (extract_scout_brain, "out_file"), + "space-template_desc-preproc_bold": (merge_func_to_standard, "merged_file"), + "space-template_desc-scout_bold": (applywarp_scout, "out_file"), "space-template_desc-head_bold": (merge_func_to_standard, "merged_file"), } From 47cdb13942f0c8efb6bc8ad6ed413461b809e272 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Tue, 2 Sep 2025 13:12:09 -0400 Subject: [PATCH 08/17] Turning EPI off for abcd-options config --- CHANGELOG.md | 1 + CPAC/resources/configs/pipeline_config_abcd-options.yml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cac9fc998..ceb319991 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed broken support for native-space masking. - Introduced a new `template_space_func_masking` section in the pipeline config for template-space-only methods. - Moved `Anatomical_Resampled` masking method from `func_masking` to the `template_space_func_masking`. +- Moved `reference` in the bbreg config out to the whole co-registration block in all configs. ### Upgraded diff --git a/CPAC/resources/configs/pipeline_config_abcd-options.yml b/CPAC/resources/configs/pipeline_config_abcd-options.yml index de7d04a47..733941323 100644 --- a/CPAC/resources/configs/pipeline_config_abcd-options.yml +++ b/CPAC/resources/configs/pipeline_config_abcd-options.yml @@ -273,8 +273,8 @@ registration_workflows: # directly register the mean functional to an EPI template # instead of applying the anatomical T1-to-template transform to the functional data that has been # coregistered to anatomical/T1 space - run: on - + run: off + functional_preproc: run: On motion_estimates_and_correction: From 66d40dc7cfecca282fa72a70af07a654ba7cff28 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Tue, 2 Sep 2025 13:30:23 -0400 Subject: [PATCH 09/17] adding to changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ceb319991..7a97e6345 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Introduced a new `template_space_func_masking` section in the pipeline config for template-space-only methods. - Moved `Anatomical_Resampled` masking method from `func_masking` to the `template_space_func_masking`. - Moved `reference` in the bbreg config out to the whole co-registration block in all configs. +- Turned `On` boundary_based_registration for abcd-options preconfig. +- Refactored `transform_timeseries_to_T1template_abcd` nodeblock removing unnecessary nodes, changing `desc-preproc_T1w` inputs as reference to `desc-head_T1w`. +- Appended `T1w to Template` FOV match transform to the XFM. ### Upgraded From f2a75786d9c047c20e0f60bfb47849e8ea833b88 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 18:25:49 +0000 Subject: [PATCH 10/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CPAC/registration/registration.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index b4e4e85ab..1a2385b64 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -3116,7 +3116,9 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None merge_xfms, "merged_file", fsl_apply_warp_t1_to_template, "field_file" ) - concat_match_fov = pe.Node(interface=fsl.ConvertWarp(), name=f"concat_match_fov_{pipe_num}") + concat_match_fov = pe.Node( + interface=fsl.ConvertWarp(), name=f"concat_match_fov_{pipe_num}" + ) concat_match_fov.inputs.relwarp = True wf.connect(match_fovs_T1w, "out_matrix_file", concat_match_fov, "premat") @@ -3126,8 +3128,7 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # Node to concatenate the inverse warp with the FOV matrix concat_match_fov_inv = pe.Node( - interface=fsl.ConvertWarp(), - name=f"concat_match_fov_inv_{pipe_num}" + interface=fsl.ConvertWarp(), name=f"concat_match_fov_inv_{pipe_num}" ) concat_match_fov_inv.inputs.relwarp = True @@ -3146,15 +3147,16 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # TODO connect T1wRestoreBrain, check T1wRestoreBrain quality node, out = strat_pool.get_data(["desc-restore-brain_T1w", "desc-preproc_T1w"]) - wf.connect( - node, out, fsl_apply_warp_t1_brain_to_template, "in_file" - ) + wf.connect(node, out, fsl_apply_warp_t1_brain_to_template, "in_file") node, out = strat_pool.get_data("T1w-brain-template") wf.connect(node, out, fsl_apply_warp_t1_brain_to_template, "ref_file") wf.connect( - concat_match_fov, "out_file", fsl_apply_warp_t1_brain_to_template, "field_file" + concat_match_fov, + "out_file", + fsl_apply_warp_t1_brain_to_template, + "field_file", ) fsl_apply_warp_t1_brain_mask_to_template = pe.Node( @@ -3166,9 +3168,7 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None node, out = strat_pool.get_data("space-T1w_desc-brain_mask") - wf.connect( - node, out, fsl_apply_warp_t1_brain_mask_to_template, "in_file" - ) + wf.connect(node, out, fsl_apply_warp_t1_brain_mask_to_template, "in_file") node, out = strat_pool.get_data("T1w-brain-template-mask") wf.connect(node, out, fsl_apply_warp_t1_brain_mask_to_template, "ref_file") From e9925b7d51d4c2f967b8c8f4272f3d5b10f8a5b1 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Wed, 3 Sep 2025 16:58:32 -0400 Subject: [PATCH 11/17] changing func_input from Selected_Functional_Volume to Mean_Functional in abcd-options preconfig --- CPAC/registration/registration.py | 6 +++++- CPAC/resources/configs/pipeline_config_abcd-options.yml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index 1a2385b64..696f9ad83 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -4039,7 +4039,11 @@ def warp_wholeheadT1_to_template(wf, cfg, strat_pool, pipe_num, opt=None): ) def warp_T1mask_to_template(wf, cfg, strat_pool, pipe_num, opt=None): """Warp T1 mask to template.""" - reg_tool = strat_pool.reg_tool("from-T1w_to-template_mode-image_xfm") + + if cfg.registration_workflows["anatomical_registration"]["overwrite_transform"] and cfg.registration_workflows["anatomical_registration"]["overwrite_transform"]["using"] == 'FSL': + reg_tool = 'fsl' + else: + reg_tool = strat_pool.reg_tool("from-T1w_to-template_mode-image_xfm") num_cpus = cfg.pipeline_setup["system_config"]["max_cores_per_participant"] diff --git a/CPAC/resources/configs/pipeline_config_abcd-options.yml b/CPAC/resources/configs/pipeline_config_abcd-options.yml index 733941323..111f53232 100644 --- a/CPAC/resources/configs/pipeline_config_abcd-options.yml +++ b/CPAC/resources/configs/pipeline_config_abcd-options.yml @@ -212,7 +212,7 @@ registration_workflows: # Choose whether to use the mean of the functional/EPI as the input to functional-to-anatomical registration or one of the volumes from the functional 4D timeseries that you choose. # input: ['Mean_Functional', 'Selected_Functional_Volume', 'fmriprep_reference'] - input: [Selected_Functional_Volume] + input: [Mean_Functional] # Mask the sbref created by coregistration input prep nodeblocks above before registration mask_sbref: Off From 009ba4a822077800a699162a26706d4aa84b5182 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Wed, 3 Sep 2025 16:58:41 -0400 Subject: [PATCH 12/17] changing func_input from Selected_Functional_Volume to Mean_Functional in abcd-options preconfig --- CPAC/registration/registration.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index 696f9ad83..f5af23979 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -4039,9 +4039,14 @@ def warp_wholeheadT1_to_template(wf, cfg, strat_pool, pipe_num, opt=None): ) def warp_T1mask_to_template(wf, cfg, strat_pool, pipe_num, opt=None): """Warp T1 mask to template.""" - - if cfg.registration_workflows["anatomical_registration"]["overwrite_transform"] and cfg.registration_workflows["anatomical_registration"]["overwrite_transform"]["using"] == 'FSL': - reg_tool = 'fsl' + if ( + cfg.registration_workflows["anatomical_registration"]["overwrite_transform"] + and cfg.registration_workflows["anatomical_registration"][ + "overwrite_transform" + ]["using"] + == "FSL" + ): + reg_tool = "fsl" else: reg_tool = strat_pool.reg_tool("from-T1w_to-template_mode-image_xfm") From 2b13ca56b6fec6f007687482518f1345dcaf61c9 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Wed, 3 Sep 2025 20:58:17 -0400 Subject: [PATCH 13/17] reverting some unnecessary changes --- CPAC/pipeline/schema.py | 2 +- CPAC/registration/registration.py | 67 ++++++------------- .../configs/pipeline_config_abcd-options.yml | 9 +-- .../configs/pipeline_config_blank.yml | 7 +- .../configs/pipeline_config_default.yml | 7 +- .../pipeline_config_fmriprep-options.yml | 7 +- 6 files changed, 39 insertions(+), 60 deletions(-) diff --git a/CPAC/pipeline/schema.py b/CPAC/pipeline/schema.py index abfb7a3c4..81c542e8e 100644 --- a/CPAC/pipeline/schema.py +++ b/CPAC/pipeline/schema.py @@ -843,9 +843,9 @@ def sanitize(filename): }, "mask_sbref": bool1_1, }, - "reference": In({"whole-head", "brain"}), "boundary_based_registration": { "run": forkable, + "reference": In({"whole-head", "brain"}), "bbr_schedule": str, "bbr_wm_map": In({"probability_map", "partial_volume_map"}), "bbr_wm_mask_args": str, diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index f5af23979..2865c15b7 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -769,14 +769,6 @@ def create_register_func_to_anat( "coregistration" ]["dof"] - if ( - config.registration_workflows["functional_registration"]["coregistration"][ - "reference" - ] - == "whole-head" - ): - register_func_to_anat.connect(inputspec, "ref_weight", linear_reg, "ref_weight") - if ( config.registration_workflows["functional_registration"]["coregistration"][ "arguments" @@ -3116,9 +3108,7 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None merge_xfms, "merged_file", fsl_apply_warp_t1_to_template, "field_file" ) - concat_match_fov = pe.Node( - interface=fsl.ConvertWarp(), name=f"concat_match_fov_{pipe_num}" - ) + concat_match_fov = pe.Node(interface=fsl.ConvertWarp(), name=f"concat_match_fov_{pipe_num}") concat_match_fov.inputs.relwarp = True wf.connect(match_fovs_T1w, "out_matrix_file", concat_match_fov, "premat") @@ -3128,7 +3118,8 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # Node to concatenate the inverse warp with the FOV matrix concat_match_fov_inv = pe.Node( - interface=fsl.ConvertWarp(), name=f"concat_match_fov_inv_{pipe_num}" + interface=fsl.ConvertWarp(), + name=f"concat_match_fov_inv_{pipe_num}" ) concat_match_fov_inv.inputs.relwarp = True @@ -3147,16 +3138,15 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # TODO connect T1wRestoreBrain, check T1wRestoreBrain quality node, out = strat_pool.get_data(["desc-restore-brain_T1w", "desc-preproc_T1w"]) - wf.connect(node, out, fsl_apply_warp_t1_brain_to_template, "in_file") + wf.connect( + node, out, fsl_apply_warp_t1_brain_to_template, "in_file" + ) node, out = strat_pool.get_data("T1w-brain-template") wf.connect(node, out, fsl_apply_warp_t1_brain_to_template, "ref_file") wf.connect( - concat_match_fov, - "out_file", - fsl_apply_warp_t1_brain_to_template, - "field_file", + concat_match_fov, "out_file", fsl_apply_warp_t1_brain_to_template, "field_file" ) fsl_apply_warp_t1_brain_mask_to_template = pe.Node( @@ -3168,7 +3158,9 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None node, out = strat_pool.get_data("space-T1w_desc-brain_mask") - wf.connect(node, out, fsl_apply_warp_t1_brain_mask_to_template, "in_file") + wf.connect( + node, out, fsl_apply_warp_t1_brain_mask_to_template, "in_file" + ) node, out = strat_pool.get_data("T1w-brain-template-mask") wf.connect(node, out, fsl_apply_warp_t1_brain_mask_to_template, "ref_file") @@ -3446,22 +3438,10 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("sbref") wf.connect(node, out, func_to_anat, "inputspec.func") - if ( - cfg.registration_workflows["functional_registration"]["coregistration"][ - "reference" - ] - == "whole-head" - ): - node, out = strat_pool.get_data(["desc-restore_T1w", "desc-head_T1w"]) - wf.connect(node, out, func_to_anat, "inputspec.anat") - - node, out = strat_pool.get_data("space-T1w_desc-brain_mask") - wf.connect(node, out, func_to_anat, "inputspec.ref_weight") - else: - node, out = strat_pool.get_data( - ["desc-restore-brain_T1w", "desc-preproc_T1w"] - ) - wf.connect(node, out, func_to_anat, "inputspec.anat") + node, out = strat_pool.get_data( + ["desc-restore-brain_T1w", "desc-preproc_T1w"] + ) + wf.connect(node, out, func_to_anat, "inputspec.anat") if diff_complete: node, out = strat_pool.get_data("effectiveEchoSpacing") @@ -3521,8 +3501,8 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): if ( cfg.registration_workflows["functional_registration"]["coregistration"][ - "reference" - ] + "boundary_based_registration" + ]["reference"] == "whole-head" ): node, out = strat_pool.get_data("desc-head_T1w") @@ -3530,8 +3510,8 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): elif ( cfg.registration_workflows["functional_registration"]["coregistration"][ - "reference" - ] + "boundary_based_registration" + ]["reference"] == "brain" ): node, out = strat_pool.get_data("desc-preproc_T1w") @@ -4039,14 +4019,9 @@ def warp_wholeheadT1_to_template(wf, cfg, strat_pool, pipe_num, opt=None): ) def warp_T1mask_to_template(wf, cfg, strat_pool, pipe_num, opt=None): """Warp T1 mask to template.""" - if ( - cfg.registration_workflows["anatomical_registration"]["overwrite_transform"] - and cfg.registration_workflows["anatomical_registration"][ - "overwrite_transform" - ]["using"] - == "FSL" - ): - reg_tool = "fsl" + + if cfg.registration_workflows["anatomical_registration"]["overwrite_transform"] and cfg.registration_workflows["anatomical_registration"]["overwrite_transform"]["using"] == 'FSL': + reg_tool = 'fsl' else: reg_tool = strat_pool.reg_tool("from-T1w_to-template_mode-image_xfm") diff --git a/CPAC/resources/configs/pipeline_config_abcd-options.yml b/CPAC/resources/configs/pipeline_config_abcd-options.yml index 111f53232..fa682d8c7 100644 --- a/CPAC/resources/configs/pipeline_config_abcd-options.yml +++ b/CPAC/resources/configs/pipeline_config_abcd-options.yml @@ -212,14 +212,11 @@ registration_workflows: # Choose whether to use the mean of the functional/EPI as the input to functional-to-anatomical registration or one of the volumes from the functional 4D timeseries that you choose. # input: ['Mean_Functional', 'Selected_Functional_Volume', 'fmriprep_reference'] - input: [Mean_Functional] + input: [Selected_Functional_Volume] # Mask the sbref created by coregistration input prep nodeblocks above before registration mask_sbref: Off - # options: 'whole-head' or 'brain' - reference: whole-head - # Choose coregistration interpolation interpolation: spline @@ -231,6 +228,10 @@ registration_workflows: # run: [On, Off] - this will run both and fork the pipeline run: [On] + # reference for boundary based registration + # options: 'whole-head' or 'brain' + reference: whole-head + func_registration_to_template: # these options modify the application (to the functional data), not the calculation, of the diff --git a/CPAC/resources/configs/pipeline_config_blank.yml b/CPAC/resources/configs/pipeline_config_blank.yml index 008090280..11e480946 100644 --- a/CPAC/resources/configs/pipeline_config_blank.yml +++ b/CPAC/resources/configs/pipeline_config_blank.yml @@ -738,15 +738,16 @@ registration_workflows: # Mask the sbref created by coregistration input prep nodeblocks above before registration mask_sbref: On - # options: 'whole-head' or 'brain' - reference: whole-head - boundary_based_registration: # this is a fork point # run: [On, Off] - this will run both and fork the pipeline run: [Off] + # reference for boundary based registration + # options: 'whole-head' or 'brain' + reference: whole-head + # choose which FAST map to generate BBR WM mask # options: 'probability_map', 'partial_volume_map' bbr_wm_map: probability_map diff --git a/CPAC/resources/configs/pipeline_config_default.yml b/CPAC/resources/configs/pipeline_config_default.yml index c69cc8d4b..7bdbf527c 100644 --- a/CPAC/resources/configs/pipeline_config_default.yml +++ b/CPAC/resources/configs/pipeline_config_default.yml @@ -808,14 +808,15 @@ registration_workflows: # Mask the sbref created by coregistration input prep nodeblocks above before registration mask_sbref: On - # options: 'whole-head' or 'brain' - reference: whole-head - boundary_based_registration: # this is a fork point # run: [On, Off] - this will run both and fork the pipeline run: [On] + # reference for boundary based registration + # options: 'whole-head' or 'brain' + reference: whole-head + # Standard FSL 5.0 Scheduler used for Boundary Based Registration. # It is not necessary to change this path unless you intend to use non-standard MNI registration. bbr_schedule: $FSLDIR/etc/flirtsch/bbr.sch diff --git a/CPAC/resources/configs/pipeline_config_fmriprep-options.yml b/CPAC/resources/configs/pipeline_config_fmriprep-options.yml index 2b268930a..5453144af 100644 --- a/CPAC/resources/configs/pipeline_config_fmriprep-options.yml +++ b/CPAC/resources/configs/pipeline_config_fmriprep-options.yml @@ -251,15 +251,16 @@ registration_workflows: # input: ['Mean_Functional', 'Selected_Functional_Volume', 'fmriprep_reference'] input: [fmriprep_reference] - # options: 'whole-head' or 'brain' - reference: brain - boundary_based_registration: # this is a fork point # run: [On, Off] - this will run both and fork the pipeline run: [On] + # reference for boundary based registration + # options: 'whole-head' or 'brain' + reference: brain + # choose which FAST map to generate BBR WM mask # options: 'probability_map', 'partial_volume_map' bbr_wm_map: partial_volume_map From c3957a969d82fc3baddd6aff17fb1a431b3cfabb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 00:58:57 +0000 Subject: [PATCH 14/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CPAC/registration/registration.py | 34 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/CPAC/registration/registration.py b/CPAC/registration/registration.py index 2865c15b7..6bf649b44 100644 --- a/CPAC/registration/registration.py +++ b/CPAC/registration/registration.py @@ -3108,7 +3108,9 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None merge_xfms, "merged_file", fsl_apply_warp_t1_to_template, "field_file" ) - concat_match_fov = pe.Node(interface=fsl.ConvertWarp(), name=f"concat_match_fov_{pipe_num}") + concat_match_fov = pe.Node( + interface=fsl.ConvertWarp(), name=f"concat_match_fov_{pipe_num}" + ) concat_match_fov.inputs.relwarp = True wf.connect(match_fovs_T1w, "out_matrix_file", concat_match_fov, "premat") @@ -3118,8 +3120,7 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # Node to concatenate the inverse warp with the FOV matrix concat_match_fov_inv = pe.Node( - interface=fsl.ConvertWarp(), - name=f"concat_match_fov_inv_{pipe_num}" + interface=fsl.ConvertWarp(), name=f"concat_match_fov_inv_{pipe_num}" ) concat_match_fov_inv.inputs.relwarp = True @@ -3138,15 +3139,16 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None # TODO connect T1wRestoreBrain, check T1wRestoreBrain quality node, out = strat_pool.get_data(["desc-restore-brain_T1w", "desc-preproc_T1w"]) - wf.connect( - node, out, fsl_apply_warp_t1_brain_to_template, "in_file" - ) + wf.connect(node, out, fsl_apply_warp_t1_brain_to_template, "in_file") node, out = strat_pool.get_data("T1w-brain-template") wf.connect(node, out, fsl_apply_warp_t1_brain_to_template, "ref_file") wf.connect( - concat_match_fov, "out_file", fsl_apply_warp_t1_brain_to_template, "field_file" + concat_match_fov, + "out_file", + fsl_apply_warp_t1_brain_to_template, + "field_file", ) fsl_apply_warp_t1_brain_mask_to_template = pe.Node( @@ -3158,9 +3160,7 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None node, out = strat_pool.get_data("space-T1w_desc-brain_mask") - wf.connect( - node, out, fsl_apply_warp_t1_brain_mask_to_template, "in_file" - ) + wf.connect(node, out, fsl_apply_warp_t1_brain_mask_to_template, "in_file") node, out = strat_pool.get_data("T1w-brain-template-mask") wf.connect(node, out, fsl_apply_warp_t1_brain_mask_to_template, "ref_file") @@ -3438,9 +3438,7 @@ def coregistration(wf, cfg, strat_pool, pipe_num, opt=None): node, out = strat_pool.get_data("sbref") wf.connect(node, out, func_to_anat, "inputspec.func") - node, out = strat_pool.get_data( - ["desc-restore-brain_T1w", "desc-preproc_T1w"] - ) + node, out = strat_pool.get_data(["desc-restore-brain_T1w", "desc-preproc_T1w"]) wf.connect(node, out, func_to_anat, "inputspec.anat") if diff_complete: @@ -4020,8 +4018,14 @@ def warp_wholeheadT1_to_template(wf, cfg, strat_pool, pipe_num, opt=None): def warp_T1mask_to_template(wf, cfg, strat_pool, pipe_num, opt=None): """Warp T1 mask to template.""" - if cfg.registration_workflows["anatomical_registration"]["overwrite_transform"] and cfg.registration_workflows["anatomical_registration"]["overwrite_transform"]["using"] == 'FSL': - reg_tool = 'fsl' + if ( + cfg.registration_workflows["anatomical_registration"]["overwrite_transform"] + and cfg.registration_workflows["anatomical_registration"][ + "overwrite_transform" + ]["using"] + == "FSL" + ): + reg_tool = "fsl" else: reg_tool = strat_pool.reg_tool("from-T1w_to-template_mode-image_xfm") From 54994b09287a2c2f4779bfe02d433a892a2c8348 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Wed, 3 Sep 2025 21:06:51 -0400 Subject: [PATCH 15/17] updating the changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a97e6345..4de4717bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,7 +57,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed broken support for native-space masking. - Introduced a new `template_space_func_masking` section in the pipeline config for template-space-only methods. - Moved `Anatomical_Resampled` masking method from `func_masking` to the `template_space_func_masking`. -- Moved `reference` in the bbreg config out to the whole co-registration block in all configs. - Turned `On` boundary_based_registration for abcd-options preconfig. - Refactored `transform_timeseries_to_T1template_abcd` nodeblock removing unnecessary nodes, changing `desc-preproc_T1w` inputs as reference to `desc-head_T1w`. - Appended `T1w to Template` FOV match transform to the XFM. From e408c74c2dce7fd139031959a4ea71b2091c3256 Mon Sep 17 00:00:00 2001 From: "birajstha:construction_worker::penguin" Date: Fri, 5 Sep 2025 16:58:05 -0400 Subject: [PATCH 16/17] moving the addition of bold masking below and enabling previously blocked nodeblocks --- CPAC/pipeline/cpac_pipeline.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/CPAC/pipeline/cpac_pipeline.py b/CPAC/pipeline/cpac_pipeline.py index b9e686593..12ff690f4 100644 --- a/CPAC/pipeline/cpac_pipeline.py +++ b/CPAC/pipeline/cpac_pipeline.py @@ -1291,13 +1291,6 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None): mask_sbref, ] - # Template space functional mask - if cfg.functional_preproc["template_space_func_masking"]["run"]: - if not rpool.check_rpool("space-template_desc-bold_mask"): - pipeline_blocks += [ - bold_mask_anatomical_resampled, - ] - # Distortion/Susceptibility Correction distcor_blocks = [] if "fmap" in sub_dict: @@ -1320,6 +1313,14 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None): pipeline_blocks += stack_motion_blocks(func_blocks, cfg, rpool) + + # Template space functional mask + if cfg.functional_preproc["template_space_func_masking"]["run"]: + if not rpool.check_rpool("space-template_desc-bold_mask"): + pipeline_blocks += [ + bold_mask_anatomical_resampled, + ] + # BOLD to T1 coregistration if cfg.registration_workflows["functional_registration"]["coregistration"][ "run" From fb7e86f0622f4b5fff7bd119e59195a2eaeae69e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 20:58:51 +0000 Subject: [PATCH 17/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CPAC/pipeline/cpac_pipeline.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CPAC/pipeline/cpac_pipeline.py b/CPAC/pipeline/cpac_pipeline.py index 12ff690f4..a54fa929b 100644 --- a/CPAC/pipeline/cpac_pipeline.py +++ b/CPAC/pipeline/cpac_pipeline.py @@ -1313,14 +1313,13 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None): pipeline_blocks += stack_motion_blocks(func_blocks, cfg, rpool) - # Template space functional mask if cfg.functional_preproc["template_space_func_masking"]["run"]: if not rpool.check_rpool("space-template_desc-bold_mask"): pipeline_blocks += [ bold_mask_anatomical_resampled, ] - + # BOLD to T1 coregistration if cfg.registration_workflows["functional_registration"]["coregistration"][ "run"