示例#1
0
def create_templates_2func_workflow(threshold=0.5,
                                    name='templates_2func_workflow'):
    templates_2func_workflow = Workflow(name=name)

    # Input Node
    inputspec = Node(utility.IdentityInterface(fields=[
        'func_file',
        'premat',
        'warp',
        'templates',
    ]),
                     name='inputspec')

    # Get the overal EPI to MNI warp
    func_2mni_warp = Node(fsl.ConvertWarp(), name='func_2mni_warp')
    func_2mni_warp.inputs.reference = fsl.Info.standard_image(
        'MNI152_T1_2mm.nii.gz')

    # Calculate the inverse warp
    mni_2func_warp = Node(fsl.InvWarp(), name='mni_2func_warp')

    # Transform MNI templates to EPI space
    templates_2func_apply = MapNode(fsl.ApplyWarp(),
                                    iterfield=['in_file'],
                                    name='templates_2func_apply')

    # Threshold templates
    templates_threshold = MapNode(
        fsl.ImageMaths(op_string='-thr {0} -bin'.format(threshold)),
        iterfield=['in_file'],
        name='templates_threshold')

    # Output Node
    outputspec = Node(utility.IdentityInterface(
        fields=['templates_2func_files', 'func_2mni_warp']),
                      name='outputspec')

    # Connect the workflow nodes
    templates_2func_workflow.connect(inputspec, 'premat', func_2mni_warp,
                                     'premat')
    templates_2func_workflow.connect(inputspec, 'warp', func_2mni_warp,
                                     'warp1')
    templates_2func_workflow.connect(inputspec, 'func_file', mni_2func_warp,
                                     'reference')
    templates_2func_workflow.connect(func_2mni_warp, 'out_file',
                                     mni_2func_warp, 'warp')
    templates_2func_workflow.connect(inputspec, 'templates',
                                     templates_2func_apply, 'in_file')
    templates_2func_workflow.connect(inputspec, 'func_file',
                                     templates_2func_apply, 'ref_file')
    templates_2func_workflow.connect(mni_2func_warp, 'inverse_warp',
                                     templates_2func_apply, 'field_file')
    templates_2func_workflow.connect(templates_2func_apply, 'out_file',
                                     templates_threshold, 'in_file')
    templates_2func_workflow.connect(func_2mni_warp, 'out_file', outputspec,
                                     'func_2mni_warp')
    templates_2func_workflow.connect(templates_threshold, 'out_file',
                                     outputspec, 'templates_2func_files')

    return templates_2func_workflow
示例#2
0
文件: utils.py 项目: wanderine/nipype
def vsm2warp(name='Shiftmap2Warping'):
    """
    Converts a voxel shift map (vsm) to a displacements field (warp).
    """
    inputnode = pe.Node(niu.IdentityInterface(
        fields=['in_vsm', 'in_ref', 'scaling', 'enc_dir']),
                        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(fields=['out_warp']),
                         name='outputnode')
    fixhdr = pe.Node(niu.Function(input_names=['in_file', 'in_file_hdr'],
                                  output_names=['out_file'],
                                  function=copy_hdr),
                     name='Fix_hdr')
    vsm = pe.Node(fsl.maths.BinaryMaths(operation='mul'), name='ScaleField')
    vsm2dfm = pe.Node(fsl.ConvertWarp(relwarp=True, out_relwarp=True),
                      name='vsm2dfm')

    wf = pe.Workflow(name=name)
    wf.connect([(inputnode, fixhdr, [('in_vsm', 'in_file'),
                                     ('in_ref', 'in_file_hdr')]),
                (inputnode, vsm, [('scaling', 'operand_value')]),
                (fixhdr, vsm, [('out_file', 'in_file')]),
                (vsm, vsm2dfm, [('out_file', 'shift_in_file')]),
                (inputnode, vsm2dfm, [('in_ref', 'reference'),
                                      ('enc_dir', 'shift_direction')]),
                (vsm2dfm, outputnode, [('out_file', 'out_warp')])])
    return wf
示例#3
0
def apply_all_corrections(name='UnwarpArtifacts'):
    """
    Combines two lists of linear transforms with the deformation field
    map obtained typically after the SDC process.
    Additionally, computes the corresponding bspline coefficients and
    the map of determinants of the jacobian.
    """

    inputnode = pe.Node(niu.IdentityInterface(fields=['in_sdc',
                        'in_hmc', 'in_ecc', 'in_dwi']), name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(fields=['out_file', 'out_warp',
                         'out_coeff', 'out_jacobian']), name='outputnode')
    warps = pe.MapNode(fsl.ConvertWarp(relwarp=True),
                       iterfield=['premat', 'postmat'],
                       name='ConvertWarp')

    selref = pe.Node(niu.Select(index=[0]), name='Reference')

    split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
    unwarp = pe.MapNode(fsl.ApplyWarp(), iterfield=['in_file', 'field_file'],
                        name='UnwarpDWIs')

    coeffs = pe.MapNode(fsl.WarpUtils(out_format='spline'),
                        iterfield=['in_file'], name='CoeffComp')
    jacobian = pe.MapNode(fsl.WarpUtils(write_jacobian=True),
                          iterfield=['in_file'], name='JacobianComp')
    jacmult = pe.MapNode(fsl.MultiImageMaths(op_string='-mul %s'),
                         iterfield=['in_file', 'operand_files'],
                         name='ModulateDWIs')

    thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'],
                       name='RemoveNegative')
    merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')

    wf = pe.Workflow(name=name)
    wf.connect([
        (inputnode,   warps,      [('in_sdc', 'warp1'),
                                   ('in_hmc', 'premat'),
                                   ('in_ecc', 'postmat'),
                                   ('in_dwi', 'reference')]),
        (inputnode,   split,      [('in_dwi', 'in_file')]),
        (split,       selref,     [('out_files', 'inlist')]),
        (warps,       unwarp,     [('out_file', 'field_file')]),
        (split,       unwarp,     [('out_files', 'in_file')]),
        (selref,      unwarp,     [('out', 'ref_file')]),
        (selref,      coeffs,     [('out', 'reference')]),
        (warps,       coeffs,     [('out_file', 'in_file')]),
        (selref,      jacobian,   [('out', 'reference')]),
        (coeffs,      jacobian,   [('out_file', 'in_file')]),
        (unwarp,      jacmult,    [('out_file', 'in_file')]),
        (jacobian,    jacmult,    [('out_jacobian', 'operand_files')]),
        (jacmult,     thres,      [('out_file', 'in_file')]),
        (thres,       merge,      [('out_file', 'in_files')]),
        (warps,       outputnode, [('out_file', 'out_warp')]),
        (coeffs,      outputnode, [('out_file', 'out_coeff')]),
        (jacobian,    outputnode, [('out_jacobian', 'out_jacobian')]),
        (merge,       outputnode, [('merged_file', 'out_file')])
    ])
    return wf
