Exemplo n.º 1
0
def _reorient(unifized_anat_file,
              unbiased_modality_file,
              write_dir,
              modality_name='modality',
              terminal_output='allatonce',
              caching=False,
              verbose=True,
              environ=None):
    """
    Reorientation of the subject's anatomical image to the modality.

    Parameters
    ----------
    modality_name : str, optional
        Name to be used in the transform filename
    caching : bool, optional
        Wether or not to use caching.
    verbose : bool, optional
        If True, all steps are verbose. Note that caching implies some
        verbosity in any case.

    Returns
    -------
    2-tuple of str : Path to the reoriented anatomical image and to the
        transform from anat to modality.
    """
    if environ is None:
        environ = {'AFNI_DECONFLICT': 'OVERWRITE'}

    if caching:
        memory = Memory(write_dir)
        catmatvec = memory.cache(afni.CatMatvec)
    else:
        catmatvec = afni.CatMatvec().run

    registered_anat_oblique_file, mat_file =\
        _warp(unifized_anat_file, unbiased_modality_file, write_dir,
              caching=caching, verbose=verbose,
              terminal_output=terminal_output,
              environ=environ)
    transform_file = fname_presuffix(
        registered_anat_oblique_file,
        suffix='_anat_to_{}.aff12.1D'.format(modality_name),
        use_ext=False)
    _ = catmatvec(in_file=[(mat_file, 'ONELINE')],
                  oneline=True,
                  out_file=transform_file,
                  environ=environ)

    # Remove the intermediate outputs
    if not caching:
        os.remove(mat_file)

    return registered_anat_oblique_file, transform_file
Exemplo n.º 2
0
def _func_to_template(func_coreg_filename,
                      template_filename,
                      write_dir,
                      func_to_anat_oned_filename,
                      anat_to_template_oned_filename,
                      anat_to_template_warp_filename,
                      voxel_size=None,
                      caching=False,
                      verbose=True):
    """ Applies successive transforms to coregistered functional to put it in
    template space.

    Parameters
    ----------
    coreg_func_filename : str
        Path to functional volume, coregistered to a common space with the
        anatomical volume.

    template_filename : str
        Template to register the functional to.

    func_to_anat_oned_filename : str
        Path to the affine 1D transform from functional to coregistration
        space.

    anat_to_template_oned_filename : str
        Path to the affine 1D transform from anatomical to template space.

    anat_to_template_warp_filename : str
        Path to the warp transform from anatomical to template space.

    voxel_size : 3-tuple of floats, optional
        Voxel size of the registered functional, in mm.

    caching : bool, optional
        Wether or not to use caching.

    verbose : bool, optional
        If True, all steps are verbose. Note that caching implies some
        verbosity in any case.
    """
    environ = {}
    if verbose:
        terminal_output = 'allatonce'
    else:
        terminal_output = 'none'

    if caching:
        memory = Memory(write_dir)
        resample = memory.cache(afni.Resample)
        catmatvec = memory.cache(afni.CatMatvec)
        allineate = memory.cache(afni.Allineate)
        warp_apply = memory.cache(afni.NwarpApply)
        for step in [resample, allineate, warp_apply]:
            step.interface().set_default_terminal_output(terminal_output)
    else:
        resample = afni.Resample(terminal_output=terminal_output).run
        catmatvec = afni.CatMatvec().run
        allineate = afni.Allineate(terminal_output=terminal_output).run
        warp_apply = afni.NwarpApply(terminal_output=terminal_output).run
        environ['AFNI_DECONFLICT'] = 'OVERWRITE'

    current_dir = os.getcwd()
    os.chdir(write_dir)  # XXX to remove
    normalized_filename = fname_presuffix(func_coreg_filename,
                                          suffix='_normalized')
    if voxel_size is None:
        func_template_filename = template_filename
    else:
        out_resample = resample(in_file=template_filename,
                                voxel_size=voxel_size,
                                outputtype='NIFTI_GZ',
                                environ=environ)
        func_template_filename = out_resample.outputs.out_file

    if anat_to_template_warp_filename is None:
        affine_transform_filename = fname_presuffix(func_to_anat_oned_filename,
                                                    suffix='_to_template')
        _ = catmatvec(in_file=[(anat_to_template_oned_filename, 'ONELINE'),
                               (func_to_anat_oned_filename, 'ONELINE')],
                      oneline=True,
                      out_file=affine_transform_filename,
                      environ=environ)
        _ = allineate(in_file=func_coreg_filename,
                      master=func_template_filename,
                      in_matrix=affine_transform_filename,
                      out_file=normalized_filename,
                      environ=environ)
    else:
        warp = "'{0} {1} {2}'".format(anat_to_template_warp_filename,
                                      anat_to_template_oned_filename,
                                      func_to_anat_oned_filename)

        _ = warp_apply(in_file=func_coreg_filename,
                       master=func_template_filename,
                       warp=warp,
                       out_file=normalized_filename,
                       environ=environ)
    os.chdir(current_dir)
    return normalized_filename
