def segmentation_workflow(workflow, resource_pool, config): # resource pool should have: # anatomical_brain import os import sys import nipype.interfaces.io as nio import nipype.pipeline.engine as pe import nipype.interfaces.fsl as fsl import nipype.interfaces.ants as ants import nipype.interfaces.utility as util from anatomical_preproc_utils import pick_seg_type from workflow_utils import check_input_resources, \ check_config_settings if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow workflow, resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config) segment = pe.Node(interface=fsl.FAST(), name='segmentation') segment.inputs.img_type = 1 segment.inputs.segments = True segment.inputs.probability_maps = True segment.inputs.out_basename = 'segment' if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, segment, 'in_files') else: segment.inputs.in_files = resource_pool["anatomical_brain"] # process masks seg_types = ["gm", "wm", "csf"] for seg in seg_types: pick_seg = pe.Node(interface=util.Function( input_names=['probability_maps', 'seg_type'], output_names=['filename'], function=pick_seg_type), name='pick_%s' % seg) pick_seg.inputs.seg_type = seg workflow.connect(segment, 'tissue_class_files', pick_seg, 'probability_maps') resource_pool["anatomical_%s_mask" % seg] = (pick_seg, 'filename') return workflow, resource_pool
def segmentation_workflow(workflow, resource_pool, config): # resource pool should have: # anatomical_brain import os import sys import nipype.interfaces.io as nio import nipype.pipeline.engine as pe import nipype.interfaces.fsl as fsl import nipype.interfaces.ants as ants import nipype.interfaces.utility as util from anatomical_preproc_utils import pick_seg_type from workflow_utils import check_input_resources, check_config_settings if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow workflow, resource_pool = anatomical_skullstrip_workflow(workflow, resource_pool, config) segment = pe.Node(interface=fsl.FAST(), name="segmentation") segment.inputs.img_type = 1 segment.inputs.segments = True segment.inputs.probability_maps = True segment.inputs.out_basename = "segment" if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, segment, "in_files") else: segment.inputs.in_files = resource_pool["anatomical_brain"] # process masks seg_types = ["gm", "wm", "csf"] for seg in seg_types: pick_seg = pe.Node( interface=util.Function( input_names=["probability_maps", "seg_type"], output_names=["filename"], function=pick_seg_type ), name="pick_%s" % seg, ) pick_seg.inputs.seg_type = seg workflow.connect(segment, "tissue_class_files", pick_seg, "probability_maps") resource_pool["anatomical_%s_mask" % seg] = (pick_seg, "filename") return workflow, resource_pool
def flirt_anatomical_linear_registration(workflow, resource_pool, config): # resource pool should have: # anatomical_brain import os import sys import nipype.interfaces.io as nio import nipype.pipeline.engine as pe import nipype.interfaces.utility as util import nipype.interfaces.fsl as fsl from workflow_utils import check_input_resources, \ check_config_settings check_config_settings(config, "template_brain_for_anat") if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow workflow, resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config) #check_input_resources(resource_pool, "anatomical_brain") calc_flirt_warp = pe.Node(interface=fsl.FLIRT(), name='calc_flirt_warp') calc_flirt_warp.inputs.cost = 'corratio' if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, calc_flirt_warp, 'in_file') else: calc_flirt_warp.inputs.in_file = resource_pool["anatomical_brain"] calc_flirt_warp.inputs.reference = config["template_brain_for_anat"] resource_pool["flirt_affine_xfm"] = (calc_flirt_warp, 'out_matrix_file') resource_pool["flirt_linear_warped_image"] = (calc_flirt_warp, 'out_file') return workflow, resource_pool
def flirt_anatomical_linear_registration(workflow, resource_pool, config): # resource pool should have: # anatomical_brain import os import sys import nipype.interfaces.io as nio import nipype.pipeline.engine as pe import nipype.interfaces.utility as util import nipype.interfaces.fsl as fsl from workflow_utils import check_input_resources, \ check_config_settings from nipype.interfaces.fsl.base import Info if "template_brain_for_anat" not in config: config["template_brain_for_anat"] = Info.standard_image( "MNI152_T1_2mm_brain.nii.gz") check_config_settings(config, "template_brain_for_anat") if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow workflow, resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config) #check_input_resources(resource_pool, "anatomical_brain") calc_flirt_warp = pe.Node(interface=fsl.FLIRT(), name='calc_flirt_warp') calc_flirt_warp.inputs.cost = 'corratio' if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, calc_flirt_warp, 'in_file') else: calc_flirt_warp.inputs.in_file = resource_pool["anatomical_brain"] calc_flirt_warp.inputs.reference = config["template_brain_for_anat"] resource_pool["flirt_affine_xfm"] = (calc_flirt_warp, 'out_matrix_file') resource_pool["flirt_linear_warped_image"] = (calc_flirt_warp, 'out_file') return workflow, resource_pool
def run_anatomical_skullstrip(anatomical_reorient, run=True): # stand-alone runner for anatomical skullstrip workflow import os import sys import glob import nipype.interfaces.io as nio import nipype.pipeline.engine as pe workflow = pe.Workflow(name='anatomical_skullstrip_workflow') current_dir = os.getcwd() workflow_dir = os.path.join(current_dir, "anatomical_skullstrip") workflow.base_dir = workflow_dir resource_pool = {} config = {} num_cores_per_subject = 1 resource_pool["anatomical_reorient"] = anatomical_reorient workflow, resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config) ds = pe.Node(nio.DataSink(), name='datasink_anatomical_skullstrip') ds.inputs.base_directory = workflow_dir node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, ds, 'anatomical_brain') if run == True: workflow.run(plugin='MultiProc', plugin_args= \ {'n_procs': num_cores_per_subject}) outpath = glob.glob(os.path.join(workflow_dir, "anatomical_brain", \ "*"))[0] return outpath else: return workflow, workflow.base_dir
def afni_segmentation_workflow(workflow, resource_pool, config, name="_"): """Build a Nipype workflow to generate anatomical tissue segmentation maps using AFNI's 3dSeg. - If any resources/outputs required by this workflow are not in the resource pool, this workflow will call pre-requisite workflow builder functions to further populate the pipeline with workflows which will calculate/generate these necessary pre-requisites. Expected Resources in Resource Pool anatomical_brain: The skull-stripped anatomical image (brain only). New Resources Added to Resource Pool anatomical_csf_mask: The binary mask mapping the CSF voxels. anatomical_gm_mask: The binary mask mapping the gray matter voxels. anatomical_wm_mask: The binary mask mapping the white matter voxels. Workflow Steps 1. AFNI 3dSeg to run tissue segmentation on the anatomical brain. 2. AFNI 3dAFNItoNIFTI to convert the AFNI-format 3dSeg output into a NIFTI file (as of Oct 2016 3dSeg cannot be configured to write to NIFTI). 3. AFNI 3dcalc to separate the three masks within the output file into three separate images. :type workflow: Nipype workflow object :param workflow: A Nipype workflow object which can already contain other connected nodes; this function will insert the following workflow into this one provided. :type resource_pool: dict :param resource_pool: A dictionary defining input files and pointers to Nipype node outputs / workflow connections; the keys are the resource names. :type config: dict :param config: A dictionary defining the configuration settings for the workflow, such as directory paths or toggled options. :type name: str :param name: (default: "_") A string to append to the end of each node name. :rtype: Nipype workflow object :return: The Nipype workflow originally provided, but with this function's sub-workflow connected into it. :rtype: dict :return: The resource pool originally provided, but updated (if applicable) with the newest outputs and connections. """ import copy import nipype.pipeline.engine as pe from nipype.interfaces.afni import preprocess if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow old_rp = copy.copy(resource_pool) workflow, new_resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config, name) if resource_pool == old_rp: return workflow, resource_pool segment = pe.Node(interface=preprocess.Seg(), name='segmentation%s' % name) segment.inputs.mask = 'AUTO' if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, segment, 'in_file') else: segment.inputs.in_file = resource_pool["anatomical_brain"] # output processing AFNItoNIFTI = pe.Node(interface=preprocess.AFNItoNIFTI(), name="segment_AFNItoNIFTI%s" % name) AFNItoNIFTI.inputs.out_file = "classes.nii.gz" workflow.connect(segment, 'out_file', AFNItoNIFTI, 'in_file') # break out each of the three tissue types into # three separate NIFTI files extract_CSF = pe.Node(interface=preprocess.Calc(), name='extract_CSF_mask%s' % name) extract_CSF.inputs.expr = "within(a,1,1)" extract_CSF.inputs.out_file = "anatomical_csf_mask.nii.gz" extract_GM = pe.Node(interface=preprocess.Calc(), name='extract_GM_mask%s' % name) extract_GM.inputs.expr = "within(a,2,2)" extract_GM.inputs.out_file = "anatomical_gm_mask.nii.gz" extract_WM = pe.Node(interface=preprocess.Calc(), name='extract_WM_mask%s' % name) extract_WM.inputs.expr = "within(a,3,3)" extract_WM.inputs.out_file = "anatomical_wm_mask.nii.gz" workflow.connect(AFNItoNIFTI, 'out_file', extract_CSF, 'in_file_a') workflow.connect(AFNItoNIFTI, 'out_file', extract_GM, 'in_file_a') workflow.connect(AFNItoNIFTI, 'out_file', extract_WM, 'in_file_a') resource_pool["anatomical_csf_mask"] = (extract_CSF, 'out_file') resource_pool["anatomical_gm_mask"] = (extract_GM, 'out_file') resource_pool["anatomical_wm_mask"] = (extract_WM, 'out_file') return workflow, resource_pool
def afni_anatomical_linear_registration(workflow, resource_pool, \ config, name="_"): """Build Nipype workflow to calculate the linear registration (participant to template) of an anatomical image using AFNI's 3dAllineate. - If any resources/outputs required by this workflow are not in the resource pool, this workflow will call pre-requisite workflow builder functions to further populate the pipeline with workflows which will calculate/generate these necessary pre-requisites. Expected Settings in Configuration - skull_on_registration: (optional- default: True) Whether or not to accept anatomical_reorient or anatomical_brain as the input for registration. - template_head_for_anat: (for skull-on registration) The reference template of the whole head. - template_brain_for_anat: (for skull-off registration) The reference template of the brain without skull. Expected Resources in Resource Pool - anatomical_reorient: The deobliqued, reoriented anatomical scan. OR - anatomical_brain: The skull-stripped anatomical image (brain only). New Resources Added to Resource Pool - afni_linear_warped_image: The anatomical image transformed to the template (using linear warps). - allineate_linear_xfm: The text file containing the linear warp matrix produced by AFNI's 3dAllineate. Workflow Steps 1. AFNI's 3dAllineate to calculate the linear registration. :type workflow: Nipype workflow object :param workflow: A Nipype workflow object which can already contain other connected nodes; this function will insert the following workflow into this one provided. :type resource_pool: dict :param resource_pool: A dictionary defining input files and pointers to Nipype node outputs / workflow connections; the keys are the resource names. :type config: dict :param config: A dictionary defining the configuration settings for the workflow, such as directory paths or toggled options. :type name: str :param name: (default: "_") A string to append to the end of each node name. :rtype: Nipype workflow object :return: The Nipype workflow originally provided, but with this function's sub-workflow connected into it. :rtype: dict :return: The resource pool originally provided, but updated (if applicable) with the newest outputs and connections. """ import copy import nipype.pipeline.engine as pe import nipype.interfaces.afni as afni if "skull_on_registration" not in config.keys(): config["skull_on_registration"] = True calc_allineate_warp = pe.Node(interface=afni.Allineate(), name='calc_3dAllineate_warp%s' % name) calc_allineate_warp.inputs.outputtype = "NIFTI_GZ" if config["skull_on_registration"]: if "anatomical_reorient" not in resource_pool.keys(): from anatomical_preproc import anatomical_reorient_workflow old_rp = copy.copy(resource_pool) workflow, new_resource_pool = \ anatomical_reorient_workflow(workflow, resource_pool, config, name) if resource_pool == old_rp: return workflow, resource_pool if len(resource_pool["anatomical_reorient"]) == 2: node, out_file = resource_pool["anatomical_reorient"] workflow.connect(node, out_file, calc_allineate_warp, 'in_file') else: calc_allineate_warp.inputs.in_file = \ resource_pool["anatomical_reorient"] calc_allineate_warp.inputs.reference = \ config["template_head_for_anat"] calc_allineate_warp.inputs.out_file = "allineate_warped_head.nii.gz" else: if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow old_rp = copy.copy(resource_pool) workflow, new_resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, \ config, name) if resource_pool == old_rp: return workflow, resource_pool if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, calc_allineate_warp, 'in_file') else: calc_allineate_warp.inputs.in_file = \ resource_pool["anatomical_brain"] calc_allineate_warp.inputs.reference = \ config["template_brain_for_anat"] calc_allineate_warp.inputs.out_file = \ "allineate_warped_brain.nii.gz" calc_allineate_warp.inputs.out_matrix = "3dallineate_warp" resource_pool["allineate_linear_xfm"] = \ (calc_allineate_warp, 'matrix') resource_pool["afni_linear_warped_image"] = \ (calc_allineate_warp, 'out_file') return workflow, resource_pool
def run_anatomical_skullstrip(anatomical_reorient, out_dir=None, run=True): """Run the 'anatomical_skullstrip_workflow' function to execute the modular workflow with the provided inputs. :type anatomical_reorient: str :param anatomical_reorient: The filepath of the deobliqued, reoriented anatomical image NIFTI file. :type out_dir: str :param out_dir: (default: None) The output directory to write the results to; if left as None, will write to the current directory. :type run: bool :param run: (default: True) Will run the workflow; if set to False, will connect the Nipype workflow and return the workflow object instead. :rtype: str :return: (if run=True) The filepath of the generated anatomical_reorient file. :rtype: Nipype workflow object :return: (if run=False) The connected Nipype workflow object. :rtype: str :return: (if run=False) The base directory of the workflow if it were to be run. """ import os import glob import nipype.interfaces.io as nio import nipype.pipeline.engine as pe output = "anatomical_brain" workflow = pe.Workflow(name='anatomical_skullstrip_workflow') if not out_dir: out_dir = os.getcwd() workflow_dir = os.path.join(out_dir, "workflow_output", output) workflow.base_dir = workflow_dir resource_pool = {} config = {} num_cores_per_subject = 1 resource_pool["anatomical_reorient"] = anatomical_reorient workflow, resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config) ds = pe.Node(nio.DataSink(), name='datasink_anatomical_skullstrip') ds.inputs.base_directory = workflow_dir node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, ds, 'anatomical_brain') if run == True: workflow.run(plugin='MultiProc', plugin_args= \ {'n_procs': num_cores_per_subject}) outpath = glob.glob(os.path.join(workflow_dir, "anatomical_brain", \ "*"))[0] return outpath else: return workflow, workflow.base_dir
def ants_anatomical_linear_registration(workflow, resource_pool, config): # resource pool should have: # anatomical_brain # linear ANTS registration takes roughly 2.5 minutes per subject running # on one core of an Intel Core i7-4800MQ CPU @ 2.70GHz import os import sys import nipype.interfaces.io as nio import nipype.pipeline.engine as pe import nipype.interfaces.utility as util from anatomical_preproc_utils import ants_lin_reg, \ separate_warps_list from workflow_utils import check_input_resources, \ check_config_settings from nipype.interfaces.fsl.base import Info if "template_brain_for_anat" not in config: config["template_brain_for_anat"] = Info.standard_image( "MNI152_T1_2mm_brain.nii.gz") check_config_settings(config, "template_brain_for_anat") if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow workflow, resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config) #check_input_resources(resource_pool, "anatomical_brain") calc_ants_warp = pe.Node(interface=util.Function( input_names=['anatomical_brain', 'reference_brain'], output_names=['warp_list', 'warped_image'], function=ants_lin_reg), name='calc_ants_linear_warp') select_forward_initial = pe.Node(util.Function( input_names=['warp_list', 'selection'], output_names=['selected_warp'], function=separate_warps_list), name='select_forward_initial') select_forward_initial.inputs.selection = "Initial" select_forward_rigid = pe.Node(util.Function( input_names=['warp_list', 'selection'], output_names=['selected_warp'], function=separate_warps_list), name='select_forward_rigid') select_forward_rigid.inputs.selection = "Rigid" select_forward_affine = pe.Node(util.Function( input_names=['warp_list', 'selection'], output_names=['selected_warp'], function=separate_warps_list), name='select_forward_affine') select_forward_affine.inputs.selection = "Affine" if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, calc_ants_warp, 'anatomical_brain') else: calc_ants_warp.inputs.anatomical_brain = \ resource_pool["anatomical_brain"] calc_ants_warp.inputs.reference_brain = config["template_brain_for_anat"] workflow.connect(calc_ants_warp, 'warp_list', select_forward_initial, 'warp_list') workflow.connect(calc_ants_warp, 'warp_list', select_forward_rigid, 'warp_list') workflow.connect(calc_ants_warp, 'warp_list', select_forward_affine, 'warp_list') resource_pool["ants_initial_xfm"] = \ (select_forward_initial, 'selected_warp') resource_pool["ants_rigid_xfm"] = (select_forward_rigid, 'selected_warp') resource_pool["ants_affine_xfm"] = \ (select_forward_affine, 'selected_warp') resource_pool["ants_linear_warped_image"] = \ (calc_ants_warp, 'warped_image') return workflow, resource_pool
def ants_anatomical_linear_registration(workflow, resource_pool, config): # resource pool should have: # anatomical_brain # linear ANTS registration takes roughly 2.5 minutes per subject running # on one core of an Intel Core i7-4800MQ CPU @ 2.70GHz import os import sys import nipype.interfaces.io as nio import nipype.pipeline.engine as pe import nipype.interfaces.utility as util from anatomical_preproc_utils import ants_lin_reg, \ separate_warps_list from workflow_utils import check_input_resources, \ check_config_settings check_config_settings(config, "template_brain_for_anat") if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow workflow, resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, config) #check_input_resources(resource_pool, "anatomical_brain") calc_ants_warp = pe.Node(interface=util.Function( input_names=['anatomical_brain', 'reference_brain'], output_names=['warp_list', 'warped_image'], function=ants_lin_reg), name='calc_ants_linear_warp') select_forward_initial = pe.Node(util.Function(input_names=['warp_list', 'selection'], output_names=['selected_warp'], function=separate_warps_list), name='select_forward_initial') select_forward_initial.inputs.selection = "Initial" select_forward_rigid = pe.Node(util.Function(input_names=['warp_list', 'selection'], output_names=['selected_warp'], function=separate_warps_list), name='select_forward_rigid') select_forward_rigid.inputs.selection = "Rigid" select_forward_affine = pe.Node(util.Function(input_names=['warp_list', 'selection'], output_names=['selected_warp'], function=separate_warps_list), name='select_forward_affine') select_forward_affine.inputs.selection = "Affine" if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, calc_ants_warp, 'anatomical_brain') else: calc_ants_warp.inputs.anatomical_brain = \ resource_pool["anatomical_brain"] calc_ants_warp.inputs.reference_brain = config["template_brain_for_anat"] workflow.connect(calc_ants_warp, 'warp_list', select_forward_initial, 'warp_list') workflow.connect(calc_ants_warp, 'warp_list', select_forward_rigid, 'warp_list') workflow.connect(calc_ants_warp, 'warp_list', select_forward_affine, 'warp_list') resource_pool["ants_initial_xfm"] = \ (select_forward_initial, 'selected_warp') resource_pool["ants_rigid_xfm"] = (select_forward_rigid, 'selected_warp') resource_pool["ants_affine_xfm"] = \ (select_forward_affine, 'selected_warp') resource_pool["ants_linear_warped_image"] = \ (calc_ants_warp, 'warped_image') return workflow, resource_pool
def ants_anatomical_linear_registration(workflow, resource_pool, config): # resource pool should have: # anatomical_brain # linear ANTS registration takes roughly 2.5 minutes per subject running # on one core of an Intel Core i7-4800MQ CPU @ 2.70GHz import os import sys import nipype.interfaces.io as nio import nipype.pipeline.engine as pe import nipype.interfaces.utility as util from anatomical_preproc_utils import ants_lin_reg, separate_warps_list from workflow_utils import check_input_resources, check_config_settings from nipype.interfaces.fsl.base import Info if "template_brain_for_anat" not in config: config["template_brain_for_anat"] = Info.standard_image("MNI152_T1_2mm_brain.nii.gz") check_config_settings(config, "template_brain_for_anat") if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow workflow, resource_pool = anatomical_skullstrip_workflow(workflow, resource_pool, config) # check_input_resources(resource_pool, "anatomical_brain") calc_ants_warp = pe.Node( interface=util.Function( input_names=["anatomical_brain", "reference_brain"], output_names=["warp_list", "warped_image"], function=ants_lin_reg, ), name="calc_ants_linear_warp", ) select_forward_initial = pe.Node( util.Function( input_names=["warp_list", "selection"], output_names=["selected_warp"], function=separate_warps_list ), name="select_forward_initial", ) select_forward_initial.inputs.selection = "Initial" select_forward_rigid = pe.Node( util.Function( input_names=["warp_list", "selection"], output_names=["selected_warp"], function=separate_warps_list ), name="select_forward_rigid", ) select_forward_rigid.inputs.selection = "Rigid" select_forward_affine = pe.Node( util.Function( input_names=["warp_list", "selection"], output_names=["selected_warp"], function=separate_warps_list ), name="select_forward_affine", ) select_forward_affine.inputs.selection = "Affine" if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, calc_ants_warp, "anatomical_brain") else: calc_ants_warp.inputs.anatomical_brain = resource_pool["anatomical_brain"] calc_ants_warp.inputs.reference_brain = config["template_brain_for_anat"] workflow.connect(calc_ants_warp, "warp_list", select_forward_initial, "warp_list") workflow.connect(calc_ants_warp, "warp_list", select_forward_rigid, "warp_list") workflow.connect(calc_ants_warp, "warp_list", select_forward_affine, "warp_list") resource_pool["ants_initial_xfm"] = (select_forward_initial, "selected_warp") resource_pool["ants_rigid_xfm"] = (select_forward_rigid, "selected_warp") resource_pool["ants_affine_xfm"] = (select_forward_affine, "selected_warp") resource_pool["ants_linear_warped_image"] = (calc_ants_warp, "warped_image") return workflow, resource_pool