def apply_all_corrections_using_ants(name='UnwarpArtifacts'):
    """
    Combines two lists of linear transforms with the deformation field
    map obtained epi_correction by Ants.
    Additionally, computes the corresponding bspline coefficients and
    the map of determinants of the jacobian.
    """
    import nipype.interfaces.fsl as fsl
    import nipype.interfaces.utility as niu
    import nipype.pipeline.engine as pe

    inputnode = pe.Node(niu.IdentityInterface(
        fields=['in_sdc_syb', 'in_hmc', 'in_ecc', 'in_dwi', 'in_t1']),
        name='inputnode')

    outputnode = pe.Node(niu.IdentityInterface(
        fields=['out_file', 'out_warp', 'out_coeff', 'out_jacobian']),
        name='outputnode')

    split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')

    concat_hmc_ecc = pe.MapNode(fsl.ConvertXFM(), name="concat_hmc_ecc",
                                iterfield=['in_file', 'in_file2'])
    concat_hmc_ecc.inputs.concat_xfm = True

    warps = pe.MapNode(fsl.ConvertWarp(), iterfield=['premat'],
                       name='ConvertWarp')

    unwarp = pe.MapNode(interface=fsl.ApplyWarp(),
                        iterfield=['in_file', 'field_file'],
                        name='unwarp_warp')
    unwarp.inputs.interp = 'spline'

    coeffs = pe.MapNode(fsl.WarpUtils(out_format='spline'),
                        iterfield=['in_file'], name='CoeffComp')
    jacobian = pe.MapNode(fsl.WarpUtils(write_jacobian=True),
                          iterfield=['in_file'], name='JacobianComp')
    jacmult = pe.MapNode(fsl.MultiImageMaths(op_string='-mul %s'),
                         iterfield=['in_file', 'operand_files'],
                         name='ModulateDWIs')

    thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'],
                       name='RemoveNegative')
    merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')

    wf = pe.Workflow(name=name)
    wf.connect([
        (inputnode, concat_hmc_ecc, [('in_ecc', 'in_file2')]),  # noqa
        (inputnode, concat_hmc_ecc, [('in_hmc', 'in_file')]),  # noqa

        (concat_hmc_ecc, warps, [('out_file',            'premat')]),  # noqa
        (inputnode,      warps, [('in_sdc_syb',           'warp1')]),  # noqa
        (inputnode,      warps, [('in_t1',            'reference')]),  # noqa
        (inputnode,      split, [('in_dwi',             'in_file')]),  # noqa
        (warps,         unwarp, [('out_file',        'field_file')]),  # noqa
        (split,         unwarp, [('out_files',          'in_file')]),  # noqa
        (inputnode,     unwarp, [('in_t1',             'ref_file')]),  # noqa
        (inputnode,     coeffs, [('in_t1',            'reference')]),  # noqa
        (warps,         coeffs, [('out_file',           'in_file')]),  # noqa
        (inputnode,   jacobian, [('in_t1',            'reference')]),  # noqa
        (coeffs,      jacobian, [('out_file',           'in_file')]),  # noqa
        (unwarp,       jacmult, [('out_file',           'in_file')]),  # noqa
        (jacobian,     jacmult, [('out_jacobian', 'operand_files')]),  # noqa
        (jacmult,        thres, [('out_file',           'in_file')]),  # noqa
        (thres,          merge, [('out_file',          'in_files')]),  # noqa
        (warps,     outputnode, [('out_file',          'out_warp')]),  # noqa
        (coeffs,    outputnode, [('out_file',         'out_coeff')]),  # noqa
        (jacobian,  outputnode, [('out_jacobian',  'out_jacobian')]),  # noqa
        (merge,     outputnode, [('merged_file',        'out_file')])  # noqa
    ])

    return wf
示例#5
0
# roi_datasource.inputs.template_args = {'seed_rois': [['subject_id']] }
"""
Setup for Tracktography
-----------------------
Here we will create a generic workflow for DTI computation, this workflow assumes the .bedpostX has already been run...
Here we will create a workflow to enable probabilistic tracktography and hard segmentation of the seed region
"""
stout_tractography = pe.Workflow(name='stout_tractography')
stout_tractography.base_dir = WORKINGDATAPATH

### First connect the subject list to the workflow to build up the patient lists
stout_tractography.connect(infosource, 'subject_id', dti_datasource,
                           'subject_id')

### GENERATE THE WARP FIELDS
cvtwarp_mni_to_dti = pe.Node(interface=fsl.ConvertWarp(),
                             name='cvtwarp_mni_to_dti')
cvtwarp_mni_to_dti.inputs.reference = os.path.join(
    RAWDATAPATH, "MNI152_T1_1mm_brain.nii.gz")

stout_tractography.connect(dti_datasource, 'nodif_to_struct_aff',
                           cvtwarp_mni_to_dti, 'premat')
stout_tractography.connect(dti_datasource, 'struct_warpto_MNI',
                           cvtwarp_mni_to_dti, 'warp1')

# $statement .= " --premat=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc.mat ";
# $statement .= " --warp1=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/struc_warp_MNI_warpfield.nii.gz ";
# $statement .= " --out=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc_warp_MNI_warpfield.nii.gz ";

cvtwarp_dti_to_mni = pe.Node(interface=fsl.ConvertWarp(),
                             name='cvtwarp_dti_to_mni')