Exemplo n.º 3
0
def coregister_fmri_session(session_data,
                            t_r,
                            write_dir,
                            brain_volume,
                            use_rats_tool=True,
                            slice_timing=True,
                            prior_rigid_body_registration=False,
                            caching=False,
                            voxel_size_x=.1,
                            voxel_size_y=.1,
                            verbose=True,
                            **environ_kwargs):
    """
    Coregistration of the subject's functional and anatomical images.
    The functional volume is aligned to the anatomical, first with a rigid body
    registration and then on a per-slice basis (only a fine correction, this is
    mostly for correction of EPI distortion).


    Parameters
    ----------
    session_data : sammba.registration.SessionData
        Single animal data, giving paths to its functional and anatomical
        image, as well as it identifier.

    t_r : float
        Repetition time for the EPI, in seconds.

    write_dir : str
        Directory to save the output and temporary images.

    brain_volume : int
        Volume of the brain in mm3 used for brain extraction.
        Typically 400 for mouse and 1800 for rat.

    use_rats_tool : bool, optional
        If True, brain mask is computed using RATS Mathematical Morphology.
        Otherwise, a histogram-based brain segmentation is used.

    prior_rigid_body_registration : bool, optional
        If True, a rigid-body registration of the anat to the func is performed
        prior to the warp. Useful if the images headers have missing/wrong
        information.

    voxel_size_x : float, optional
        Resampling resolution for the x-axis, in mm.

    voxel_size_y : float, optional
        Resampling resolution for the y-axis, in mm.

    caching : bool, optional
        Wether or not to use caching.

    verbose : bool, optional
        If True, all steps are verbose. Note that caching implies some
        verbosity in any case.

    environ_kwargs : extra arguments keywords
        Extra arguments keywords, passed to interfaces environ variable.

    Returns
    -------
    the same sequence with each animal_data updated: the following attributes
    are added
        - `output_dir_` : str
                          Path to the output directory.
        - `coreg_func_` : str
                          Path to paths to the coregistered functional image.
        - `coreg_anat_` : str
                          Path to paths to the coregistered functional image.
        - `coreg_transform_` : str
                               Path to the transform from anat to func.

    Notes
    -----
    If `use_rats_tool` is turned on, RATS tool is used for brain extraction
    and has to be cited. For more information, see
    `RATS <http://www.iibi.uiowa.edu/content/rats-overview/>`_
    """
    func_filename = session_data.func
    anat_filename = session_data.anat

    environ = {'AFNI_DECONFLICT': 'OVERWRITE'}
    for (key, value) in environ_kwargs.items():
        environ[key] = value

    if verbose:
        terminal_output = 'allatonce'
    else:
        terminal_output = 'none'

    if use_rats_tool:
        if segmentation.interfaces.Info().version() is None:
            raise ValueError('Can not locate RATS')
        else:
            ComputeMask = segmentation.MathMorphoMask
    else:
        ComputeMask = segmentation.HistogramMask

    if ants.base.Info().version is None:
        raise ValueError('Can not locate ANTS')

    if caching:
        memory = Memory(write_dir)
        tshift = memory.cache(afni.TShift)
        clip_level = memory.cache(afni.ClipLevel)
        volreg = memory.cache(afni.Volreg)
        allineate = memory.cache(afni.Allineate)
        tstat = memory.cache(afni.TStat)
        compute_mask = memory.cache(ComputeMask)
        calc = memory.cache(afni.Calc)
        allineate = memory.cache(afni.Allineate)
        allineate2 = memory.cache(afni.Allineate)
        unifize = memory.cache(afni.Unifize)
        bias_correct = memory.cache(ants.N4BiasFieldCorrection)
        catmatvec = memory.cache(afni.CatMatvec)
        warp = memory.cache(afni.Warp)
        resample = memory.cache(afni.Resample)
        slicer = memory.cache(afni.ZCutUp)
        warp_apply = memory.cache(afni.NwarpApply)
        qwarp = memory.cache(afni.Qwarp)
        merge = memory.cache(afni.Zcat)
        copy_geom = memory.cache(fsl.CopyGeom)
        overwrite = False
        for step in [
                tshift, volreg, allineate, allineate2, tstat, compute_mask,
                calc, unifize, resample, slicer, warp_apply, qwarp, merge
        ]:
            step.interface().set_default_terminal_output(terminal_output)
    else:
        tshift = afni.TShift(terminal_output=terminal_output).run
        clip_level = afni.ClipLevel().run
        volreg = afni.Volreg(terminal_output=terminal_output).run
        allineate = afni.Allineate(terminal_output=terminal_output).run
        allineate2 = afni.Allineate(terminal_output=terminal_output
                                    ).run  # TODO: remove after fixed bug
        tstat = afni.TStat(terminal_output=terminal_output).run
        compute_mask = ComputeMask().run
        calc = afni.Calc(terminal_output=terminal_output).run
        unifize = afni.Unifize(terminal_output=terminal_output).run
        bias_correct = ants.N4BiasFieldCorrection(
            terminal_output=terminal_output).run
        catmatvec = afni.CatMatvec().run
        warp = afni.Warp().run
        resample = afni.Resample(terminal_output=terminal_output).run
        slicer = afni.ZCutUp(terminal_output=terminal_output).run
        warp_apply = afni.NwarpApply(terminal_output=terminal_output).run
        qwarp = afni.Qwarp(terminal_output=terminal_output).run
        merge = afni.Zcat(terminal_output=terminal_output).run
        copy_geom = fsl.CopyGeom(terminal_output=terminal_output).run
        overwrite = True

    session_data._check_inputs()
    output_dir = os.path.join(os.path.abspath(write_dir),
                              session_data.animal_id)
    session_data._set_output_dir_(output_dir)
    current_dir = os.getcwd()
    os.chdir(output_dir)
    output_files = []

    #######################################
    # Correct functional for slice timing #
    #######################################
    if slice_timing:
        out_tshift = tshift(in_file=func_filename,
                            outputtype='NIFTI_GZ',
                            tpattern='altplus',
                            tr=str(t_r),
                            environ=environ)
        func_filename = out_tshift.outputs.out_file
        output_files.append(func_filename)

    ################################################
    # Register functional volumes to the first one #
    ################################################
    # XXX why do you need a thresholded image ?
    out_clip_level = clip_level(in_file=func_filename)
    out_calc_threshold = calc(in_file_a=func_filename,
                              expr='ispositive(a-{0}) * a'.format(
                                  out_clip_level.outputs.clip_val),
                              outputtype='NIFTI_GZ')
    thresholded_filename = out_calc_threshold.outputs.out_file

    out_volreg = volreg(  # XXX dfile not saved
        in_file=thresholded_filename,
        outputtype='NIFTI_GZ',
        environ=environ,
        oned_file=fname_presuffix(thresholded_filename,
                                  suffix='Vr.1Dfile.1D',
                                  use_ext=False),
        oned_matrix_save=fname_presuffix(thresholded_filename,
                                         suffix='Vr.aff12.1D',
                                         use_ext=False))

    # Apply the registration to the whole head
    out_allineate = allineate(in_file=func_filename,
                              master=func_filename,
                              in_matrix=out_volreg.outputs.oned_matrix_save,
                              out_file=fname_presuffix(func_filename,
                                                       suffix='Av'),
                              environ=environ)

    # 3dAllineate removes the obliquity. This is not a good way to readd it as
    # removes motion correction info in the header if it were an AFNI file...as
    # it happens it's NIfTI which does not store that so irrelevant!
    out_copy_geom = copy_geom(dest_file=out_allineate.outputs.out_file,
                              in_file=out_volreg.outputs.out_file)

    allineated_filename = out_copy_geom.outputs.out_file

    # Create a (hopefully) nice mean image for use in the registration
    out_tstat = tstat(in_file=allineated_filename,
                      args='-mean',
                      outputtype='NIFTI_GZ',
                      environ=environ)

    # Update outputs
    output_files.extend([
        thresholded_filename, out_volreg.outputs.oned_matrix_save,
        out_volreg.outputs.out_file, out_volreg.outputs.md1d_file,
        allineated_filename, out_tstat.outputs.out_file
    ])

    ###########################################
    # Corret anat and func for intensity bias #
    ###########################################
    # Correct the functional average for intensities bias
    out_bias_correct = bias_correct(input_image=out_tstat.outputs.out_file)
    unbiased_func_filename = out_bias_correct.outputs.output_image

    # Bias correct the antomical image
    out_unifize = unifize(in_file=anat_filename,
                          outputtype='NIFTI_GZ',
                          environ=environ)
    unbiased_anat_filename = out_unifize.outputs.out_file

    # Update outputs
    output_files.extend([unbiased_func_filename, unbiased_anat_filename])

    #############################################
    # Rigid-body registration anat -> mean func #
    #############################################
    if prior_rigid_body_registration:
        # Mask the mean functional volume outside the brain.
        out_clip_level = clip_level(in_file=unbiased_func_filename)
        out_compute_mask_func = compute_mask(
            in_file=unbiased_func_filename,
            volume_threshold=brain_volume,
            intensity_threshold=int(out_clip_level.outputs.clip_val))
        out_cacl_func = calc(in_file_a=unbiased_func_filename,
                             in_file_b=out_compute_mask_func.outputs.out_file,
                             expr='a*b',
                             outputtype='NIFTI_GZ',
                             environ=environ)

        # Mask the anatomical volume outside the brain.
        out_clip_level = clip_level(in_file=unbiased_anat_filename)
        out_compute_mask_anat = compute_mask(
            in_file=unbiased_anat_filename,
            volume_threshold=brain_volume,
            intensity_threshold=int(out_clip_level.outputs.clip_val))
        out_cacl_anat = calc(in_file_a=unbiased_anat_filename,
                             in_file_b=out_compute_mask_anat.outputs.out_file,
                             expr='a*b',
                             outputtype='NIFTI_GZ',
                             environ=environ)

        # Compute the transformation from functional to anatomical brain
        # XXX: why in this sense
        out_allineate = allineate2(
            in_file=out_cacl_func.outputs.out_file,
            reference=out_cacl_anat.outputs.out_file,
            out_matrix=fname_presuffix(out_cacl_func.outputs.out_file,
                                       suffix='_shr.aff12.1D',
                                       use_ext=False),
            center_of_mass='',
            warp_type='shift_rotate',
            out_file=fname_presuffix(out_cacl_func.outputs.out_file,
                                     suffix='_shr'),
            environ=environ)
        rigid_transform_file = out_allineate.outputs.out_matrix
        output_files.extend([
            out_compute_mask_func.outputs.out_file,
            out_cacl_func.outputs.out_file,
            out_compute_mask_anat.outputs.out_file,
            out_cacl_anat.outputs.out_file, rigid_transform_file,
            out_allineate.outputs.out_file
        ])

        # apply the inverse transform to register the anatomical to the func
        catmatvec_out_file = fname_presuffix(rigid_transform_file,
                                             suffix='INV')
        out_catmatvec = catmatvec(in_file=[(rigid_transform_file, 'I')],
                                  oneline=True,
                                  out_file=catmatvec_out_file)
        output_files.append(out_catmatvec.outputs.out_file)
        out_allineate = allineate(in_file=unbiased_anat_filename,
                                  master=unbiased_func_filename,
                                  in_matrix=out_catmatvec.outputs.out_file,
                                  out_file=fname_presuffix(
                                      unbiased_anat_filename,
                                      suffix='_shr_in_func_space'),
                                  environ=environ)
        allineated_anat_filename = out_allineate.outputs.out_file
        output_files.append(allineated_anat_filename)
    else:
        allineated_anat_filename = unbiased_anat_filename

    ############################################
    # Nonlinear registration anat -> mean func #
    ############################################
    # 3dWarp doesn't put the obliquity in the header, so do it manually
    # This step generates one file per slice and per time point, so we are
    # making sure they are removed at the end
    out_warp = warp(in_file=allineated_anat_filename,
                    oblique_parent=unbiased_func_filename,
                    interp='quintic',
                    gridset=unbiased_func_filename,
                    outputtype='NIFTI_GZ',
                    verbose=True,
                    environ=environ)
    registered_anat_filename = out_warp.outputs.out_file
    registered_anat_oblique_filename = fix_obliquity(registered_anat_filename,
                                                     unbiased_func_filename,
                                                     verbose=verbose)

    # Concatenate all the anat to func tranforms
    mat_filename = fname_presuffix(registered_anat_filename,
                                   suffix='_warp.mat',
                                   use_ext=False)
    # XXX Handle this correctly according to caching
    if not os.path.isfile(mat_filename):
        np.savetxt(mat_filename, [out_warp.runtime.stdout], fmt='%s')
        output_files.append(mat_filename)

    transform_filename = fname_presuffix(registered_anat_filename,
                                         suffix='_anat_to_func.aff12.1D',
                                         use_ext=False)
    if prior_rigid_body_registration:
        _ = catmatvec(in_file=[(mat_filename, 'ONELINE'),
                               (rigid_transform_file, 'ONELINE')],
                      oneline=True,
                      out_file=transform_filename)
    else:
        _ = catmatvec(in_file=[(mat_filename, 'ONELINE')],
                      oneline=True,
                      out_file=transform_filename)

    ##################################################
    # Per-slice non-linear registration func -> anat #
    ##################################################
    # Slice anatomical image
    anat_img = nibabel.load(registered_anat_oblique_filename)
    anat_n_slices = anat_img.header.get_data_shape()[2]
    sliced_registered_anat_filenames = []
    for slice_n in range(anat_n_slices):
        out_slicer = slicer(in_file=registered_anat_oblique_filename,
                            keep='{0} {0}'.format(slice_n),
                            out_file=fname_presuffix(
                                registered_anat_oblique_filename,
                                suffix='Sl%d' % slice_n),
                            environ=environ)
        oblique_slice = fix_obliquity(out_slicer.outputs.out_file,
                                      registered_anat_oblique_filename,
                                      verbose=verbose)
        sliced_registered_anat_filenames.append(oblique_slice)

    # Slice mean functional
    sliced_bias_corrected_filenames = []
    img = nibabel.load(func_filename)
    n_slices = img.header.get_data_shape()[2]
    for slice_n in range(n_slices):
        out_slicer = slicer(in_file=unbiased_func_filename,
                            keep='{0} {0}'.format(slice_n),
                            out_file=fname_presuffix(unbiased_func_filename,
                                                     suffix='Sl%d' % slice_n),
                            environ=environ)
        oblique_slice = fix_obliquity(out_slicer.outputs.out_file,
                                      unbiased_func_filename,
                                      verbose=verbose)
        sliced_bias_corrected_filenames.append(oblique_slice)

    # Below line is to deal with slices where there is no signal (for example
    # rostral end of some anatomicals)

    # The inverse warp frequently fails, Resampling can help it work better
    # XXX why specifically .1 in voxel_size ?
    voxel_size_z = anat_img.header.get_zooms()[2]
    resampled_registered_anat_filenames = []
    for sliced_registered_anat_filename in sliced_registered_anat_filenames:
        out_resample = resample(in_file=sliced_registered_anat_filename,
                                voxel_size=(voxel_size_x, voxel_size_y,
                                            voxel_size_z),
                                outputtype='NIFTI_GZ',
                                environ=environ)
        resampled_registered_anat_filenames.append(
            out_resample.outputs.out_file)

    resampled_bias_corrected_filenames = []
    for sliced_bias_corrected_filename in sliced_bias_corrected_filenames:
        out_resample = resample(in_file=sliced_bias_corrected_filename,
                                voxel_size=(voxel_size_x, voxel_size_y,
                                            voxel_size_z),
                                outputtype='NIFTI_GZ',
                                environ=environ)
        resampled_bias_corrected_filenames.append(
            out_resample.outputs.out_file)

    # single slice non-linear functional to anatomical registration
    warped_slices = []
    warp_filenames = []
    for (resampled_bias_corrected_filename,
         resampled_registered_anat_filename) in zip(
             resampled_bias_corrected_filenames,
             resampled_registered_anat_filenames):
        warped_slice = fname_presuffix(resampled_bias_corrected_filename,
                                       suffix='_qw')
        out_qwarp = qwarp(
            in_file=resampled_bias_corrected_filename,
            base_file=resampled_registered_anat_filename,
            iwarp=True,  # XXX: is this necessary
            noneg=True,
            blur=[0],
            nmi=True,
            noXdis=True,
            allineate=True,
            allineate_opts='-parfix 1 0 -parfix 2 0 -parfix 3 0 '
            '-parfix 4 0 -parfix 5 0 -parfix 6 0 '
            '-parfix 7 0 -parfix 9 0 '
            '-parfix 10 0 -parfix 12 0',
            out_file=warped_slice,
            environ=environ)
        warped_slices.append(out_qwarp.outputs.warped_source)
        warp_filenames.append(out_qwarp.outputs.source_warp)
        output_files.append(out_qwarp.outputs.base_warp)
        # There are files geenrated by the allineate option
        output_files.extend([
            fname_presuffix(out_qwarp.outputs.warped_source, suffix='_Allin'),
            fname_presuffix(out_qwarp.outputs.warped_source,
                            suffix='_Allin.nii',
                            use_ext=False),
            fname_presuffix(out_qwarp.outputs.warped_source,
                            suffix='_Allin.aff12.1D',
                            use_ext=False)
        ])

    # Resample the mean volume back to the initial resolution,
    voxel_size = nibabel.load(unbiased_func_filename).header.get_zooms()
    resampled_warped_slices = []
    for warped_slice in warped_slices:
        out_resample = resample(in_file=warped_slice,
                                voxel_size=voxel_size,
                                outputtype='NIFTI_GZ',
                                environ=environ)
        resampled_warped_slices.append(out_resample.outputs.out_file)

    # fix the obliquity
    resampled_warped_slices_oblique = []
    for (sliced_registered_anat_filename,
         resampled_warped_slice) in zip(sliced_registered_anat_filenames,
                                        resampled_warped_slices):
        oblique_slice = fix_obliquity(resampled_warped_slice,
                                      sliced_registered_anat_filename,
                                      verbose=verbose)
        resampled_warped_slices_oblique.append(oblique_slice)

    # slice functional
    sliced_func_filenames = []
    for slice_n in range(n_slices):
        out_slicer = slicer(in_file=allineated_filename,
                            keep='{0} {0}'.format(slice_n),
                            out_file=fname_presuffix(allineated_filename,
                                                     suffix='Sl%d' % slice_n),
                            environ=environ)
        oblique_slice = fix_obliquity(out_slicer.outputs.out_file,
                                      allineated_filename,
                                      verbose=verbose)
        sliced_func_filenames.append(oblique_slice)

    # Apply the precomputed warp slice by slice
    warped_func_slices = []
    for (sliced_func_filename, warp_filename) in zip(sliced_func_filenames,
                                                     warp_filenames):
        out_warp_apply = warp_apply(in_file=sliced_func_filename,
                                    master=sliced_func_filename,
                                    warp=warp_filename,
                                    out_file=fname_presuffix(
                                        sliced_func_filename, suffix='_qw'),
                                    environ=environ)
        warped_func_slices.append(out_warp_apply.outputs.out_file)

    # Finally, merge all slices !
    out_merge_func = merge(in_files=warped_func_slices,
                           outputtype='NIFTI_GZ',
                           environ=environ)

    # Fix the obliquity
    merged_oblique = fix_obliquity(out_merge_func.outputs.out_file,
                                   allineated_filename,
                                   verbose=verbose)

    # Update the fmri data
    setattr(session_data, "coreg_func_", merged_oblique)
    setattr(session_data, "coreg_anat_", registered_anat_oblique_filename)
    setattr(session_data, "coreg_transform_", transform_filename)
    os.chdir(current_dir)

    # Collect the outputs
    output_files.extend(sliced_registered_anat_filenames +
                        sliced_bias_corrected_filenames +
                        resampled_registered_anat_filenames +
                        resampled_bias_corrected_filenames + warped_slices +
                        warp_filenames + resampled_warped_slices_oblique +
                        sliced_func_filenames + warped_func_slices)
    if not caching:
        for out_file in output_files:
            if os.path.isfile(out_file):
                os.remove(out_file)
