1- # Copyright (C) 2012-2024 C-PAC Developers
1+ # Copyright (C) 2012-2025 C-PAC Developers
22
33# This file is part of C-PAC.
44
1717# pylint: disable=too-many-lines,ungrouped-imports,wrong-import-order
1818"""Workflows for registration."""
1919
20- from typing import Optional
20+ from typing import Literal , Optional
2121
2222from voluptuous import RequiredFieldInvalid
2323from nipype .interfaces import afni , ants , c3 , fsl , utility as util
4040 seperate_warps_list ,
4141 single_ants_xfm_to_list ,
4242)
43+ from CPAC .utils .configuration import Configuration
4344from CPAC .utils .interfaces import Function
4445from CPAC .utils .interfaces .fsl import Merge as fslMerge
4546from CPAC .utils .utils import check_prov_for_motion_tool , check_prov_for_regtool
@@ -1454,9 +1455,15 @@ def create_wf_calculate_ants_warp(
14541455
14551456
14561457def FSL_registration_connector (
1457- wf_name , cfg , orig = "T1w" , opt = None , symmetric = False , template = "T1w"
1458- ):
1458+ wf_name : str ,
1459+ cfg : Configuration ,
1460+ orig : str = "T1w" ,
1461+ opt : Literal ["FSL" , "FSL-linear" ] = "FSL" ,
1462+ symmetric : bool = False ,
1463+ template : str = "T1w" ,
1464+ ) -> tuple [pe .Workflow , dict [str , tuple ]]:
14591465 """Transform raw data to template with FSL."""
1466+ assert opt in ["FSL" , "FSL-linear" ]
14601467 wf = pe .Workflow (name = wf_name )
14611468
14621469 inputNode = pe .Node (
@@ -1485,78 +1492,71 @@ def FSL_registration_connector(
14851492 tmpl = ""
14861493 if template == "EPI" :
14871494 tmpl = "EPI"
1495+ flirt_reg_anat_mni = create_fsl_flirt_linear_reg (f"anat_mni_flirt_register{ symm } " )
14881496
1489- if opt in ("FSL" , "FSL-linear" ):
1490- flirt_reg_anat_mni = create_fsl_flirt_linear_reg (
1491- f"anat_mni_flirt_register{ symm } "
1492- )
1497+ # Input registration parameters
1498+ wf .connect (inputNode , "interpolation" , flirt_reg_anat_mni , "inputspec.interp" )
14931499
1494- # Input registration parameters
1495- wf .connect (inputNode , "interpolation" , flirt_reg_anat_mni , "inputspec.interp" )
1500+ wf .connect (inputNode , "input_brain" , flirt_reg_anat_mni , "inputspec.input_brain" )
14961501
1497- wf .connect (
1498- inputNode , "input_brain" , flirt_reg_anat_mni , "inputspec.input_brain"
1499- )
1502+ wf .connect (
1503+ inputNode ,
1504+ "reference_brain" ,
1505+ flirt_reg_anat_mni ,
1506+ "inputspec.reference_brain" ,
1507+ )
15001508
1501- wf .connect (
1502- inputNode ,
1503- "reference_brain" ,
1504- flirt_reg_anat_mni ,
1505- "inputspec.reference_brain" ,
1506- )
1509+ write_lin_composite_xfm = pe .Node (
1510+ interface = fsl .ConvertWarp (), name = f"fsl_lin-warp_to_nii{ symm } "
1511+ )
15071512
1508- write_lin_composite_xfm = pe .Node (
1509- interface = fsl .ConvertWarp (), name = f"fsl_lin-warp_to_nii{ symm } "
1510- )
1513+ wf .connect (inputNode , "reference_brain" , write_lin_composite_xfm , "reference" )
15111514
1512- wf .connect (inputNode , "reference_brain" , write_lin_composite_xfm , "reference" )
1515+ wf .connect (
1516+ flirt_reg_anat_mni ,
1517+ "outputspec.linear_xfm" ,
1518+ write_lin_composite_xfm ,
1519+ "premat" ,
1520+ )
15131521
1514- wf .connect (
1515- flirt_reg_anat_mni ,
1516- "outputspec.linear_xfm" ,
1517- write_lin_composite_xfm ,
1518- "premat" ,
1519- )
1522+ write_invlin_composite_xfm = pe .Node (
1523+ interface = fsl .ConvertWarp (), name = f"fsl_invlin-warp_to_nii{ symm } "
1524+ )
15201525
1521- write_invlin_composite_xfm = pe .Node (
1522- interface = fsl .ConvertWarp (), name = f"fsl_invlin-warp_to_nii{ symm } "
1523- )
1526+ wf .connect (inputNode , "reference_brain" , write_invlin_composite_xfm , "reference" )
15241527
1525- wf .connect (
1526- inputNode , "reference_brain" , write_invlin_composite_xfm , "reference"
1527- )
1528+ wf .connect (
1529+ flirt_reg_anat_mni ,
1530+ "outputspec.invlinear_xfm" ,
1531+ write_invlin_composite_xfm ,
1532+ "premat" ,
1533+ )
15281534
1529- wf .connect (
1535+ outputs = {
1536+ f"space-{ sym } template_desc-preproc_{ orig } " : (
15301537 flirt_reg_anat_mni ,
1531- "outputspec.invlinear_xfm" ,
1538+ "outputspec.output_brain" ,
1539+ ),
1540+ f"from-{ orig } _to-{ sym } { tmpl } template_mode-image_desc-linear_xfm" : (
1541+ write_lin_composite_xfm ,
1542+ "out_file" ,
1543+ ),
1544+ f"from-{ sym } { tmpl } template_to-{ orig } _mode-image_desc-linear_xfm" : (
15321545 write_invlin_composite_xfm ,
1533- "premat" ,
1534- )
1535-
1536- outputs = {
1537- f"space-{ sym } template_desc-preproc_{ orig } " : (
1538- flirt_reg_anat_mni ,
1539- "outputspec.output_brain" ,
1540- ),
1541- f"from-{ orig } _to-{ sym } { tmpl } template_mode-image_desc-linear_xfm" : (
1542- write_lin_composite_xfm ,
1543- "out_file" ,
1544- ),
1545- f"from-{ sym } { tmpl } template_to-{ orig } _mode-image_desc-linear_xfm" : (
1546- write_invlin_composite_xfm ,
1547- "out_file" ,
1548- ),
1549- f"from-{ orig } _to-{ sym } { tmpl } template_mode-image_xfm" : (
1550- write_lin_composite_xfm ,
1551- "out_file" ,
1552- ),
1553- }
1554-
1555- if opt == "FSL" and cfg ["pipeline_setup" , "organism" ] == "non-human primate" :
1556- fnirt_reg_anat_mni = create_fsl_fnirt_nonlinear_reg_nhp (
1557- f"anat_mni_fnirt_register{ symm } "
1558- )
1546+ "out_file" ,
1547+ ),
1548+ f"from-{ orig } _to-{ sym } { tmpl } template_mode-image_xfm" : (
1549+ write_lin_composite_xfm ,
1550+ "out_file" ,
1551+ ),
1552+ }
15591553
1554+ if opt == "FSL" :
1555+ fnirt_reg_anat_mni = (
1556+ create_fsl_fnirt_nonlinear_reg_nhp
1557+ if cfg ["pipeline_setup" , "organism" ] == "non-human primate"
1558+ else create_fsl_fnirt_nonlinear_reg
1559+ )(f"anat_mni_fnirt_register{ symm } " )
15601560 wf .connect (
15611561 inputNode , "input_brain" , fnirt_reg_anat_mni , "inputspec.input_brain"
15621562 )
@@ -1597,30 +1597,35 @@ def FSL_registration_connector(
15971597 fnirt_reg_anat_mni ,
15981598 "outputspec.output_brain" ,
15991599 ),
1600- f"space-{ sym } template_desc-head_{ orig } " : (
1601- fnirt_reg_anat_mni ,
1602- "outputspec.output_head" ,
1603- ),
1604- f"space-{ sym } template_desc-{ 'brain' if orig == 'T1w' else orig } _mask" : (
1605- fnirt_reg_anat_mni ,
1606- "outputspec.output_mask" ,
1607- ),
1608- f"space-{ sym } template_desc-T1wT2w_biasfield" : (
1609- fnirt_reg_anat_mni ,
1610- "outputspec.output_biasfield" ,
1611- ),
16121600 f"from-{ orig } _to-{ sym } { tmpl } template_mode-image_xfm" : (
16131601 fnirt_reg_anat_mni ,
16141602 "outputspec.nonlinear_xfm" ,
16151603 ),
1616- f"from-{ orig } _to-{ sym } { tmpl } template_mode-image_warp" : (
1617- fnirt_reg_anat_mni ,
1618- "outputspec.nonlinear_warp" ,
1619- ),
16201604 }
1605+ if cfg ["pipeline_setup" , "organism" ] == "non-human primate" :
1606+ added_outputs .update (
1607+ {
1608+ f"space-{ sym } template_desc-head_{ orig } " : (
1609+ fnirt_reg_anat_mni ,
1610+ "outputspec.output_head" ,
1611+ ),
1612+ f"space-{ sym } template_desc-{ 'brain' if orig == 'T1w' else orig } _mask" : (
1613+ fnirt_reg_anat_mni ,
1614+ "outputspec.output_mask" ,
1615+ ),
1616+ f"space-{ sym } template_desc-T1wT2w_biasfield" : (
1617+ fnirt_reg_anat_mni ,
1618+ "outputspec.output_biasfield" ,
1619+ ),
1620+ f"from-{ orig } _to-{ sym } { tmpl } template_mode-image_warp" : (
1621+ fnirt_reg_anat_mni ,
1622+ "outputspec.nonlinear_warp" ,
1623+ ),
1624+ }
1625+ )
16211626 outputs .update (added_outputs )
16221627
1623- return ( wf , outputs )
1628+ return wf , outputs
16241629
16251630
16261631def ANTs_registration_connector (
@@ -2256,6 +2261,7 @@ def bold_to_T1template_xfm_connector(
22562261)
22572262def register_FSL_anat_to_template (wf , cfg , strat_pool , pipe_num , opt = None ):
22582263 """Register T1w to template with FSL."""
2264+ assert opt in ["FSL" , "FSL-linear" ]
22592265 fsl , outputs = FSL_registration_connector (
22602266 f"register_{ opt } _anat_to_template_{ pipe_num } " , cfg , orig = "T1w" , opt = opt
22612267 )
@@ -2274,11 +2280,18 @@ def register_FSL_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None):
22742280 node , out = connect
22752281 wf .connect (node , out , fsl , "inputspec.input_brain" )
22762282
2277- node , out = strat_pool .get_data ("T1w-brain-template" )
2278- wf .connect (node , out , fsl , "inputspec.reference_brain" )
2283+ if cfg ["pipeline_setup" , "organism" ] == "non-human primate" :
2284+ node , out = strat_pool .get_data ("FNIRT-T1w-brain-template" )
2285+ wf .connect (node , out , fsl , "inputspec.reference_brain" )
22792286
2280- node , out = strat_pool .get_data ("T1w-template" )
2281- wf .connect (node , out , fsl , "inputspec.reference_head" )
2287+ node , out = strat_pool .get_data ("FNIRT-T1w-template" )
2288+ wf .connect (node , out , fsl , "inputspec.reference_head" )
2289+ else :
2290+ node , out = strat_pool .get_data ("T1w-brain-template" )
2291+ wf .connect (node , out , fsl , "inputspec.reference_brain" )
2292+
2293+ node , out = strat_pool .get_data ("T1w-template" )
2294+ wf .connect (node , out , fsl , "inputspec.reference_head" )
22822295
22832296 node , out = strat_pool .get_data (
22842297 ["desc-preproc_T1w" , "space-longitudinal_desc-reorient_T1w" ]
@@ -2345,6 +2358,7 @@ def register_FSL_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None):
23452358)
23462359def register_symmetric_FSL_anat_to_template (wf , cfg , strat_pool , pipe_num , opt = None ):
23472360 """Register T1w to symmetric template with FSL."""
2361+ assert opt in ["FSL" , "FSL-linear" ]
23482362 fsl , outputs = FSL_registration_connector (
23492363 f"register_{ opt } _anat_to_template_symmetric_{ pipe_num } " ,
23502364 cfg ,
@@ -2419,6 +2433,7 @@ def register_symmetric_FSL_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=N
24192433)
24202434def register_FSL_EPI_to_template (wf , cfg , strat_pool , pipe_num , opt = None ):
24212435 """Directly register the mean functional to an EPI template. No T1w involved."""
2436+ assert opt in ["FSL" , "FSL-linear" ]
24222437 fsl , outputs = FSL_registration_connector (
24232438 f"register_{ opt } _EPI_to_template_{ pipe_num } " ,
24242439 cfg ,
0 commit comments