def susceptibility_distortion_correction_using_t1(
        name='susceptibility_distortion_correction_using_t1'):
    """
    Susceptibility distortion correction using the T1w image.

    This workflow allows to correct for echo-planar induced susceptibility
    artifacts without fieldmap (e.g. ADNI Database) by elastically register
    DWIs to their respective baseline T1-weighted structural scans using an
    inverse consistent registration algorithm with a mutual information cost
    function (SyN algorithm).

    Args:
        name (Optional[str]): Name of the workflow.

    Inputnode:
        in_t1 (str): T1w image.
        in_dwi (str): DWI dataset

    Outputnode:
        out_dwi (str): Corrected DWI dataset
        out_warp (str): Out warp allowing DWI to T1 registration and
            susceptibilty induced artifacts correction
        out_b0_to_t1_rigid_body_matrix (str): B0 to T1 image FLIRT rigid body
            FSL coregistration matrix
        out_t1_to_b0_rigid_body_matrix (str): T1 to B0 image FLIRT rigid body
            FSL coregistration matrix
        out_t1_coregistered_to_b0 (str): T1 image rigid body coregistered to
            the B0 image
        out_b0_to_t1_syn_deformation_field (str): B0 to T1 image ANTs SyN
            ITK warp
        out_b0_to_t1_affine_matrix (str): B0 to T1 image ANTs affine ITK
            coregistration matrix

    References:
      .. Nir et al. (Neurobiology of Aging 2015): Connectivity network measures
        predict volumetric atrophy in mild cognitive impairment

      .. Leow et al. (IEEE Trans Med Imaging 2007): Statistical Properties of
        Jacobian Maps and the Realization of Unbiased Large Deformation
        Nonlinear Image Registration


    Returns:
        The workflow

    Example:
        >>> epi = susceptibility_distortion_correction_using_t1()
        >>> epi.inputs.inputnode.in_dwi = 'dwi.nii'
        >>> epi.inputs.inputnode.in_t1 = 'T1w.nii'
        >>> epi.run() # doctest: +SKIP
    """
    import nipype
    import nipype.pipeline.engine as pe
    import nipype.interfaces.utility as niu
    import nipype.interfaces.fsl as fsl
    import clinica.pipelines.dwi_preprocessing_using_t1.dwi_preprocessing_using_t1_utils as utils

    def expend_matrix_list(in_matrix, in_bvec):
        import numpy as np

        bvecs = np.loadtxt(in_bvec).T
        out_matrix_list = [in_matrix]

        out_matrix_list = out_matrix_list * len(bvecs)

        return out_matrix_list

    def rotate_bvecs(in_bvec, in_matrix):
        """
        Rotates the input bvec file accordingly with a list of matrices.
        .. note:: the input affine matrix transforms points in the destination
          image to their corresponding coordinates in the original image.
          Therefore, this matrix should be inverted first, as we want to know
          the target position of :math:`\\vec{r}`.
        """
        import os
        import numpy as np

        name, fext = os.path.splitext(os.path.basename(in_bvec))
        if fext == '.gz':
            name, _ = os.path.splitext(name)
        out_file = os.path.abspath('%s_rotated.bvec' % name)
        bvecs = np.loadtxt(
            in_bvec).T  # Warning, bvecs.txt are not in the good configuration, need to put '.T'
        new_bvecs = []

        if len(bvecs) != len(in_matrix):
            raise RuntimeError(('Number of b-vectors (%d) and rotation '
                                'matrices (%d) should match.') %
                               (len(bvecs), len(in_matrix)))

        for bvec, mat in zip(bvecs, in_matrix):
            if np.all(bvec == 0.0):
                new_bvecs.append(bvec)
            else:
                invrot = np.linalg.inv(np.loadtxt(mat))[:3, :3]
                newbvec = invrot.dot(bvec)
                new_bvecs.append((newbvec / np.linalg.norm(newbvec)))

        np.savetxt(out_file, np.array(new_bvecs).T, fmt='%0.15f')
        return out_file

    inputnode = pe.Node(
        niu.IdentityInterface(fields=['in_t1', 'in_dwi', 'in_bvec']),
        name='inputnode')

    split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
    pick_ref = pe.Node(niu.Select(), name='Pick_b0')
    pick_ref.inputs.index = [0]

    flirt_b0_to_t1 = pe.Node(interface=fsl.FLIRT(dof=6),
                            name='flirt_b0_to_t1')
    flirt_b0_to_t1.inputs.interp = "spline"
    flirt_b0_to_t1.inputs.cost = 'normmi'
    flirt_b0_to_t1.inputs.cost_func = 'normmi'

    if nipype.__version__.split('.') < ['0', '13', '0']:
        apply_xfm = pe.Node(interface=fsl.ApplyXfm(),
                            name='apply_xfm')
    else:
        apply_xfm = pe.Node(interface=fsl.ApplyXFM(),
                            name='apply_xfm')
    apply_xfm.inputs.apply_xfm = True

    expend_matrix = pe.Node(
        interface=niu.Function(input_names=['in_matrix', 'in_bvec'],
                               output_names=['out_matrix_list'],
                               function=expend_matrix_list),
        name='expend_matrix')

    rot_bvec = pe.Node(niu.Function(input_names=['in_matrix', 'in_bvec'],
                                    output_names=['out_file'],
                                    function=rotate_bvecs),
                       name='Rotate_Bvec')

    ants_registration_syn_quick = pe.Node(interface=niu.Function(
        input_names=['fix_image', 'moving_image'],
        output_names=['image_warped', 'affine_matrix',
                      'warp', 'inverse_warped', 'inverse_warp'],
        function=utils.ants_registration_syn_quick),
        name='ants_registration_syn_quick')

    merge_transform = pe.Node(niu.Merge(2), name='MergeTransforms')

    combine_warp = pe.Node(interface=niu.Function(
        input_names=['in_file', 'transforms_list', 'reference'],
        output_names=['out_warp'],
        function=utils.ants_combine_transform), name='combine_warp')

    coeffs = pe.Node(fsl.WarpUtils(out_format='spline'), name='CoeffComp')

    fsl_transf = pe.Node(fsl.WarpUtils(out_format='field'),
                         name='fsl_transf')

    warp_epi = pe.Node(fsl.ConvertWarp(), name='warp_epi')

    apply_warp = pe.MapNode(interface=fsl.ApplyWarp(),
                            iterfield=['in_file'], name='apply_warp')
    apply_warp.inputs.interp = 'spline'

    thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'],
                       name='RemoveNegative')

    merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')

    outputnode = pe.Node(niu.IdentityInterface(
        fields=['dwi_to_t1_coregistration_matrix',
                'itk_dwi_t1_coregistration_matrix',
                'epi_correction_deformation_field',
                'epi_correction_affine_transform',
                'merge_epi_transform', 'out_dwi', 'out_warp',
                'out_bvec']), name='outputnode')

    wf = pe.Workflow(name=name)

    wf.connect([
        (inputnode, split, [('in_dwi', 'in_file')]),  # noqa

        (split, pick_ref, [('out_files', 'inlist')]),  # noqa

        (pick_ref,  flirt_b0_to_t1, [('out',     'in_file')]),  # noqa
        (inputnode, flirt_b0_to_t1, [('in_t1', 'reference')]),  # noqa

        (flirt_b0_to_t1, expend_matrix, [('out_matrix_file', 'in_matrix')]),  # noqa
        (inputnode,      expend_matrix, [('in_bvec',           'in_bvec')]),  # noqa

        (inputnode,     rot_bvec, [('in_bvec', 'in_bvec')]),  # noqa
        (expend_matrix, rot_bvec, [('out_matrix_list', 'in_matrix')]),  # noqa
        
        (inputnode,                   ants_registration_syn_quick, [('in_t1',       'fix_image')]),  # noqa
        (flirt_b0_to_t1,              ants_registration_syn_quick, [('out_file', 'moving_image')]),  # noqa

        (ants_registration_syn_quick, merge_transform, [('affine_matrix', 'in2'),  # noqa
                                                        ('warp',          'in1')]),  # noqa

        (flirt_b0_to_t1,  combine_warp, [('out_file',    'in_file')]),  # noqa
        (merge_transform, combine_warp, [('out', 'transforms_list')]),  # noqa
        (inputnode,       combine_warp, [('in_t1',     'reference')]),  # noqa

        (inputnode,    coeffs, [('in_t1',  'reference')]),  # noqa
        (combine_warp, coeffs, [('out_warp', 'in_file')]),  # noqa

        (coeffs,    fsl_transf, [('out_file', 'in_file')]),  # noqa
        (inputnode, fsl_transf, [('in_t1',  'reference')]),  # noqa

        (inputnode,      warp_epi, [('in_t1',        'reference')]),  # noqa
        (flirt_b0_to_t1, warp_epi, [('out_matrix_file', 'premat')]),  # noqa
        (fsl_transf,     warp_epi, [('out_file',         'warp1')]),  # noqa

        (warp_epi,  apply_warp, [('out_file', 'field_file')]),  # noqa
        (split,     apply_warp, [('out_files',   'in_file')]),  # noqa
        (inputnode, apply_warp, [('in_t1',      'ref_file')]),  # noqa

        (apply_warp, thres, [('out_file', 'in_file')]),  # noqa

        (thres, merge, [('out_file', 'in_files')]),  # noqa
        # Outputnode
        (merge,                       outputnode, [('merged_file',                             'out_dwi')]),  # noqa
        (flirt_b0_to_t1,              outputnode, [('out_matrix_file', 'dwi_to_t1_coregistration_matrix')]),  # noqa
        (ants_registration_syn_quick, outputnode, [('warp',             'epi_correction_deformation_field'),  # noqa
                                                   ('affine_matrix',   'epi_correction_affine_transform')]),  # noqa
        (warp_epi,                    outputnode, [('out_file',                               'out_warp')]),  # noqa
        (rot_bvec,                    outputnode, [('out_file',                               'out_bvec')]),  # noqa
    ])
    return wf