Exemplo n.º 4
0
def coregister(unifized_anat_file,
               unbiased_mean_func_file,
               write_dir,
               anat_brain_file=None,
               func_brain_file=None,
               slice_timing=True,
               t_r=None,
               prior_rigid_body_registration=None,
               reorient_only=False,
               voxel_size_x=.1,
               voxel_size_y=.1,
               caching=False,
               verbose=True,
               **environ_kwargs):
    """
    Coregistration of the subject's functional and anatomical images.
    The functional volume is aligned to the anatomical, first with a
    rigid body registration and then on a per-slice basis (only a fine
    correction, this is mostly for correction of EPI distortion).

    Parameters
    ----------
    unbiased_mean_func_file : str
        Path to the slice-time corrected, volume registrated, averaged
        and bias field corrected functional file
    prior_rigid_body_registration : bool, optional
        If True, a rigid-body registration of the anat to the func is
        performed prior to the warp. Useful if the images headers have
        missing/wrong information.
        NOTE: prior_rigid_body_registration is deprecated from 0.1 and will be
        removed in next release. Use `reorient_only` instead.
    reorient_only :  bool, optional
        If True, the rigid-body registration of the anat to the func is not
        performed and only reorientation is done.
    voxel_size_x : float, optional
        Resampling resolution for the x-axis, in mm.
    voxel_size_y : float, optional
        Resampling resolution for the y-axis, in mm.
    caching : bool, optional
        Wether or not to use caching.
    verbose : bool, optional
        If True, all steps are verbose. Note that caching implies some
        verbosity in any case.
    environ_kwargs : extra arguments keywords
        Extra arguments keywords, passed to interfaces environ variable.

    Returns
    -------
    The following attributes are added
        - `coreg_func_` : str
                          Path to paths to the coregistered functional
                          image.
        - `coreg_anat_` : str
                          Path to paths to the coregistered functional
                          image.
        - `coreg_transform_` : str
                               Path to the transform from anat to func.
    Notes
    -----
    If `use_rats_tool` is turned on, RATS tool is used for brain extraction
    and has to be cited. For more information, see
    `RATS <http://www.iibi.uiowa.edu/content/rats-overview/>`_
    """
    if prior_rigid_body_registration is not None:
        warn_str = ("The parameter 'prior_rigid_body_registration' is "
                    "deprecated and will be removed in sammba-mri next "
                    "release. Use parameter 'reorient_only' instead.")
        warnings.warn(warn_str, VisibleDeprecationWarning, stacklevel=2)
        reorient_only = not (prior_rigid_body_registration)

    environ = {'AFNI_DECONFLICT': 'OVERWRITE'}
    if verbose:
        terminal_output = 'allatonce'
    else:
        terminal_output = 'none'

    if caching:
        memory = Memory(write_dir)
        catmatvec = memory.cache(afni.CatMatvec)
    else:
        catmatvec = afni.CatMatvec().run

    for (key, value) in environ_kwargs.items():
        environ[key] = value

    output_files = []

    #############################################
    # Rigid-body registration anat -> mean func #
    #############################################
    if reorient_only:
        allineated_anat_file = unifized_anat_file
    else:
        if anat_brain_file is None:
            raise ValueError("'anat_brain_mask_file' is needed for "
                             "rigid-body registration")
        if func_brain_file is None:
            raise ValueError("'func_brain_mask_file' is needed for "
                             "rigid-body registration")
        allineated_anat_file, rigid_transform_file = \
            _rigid_body_register(unifized_anat_file,
                                 unbiased_mean_func_file,
                                 anat_brain_file,
                                 func_brain_file,
                                 write_dir=write_dir,
                                 caching=caching,
                                 terminal_output=terminal_output,
                                 environ=environ)
        output_files.extend([rigid_transform_file, allineated_anat_file])

    ############################################
    # Nonlinear registration anat -> mean func #
    ############################################
    registered_anat_oblique_file, mat_file =\
        _warp(allineated_anat_file, unbiased_mean_func_file, write_dir,
              caching=caching, verbose=verbose,
              terminal_output=terminal_output,
              environ=environ)

    output_files.append(mat_file)
    transform_file = fname_presuffix(registered_anat_oblique_file,
                                     suffix='_func_to_anat.aff12.1D',
                                     use_ext=False)
    if reorient_only:
        _ = catmatvec(in_file=[(mat_file, 'ONELINE')],
                      oneline=True,
                      out_file=transform_file,
                      environ=environ)
    else:
        _ = catmatvec(in_file=[(rigid_transform_file, 'ONELINE'),
                               (mat_file, 'ONELINE')],
                      oneline=True,
                      out_file=transform_file,
                      environ=environ)

    ##################################################
    # Per-slice non-linear registration func -> anat #
    ##################################################
    warped_mean_func_file, warp_files, _ =\
        _per_slice_qwarp(unbiased_mean_func_file,
                         registered_anat_oblique_file, voxel_size_x,
                         voxel_size_y,
                         write_dir=write_dir, verbose=verbose,
                         caching=caching, terminal_output=terminal_output,
                         environ=environ)

    # Update the outputs
    if not caching:
        for out_file in output_files:
            os.remove(out_file)

    return Bunch(coreg_func_=warped_mean_func_file,
                 coreg_anat_=registered_anat_oblique_file,
                 coreg_transform_=transform_file,
                 coreg_warps_=warp_files)
Exemplo n.º 5
0
def create_pipeline_graph(pipeline_name, graph_file,
                          graph_kind='hierarchical'):
    """Creates pipeline graph for a given piepline.

    Parameters
    ----------
    pipeline_name : one of {'anat_to_common_rigid', 'anat_to_common_affine',
        'anat_to_common_nonlinear'}
        Pipeline name.

    graph_file : str.
        Path to save the graph image to.

    graph_kind : one of {'orig', 'hierarchical', 'flat', 'exec', 'colored'}, optional.
        The kind of the graph, passed to
        nipype.pipeline.workflows.Workflow().write_graph
    """
    pipeline_names = ['anats_to_common_rigid', 'anats_to_common_affine',
                      'anats_to_common_nonlinear']
    if pipeline_name not in pipeline_names:
        raise NotImplementedError(
            'Pipeline name must be one of {0}, you entered {1}'.format(
                pipeline_names, pipeline_name))
    graph_kinds = ['orig', 'hierarchical', 'flat', 'exec', 'colored']
    if graph_kind not in graph_kinds:
        raise ValueError(
            'Graph kind must be one of {0}, you entered {1}'.format(
                graph_kinds, graph_kind))

    workflow = pe.Workflow(name=pipeline_name)

    #######################################################################
    # Specify rigid body registration pipeline steps
    unifize = pe.Node(interface=afni.Unifize(), name='bias_correct')
    clip_level = pe.Node(interface=afni.ClipLevel(),
                         name='compute_mask_threshold')
    compute_mask = pe.Node(interface=interfaces.MathMorphoMask(),
                           name='compute_brain_mask')
    apply_mask = pe.Node(interface=afni.Calc(), name='apply_brain_mask')
    center_mass = pe.Node(interface=afni.CenterMass(),
                          name='compute_and_set_cm_in_header')
    refit_copy = pe.Node(afni.Refit(), name='copy_cm_in_header')
    tcat1 = pe.Node(afni.TCat(), name='concatenate_across_individuals1')
    tstat1 = pe.Node(afni.TStat(), name='compute_average1')
    undump = pe.Node(afni.Undump(), name='create_empty_template')
    refit_set = pe.Node(afni.Refit(), name='set_cm_in_header')
    resample1 = pe.Node(afni.Resample(), name='resample1')
    resample2 = pe.Node(afni.Resample(), name='resample2')
    shift_rotate = pe.Node(afni.Allineate(), name='shift_rotate')
    apply_allineate1 = pe.Node(afni.Allineate(), name='apply_transform1')
    tcat2 = pe.Node(afni.TCat(), name='concatenate_across_individuals2')
    tstat2 = pe.Node(afni.TStat(), name='compute_average2')
    tcat3 = pe.Node(afni.TCat(), name='concatenate_across_individuals3')
    tstat3 = pe.Node(afni.TStat(), name='compute_average3')

    workflow.add_nodes([unifize, clip_level, compute_mask, apply_mask,
                        center_mass,
                        refit_copy, tcat1, tstat1, undump, refit_set,
                        resample1, resample2, shift_rotate, apply_allineate1,
                        tcat2, tstat2, tcat3, tstat3])

    #######################################################################
    # and connections
    workflow.connect(unifize, 'out_file', clip_level, 'in_file')
    workflow.connect(clip_level, 'clip_val',
                     compute_mask, 'intensity_threshold')
    workflow.connect(unifize, 'out_file', compute_mask, 'in_file')
    workflow.connect(compute_mask, 'out_file', apply_mask, 'in_file_a')
    workflow.connect(unifize, 'out_file', apply_mask, 'in_file_b')
    workflow.connect(apply_mask, 'out_file',
                     center_mass, 'in_file')
    workflow.connect(unifize, 'out_file', refit_copy, 'in_file')
    workflow.connect(center_mass, 'out_file',
                     refit_copy, 'duporigin_file')
    workflow.connect(center_mass, 'out_file', tcat1, 'in_files')
    workflow.connect(tcat1, 'out_file', tstat1, 'in_file')
    workflow.connect(tstat1, 'out_file', undump, 'in_file')
    workflow.connect(undump, 'out_file', refit_set, 'in_file')
    workflow.connect(refit_set, 'out_file', resample1, 'master')
    workflow.connect(refit_copy, 'out_file', resample1, 'in_file')
    workflow.connect(refit_set, 'out_file', resample2, 'master')
    workflow.connect(center_mass, 'out_file', resample2, 'in_file')
    workflow.connect(resample2, 'out_file', tcat2, 'in_files')
    workflow.connect(tcat2, 'out_file', tstat2, 'in_file')
    workflow.connect(tstat2, 'out_file', shift_rotate, 'reference')
    workflow.connect(resample2, 'out_file', shift_rotate, 'in_file')
    workflow.connect(tstat2, 'out_file', apply_allineate1, 'master')
    workflow.connect(resample1, 'out_file',
                     apply_allineate1, 'in_file')
    workflow.connect(shift_rotate, 'out_matrix',
                     apply_allineate1, 'in_matrix')
    workflow.connect(apply_allineate1, 'out_file', tcat3, 'in_files')
    workflow.connect(tcat3, 'out_file', tstat3, 'in_file')
    if pipeline_name in ['anats_to_common_affine',
                         'anat_to_common_nonlinear']:
        mask = pe.Node(afni.MaskTool(), name='generate_count_mask')
        allineate = pe.Node(afni.Allineate(), name='allineate')
        catmatvec = pe.Node(afni.CatMatvec(), name='concatenate_transforms')
        apply_allineate2 = pe.Node(afni.Allineate(), name='apply_transform2')
        tcat3 = pe.Node(
            afni.TCat(), name='concatenate_across_individuals4')
        tstat3 = pe.Node(afni.TStat(), name='compute_average4')

        workflow.add_nodes([mask, allineate, catmatvec, apply_allineate2,
                            tcat3, tstat3])

        workflow.connect(tcat2, 'out_file', mask, 'in_file')
        workflow.connect(mask, 'out_file', allineate, 'weight')
        workflow.connect(apply_allineate1, 'out_file',
                         allineate, 'in_file')
        workflow.connect(allineate, 'out_matrix',
                         catmatvec, 'in_file')
        #XXX how can we enter multiple files ? 
        workflow.connect(catmatvec, 'out_file',
                         apply_allineate2, 'in_matrix')
        workflow.connect(resample1, 'out_file',
                         apply_allineate2, 'in_file')
        workflow.connect(apply_allineate2, 'out_file', tcat3, 'in_files')
        workflow.connect(tcat3, 'out_file', tstat3, 'in_file')

    if pipeline_name == 'anats_to_common_nonlinear':
        pass

    graph_file_root, graph_file_ext = os.path.splitext(graph_file)
    if graph_file_ext:
        _ = workflow.write_graph(graph2use=graph_kind,
                                 format=graph_file_ext[1:],
                                 dotfilename=graph_file_root)
    else:
        _ = workflow.write_graph(graph2use=graph_kind,
                                 dotfilename=graph_file_root)