示例#7
0
def fsl_apply_transform_func_to_mni(workflow,
                                    output_name,
                                    func_key,
                                    ref_key,
                                    num_strat,
                                    strat,
                                    interpolation_method,
                                    distcor=False,
                                    map_node=False,
                                    func_ts=False,
                                    num_cpus=1):
    """
    Applies previously calculated FSL registration transforms to input
    images. This workflow employs the FSL applywarp tool:

    https://fsl.fmrib.ox.ac.uk/fslcourse/lectures/practicals/registration/index.html

    Parameters
    ----------
    workflow : Nipype workflow object
        the workflow containing the resources involved
    output_name : str
        what the name of the warped functional should be when written to the
        resource pool
    func_key : string
        resource pool key correspoding to the node containing the 3D or 4D
        functional file to be written into MNI space, use 'leaf' for a
        leaf node
    ref_key : string
        resource pool key correspoding to the file path to the template brain
        used for functional-to-template registration
    num_strat : int
        the number of strategy objects
    strat : C-PAC Strategy object
        a strategy with one or more resource pools
    interpolation_method : str
        which interpolation to use when applying the warps
    distcor : boolean
        indicates whether a distortion correction transformation should be
        added to the transforms, this of course requires that a distortion
        correction map exist in the resource pool
    map_node : boolean
        indicates whether a mapnode should be used, if TRUE func_key is
        expected to correspond to a list of resources that should each
        be written into standard space with the other parameters
    func_ts : boolean
        indicates whether the input image is a 4D time series
    num_cpus : int
        the number of CPUs dedicated to each participant workflow - this
        is used to determine how to parallelize the warp application step

    Returns
    -------
    workflow : nipype.pipeline.engine.Workflow

    """

    strat_nodes = strat.get_nodes_names()

    # if the input is a string, assume that it is resource pool key,
    # if it is a tuple, assume that it is a node, outfile pair,
    # otherwise, something funky is going on
    if isinstance(func_key, str):
        if func_key == "leaf":
            func_node, func_file = strat.get_leaf_properties()
        else:
            func_node, func_file = strat[func_key]
    elif isinstance(func_key, tuple):
        func_node, func_file = func_key

    if isinstance(ref_key, str):
        ref_node, ref_out_file = strat[ref_key]
    elif isinstance(ref_key, tuple):
        ref_node, ref_out_file = ref_key

    if int(num_cpus) > 1 and func_ts:
        # parallelize time series warp application
        map_node = True

    if map_node == True:
        # func_mni_warp
        func_mni_warp = pe.MapNode(interface=fsl.ApplyWarp(),
                                   name='func_mni_fsl_warp_{0}_{1:d}'.format(
                                       output_name, num_strat),
                                   iterfield=['in_file'],
                                   mem_gb=1.5)
    else:
        # func_mni_warp
        func_mni_warp = pe.Node(interface=fsl.ApplyWarp(),
                                name='func_mni_fsl_warp_{0}_{1:d}'.format(
                                    output_name, num_strat))

    func_mni_warp.inputs.interp = interpolation_method

    # parallelize the apply warp, if multiple CPUs, and it's a time series!
    if int(num_cpus) > 1 and func_ts:

        node_id = '{0}_{1:d}'.format(output_name, num_strat)

        chunk_imports = ['import nibabel as nb']
        chunk = pe.Node(Function(input_names=['func_file', 'n_cpus'],
                                 output_names=['TR_ranges'],
                                 function=chunk_ts,
                                 imports=chunk_imports),
                        name=f'chunk_{node_id}')

        chunk.inputs.n_cpus = int(num_cpus)
        workflow.connect(func_node, func_file, chunk, 'func_file')

        split_imports = ['import os', 'import subprocess']
        split = pe.Node(Function(input_names=['func_file', 'tr_ranges'],
                                 output_names=['split_funcs'],
                                 function=split_ts_chunks,
                                 imports=split_imports),
                        name=f'split_{node_id}')

        workflow.connect(func_node, func_file, split, 'func_file')
        workflow.connect(chunk, 'TR_ranges', split, 'tr_ranges')

        workflow.connect(split, 'split_funcs', func_mni_warp, 'in_file')

        func_concat = pe.Node(interface=afni_utils.TCat(),
                              name=f'func_concat{node_id}')
        func_concat.inputs.outputtype = 'NIFTI_GZ'

        workflow.connect(func_mni_warp, 'out_file', func_concat, 'in_files')

        strat.update_resource_pool({output_name: (func_concat, 'out_file')})

    else:
        workflow.connect(func_node, func_file, func_mni_warp, 'in_file')
        strat.update_resource_pool({output_name: (func_mni_warp, 'out_file')})

    workflow.connect(ref_node, ref_out_file, func_mni_warp, 'ref_file')

    if 'anat_mni_fnirt_register' in strat_nodes:

        node, out_file = strat['functional_to_anat_linear_xfm']
        workflow.connect(node, out_file, func_mni_warp, 'premat')

        node, out_file = strat['anatomical_to_mni_nonlinear_xfm']
        workflow.connect(node, out_file, func_mni_warp, 'field_file')

        if output_name == "functional_to_standard":
            write_composite_xfm = pe.Node(interface=fsl.ConvertWarp(),
                name='combine_fsl_warps_{0}_{1:d}'.format(output_name,\
                        num_strat))

            workflow.connect(ref_node, ref_out_file, write_composite_xfm,
                             'reference')

            node, out_file = strat['functional_to_anat_linear_xfm']
            workflow.connect(node, out_file, write_composite_xfm, 'premat')

            node, out_file = strat['anatomical_to_mni_nonlinear_xfm']
            workflow.connect(node, out_file, write_composite_xfm, 'warp1')

            strat.update_resource_pool({
                "functional_to_standard_xfm": (write_composite_xfm, 'out_file')
            })

    elif 'anat_mni_flirt_register' in strat_nodes:

        if 'functional_to_mni_linear_xfm' not in strat:

            combine_transforms = pe.Node(interface=fsl.ConvertXFM(),
                name='combine_fsl_xforms_{0}_{1:d}'.format(output_name,\
                        num_strat))

            combine_transforms.inputs.concat_xfm = True

            node, out_file = strat['anatomical_to_mni_linear_xfm']
            workflow.connect(node, out_file, combine_transforms, 'in_file2')

            node, out_file = strat['functional_to_anat_linear_xfm']
            workflow.connect(node, out_file, combine_transforms, 'in_file')

            strat.update_resource_pool({
                'functional_to_mni_linear_xfm':
                (combine_transforms, 'out_file')
            })
            strat.append_name(combine_transforms.name)

        combine_transforms, outfile = strat['functional_to_mni_linear_xfm']

        workflow.connect(combine_transforms, outfile, func_mni_warp, 'premat')

    else:
        raise ValueError('Could not find flirt or fnirt registration in nodes')

    strat.append_name(func_mni_warp.name)

    return workflow
示例#8
0
def create_registration_pipeline(working_dir,
                                 freesurfer_dir,
                                 ds_dir,
                                 name='registration'):
    """
    find transformations between struct, funct, and MNI
    """

    # initiate workflow
    reg_wf = Workflow(name=name)
    reg_wf.base_dir = os.path.join(working_dir, 'LeiCA_resting',
                                   'rsfMRI_preprocessing')

    # set fsl output
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    freesurfer.FSCommand.set_default_subjects_dir(freesurfer_dir)

    # inputnode
    inputnode = Node(util.IdentityInterface(fields=[
        'initial_mean_epi_moco', 't1w', 't1w_brain', 'subject_id',
        'wm_mask_4_bbr', 'struct_brain_mask'
    ]),
                     name='inputnode')

    outputnode = Node(util.IdentityInterface(fields=[
        'struct_2_MNI_warp', 'epi_2_struct_mat', 'struct_2_epi_mat',
        'epi_2_MNI_warp', 'MNI_2_epi_warp', 'fs_2_struct_mat',
        'mean_epi_structSpace', 'mean_epi_MNIspace', 'struct_MNIspace'
    ]),
                      name='outputnode')

    ds = Node(nio.DataSink(base_directory=ds_dir), name='ds')
    ds.inputs.substitutions = [('_TR_id_', 'TR_')]

    ##########################################
    # TOC REGISTRATION MATS AND WARPS
    ##########################################
    # I. STRUCT -> MNI
    ## 1. STRUCT -> MNI with FLIRT
    ## 2. CALC. WARP STRUCT -> MNI with FNIRT

    # II.EPI -> STRUCT
    ## 3. calc EPI->STRUCT initial registration
    ## 4. run EPI->STRUCT via bbr
    ## 5. INVERT to get: STRUCT -> EPI

    # III. COMBINE I. & II.: EPI -> MNI
    ## 6. COMBINE MATS: EPI -> MNI
    ## 7. MNI -> EPI

    ##########################################
    # CREATE REGISTRATION MATS AND WARPS
    ##########################################

    # I. STRUCT -> MNI
    ##########################################
    # 1. REGISTER STRUCT -> MNI with FLIRT
    struct_2_MNI_mat = Node(fsl.FLIRT(dof=12), name='struct_2_MNI_mat')
    struct_2_MNI_mat.inputs.reference = fsl.Info.standard_image(
        'MNI152_T1_2mm_brain.nii.gz')

    reg_wf.connect(inputnode, 't1w_brain', struct_2_MNI_mat, 'in_file')
    reg_wf.connect(struct_2_MNI_mat, 'out_matrix_file', outputnode,
                   'struct_2_MNI_mat_flirt')

    # 2. CALC. WARP STRUCT -> MNI with FNIRT
    # cf. wrt. 2mm
    # https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind1311&L=FSL&P=R86108&1=FSL&9=A&J=on&d=No+Match%3BMatch%3BMatches&z=4
    struct_2_MNI_warp = Node(fsl.FNIRT(), name='struct_2_MNI_warp')
    struct_2_MNI_warp.inputs.config_file = 'T1_2_MNI152_2mm'
    struct_2_MNI_warp.inputs.ref_file = fsl.Info.standard_image(
        'MNI152_T1_2mm.nii.gz')
    struct_2_MNI_warp.inputs.field_file = 'struct_2_MNI_warp.nii.gz'
    struct_2_MNI_warp.plugin_args = {'submit_specs': 'request_memory = 4000'}

    reg_wf.connect(inputnode, 't1w', struct_2_MNI_warp, 'in_file')
    reg_wf.connect(struct_2_MNI_mat, 'out_matrix_file', struct_2_MNI_warp,
                   'affine_file')
    reg_wf.connect(struct_2_MNI_warp, 'field_file', ds,
                   'registration.struct_2_MNI_warp')
    reg_wf.connect(struct_2_MNI_warp, 'field_file', outputnode,
                   'struct_2_MNI_warp')
    reg_wf.connect(struct_2_MNI_warp, 'warped_file', outputnode,
                   'struct_MNIspace')
    reg_wf.connect(struct_2_MNI_warp, 'warped_file', ds,
                   'registration.struct_MNIspace')

    # II.EPI -> STRUCT (via bbr)
    ##########################################

    # 3. calc EPI->STRUCT initial registration with flirt dof=6 and corratio
    epi_2_struct_flirt6_mat = Node(fsl.FLIRT(dof=6, cost='corratio'),
                                   name='epi_2_struct_flirt6_mat')
    epi_2_struct_flirt6_mat.inputs.out_file = 'epi_structSpace_flirt6.nii.gz'
    reg_wf.connect(inputnode, 't1w_brain', epi_2_struct_flirt6_mat,
                   'reference')
    reg_wf.connect(inputnode, 'initial_mean_epi_moco', epi_2_struct_flirt6_mat,
                   'in_file')

    # 4. run EPI->STRUCT via bbr
    bbr_shedule = os.path.join(os.getenv('FSLDIR'), 'etc/flirtsch/bbr.sch')
    epi_2_struct_bbr_mat = Node(interface=fsl.FLIRT(dof=6, cost='bbr'),
                                name='epi_2_struct_bbr_mat')
    epi_2_struct_bbr_mat.inputs.schedule = bbr_shedule
    epi_2_struct_bbr_mat.inputs.out_file = 'epi_structSpace.nii.gz'
    reg_wf.connect(inputnode, 'initial_mean_epi_moco', epi_2_struct_bbr_mat,
                   'in_file')
    reg_wf.connect(inputnode, 't1w_brain', epi_2_struct_bbr_mat, 'reference')
    reg_wf.connect(epi_2_struct_flirt6_mat, 'out_matrix_file',
                   epi_2_struct_bbr_mat, 'in_matrix_file')
    reg_wf.connect(inputnode, 'wm_mask_4_bbr', epi_2_struct_bbr_mat, 'wm_seg')
    reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', ds,
                   'registration.epi_2_struct_mat')
    reg_wf.connect(epi_2_struct_bbr_mat, 'out_file', outputnode,
                   'mean_epi_structSpace')

    # 5. INVERT to get: STRUCT -> EPI
    struct_2_epi_mat = Node(fsl.ConvertXFM(invert_xfm=True),
                            name='struct_2_epi_mat')
    reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', struct_2_epi_mat,
                   'in_file')
    reg_wf.connect(struct_2_epi_mat, 'out_file', outputnode,
                   'struct_2_epi_mat')

    # III. COMBINE I. & II.: EPI -> MNI
    ##########################################
    # 6. COMBINE MATS: EPI -> MNI
    epi_2_MNI_warp = Node(fsl.ConvertWarp(), name='epi_2_MNI_warp')
    epi_2_MNI_warp.inputs.reference = fsl.Info.standard_image(
        'MNI152_T1_2mm.nii.gz')
    reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', epi_2_MNI_warp,
                   'premat')  # epi2struct
    reg_wf.connect(struct_2_MNI_warp, 'field_file', epi_2_MNI_warp,
                   'warp1')  # struct2mni
    reg_wf.connect(epi_2_MNI_warp, 'out_file', outputnode, 'epi_2_MNI_warp')
    reg_wf.connect(epi_2_MNI_warp, 'out_file', ds,
                   'registration.epi_2_MNI_warp')

    # output: out_file

    # 7. MNI -> EPI
    MNI_2_epi_warp = Node(fsl.InvWarp(), name='MNI_2_epi_warp')
    MNI_2_epi_warp.inputs.reference = fsl.Info.standard_image(
        'MNI152_T1_2mm.nii.gz')
    reg_wf.connect(epi_2_MNI_warp, 'out_file', MNI_2_epi_warp, 'warp')
    reg_wf.connect(inputnode, 'initial_mean_epi_moco', MNI_2_epi_warp,
                   'reference')
    reg_wf.connect(MNI_2_epi_warp, 'inverse_warp', outputnode,
                   'MNI_2_epi_warp')
    # output: inverse_warp

    ##########################################
    # TRANSFORM VOLUMES
    ##########################################

    # CREATE STRUCT IN EPI SPACE FOR DEBUGGING
    struct_epiSpace = Node(fsl.ApplyXfm(), name='struct_epiSpace')
    struct_epiSpace.inputs.out_file = 'struct_brain_epiSpace.nii.gz'
    reg_wf.connect(inputnode, 't1w_brain', struct_epiSpace, 'in_file')
    reg_wf.connect(inputnode, 'initial_mean_epi_moco', struct_epiSpace,
                   'reference')
    reg_wf.connect(struct_2_epi_mat, 'out_file', struct_epiSpace,
                   'in_matrix_file')
    reg_wf.connect(struct_epiSpace, 'out_file', ds, 'QC.struct_brain_epiSpace')

    # CREATE EPI IN MNI SPACE
    mean_epi_MNIspace = Node(fsl.ApplyWarp(), name='mean_epi_MNIspace')
    mean_epi_MNIspace.inputs.ref_file = fsl.Info.standard_image(
        'MNI152_T1_2mm_brain.nii.gz')
    mean_epi_MNIspace.inputs.out_file = 'mean_epi_MNIspace.nii.gz'
    reg_wf.connect(inputnode, 'initial_mean_epi_moco', mean_epi_MNIspace,
                   'in_file')
    reg_wf.connect(epi_2_MNI_warp, 'out_file', mean_epi_MNIspace, 'field_file')
    reg_wf.connect(mean_epi_MNIspace, 'out_file', ds,
                   'registration.mean_epi_MNIspace')
    reg_wf.connect(mean_epi_MNIspace, 'out_file', outputnode,
                   'mean_epi_MNIspace')

    # CREATE MNI IN EPI SPACE FOR DEBUGGING
    MNI_epiSpace = Node(fsl.ApplyWarp(), name='MNI_epiSpace')
    MNI_epiSpace.inputs.in_file = fsl.Info.standard_image(
        'MNI152_T1_2mm_brain.nii.gz')
    MNI_epiSpace.inputs.out_file = 'MNI_epiSpace.nii.gz'
    reg_wf.connect(inputnode, 'initial_mean_epi_moco', MNI_epiSpace,
                   'ref_file')
    reg_wf.connect(MNI_2_epi_warp, 'inverse_warp', MNI_epiSpace, 'field_file')
    reg_wf.connect(MNI_epiSpace, 'out_file', ds, 'registration.MNI_epiSpace')

    reg_wf.write_graph(dotfilename=reg_wf.name, graph2use='flat', format='pdf')

    return reg_wf