Exemplo n.º 6
0
def _apply_transforms(to_register_filename,
                      target_filename,
                      write_dir,
                      transforms,
                      transformed_filename=None,
                      transforms_kind='nonlinear',
                      interpolation=None,
                      voxel_size=None,
                      inverse=False,
                      caching=False,
                      verbose=True):
    """ Applies successive transforms to a given image to put it in
    template space.

    Parameters
    ----------
    to_register_filename : str
        Path to the source file to register.

    target_filename : str
        Reference file to register to.

    transforms : list
        List of transforms in order of 3dNWarpApply application: first must
        one must be in the target space and last one must be in
        the source space.

    transformed_filename : str, optional
        Path to the output registered file

    inverse : bool, optional
        If True, after the transforms composition is computed, invert it.
        If the input transforms would take a dataset from space A to B,
        then the inverted transform will do the reverse.

    interpolation : one of {'nearestneighbour', 'linear', 'cubic', 'quintic',
                            'wsinc5'} or None, optional
        Interpolation type. If None, AFNI defaults are used.

    voxel_size : 3-tuple of floats, optional
        Voxel size of the registered functional, in mm.

    caching : bool, optional
        Wether or not to use caching.

    verbose : bool, optional
        If True, all steps are verbose. Note that caching implies some
        verbosity in any case.
    """
    environ = {'AFNI_DECONFLICT': 'OVERWRITE'}
    if verbose:
        terminal_output = 'allatonce'
    else:
        terminal_output = 'none'

    if caching:
        memory = Memory(write_dir)
        catmatvec = memory.cache(afni.CatMatvec)
        allineate = memory.cache(afni.Allineate)
        warp_apply = memory.cache(afni.NwarpApply)
        resample = memory.cache(afni.Resample)
        for step in [resample, allineate, warp_apply]:
            step.interface().set_default_terminal_output(terminal_output)
    else:
        resample = afni.Resample(terminal_output=terminal_output).run
        catmatvec = afni.CatMatvec().run
        allineate = afni.Allineate(terminal_output=terminal_output).run
        warp_apply = afni.NwarpApply(terminal_output=terminal_output).run

    if transformed_filename is None:
        target_basename = os.path.basename(target_filename)
        target_basename = os.path.splitext(target_basename)[0]
        target_basename = os.path.splitext(target_basename)[0]
        transformed_filename = fname_presuffix(to_register_filename,
                                               suffix='_to_' + target_basename,
                                               newpath=write_dir)

    if voxel_size is None:
        resampled_target_filename = target_filename
    else:
        out_resample = resample(in_file=target_filename,
                                voxel_size=voxel_size,
                                out_file=fname_presuffix(target_filename,
                                                         suffix='_resampled',
                                                         newpath=write_dir),
                                environ=environ)
        resampled_target_filename = out_resample.outputs.out_file
    if transforms_kind is not 'nonlinear':
        affine_transform_filename = fname_presuffix(transformed_filename,
                                                    suffix='.aff12.1D',
                                                    use_ext=False)
        out_catmatvec = catmatvec(in_file=[(transform, 'ONELINE')
                                           for transform in transforms],
                                  oneline=True,
                                  out_file=affine_transform_filename,
                                  environ=environ)
        if inverse:
            affine_transform_filename = fname_presuffix(transformed_filename,
                                                        suffix='_INV.aff12.1D',
                                                        use_ext=False)
            _ = catmatvec(in_file=[(out_catmatvec.outputs.out_file, 'I')],
                          oneline=True,
                          out_file=affine_transform_filename,
                          environ=environ)
        if interpolation is None:
            _ = allineate(in_file=to_register_filename,
                          master=resampled_target_filename,
                          in_matrix=affine_transform_filename,
                          out_file=transformed_filename,
                          environ=environ)
        else:
            _ = allineate(in_file=to_register_filename,
                          master=resampled_target_filename,
                          in_matrix=affine_transform_filename,
                          final_interpolation=interpolation,
                          out_file=transformed_filename,
                          environ=environ)
    else:
        warp = "'"
        warp += " ".join(transforms)
        warp += "'"
        if interpolation is None:
            _ = warp_apply(in_file=to_register_filename,
                           master=resampled_target_filename,
                           warp=warp,
                           inv_warp=inverse,
                           out_file=transformed_filename,
                           environ=environ)
        else:
            _ = warp_apply(in_file=to_register_filename,
                           master=resampled_target_filename,
                           warp=warp,
                           inv_warp=inverse,
                           interp=interpolation,
                           out_file=transformed_filename,
                           environ=environ)

    # XXX obliquity information is lost if resampling is done
    transformed_filename = fix_obliquity(transformed_filename,
                                         resampled_target_filename,
                                         verbose=verbose,
                                         caching=caching,
                                         caching_dir=write_dir,
                                         environ=environ)
    return transformed_filename