示例#9
0
                      'config_file')
register_flow.connect(reg_inputnode, 'target_image', highres2standard_warp,
                      'ref_file')
register_flow.connect(reg_inputnode, 'target_mask', highres2standard_warp,
                      'refmask_file')

# Combine linear FLIRT transformations into one to create a transformation matrix from functional to target
func2standard = Node(fsl.ConvertXFM(concat_xfm=True),
                     name='func2standard_linear')
register_flow.connect(func2highres_bbr, 'out_matrix_file', func2standard,
                      'in_file')
register_flow.connect(highres2standard, 'out_matrix_file', func2standard,
                      'in_file2')

# Combine non linear FNIRT transformations into one to create a transformation matrix from functional to target
func2standard_warp = Node(fsl.ConvertWarp(),
                          name='example_func2standard_nonlinear')
register_flow.connect(reg_inputnode, 'target_image_brain', func2standard_warp,
                      'reference')
register_flow.connect(func2highres_bbr, 'out_matrix_file', func2standard_warp,
                      'premat')
register_flow.connect(highres2standard_warp, 'fieldcoeff_file',
                      func2standard_warp, 'warp1')

# Apply nonlinear transform to the reference image.
warpmean = Node(fsl.ApplyWarp(interp='trilinear'), name='warpmean')
register_flow.connect(extract_ref, 'roi_file', warpmean, 'in_file')
register_flow.connect(reg_inputnode, 'target_image_brain', warpmean,
                      'ref_file')
register_flow.connect(func2standard_warp, 'out_file', warpmean, 'field_file')

"""
Setup for Tracktography
-----------------------
Here we will create a generic workflow for DTI computation, this workflow assumes the .bedpostX has already been run...
Here we will create a workflow to enable probabilistic tracktography and hard segmentation of the seed region
"""
stout_tractography = pe.Workflow(name='stout_tractography')
stout_tractography.base_dir = WORKINGDATAPATH

### First connect the subject list to the workflow to build up the patient lists
stout_tractography.connect( infosource,'subject_id',dti_datasource, 'subject_id' )

### GENERATE THE WARP FIELDS
cvtwarp_mni_to_dti = pe.Node(interface=fsl.ConvertWarp(),name='cvtwarp_mni_to_dti' )
cvtwarp_mni_to_dti.inputs.reference = os.path.join(RAWDATAPATH,"MNI152_T1_1mm_brain.nii.gz")

stout_tractography.connect( dti_datasource, 'nodif_to_struct_aff', cvtwarp_mni_to_dti, 'premat')
stout_tractography.connect( dti_datasource, 'struct_warpto_MNI', cvtwarp_mni_to_dti, 'warp1')

# $statement .= " --premat=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc.mat ";
# $statement .= " --warp1=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/struc_warp_MNI_warpfield.nii.gz ";
# $statement .= " --out=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc_warp_MNI_warpfield.nii.gz ";

cvtwarp_dti_to_mni = pe.Node(interface=fsl.ConvertWarp(),name='cvtwarp_dti_to_mni'  )
stout_tractography.connect( dti_datasource, 'nodif_brain_mask', cvtwarp_dti_to_mni, 'reference')
stout_tractography.connect( dti_datasource, 'MNI_to_struct', cvtwarp_dti_to_mni, 'warp1')
stout_tractography.connect( dti_datasource, 'struct_to_nodif_aff', cvtwarp_dti_to_mni, 'postmat')