Exemplo n.º 7
0
def _rigid_body_register(moving_head_file,
                         reference_head_file,
                         moving_brain_file,
                         reference_brain_file,
                         write_dir=None,
                         verbose=True,
                         caching=False,
                         terminal_output='allatonce',
                         environ=None):
    # XXX: add verbosity
    if write_dir is None:
        write_dir = os.path.dirname(moving_head_file)

    if environ is None:
        environ = {'AFNI_DECONFLICT': 'OVERWRITE'}

    if caching:
        memory = Memory(write_dir)
        allineate = memory.cache(afni.Allineate)
        allineate2 = memory.cache(afni.Allineate)
        catmatvec = memory.cache(afni.CatMatvec)
        for step in [allineate, allineate2]:
            step.interface().set_default_terminal_output(terminal_output)
    else:
        allineate = afni.Allineate(terminal_output=terminal_output).run
        allineate2 = afni.Allineate(terminal_output=terminal_output).run
        catmatvec = afni.CatMatvec().run

    output_files = [moving_brain_file, reference_brain_file]

    # Compute the transformation from functional to anatomical brain
    # XXX: why in this sense
    # XXX: caching does not work if out_matrix
    # path is absolute
    out_matrix = fname_presuffix(reference_brain_file,
                                 suffix='_shr.aff12.1D',
                                 use_ext=False)
    if caching:
        out_matrix = os.path.basename(out_matrix)

    out_allineate = allineate2(in_file=reference_brain_file,
                               reference=moving_brain_file,
                               out_matrix=out_matrix,
                               center_of_mass='',
                               warp_type='shift_rotate',
                               out_file='%s_shr',
                               environ=environ,
                               verbose=verbose,
                               outputtype='NIFTI_GZ')
    rigid_transform_file = out_allineate.outputs.out_matrix
    output_files.append(out_allineate.outputs.out_file)

    # apply the inverse transform to register the anatomical to the func
    out_catmatvec = catmatvec(in_file=[(rigid_transform_file, 'I')],
                              oneline=True,
                              out_file=fname_presuffix(rigid_transform_file,
                                                       suffix='INV',
                                                       newpath=write_dir),
                              environ=environ)
    output_files.append(out_catmatvec.outputs.out_file)
    out_allineate_apply = allineate(in_file=moving_head_file,
                                    master=reference_head_file,
                                    in_matrix=out_catmatvec.outputs.out_file,
                                    out_file=fname_presuffix(
                                        moving_head_file,
                                        suffix='_shr',
                                        newpath=write_dir),
                                    environ=environ)

    # Remove intermediate output
    if not caching:
        for output_file in output_files:
            os.remove(output_file)

    return out_allineate_apply.outputs.out_file, rigid_transform_file