# $statement .= " --ref=$WORKINGDATAPATH/" . $subj[$i] . "/DTI/data/nodif_brain_mask.nii.gz ";
示例#11
0
def generate_workflow(**inputs):
    """
    generates computation graph for daic2hcp
    :param t1w_file: t1w mgz file in some space
    :param t2w_file: t2w mgz file aligned to t1w
    :param mask_file: mask or brain mgz file aligned to t1w
    :param fmri_files: list of fmri mgz files
    :param rs_files: list of fc-preprocessed resting state fmri mgz files
    :param output_dir: desired output "HCP" directory
    :return: nipype workflow
    """
    # setup variables
    subject_id = inputs['subjectid']
    reference = os.path.join(os.environ['HCPPIPEDIR_Templates'],
                             'MNI152_T1_1mm.nii.gz')
    reference2mm = os.path.join(os.environ['HCPPIPEDIR_Templates'],
                                "MNI152_T1_2mm.nii.gz")

    # io spec
    input_spec = pe.Node(nipype.IdentityInterface(
        fields=['t1w_file', 't2w_file', 'mask_file']),
        name='input_spec'
    )
    input_func_spec = pe.Node(nipype.IdentityInterface(fields=['fmri_file']),
                              name='input_func_spec')
    hcp_spec = pe.Node(nipype.IdentityInterface(
        fields=['t1w', 't2w', 't1w_acpc_xfm', 't2w_acpc_xfm',
                't2w_to_t1w_xfm', 't1w_distortion', 't2w_distortion',
                'bias_field', 't1w_res', 't2w_res', 't2w_dc', 't1w_res_brain',
                't2w_res_brain', 'wmparc', 'wmparc_1mm', 'fs2standard',
                'standard2fs']),
        name='hcp_spec'
    )

    # connect input DAIC files
    input_spec.inputs.t1w_file = inputs['t1w_file']
    input_spec.inputs.t2w_file = inputs['t2w_file']
    input_spec.inputs.mask_file = inputs['mask_file']
    input_func_spec.iterables = ('fmri_file', inputs['fmri_files'] + inputs[
        'rs_files'])

    # setup HCP directory specification
    output_dir = os.path.abspath(inputs['output_dir'])
    subjects_dir = os.path.join(output_dir, 'T1w')
    freesurfer_dir = os.path.join(subjects_dir, subject_id)
    native_xfms_dir = os.path.join(subjects_dir, 'xfms')
    t2w_dir = os.path.join(output_dir, 'T2w')
    t2w_xfms_dir = os.path.join(t2w_dir, 'xfms')
    nonlinear_dir = os.path.join(output_dir, 'MNINonLinear')
    results_dir = os.path.join(nonlinear_dir, 'Results')
    nonlin_xfms_dir = os.path.join(nonlinear_dir, 'xfms')
    fs_transforms = os.path.join(freesurfer_dir, 'mri', 'transforms')

    # create directory tree
    for directory in [output_dir, subjects_dir, native_xfms_dir, t2w_dir,
                      t2w_xfms_dir, results_dir, nonlin_xfms_dir]:
        os.makedirs(directory, exist_ok=True)
    if not os.path.isdir(freesurfer_dir):
        shutil.copytree(inputs['fs_source_dir'], freesurfer_dir)
    os.makedirs(fs_transforms, exist_ok=True)

    def get_name(x):
        boldid = re.compile(r'(BOLD[0-9]*).*')
        number = re.compile(r'rsBOLD_data_scan([0-9]*).*')
        basename = os.path.basename(x).split('.')[0]
        match = boldid.match(basename)
        if match is not None:
            name = match.groups()[0]
        else:
            name = 'fcproc%s' % number.match(basename).groups()[0]
        taskname = 'task-%s' % name
        return taskname

    fmrinames = map(get_name, inputs['fmri_files'] + inputs['rs_files'])
    for fmriname in fmrinames:
        directory = os.path.join(results_dir, fmriname)
        os.makedirs(directory, exist_ok=True)

    # HCP filename specification
    hcp_spec.inputs.t1w = os.path.join(subjects_dir, 'T1w.nii.gz')
    hcp_spec.inputs.t2w = os.path.join(t2w_dir, 'T2w.nii.gz')
    hcp_spec.inputs.t1w_acpc_xfm = os.path.join(native_xfms_dir, 'acpc.mat')
    hcp_spec.inputs.t2w_acpc_xfm = os.path.join(t2w_xfms_dir, 'acpc.mat')
    hcp_spec.inputs.t2w_to_t1w_xfm = os.path.join(fs_transforms, 'T2wtoT1w.mat')
    hcp_spec.inputs.t1w_distortion = os.path.join(
        native_xfms_dir, 'T1w_dc.nii.gz')
    hcp_spec.inputs.t2w_distortion = os.path.join(
        native_xfms_dir, 'T2w_reg_dc.nii.gz')
    hcp_spec.inputs.bias_field = os.path.join(
        subjects_dir, 'BiasField_acpc_dc.nii.gz')
    hcp_spec.inputs.t1w_res = os.path.join(
        subjects_dir, 'T1w_acpc_dc_restore.nii.gz')
    hcp_spec.inputs.t1w_res_brain = os.path.join(
        subjects_dir, 'T1w_acpc_dc_restore_brain.nii.gz')
    hcp_spec.inputs.t2w_res = os.path.join(
        subjects_dir, 'T2w_acpc_dc_restore.nii.gz')
    hcp_spec.inputs.t2w_dc = os.path.join(
        subjects_dir, 'T2w_acpc_dc.nii.gz')
    hcp_spec.inputs.t2w_res_brain = os.path.join(
        subjects_dir, 'T2w_acpc_dc_restore_brain.nii.gz')
    hcp_spec.inputs.wmparc = os.path.join(subjects_dir, 'wmparc.nii.gz')
    hcp_spec.inputs.wmparc_1mm = os.path.join(subjects_dir, 'wmparc_1mm.nii.gz')
    hcp_spec.inputs.warp = os.path.join(nonlin_xfms_dir, 'fs2standard.nii.gz')

    ## create workflow components

    # utility
    def rename_func(in_file, path):
        # conditional renaming for func, fcpreproc data handled separately
        import os
        import re
        import shutil
        func_pattern = re.compile(r'(?P<name>BOLD[0-9]*).*')
        fc_pattern = re.compile(r'rsBOLD_data_scan(?P<number>[0-9]*).*')
        basename = os.path.basename(in_file)
        name = func_pattern.match(basename)
        number = fc_pattern.match(basename)
        if name:
            taskname = 'task-%s' % name.groupdict()['name']
        elif number:
            taskname = 'task-fcproc%s' % number.groupdict()['number']
        out_file = os.path.join(path, 'MNINonLinear', 'Results',
                               taskname, taskname + '.nii.gz')
        shutil.copyfile(in_file, out_file)
        return out_file
    rename = pe.Node(utility.Function(input_names=['in_file', 'path'],
                                      output_names=['out_file'],
                                      function=rename_func),
                     name='rename')
    rename.inputs.path = os.path.abspath(output_dir)
    copy_str = 'def f(src, dest): shutil.copy(src, dest); return dest'
    copy = pe.Node(
        utility.Function(
            input_names=['src', 'dest'], output_names=['dest'],
            imports=['import shutil'], function_str=copy_str
        ),
        name='copy'
    )
    basename_str = 'def f(path): return osp.basename(path).split(".")[0]'
    basename = pe.Node(
        utility.Function(
            input_names=['path'], output_names=['out_name'],
            imports=['import os.path as osp'], function_str=basename_str
        ),
        name='basename'
    )

    # mri convert
    convert_t1 = pe.Node(freesurfer.MRIConvert(out_type='niigz'),
                         name='convert_t1')
    convert_t2 = convert_t1.clone(name='convert_t2')
    convert_mask = convert_t1.clone(name='convert_mask')
    convert_func = pe.Node(freesurfer.MRIConvert(out_type='niigz'),
                           name='convert_func')

    # acpc alignment
    calc_acpc = pe.Node(
        fsl.FLIRT(reference=reference, dof=6, interp='spline'),
        name='calc_acpc'
    )
    copy_xfm = copy.clone(name='copy_xfm')
    apply_acpc = pe.Node(
        fsl.FLIRT(reference=reference, apply_xfm=True, interp='spline'),
        name='apply_acpc'
    )
    copy_t2w_res = copy.clone(name='copy_t2w_res')
    apply_acpc_nn = pe.Node(
        fsl.FLIRT(reference=reference, apply_xfm=True,
                  interp='nearestneighbour'),
        name='apply_acpc_nn'
    )
    mask_t1w = pe.Node(fsl.ApplyMask(), name='mask_t1w')
    mask_t2w = pe.Node(fsl.ApplyMask(), name='mask_t2w')
    resample_mask = pe.Node(
        fsl.FLIRT(apply_isoxfm=1, interp='nearestneighbour'),
        name='resample_mask'
    )

    # functional transforms
    select_first = pe.JoinNode(
        utility.Select(index=[0]),
        joinsource='input_func_spec',
        joinfield='inlist',
        name='select_first'
    )
    fs_to_fmri = pe.Node(fsl.FLIRT(cost='mutualinfo', dof=6), name='fs_to_func')
    fmri_to_fs = pe.Node(fsl.ConvertXFM(invert_xfm=True), name='func_to_fs')
    concat_warps = pe.Node(
        fsl.ConvertWarp(relwarp=True, out_relwarp=True, reference=reference2mm),
        name='concat_warps'
    )
    warp_mask = pe.Node(
        fsl.ApplyWarp(ref_file=reference2mm, interp='nn', relwarp=True),
        name='warp_mask'
    )
    mask_func = pe.Node(fsl.ApplyMask(), name='apply_mask')
    apply_warpfield = pe.Node(
        fsl.ApplyWarp(ref_file=reference2mm, interp='spline', relwarp=True),
        name='apply_warpfield'
    )
    timeseries_mean = pe.Node(
        fsl.MeanImage(dimension='T'), name='timeseries_mean'
    )
    renamesb = pe.Node(
        utility.Rename(parse_string=r'task-(?P<name>.*)_.*',
                       format_string='%(path)s/MNINonLinear/Results/'
                                     'task-%(name)s/task-%(name)s_SBRef.nii.gz',
                       path=os.path.abspath(output_dir)),
        name='renamesb'
    )
    renamesb.inputs.path = os.path.abspath(output_dir)

    # identity transforms
    identity_matrix = pe.Node(fsl.preprocess.FLIRT(),
                              name='identity_matrix')  # t1 -> t1 matrix
    zeroes = pe.Node(fsl.BinaryMaths(operation='mul', operand_value=0),
                     name='zeroes')
    repeat_zeroes = pe.Node(utility.Merge(3), name='repeat_zeroes')
    identity_warpfield = pe.Node(fsl.Merge(dimension='t'),
                                 name='identity_warpfield')  # 3D warp in t-dim
    identity_biasfield = pe.Node(fsl.BinaryMaths(operation='add',
                                                 operand_value=1),
                                 name='identity_biasfield')  # bias 1 everywhere
    copy_warpfield = copy.clone(name='copy_warpfield')

    # hcp nodes
    postfreesurfer, fmrisurface = create_hcp_nodes(output_dir, subject_id)
    executivesummary = pe.JoinNode(
        ExecutiveSummary(in_unprocessed=os.path.abspath(output_dir),
                         in_processed=os.path.abspath(output_dir),
                         in_subjectid=subject_id,
                         in_executivesummary='executivesummary'),
        joinfield='in_files',
        joinsource='input_func_spec',
        name='executivesummary'
    )

    ## workflow DAG
    wf = pe.Workflow(name=inputs['workflow_name'], base_dir=inputs['base_dir'])

    # convert to nii.gz
    wf.connect(
        [(input_spec, convert_t1, [('t1w_file', 'in_file')]),
         (input_spec, convert_t2, [('t2w_file', 'in_file')]),
         (input_spec, convert_mask, [('mask_file', 'in_file')])]
    )
    # rigid align to acpc/MNI, apply mask
    wf.connect(
        [(convert_t1, calc_acpc, [('out_file', 'in_file')]),
         (calc_acpc, copy_xfm, [('out_matrix_file', 'src')]),
         (copy_xfm, apply_acpc, [('dest', 'in_matrix_file')]),
         (calc_acpc, apply_acpc_nn, [('out_matrix_file', 'in_matrix_file')]),
         (convert_t2, apply_acpc, [('out_file', 'in_file')]),
         (apply_acpc, copy_t2w_res, [('out_file', 'src')]),
         (convert_mask, apply_acpc_nn, [('out_file', 'in_file')]),
         (calc_acpc, mask_t1w, [('out_file', 'in_file')]),
         (apply_acpc_nn, mask_t1w, [('out_file', 'mask_file')]),
         (apply_acpc, mask_t2w, [('out_file', 'in_file')]),
         (apply_acpc_nn, mask_t2w, [('out_file', 'mask_file')]),
         (apply_acpc_nn, resample_mask, [('out_file', 'in_file'),
                                         ('out_file', 'reference')])]
    )
    # create identity transformations for data flow
    wf.connect(
        [(calc_acpc, identity_matrix, [('out_file', 'in_file'),
                                       ('out_file', 'reference')]),
         (calc_acpc, zeroes, [('out_file', 'in_file')]),
         (zeroes, repeat_zeroes, [('out_file', 'in1'), ('out_file', 'in2'),
                                  ('out_file', 'in3')]),
         (repeat_zeroes, identity_warpfield, [('out', 'in_files')]),
         (zeroes, identity_biasfield, [('out_file', 'in_file')]),
         (identity_warpfield, copy_warpfield, [('merged_file', 'src')])]
    )
    # connect postfreesurfer
    # there are more implicit connections, but these suffice dependency graph
    wf.connect(
        [(calc_acpc, postfreesurfer, [('out_file', 'in_t1')]),
         (copy_t2w_res, postfreesurfer, [('dest', 'in_t1_dc')]),
         (identity_warpfield, postfreesurfer, [('merged_file', 'in_warpfield')]),
         (identity_biasfield, postfreesurfer, [('out_file', 'in_biasfield')]),
         (copy_warpfield, postfreesurfer, [('dest', 'in_t2warpfield')]),
         (resample_mask, postfreesurfer, [('out_file', 'in_wmparc')]),
         (mask_t1w, postfreesurfer, [('out_file', 'in_t1brain')]),
         (mask_t2w, postfreesurfer, [('out_file', 'in_t2brain')]),
         (identity_matrix, postfreesurfer, [('out_file', 'in_t2_to_t1')])]
    )
    # transform functionals to final space
    # @TODO leverage SELECT and RENAME utilities with Don's information. In
    #  the interim, functional data is simply named as task-BOLD##
    wf.connect(
        [(input_func_spec, convert_func, [('fmri_file', 'in_file')]),
         (convert_func, select_first, [('out_file', 'inlist')]),
         (convert_t1, fs_to_fmri, [('out_file', 'in_file')]),
         (select_first, fs_to_fmri, [('out', 'reference')]),
         (fs_to_fmri, fmri_to_fs, [('out_matrix_file', 'in_file')]),
         (postfreesurfer, concat_warps, [('out_warp', 'warp1')]),
         (fmri_to_fs, concat_warps, [('out_file', 'premat')]),
         (concat_warps, apply_warpfield, [('out_file', 'field_file')]),
         (convert_func, apply_warpfield, [('out_file', 'in_file')]),
         (convert_mask, warp_mask, [('out_file', 'in_file')]),
         (postfreesurfer, warp_mask, [('out_warp', 'field_file')]),
         (warp_mask, mask_func, [('out_file', 'mask_file')]),
         (apply_warpfield, mask_func, [('out_file', 'in_file')])]
    )
    # connect fmrisurface
    # there are more implicit connections, but these suffice dependency graph
    wf.connect(
        [(mask_func, rename, [('out_file', 'in_file')]),
         (rename, timeseries_mean, [('out_file', 'in_file')]),
         (rename, fmrisurface, [('out_file', 'in_fmri')]),
         (rename, basename, [('out_file', 'path')]),
         (basename, fmrisurface, [('out_name', 'fmriname')]),
         (timeseries_mean, renamesb, [('out_file', 'in_file')]),
         (renamesb, fmrisurface, [('out_file', 'in_sbref')])]
    )
    # connect executivesummary
    wf.connect(
        [(fmrisurface, executivesummary, [('out_file', 'in_files')])]
    )

    # draw workflow: output/daic2hcp/graph.png
    wf.write_graph(graph2use='orig', dotfilename='graph.dot')

    # connect intermediates to hcp filename specifications (not shown in graph)
    wf.connect(
        [(hcp_spec, convert_t1, [('t1w', 'out_file')]),
         (hcp_spec, convert_t2, [('t2w', 'out_file')]),
         (hcp_spec, convert_mask, [('wmparc', 'out_file')]),
         (hcp_spec, calc_acpc, [('t1w_acpc_xfm', 'out_matrix_file')]),
         (hcp_spec, identity_matrix, [('t2w_to_t1w_xfm', 'out_matrix_file')]),
         (hcp_spec, identity_warpfield, [('t1w_distortion', 'merged_file')]),
         (hcp_spec, identity_biasfield, [('bias_field', 'out_file')]),
         (hcp_spec, copy_warpfield, [('t2w_distortion', 'dest')]),
         (hcp_spec, calc_acpc, [('t1w_res', 'out_file')]),
         (hcp_spec, apply_acpc, [('t2w_res', 'out_file')]),
         (hcp_spec, copy_xfm, [('t2w_acpc_xfm', 'dest')]),
         (hcp_spec, copy_t2w_res, [('t2w_dc', 'dest')]),
         (hcp_spec, mask_t1w, [('t1w_res_brain', 'out_file')]),
         (hcp_spec, mask_t2w, [('t2w_res_brain', 'out_file')]),
         (hcp_spec, resample_mask, [('wmparc_1mm', 'out_file')]),
         (hcp_spec, concat_warps, [('warp', 'out_file')])]
    )

    return wf