Exemplo n.º 8
0
def create_preprocess_mag_wf():
    preprocmag = pe.Workflow(name="preprocmag")
    preprocmag.config['execution']['remove_unnecessary_outputs'] = False

    # define inputs
    inputspec = pe.Node(ul.IdentityInterface(fields=['input_mag', # raw phase data
                                                     'frac', # BET franction (-f parameter)
                                                     'rest', # volumes of rest in block design
                                                     'task', # volumes of task in block design
                                                     ]),
                        name='inputspec')

    # convert image to float
    img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float', op_string='', suffix='_dtype'),
                           iterfield=['in_file'],
                           name='img2float')

    # motion correct each run
    volreg = pe.MapNode(interface=afni.Volreg(), name='volreg', iterfield='in_file')
    volreg.inputs.outputtype = 'NIFTI_GZ'

    # calculate relative motions
    calcrel = pe.MapNode(ul.Function(['in_file'], ['out_file'], calcrelmotion),
        name='calcrel', iterfield=['in_file'])

    #generate motion plots
    plotmc = pe.MapNode(interface=fsl.PlotMotionParams(), name='plotmc', iterfield='in_file')
    plotmc.inputs.in_source = 'fsl'
    plotmc.iterables = ("plot_type", ['rotations', 'translations', 'displacement'])

    # register each run to first volume of first run
    # A) extract the first volume of the first run
    extract_ref = pe.MapNode(interface=fsl.ExtractROI(t_size=1, t_min=0), name='extract_ref', iterfield=['in_file'])

    # B) registration
    align2first = pe.MapNode(interface=afni.Allineate(), name='align2first', iterfield=['in_file'])
    align2first.inputs.num_threads = 2
    align2first.inputs.out_matrix = 'align2first'

    # merge xfm from moco and first run alignment
    merge_xfm = pe.MapNode(interface=ul.Merge(2), name='merge_xfm', iterfield=['in1', 'in2'])

    # concatenate moco and alignment to run 1
    cat_xfm = pe.MapNode(interface=afni.CatMatvec(oneline=True), name='cat_xfm', iterfield=['in_file'])
    cat_xfm.inputs.out_file = 'concated_xfm.aff12.1D'

    # apply first volume registration and motion correction in a single step
    applyalign = pe.MapNode(interface=afni.Allineate(), name='applyalign', iterfield=['in_file', 'in_matrix'])
    applyalign.inputs.num_threads = 2
    applyalign.inputs.final_interpolation = 'nearestneighbour'
    applyalign.inputs.outputtype = 'NIFTI_GZ'

    # afni messes with the header (unobliques the data) this puts it back
    cpgeommoco = pe.MapNode(interface=fsl.CopyGeom(), name='cpgeommoco', iterfield=['dest_file', 'in_file'])

    # linear detrending prior to SNR calculation
    detrend = pe.MapNode(interface=pp.DetrendMag(), name='detrend', iterfield=['mag'])

    # get the mean functional of run 1 for brain extraction
    meanfunc = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',
                                                suffix='_mean'),
                       name='meanfunc', iterfield=['in_file'])

    # calculate the phase noise (takes in volume of activation, if none provided them assumes resting state)
    calcSNR = pe.MapNode(interface=pp.RestAverage(), name='calcSNR', iterfield=['func', 'rest', 'task'])

    # extract brain with fsl and save the mask
    extractor = pe.Node(interface=fsl.BET(), name="extractor")
    extractor.inputs.mask = True

    # apply the mask to all runs
    maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet',
                                                   op_string='-mas'),
                          iterfield=['in_file'],
                          name='maskfunc')

    # outputspec
    outputspec = pe.Node(ul.IdentityInterface(fields=['proc_mag','motion_par',
                                                      'motion_data', 'maxdisp_data' ,
                                                      'motion_plot', 'run_txfm',
                                                      'mask_file','mean_file','snr']),
                        name='outputspec')

    preprocmag = pe.Workflow(name='preprocmag')
    preprocmag.connect([(inputspec, img2float, [('input_mag', 'in_file')]),
                        (img2float, volreg, [('out_file', 'in_file')]),
                        (volreg, extract_ref, [('out_file', 'in_file')]),
                        (extract_ref, align2first, [('roi_file', 'in_file')]),
                        (extract_ref, align2first, [(('roi_file', pickfirst), 'reference')]),
                        (extract_ref, applyalign, [(('roi_file', pickfirst), 'reference')]),
                        (volreg, merge_xfm, [('oned_matrix_save', 'in2')]),
                        (align2first, merge_xfm, [('out_matrix', 'in1')]),
                        (merge_xfm, cat_xfm, [(('out', wraptuple), 'in_file')]),
                        (volreg,applyalign, [('out_file', 'in_file')]),
                        (volreg, calcrel, [('md1d_file', 'in_file')]),
                        (volreg, plotmc, [('oned_file', 'in_file')]),
                        (cat_xfm, applyalign, [('out_file', 'in_matrix')]),
                        (img2float, cpgeommoco, [('out_file', 'in_file')]),
                        (applyalign, cpgeommoco, [('out_file', 'dest_file')]),
                        (cpgeommoco, detrend, [('out_file', 'mag')]),
                        (detrend, meanfunc, [('detrended_mag', 'in_file')]),
                        (inputspec, calcSNR, [('rest', 'rest'),
                                              ('task', 'task')]),
                        (detrend, calcSNR, [('detrended_mag', 'func')]),
                        (inputspec, extractor, [('frac', 'frac')]),
                        (meanfunc, extractor, [(('out_file', pickfirst), 'in_file')]),
                        (cpgeommoco, maskfunc, [('out_file', 'in_file')]),
                        (extractor, maskfunc, [('mask_file', 'in_file2')]),
                        (maskfunc, outputspec, [('out_file', 'proc_mag')]),
                        (volreg, outputspec, [('oned_matrix_save', 'motion_par')]),
                        (volreg, outputspec, [('oned_file', 'motion_data')]),
                        (volreg, outputspec, [('md1d_file', 'maxdisp_data')]),
                        (plotmc, outputspec, [('out_file', 'motion_plot')]),
                        (cat_xfm, outputspec, [('out_file', 'run_txfm')]),
                        (extractor, outputspec, [('mask_file', 'mask_file')]),
                        (extractor, outputspec, [('out_file', 'mean_file')]),
                        (calcSNR, outputspec, [('tsnr', 'snr')]),
                        ])

    return preprocmag