Exemplo n.º 1
0
def init_mask_overlap_wf(name="mask_overlap_wf"):
    """Check the Dice overlap of a b=0 mask and a T1-based mask for QC.

    **Inputs**
        anatomical_mask
            Path to a high-resolution brain mask from a T1w image
        dwi_mask
            Path to a mask based on diffusion-weighted images

    **Outputs**
        dice_score
            float value of the dice overlap of the masks
    """
    inputnode = pe.Node(
        niu.IdentityInterface(fields=['anatomical_mask', 'dwi_mask']),
        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(fields=['dice_score']), name='outputnode')

    downsample_t1_mask = pe.Node(afni.Resample(resample_mode="NN", outputtype="NIFTI_GZ"),
                                 name='downsample_t1_mask')
    calculate_dice = pe.Node(DiceOverlap(), name='calculate_dice')

    workflow = Workflow(name=name)
    workflow.connect([
        (inputnode, downsample_t1_mask, [
            ('anatomical_mask', 'in_file'),
            ('dwi_mask', 'master')]),
        (inputnode, calculate_dice, [('dwi_mask', 'dwi_mask')]),
        (downsample_t1_mask, calculate_dice, [('out_file', 'anatomical_mask')]),
        (calculate_dice, outputnode, [('dice_score', 'dice_score')])])
    return workflow
Exemplo n.º 2
0
def anatomical_init(wf, cfg, strat_pool, pipe_num, opt=None):
    '''
    {"name": "anatomical_init",
     "config": "None",
     "switch": "None",
     "option_key": "None",
     "option_val": "None",
     "inputs": ["T1w"],
     "outputs": ["desc-preproc_T1w",
                 "desc-reorient_T1w"]}
    '''

    anat_deoblique = pe.Node(interface=afni.Refit(),
                             name=f'anat_deoblique_{pipe_num}')
    anat_deoblique.inputs.deoblique = True

    node, out = strat_pool.get_data('T1w')
    wf.connect(node, out, anat_deoblique, 'in_file')

    anat_reorient = pe.Node(interface=afni.Resample(),
                            name=f'anat_reorient_{pipe_num}')
    anat_reorient.inputs.orientation = 'RPI'
    anat_reorient.inputs.outputtype = 'NIFTI_GZ'

    wf.connect(anat_deoblique, 'out_file', anat_reorient, 'in_file')

    outputs = {
        'desc-preproc_T1w': (anat_reorient, 'out_file'),
        'desc-reorient_T1w': (anat_reorient, 'out_file')
    }

    return (wf, outputs)
Exemplo n.º 3
0
def preprocess(aroma_config, fwhm_config, input_img, mask_file, taskdir, task):
    # Resample to mask space
    # This is for AROMA images. Does it hurt non-AROMA?
    resample_path = os.path.join(taskdir, task + '_resample.nii.gz')
    resample = afni.Resample(master=mask_file,
                             out_file=resample_path,
                             in_file=input_img)
    resample_run = resample.run()

    # Apply fmriprep-calculated brain mask to the functional image
    masked_file_path = os.path.join(taskdir,
                                    task + "_input_functional_masked.nii.gz")
    applymask = fsl.ApplyMask(mask_file=mask_file, out_file=masked_file_path)
    applymask.inputs.in_file = resample_run.outputs.out_file
    mask_run = applymask.run()
    masked_input = masked_file_path

    if aroma_config:
        print("No smoothing required.")
        processed_image = masked_input
    else:
        # smoothing
        print("Smoothing the skull-stripped BOLD.")
        smooth = fsl.Smooth(in_file=masked_input, fwhm=fwhm_config)
        smooth_run = smooth.run()
        processed_image = smooth_run.outputs.smoothed_file

    return processed_image
Exemplo n.º 4
0
def create_workflow(config: AttrDict, resource_pool: ResourcePool,
                    context: Context):
    for _, rp in resource_pool[['T1w']]:
        anat_image = rp[R('T1w')]
        anat_deoblique = NipypeJob(interface=afni.Refit(deoblique=True),
                                   reference='anat_deoblique')
        anat_deoblique.in_file = anat_image
        output_node = anat_deoblique.out_file

        if config.non_local_means_filtering:
            denoise = NipypeJob(interface=ants.DenoiseImage(),
                                reference='anat_denoise')
            denoise.input_image = output_node
            output_node = denoise.output_image

        if config.n4_bias_field_correction:
            n4 = NipypeJob(interface=ants.N4BiasFieldCorrection(
                dimension=3, shrink_factor=2, copy_header=True),
                           reference='anat_n4')
            n4.input_image = output_node
            output_node = n4.output_image

        anat_reorient = NipypeJob(interface=afni.Resample(
            orientation='RPI', outputtype='NIFTI_GZ'),
                                  reference='anat_reorient')
        anat_reorient.in_file = output_node
        rp[R('T1w', label='reorient')] = anat_reorient.out_file
Exemplo n.º 5
0
 def preprocess_MRI(self):
     """
     Runs N4 Bias Correction and resamples MRI to higher resolution if necessary.
     """
     print('Preprocessing MRI')
     self.MRI_path = self.root_dir + 'MRI/'
     if self.input.MRI.N4 == True:
         self.MRI_path += 'N4_'
         if os.path.isfile(self.MRI_path + os.path.split(self.MRI)[1]
                           ) and self.overwrite == False:
             print(' - ' + self.MRI_path + os.path.split(self.MRI)[1] +
                   ' Already Exists')
             self.MRI = self.MRI_path + os.path.split(self.MRI)[1]
         else:
             #Run N4 Bias Field Correction on MRI Volume
             N4 = N4BiasFieldCorrection()
             N4.inputs.dimension = 3
             N4.inputs.input_image = self.MRI
             N4.inputs.output_image = self.MRI_path + os.path.split(
                 self.MRI)[1]
             N4.cmdline
             N4.run()
             #Redefine MRI as the N4 corrected volume.
             self.MRI = N4.inputs.output_image
     self.MRI_path = self.MRI_path + 'reoriented_'
     if os.path.isfile(self.MRI_path + os.path.split(self.orig_MRI)[1]
                       ) and self.overwrite == False:
         print(' - ' + self.MRI_path + os.path.split(self.orig_MRI)[1] +
               ' Already Exists')
         self.MRI = self.MRI_path + os.path.split(self.orig_MRI)[1]
     else:
         res = afni.Resample()
         res.inputs.in_file = self.MRI
         tmp = self.histology.orientation
         #Resample MRI to the orientation found in the histology and blockface images
         #NOTE: AFNI (the program used below) and Nibabel (the program used to read/write NIFTI files)
         #use opposite orientation nomenclature. While confusing, this means the orientation string must
         #be inverted before using AFNI.
         if self.histology.orientation.find('S') >= 0:
             tmp.replace('S', 'I')
         else:
             tmp.replace('I', 'S')
         if self.histology.orientation.find('R') >= 0:
             tmp.replace('R', 'L')
         else:
             tmp.replace('L', 'R')
         if self.histology.orientation.find('P') >= 0:
             tmp.replace('P', 'A')
         else:
             tmp.replace('A', 'P')
         print(tmp)
         res.inputs.orientation = tmp
         res.inputs.out_file = self.MRI_path + os.path.split(
             self.orig_MRI)[1]
         res.run()
         self.MRI = res.inputs.out_file
Exemplo n.º 6
0
def init_dsi_studio_recon_wf(name="dsi_studio_recon",
                             output_suffix="",
                             params={}):
    """Reconstructs diffusion data using DSI Studio.

    This workflow creates a ``.src.gz`` file from the input dwi, bvals and bvecs,
    then reconstructs ODFs using GQI.

    Inputs

        *Default qsiprep inputs*

    Outputs

        fibgz
            A DSI Studio fib file containing GQI ODFs, peaks and scalar values.

    Params

        ratio_of_mean_diffusion_distance: float
            Default 1.25. Distance to sample EAP at.

    """
    inputnode = pe.Node(niu.IdentityInterface(fields=input_fields),
                        name="inputnode")
    outputnode = pe.Node(niu.IdentityInterface(fields=['fibgz']),
                         name="outputnode")
    workflow = pe.Workflow(name=name)
    create_src = pe.Node(DSIStudioCreateSrc(), name="create_src")
    gqi_recon = pe.Node(DSIStudioGQIReconstruction(), name="gqi_recon")
    # Resample anat mask
    resample_mask = pe.Node(afni.Resample(outputtype='NIFTI_GZ',
                                          resample_mode="NN"),
                            name='resample_mask')

    workflow.connect([
        (inputnode, create_src, [('dwi_file', 'input_nifti_file'),
                                 ('bval_file', 'input_bvals_file'),
                                 ('bvec_file', 'input_bvecs_file')]),
        (inputnode, resample_mask, [('t1_brain_mask', 'in_file'),
                                    ('dwi_file', 'master')]),
        (create_src, gqi_recon, [('output_src', 'input_src_file')]),
        (resample_mask, gqi_recon, [('out_file', 'mask')]),
        (gqi_recon, outputnode, [('output_fib', 'fibgz')])
    ])

    if output_suffix:
        # Save the output in the outputs directory
        ds_gqi_fibgz = pe.Node(ReconDerivativesDataSink(extension='.fib.gz',
                                                        suffix=output_suffix,
                                                        compress=True),
                               name='ds_gqi_fibgz',
                               run_without_submitting=True)
        workflow.connect(gqi_recon, 'output_fib', ds_gqi_fibgz, 'in_file')
    return workflow
Exemplo n.º 7
0
def lesion_preproc(lesion_mask: str):
    lesion_deoblique = NipypeJob(interface=afni.Refit(deoblique=True),
                                 reference='lesion_deoblique')
    lesion_inverted = PythonJob(function=inverse_lesion,
                                reference='inverse_lesion')
    lesion_reorient = NipypeJob(interface=afni.Resample(orientation='RPI',
                                                        outputtype='NIFTI_GZ'),
                                reference='lesion_reorient')

    lesion_inverted.lesion_path = S3Resource(lesion_mask) if lesion_mask.lower(
    ).startswith('s3://') else lesion_mask
    lesion_deoblique.in_file = lesion_inverted.lesion_out
    lesion_reorient.in_file = lesion_deoblique.out_file
    return lesion_reorient.out_file
Exemplo n.º 8
0
def resolve_resolution(resolution, template, template_name, tag=None):

    import nipype.interfaces.afni as afni
    import nipype.pipeline.engine as pe
    from CPAC.utils.datasource import check_for_s3

    tagname = None
    local_path = None

    if "{" in template and tag is not None:
        tagname = "${" + tag + "}"
    try:
        if tagname is not None:
            local_path = check_for_s3(
                template.replace(tagname, str(resolution)))
    except (IOError, OSError):
        local_path = None

    ## TODO debug - it works in ipython but doesn't work in nipype wf
    # try:
    #     local_path = check_for_s3('/usr/local/fsl/data/standard/MNI152_T1_3.438mmx3.438mmx3.4mm_brain_mask_dil.nii.gz')
    # except (IOError, OSError):
    #     local_path = None

    if local_path is None:
        if tagname is not None:
            ref_template = template.replace(tagname, '1mm')
            local_path = check_for_s3(ref_template)
        elif tagname is None and "s3" in template:
            local_path = check_for_s3(template)
        else:
            local_path = template

        if "x" in str(resolution):
            resolution = tuple(
                float(i.replace('mm', '')) for i in resolution.split("x"))
        else:
            resolution = (float(resolution.replace('mm', '')), ) * 3

        resample = pe.Node(interface=afni.Resample(), name=template_name)
        resample.inputs.voxel_size = resolution
        resample.inputs.outputtype = 'NIFTI_GZ'
        resample.inputs.resample_mode = 'Cu'
        resample.inputs.in_file = local_path
        resample.base_dir = '.'

        resampled_template = resample.run()
        local_path = resampled_template.outputs.out_file

    return local_path
Exemplo n.º 9
0
def _reorient_wf(name='ReorientWorkflow'):
    """A workflow to reorient images to 'RPI' orientation."""
    workflow = Workflow(name=name)
    workflow.__desc__ = "Inner workflow. "
    inputnode = Node(niu.IdentityInterface(fields=['in_file']),
                     name='inputnode')
    outputnode = Node(niu.IdentityInterface(fields=['out_file']),
                      name='outputnode')
    deoblique = Node(afni.Refit(deoblique=True), name='deoblique')
    reorient = Node(afni.Resample(orientation='RPI', outputtype='NIFTI_GZ'),
                    name='reorient')
    workflow.connect([(inputnode, deoblique, [('in_file', 'in_file')]),
                      (deoblique, reorient, [('out_file', 'in_file')]),
                      (reorient, outputnode, [('out_file', 'out_file')])])
    return workflow
Exemplo n.º 10
0
def create_workflow(config: AttrDict, resource_pool: ResourcePool, context: Context):
    for _, rp in resource_pool[['T1w']]:
        anat_image = rp[R('T1w')]
        anat_deoblique = NipypeJob(
            interface=afni.Refit(deoblique=True),
            reference='deoblique'
        )
        anat_deoblique.in_file = anat_image
        output_node = anat_deoblique.out_file

        anat_reorient = NipypeJob(
            interface=afni.Resample(orientation='RPI', outputtype='NIFTI_GZ'),
            reference='reorient'
        )
        anat_reorient.in_file = output_node
        rp[R('T1w', label='reorient')] = anat_reorient.out_file
Exemplo n.º 11
0
def _reorient_wf(name="ReorientWorkflow"):
    """A workflow to reorient images to 'RPI' orientation."""
    workflow = Workflow(name=name)
    workflow.__desc__ = "Inner workflow. "
    inputnode = Node(niu.IdentityInterface(fields=["in_file"]),
                     name="inputnode")
    outputnode = Node(niu.IdentityInterface(fields=["out_file"]),
                      name="outputnode")
    deoblique = Node(afni.Refit(deoblique=True), name="deoblique")
    reorient = Node(afni.Resample(orientation="RPI", outputtype="NIFTI_GZ"),
                    name="reorient")
    workflow.connect([
        (inputnode, deoblique, [("in_file", "in_file")]),
        (deoblique, reorient, [("out_file", "in_file")]),
        (reorient, outputnode, [("out_file", "out_file")]),
    ])
    return workflow
Exemplo n.º 12
0
def resolve_resolution(resolution, template, template_name, tag=None):

    import nipype.interfaces.afni as afni
    import nipype.pipeline.engine as pe
    from CPAC.utils.datasource import check_for_s3

    tagname = None
    local_path = None
    # TODO XL think a better way to check template
    if "{" in template and tag is not None:
        tagname = "${" + tag + "}"
    try:
        if tagname is not None:
            local_path = check_for_s3(
                template.replace(tagname, str(resolution)))
    except IOError:
        local_path = None

    if local_path is None:
        if tagname is not None:
            ref_template = template.replace(tagname, '1mm')
            local_path = check_for_s3(ref_template)
        elif tagname is None and "s3" in template:
            local_path = check_for_s3(template)
        else:
            local_path = template

        if "x" in str(resolution):
            resolution = tuple(
                float(i.replace('mm', '')) for i in resolution.split("x"))
        else:
            resolution = (float(resolution.replace('mm', '')), ) * 3

        resample = pe.Node(interface=afni.Resample(), name=template_name)
        resample.inputs.voxel_size = resolution
        resample.inputs.outputtype = 'NIFTI_GZ'
        resample.inputs.resample_mode = 'Cu'
        resample.inputs.in_file = local_path
        resample.base_dir = '.'

        resampled_template = resample.run()
        local_path = resampled_template.outputs.out_file

    return local_path
Exemplo n.º 13
0
def test_resample():
    input_map = dict(
        args=dict(argstr='%s', ),
        environ=dict(usedefault=True, ),
        ignore_exception=dict(usedefault=True, ),
        in_file=dict(
            argstr='-inset %s',
            mandatory=True,
        ),
        orientation=dict(argstr='-orient %s', ),
        out_file=dict(argstr='-prefix %s', ),
        outputtype=dict(),
        suffix=dict(),
    )
    instance = afni.Resample()
    for key, metadata in input_map.items():
        for metakey, value in metadata.items():
            yield assert_equal, getattr(instance.inputs.traits()[key],
                                        metakey), value
def resample_nifti_images(images_location, voxel_dimensions, resample_method):
    """Resample the NIfTI images in a folder and put them in a new folder

    Args:
        images_location: Path where the images are stored
        voxel_dimension: tuple (dx, dy, dz)
        resample_method: NN - Nearest neighbor
                         Li - Linear interpolation

    Returns:
        None:

    """
    image_files = sorted([
        f for f in os.listdir(images_location)
        if os.path.isfile(os.path.join(images_location, f))
    ])

    voxel_size_str = '_{:.0f}mm'.format(float(voxel_dimensions[0]))
    new_folder = images_location + voxel_size_str

    if not os.path.exists(new_folder):
        os.makedirs(new_folder)

    for image_file in image_files:
        print(image_file)
        (file_name, file_ext) = os.path.splitext(image_file)
        new_file_name = ''.join([file_name, voxel_size_str, file_ext])

        resample = afni.Resample()
        resample.inputs.environ = {'AFNI_NIFTI_TYPE_WARN': 'NO'}
        resample.inputs.in_file = os.path.join(images_location, image_file)
        resample.inputs.out_file = os.path.join(new_folder, new_file_name)
        resample.inputs.voxel_size = voxel_dimensions
        resample.inputs.outputtype = 'NIFTI'
        resample.inputs.resample_mode = resample_method
        resample.run()
Exemplo n.º 15
0
def init_mask_finalize_wf(name="mask_finalize_wf"):
    """Creates a final mask using a combination of the t1 mask and dwi2mask
    """
    inputnode = pe.Node(
        niu.IdentityInterface(fields=['t1_mask', 'resampled_b0s']),
        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(fields=['mask_file']),
                         name='outputnode')
    workflow = Workflow(name=name)
    resample_t1_mask = pe.Node(afni.Resample(outputtype='NIFTI_GZ',
                                             resample_mode="NN"),
                               name='resample_t1_mask')
    b0mask = pe.Node(afni.Automask(outputtype='NIFTI_GZ'), name='b0mask')
    or_mask = pe.Node(afni.Calc(outputtype='NIFTI_GZ', expr='step(a+b)'),
                      name='or_mask')
    workflow.connect([(inputnode, resample_t1_mask, [('t1_mask', 'in_file'),
                                                     ('resampled_b0s',
                                                      'master')]),
                      (inputnode, b0mask, [('resampled_b0s', 'in_file')]),
                      (b0mask, or_mask, [('out_file', 'in_file_a')]),
                      (resample_t1_mask, or_mask, [('out_file', 'in_file_b')]),
                      (or_mask, outputnode, [('out_file', 'mask_file')])])

    return workflow
Exemplo n.º 16
0
def create_anat_preproc(template_path=None,
                        mask_path=None,
                        regmask_path=None,
                        method='afni',
                        already_skullstripped=False,
                        non_local_means_filtering=True,
                        n4_correction=True,
                        wf_name='anat_preproc'):
    """ 
    The main purpose of this workflow is to process T1 scans. Raw mprage file is deobliqued, reoriented
    into RPI and skullstripped. Also, a whole brain only mask is generated from the skull stripped image
    for later use in registration.

    Returns
    -------
    anat_preproc : workflow
        Anatomical Preprocessing Workflow

    Notes
    -----
    `Source <https://github.com/FCP-INDI/C-PAC/blob/master/CPAC/anat_preproc/anat_preproc.py>`_
    
    Workflow Inputs::
        inputspec.anat : string
            User input anatomical (T1) Image, in any of the 8 orientations
    
    Workflow Outputs::

        outputspec.refit : string
            Path to deobliqued anatomical image
    
        outputspec.reorient : string
            Path to RPI oriented anatomical image
    
        outputspec.skullstrip : string
            Path to skull stripped RPI oriented mprage file with normalized intensities.
    
        outputspec.brain : string
            Path to skull stripped RPI brain image with original intensity values and not normalized or scaled.
    
    Order of commands:
    - Deobliqing the scans. ::
        3drefit -deoblique mprage.nii.gz

    - Re-orienting the Image into Right-to-Left Posterior-to-Anterior Inferior-to-Superior  (RPI) orientation ::
        3dresample -orient RPI
                   -prefix mprage_RPI.nii.gz
                   -inset mprage.nii.gz
                   
    - Skull-Stripping the image ::
        Using AFNI ::
            3dSkullStrip -input mprage_RPI.nii.gz
                         -o_ply mprage_RPI_3dT.nii.gz
        or using BET ::
            bet mprage_RPI.nii.gz

    - The skull-stripping step modifies the intensity values. To get back the original intensity values, we do an element wise product of RPI data with step function of skull-stripped data ::
        3dcalc -a mprage_RPI.nii.gz
               -b mprage_RPI_3dT.nii.gz
               -expr 'a*step(b)'
               -prefix mprage_RPI_3dc.nii.gz
    
    High Level Workflow Graph:
    .. image:: ../images/anatpreproc_graph.dot.png
       :width: 500
    
    Detailed Workflow Graph:
    .. image:: ../images/anatpreproc_graph_detailed.dot.png
       :width: 500

    Examples
    --------
    >>> from CPAC.anat_preproc import create_anat_preproc
    >>> preproc = create_anat_preproc()
    >>> preproc.inputs.inputspec.anat = 'sub1/anat/mprage.nii.gz'
    >>> preproc.run() #doctest: +SKIP
    """

    preproc = pe.Workflow(name=wf_name)

    inputnode = pe.Node(util.IdentityInterface(fields=['anat', 'brain_mask']),
                        name='inputspec')

    outputnode = pe.Node(util.IdentityInterface(
        fields=['refit', 'reorient', 'skullstrip', 'brain', 'brain_mask']),
                         name='outputspec')

    anat_deoblique = pe.Node(interface=afni.Refit(), name='anat_deoblique')

    anat_deoblique.inputs.deoblique = True
    preproc.connect(inputnode, 'anat', anat_deoblique, 'in_file')
    preproc.connect(anat_deoblique, 'out_file', outputnode, 'refit')
    # Disable non_local_means_filtering and n4_correction when run niworkflows-ants
    if method == 'niworkflows-ants':
        non_local_means_filtering = False
        n4_correction = False

    if non_local_means_filtering and n4_correction:
        denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise')
        preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image')
        n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3,
                                                          shrink_factor=2,
                                                          copy_header=True),
                     name='anat_n4')
        preproc.connect(denoise, 'output_image', n4, 'input_image')
    elif non_local_means_filtering and not n4_correction:
        denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise')
        preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image')
    elif not non_local_means_filtering and n4_correction:
        n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3,
                                                          shrink_factor=2,
                                                          copy_header=True),
                     name='anat_n4')
        preproc.connect(anat_deoblique, 'out_file', n4, 'input_image')

    # Anatomical reorientation
    anat_reorient = pe.Node(interface=afni.Resample(), name='anat_reorient')

    anat_reorient.inputs.orientation = 'RPI'
    anat_reorient.inputs.outputtype = 'NIFTI_GZ'

    if n4_correction:
        preproc.connect(n4, 'output_image', anat_reorient, 'in_file')
    elif non_local_means_filtering and not n4_correction:
        preproc.connect(denoise, 'output_image', anat_reorient, 'in_file')
    else:
        preproc.connect(anat_deoblique, 'out_file', anat_reorient, 'in_file')

    preproc.connect(anat_reorient, 'out_file', outputnode, 'reorient')

    if already_skullstripped:

        anat_skullstrip = pe.Node(
            interface=util.IdentityInterface(fields=['out_file']),
            name='anat_skullstrip')

        preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'out_file')

        preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip')

        preproc.connect(anat_skullstrip, 'out_file', outputnode, 'brain')

    else:

        if method == 'afni':
            # Skull-stripping using AFNI 3dSkullStrip
            inputnode_afni = pe.Node(util.IdentityInterface(fields=[
                'shrink_factor', 'var_shrink_fac', 'shrink_fac_bot_lim',
                'avoid_vent', 'niter', 'pushout', 'touchup', 'fill_hole',
                'avoid_eyes', 'use_edge', 'exp_frac', 'smooth_final',
                'push_to_edge', 'use_skull', 'perc_int', 'max_inter_iter',
                'blur_fwhm', 'fac', 'monkey'
            ]),
                                     name='AFNI_options')

            skullstrip_args = pe.Node(util.Function(
                input_names=[
                    'spat_norm', 'spat_norm_dxyz', 'shrink_fac',
                    'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent',
                    'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes',
                    'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge',
                    'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm',
                    'fac', 'monkey'
                ],
                output_names=['expr'],
                function=create_3dskullstrip_arg_string),
                                      name='anat_skullstrip_args')

            preproc.connect([(inputnode_afni, skullstrip_args,
                              [('shrink_factor', 'shrink_fac'),
                               ('var_shrink_fac', 'var_shrink_fac'),
                               ('shrink_fac_bot_lim', 'shrink_fac_bot_lim'),
                               ('avoid_vent', 'avoid_vent'),
                               ('niter', 'niter'), ('pushout', 'pushout'),
                               ('touchup', 'touchup'),
                               ('fill_hole', 'fill_hole'),
                               ('avoid_eyes', 'avoid_eyes'),
                               ('use_edge', 'use_edge'),
                               ('exp_frac', 'exp_frac'),
                               ('smooth_final', 'smooth_final'),
                               ('push_to_edge', 'push_to_edge'),
                               ('use_skull', 'use_skull'),
                               ('perc_int', 'perc_int'),
                               ('max_inter_iter', 'max_inter_iter'),
                               ('blur_fwhm', 'blur_fwhm'), ('fac', 'fac'),
                               ('monkey', 'monkey')])])

            anat_skullstrip = pe.Node(interface=afni.SkullStrip(),
                                      name='anat_skullstrip')

            anat_skullstrip.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file', anat_skullstrip,
                            'in_file')
            preproc.connect(skullstrip_args, 'expr', anat_skullstrip, 'args')

            preproc.connect(anat_skullstrip, 'out_file', outputnode,
                            'skullstrip')
            # Apply skull-stripping step mask to original volume
            anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(),
                                               name='anat_skullstrip_orig_vol')

            anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)'
            anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_a')

            anat_brain_mask = pe.Node(interface=afni.Calc(),
                                      name='anat_brain_mask')

            anat_brain_mask.inputs.expr = 'step(a)'
            anat_brain_mask.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_skullstrip, 'out_file', anat_brain_mask,
                            'in_file_a')

            preproc.connect(anat_skullstrip, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_b')

            preproc.connect(anat_brain_mask, 'out_file', outputnode,
                            'brain_mask')

            preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode,
                            'brain')

        elif method == 'fsl':
            # Skull-stripping using FSL BET
            inputnode_bet = pe.Node(util.IdentityInterface(fields=[
                'frac', 'mask_boolean', 'mesh_boolean', 'outline', 'padding',
                'radius', 'reduce_bias', 'remove_eyes', 'robust', 'skull',
                'surfaces', 'threshold', 'vertical_gradient'
            ]),
                                    name='BET_options')

            anat_skullstrip = pe.Node(interface=fsl.BET(),
                                      name='anat_skullstrip')

            preproc.connect(anat_reorient, 'out_file', anat_skullstrip,
                            'in_file')

            preproc.connect([(inputnode_bet, anat_skullstrip, [
                ('frac', 'frac'),
                ('mask_boolean', 'mask'),
                ('mesh_boolean', 'mesh'),
                ('outline', 'outline'),
                ('padding', 'padding'),
                ('radius', 'radius'),
                ('reduce_bias', 'reduce_bias'),
                ('remove_eyes', 'remove_eyes'),
                ('robust', 'robust'),
                ('skull', 'skull'),
                ('surfaces', 'surfaces'),
                ('threshold', 'threshold'),
                ('vertical_gradient', 'vertical_gradient'),
            ])])

            preproc.connect(anat_skullstrip, 'out_file', outputnode,
                            'skullstrip')

            # Apply skull-stripping step mask to original volume
            anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(),
                                               name='anat_skullstrip_orig_vol')

            anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)'
            anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_a')

            preproc.connect(anat_skullstrip, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_b')

            preproc.connect(anat_skullstrip, 'mask_file', outputnode,
                            'brain_mask')

            preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode,
                            'brain')

        elif method == 'niworkflows-ants':
            # Skull-stripping using niworkflows-ants
            anat_skullstrip_ants = init_brain_extraction_wf(
                tpl_target_path=template_path,
                tpl_mask_path=mask_path,
                tpl_regmask_path=regmask_path,
                name='anat_skullstrip_ants')

            preproc.connect(anat_reorient, 'out_file', anat_skullstrip_ants,
                            'inputnode.in_files')

            preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file',
                            outputnode, 'skullstrip')

            preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file',
                            outputnode, 'brain')

            preproc.connect(anat_skullstrip_ants,
                            'atropos_wf.copy_xform.out_mask', outputnode,
                            'brain_mask')

        elif method == 'mask':

            anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(),
                                               name='anat_skullstrip_orig_vol')

            anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)'
            anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_a')

            preproc.connect(inputnode, 'brain_mask', anat_skullstrip_orig_vol,
                            'in_file_b')

            preproc.connect(inputnode, 'brain_mask', outputnode, 'brain_mask')

            preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode,
                            'brain')

    return preproc
Exemplo n.º 17
0
def create_denoise_pipeline(name='denoise'):
    # workflow
    denoise = Workflow(name='denoise')
    # Define nodes
    inputnode = Node(interface=util.IdentityInterface(fields=[
        'anat_brain', 'brain_mask', 'epi2anat_dat', 'unwarped_mean',
        'epi_coreg', 'moco_par', 'highpass_sigma', 'lowpass_sigma', 'tr'
    ]),
                     name='inputnode')
    outputnode = Node(interface=util.IdentityInterface(fields=[
        'wmcsf_mask', 'brain_mask_resamp', 'brain_mask2epi', 'combined_motion',
        'outlier_files', 'intensity_files', 'outlier_stats', 'outlier_plots',
        'mc_regressor', 'mc_F', 'mc_pF', 'comp_regressor', 'comp_F', 'comp_pF',
        'normalized_file'
    ]),
                      name='outputnode')
    # run fast to get tissue probability classes
    fast = Node(fsl.FAST(), name='fast')
    denoise.connect([(inputnode, fast, [('anat_brain', 'in_files')])])

    # functions to select tissue classes
    def selectindex(files, idx):
        import numpy as np
        from nipype.utils.filemanip import filename_to_list, list_to_filename
        return list_to_filename(
            np.array(filename_to_list(files))[idx].tolist())

    def selectsingle(files, idx):
        return files[idx]

    # resample tissue classes
    resample_tissue = MapNode(afni.Resample(resample_mode='NN',
                                            outputtype='NIFTI_GZ'),
                              iterfield=['in_file'],
                              name='resample_tissue')
    denoise.connect([
        (inputnode, resample_tissue, [('epi_coreg', 'master')]),
        (fast, resample_tissue, [(('partial_volume_files', selectindex,
                                   [0, 2]), 'in_file')]),
    ])
    # binarize tissue classes
    binarize_tissue = MapNode(
        fsl.ImageMaths(op_string='-nan -thr 0.99 -ero -bin'),
        iterfield=['in_file'],
        name='binarize_tissue')
    denoise.connect([
        (resample_tissue, binarize_tissue, [('out_file', 'in_file')]),
    ])
    # combine tissue classes to noise mask
    wmcsf_mask = Node(fsl.BinaryMaths(operation='add',
                                      out_file='wmcsf_mask_lowres.nii.gz'),
                      name='wmcsf_mask')
    denoise.connect([(binarize_tissue, wmcsf_mask,
                      [(('out_file', selectsingle, 0), 'in_file'),
                       (('out_file', selectsingle, 1), 'operand_file')]),
                     (wmcsf_mask, outputnode, [('out_file', 'wmcsf_mask')])])
    # resample brain mask
    resample_brain = Node(afni.Resample(
        resample_mode='NN',
        outputtype='NIFTI_GZ',
        out_file='T1_brain_mask_lowres.nii.gz'),
                          name='resample_brain')
    denoise.connect([(inputnode, resample_brain, [('brain_mask', 'in_file'),
                                                  ('epi_coreg', 'master')]),
                     (resample_brain, outputnode, [('out_file',
                                                    'brain_mask_resamp')])])
    # project brain mask into original epi space fpr quality assessment
    brainmask2epi = Node(fs.ApplyVolTransform(
        interp='nearest',
        inverse=True,
        transformed_file='T1_brain_mask2epi.nii.gz',
    ),
                         name='brainmask2epi')
    denoise.connect([
        (inputnode, brainmask2epi, [('brain_mask', 'target_file'),
                                    ('epi2anat_dat', 'reg_file'),
                                    ('unwarped_mean', 'source_file')]),
        (brainmask2epi, outputnode, [('transformed_file', 'brain_mask2epi')])
    ])
    # perform artefact detection
    artefact = Node(ra.ArtifactDetect(save_plot=True,
                                      use_norm=True,
                                      parameter_source='FSL',
                                      mask_type='file',
                                      norm_threshold=1,
                                      zintensity_threshold=3,
                                      use_differences=[True, False]),
                    name='artefact')
    artefact.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([
        (inputnode, artefact, [('epi_coreg', 'realigned_files'),
                               ('moco_par', 'realignment_parameters')]),
        (resample_brain, artefact, [('out_file', 'mask_file')]),
        (artefact, outputnode, [('norm_files', 'combined_motion'),
                                ('outlier_files', 'outlier_files'),
                                ('intensity_files', 'intensity_files'),
                                ('statistic_files', 'outlier_stats'),
                                ('plot_files', 'outlier_plots')])
    ])
    # Compute motion regressors
    motreg = Node(util.Function(
        input_names=['motion_params', 'order', 'derivatives'],
        output_names=['out_files'],
        function=motion_regressors),
                  name='getmotionregress')
    motreg.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([(inputnode, motreg, [('moco_par', 'motion_params')])])
    # Create a filter to remove motion and art confounds
    createfilter1 = Node(util.Function(
        input_names=['motion_params', 'comp_norm', 'outliers', 'detrend_poly'],
        output_names=['out_files'],
        function=build_filter1),
                         name='makemotionbasedfilter')
    createfilter1.inputs.detrend_poly = 2
    createfilter1.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([
        (motreg, createfilter1, [('out_files', 'motion_params')]),
        (
            artefact,
            createfilter1,
            [  #('norm_files', 'comp_norm'),
                ('outlier_files', 'outliers')
            ]),
        (createfilter1, outputnode, [('out_files', 'mc_regressor')])
    ])
    # regress out motion and art confounds
    filter1 = Node(fsl.GLM(out_f_name='F_mcart.nii.gz',
                           out_pf_name='pF_mcart.nii.gz',
                           out_res_name='rest_mc_denoised.nii.gz',
                           demean=True),
                   name='filtermotion')
    filter1.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([(inputnode, filter1, [('epi_coreg', 'in_file')]),
                     (createfilter1, filter1,
                      [(('out_files', list_to_filename), 'design')]),
                     (filter1, outputnode, [('out_f', 'mc_F'),
                                            ('out_pf', 'mc_pF')])])
    # create filter with compcor components
    createfilter2 = Node(util.Function(input_names=[
        'realigned_file', 'mask_file', 'num_components', 'extra_regressors'
    ],
                                       output_names=['out_files'],
                                       function=extract_noise_components),
                         name='makecompcorfilter')
    createfilter2.inputs.num_components = 6
    createfilter2.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([
        (createfilter1, createfilter2, [(('out_files', list_to_filename),
                                         'extra_regressors')]),
        (filter1, createfilter2, [('out_res', 'realigned_file')]),
        (wmcsf_mask, createfilter2, [('out_file', 'mask_file')]),
        (createfilter2, outputnode, [('out_files', 'comp_regressor')]),
    ])
    # regress compcor and other noise components
    filter2 = Node(fsl.GLM(out_f_name='F_noise.nii.gz',
                           out_pf_name='pF_noise.nii.gz',
                           out_res_name='rest2anat_denoised.nii.gz',
                           demean=True),
                   name='filternoise')
    filter2.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([(filter1, filter2, [('out_res', 'in_file')]),
                     (createfilter2, filter2, [('out_files', 'design')]),
                     (resample_brain, filter2, [('out_file', 'mask')]),
                     (filter2, outputnode, [('out_f', 'comp_F'),
                                            ('out_pf', 'comp_pF')])])
    # bandpass filter denoised file
    bandpass_filter = Node(
        fsl.TemporalFilter(out_file='rest_denoised_bandpassed.nii.gz'),
        name='bandpass_filter')
    bandpass_filter.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([(inputnode, bandpass_filter,
                      [('highpass_sigma', 'highpass_sigma'),
                       ('lowpass_sigma', 'lowpass_sigma')]),
                     (filter2, bandpass_filter, [('out_res', 'in_file')])])
    # time-normalize scans
    normalize_time = Node(util.Function(input_names=['in_file', 'tr'],
                                        output_names=['out_file'],
                                        function=time_normalizer),
                          name='normalize_time')
    normalize_time.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([
        (inputnode, normalize_time, [('tr', 'tr')]),
        (bandpass_filter, normalize_time, [('out_file', 'in_file')]),
        (normalize_time, outputnode, [('out_file', 'normalized_file')])
    ])
    return denoise
Exemplo n.º 18
0
def hmc_afni(name='fMRI_HMC_afni', st_correct=False, despike=False, deoblique=False):
    """A head motion correction (HMC) workflow for functional scans"""

    workflow = pe.Workflow(name=name)

    inputnode = pe.Node(niu.IdentityInterface(
        fields=['in_file', 'fd_radius', 'start_idx', 'stop_idx']), name='inputnode')

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

    drop_trs = pe.Node(afni.Calc(expr='a', outputtype='NIFTI_GZ'),
                       name='drop_trs')

    reorient = pe.Node(afni.Resample(
        orientation='RPI', outputtype='NIFTI_GZ'), name='reorient')

    get_mean_RPI = pe.Node(afni.TStat(
        options='-mean', outputtype='NIFTI_GZ'), name='get_mean_RPI')

    # calculate hmc parameters
    hmc = pe.Node(
        afni.Volreg(args='-Fourier -twopass', zpad=4, outputtype='NIFTI_GZ'),
        name='motion_correct')

    get_mean_motion = get_mean_RPI.clone('get_mean_motion')
    hmc_A = hmc.clone('motion_correct_A')
    hmc_A.inputs.md1d_file = 'max_displacement.1D'

    # Compute the frame-wise displacement
    calc_fd = pe.Node(niu.Function(
        function=fd_jenkinson, input_names=['in_file', 'rmax'],
        output_names=['out_fd']), name='calc_fd')

    workflow.connect([
        (inputnode, drop_trs, [('in_file', 'in_file_a'),
                               ('start_idx', 'start_idx'),
                               ('stop_idx', 'stop_idx')]),
        (inputnode, calc_fd, [('fd_radius', 'rmax')]),
        (reorient, get_mean_RPI, [('out_file', 'in_file')]),
        (reorient, hmc, [('out_file', 'in_file')]),
        (get_mean_RPI, hmc, [('out_file', 'basefile')]),
        (hmc, get_mean_motion, [('out_file', 'in_file')]),
        (reorient, hmc_A, [('out_file', 'in_file')]),
        (get_mean_motion, hmc_A, [('out_file', 'basefile')]),
        (hmc_A, outputnode, [('out_file', 'out_file')]),
        (hmc_A, calc_fd, [('oned_matrix_save', 'in_file')]),
        (calc_fd, outputnode, [('out_fd', 'out_fd')]),
    ])

    # Slice timing correction, despiking, and deoblique

    st_corr = pe.Node(afni.TShift(outputtype='NIFTI_GZ'), name='TimeShifts')

    deoblique_node = pe.Node(afni.Refit(deoblique=True), name='deoblique')

    despike_node = pe.Node(afni.Despike(outputtype='NIFTI_GZ'), name='despike')

    if st_correct and despike and deoblique:

        workflow.connect([
            (drop_trs, st_corr, [('out_file', 'in_file')]),
            (st_corr, despike_node, [('out_file', 'in_file')]),
            (despike_node, deoblique_node, [('out_file', 'in_file')]),
            (deoblique_node, reorient, [('out_file', 'in_file')])
        ])

    elif st_correct and despike:

        workflow.connect([
            (drop_trs, st_corr, [('out_file', 'in_file')]),
            (st_corr, despike_node, [('out_file', 'in_file')]),
            (despike_node, reorient, [('out_file', 'in_file')]),
        ])

    elif st_correct and deoblique:

        workflow.connect([
            (drop_trs, st_corr, [('out_file', 'in_file')]),
            (st_corr, deoblique_node, [('out_file', 'in_file')]),
            (deoblique_node, reorient, [('out_file', 'in_file')])
        ])

    elif st_correct:

        workflow.connect([
            (drop_trs, st_corr, [('out_file', 'in_file')]),
            (st_corr, reorient, [('out_file', 'in_file')])
        ])

    elif despike and deoblique:

        workflow.connect([
            (drop_trs, despike_node, [('out_file', 'in_file')]),
            (despike_node, deoblique_node, [('out_file', 'in_file')]),
            (deoblique_node, reorient, [('out_file', 'in_file')])
        ])

    elif despike:

        workflow.connect([
            (drop_trs, despike_node, [('out_file', 'in_file')]),
            (despike_node, reorient, [('out_file', 'in_file')]),
        ])

    elif deoblique:

        workflow.connect([
            (drop_trs, deoblique_node, [('out_file', 'in_file')]),
            (deoblique_node, reorient, [('out_file', 'in_file')])
        ])

    else:

        workflow.connect([
            (drop_trs, reorient, [('out_file', 'in_file')]),
        ])

    return workflow
def create_transform_pipeline(name='transfrom_timeseries'):
    # set fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # initiate workflow
    transform_ts = Workflow(name='transform_timeseries')
    # inputnode
    inputnode=Node(util.IdentityInterface(fields=['orig_ts',
    'anat_head',
    'mat_moco',
    'fullwarp',
    'resolution',
    'brain_mask'
    ]),
    name='inputnode')
    # outputnode
    outputnode=Node(util.IdentityInterface(fields=['trans_ts',
    'trans_ts_mean',
    'trans_ts_masked',
    'resamp_brain',
    'brain_mask_resamp',
    'out_dvars'
    ]),
    name='outputnode')
    #resample anatomy
    resample = Node(fsl.FLIRT(datatype='float',
    out_file='T1_resampled.nii.gz'),
    name = 'resample_anat')
    transform_ts.connect([(inputnode, resample, [('anat_head', 'in_file'),
    ('anat_head', 'reference'),
    ('resolution', 'apply_isoxfm')
    ]),
    (resample, outputnode, [('out_file', 'resamp_brain')])
    ])
    # split timeseries in single volumes
    split=Node(fsl.Split(dimension='t',
    out_base_name='timeseries'),
    name='split')
    transform_ts.connect([(inputnode, split, [('orig_ts','in_file')])])
    
    # applymoco premat and fullwarpfield
    applywarp = MapNode(fsl.ApplyWarp(interp='spline',
    relwarp=True,
    out_file='rest2anat.nii.gz',
    datatype='float'),
    iterfield=['in_file', 'premat'],
    name='applywarp')
    transform_ts.connect([(split, applywarp, [('out_files', 'in_file')]),
    (inputnode, applywarp, 
    [('mat_moco', 'premat'),
    ('fullwarp','field_file')]),
    (resample, applywarp, [('out_file', 'ref_file')])
    ])
    # re-concatenate volumes
    merge=Node(fsl.Merge(dimension='t',
    merged_file='rest2anat.nii.gz'),
    name='merge')
    transform_ts.connect([(applywarp,merge,[('out_file','in_files')]),
    (merge, outputnode, [('merged_file', 'trans_ts')])])
    # calculate new mean
    tmean = Node(fsl.maths.MeanImage(dimension='T',
    out_file='rest_mean2anat_lowres.nii.gz'),
    name='tmean')
    transform_ts.connect([(merge, tmean, [('merged_file', 'in_file')]),
    (tmean, outputnode, [('out_file', 'trans_ts_mean')])
    ])
    
    # resample brain mask
    resample_brain = Node(afni.Resample(resample_mode='NN',
    outputtype='NIFTI_GZ',
    out_file='T1_brain_mask_lowres.nii.gz'),
    name = 'resample_brain')
    transform_ts.connect([(inputnode, resample_brain, [('brain_mask', 'in_file')]),
                          (tmean, resample_brain,     [('out_file', 'master')]),
                          (resample_brain, outputnode, [('out_file', 'brain_mask_resamp')])
                          ])
    
    #mask the transformed file
    mask = Node(fsl.ApplyMask(), name="mask")
    transform_ts.connect([(resample_brain,mask, [('out_file', 'mask_file')]),
                          (merge, mask, [('merged_file', 'in_file')]),
                          (mask, outputnode, [('out_file', 'trans_ts_masked')])
		         ])


    #calculate DVARS
    dvars = Node(confounds.ComputeDVARS(save_all=True, save_plot=True), name="dvars")
    transform_ts.connect([(resample_brain, dvars, [('out_file', 'in_mask')]),
                          (merge, dvars, [('merged_file', 'in_file')]),
                          (dvars, outputnode, [('out_all', 'out_dvars')])
                         ])



    
    return transform_ts
Exemplo n.º 20
0
def init_dsi_studio_recon_wf(omp_nthreads,
                             has_transform,
                             name="dsi_studio_recon",
                             output_suffix="",
                             params={}):
    """Reconstructs diffusion data using DSI Studio.

    This workflow creates a ``.src.gz`` file from the input dwi, bvals and bvecs,
    then reconstructs ODFs using GQI.

    Inputs

        *Default qsiprep inputs*

    Outputs

        fibgz
            A DSI Studio fib file containing GQI ODFs, peaks and scalar values.

    Params

        ratio_of_mean_diffusion_distance: float
            Default 1.25. Distance to sample EAP at.

    """
    inputnode = pe.Node(niu.IdentityInterface(fields=input_fields +
                                              ['odf_rois']),
                        name="inputnode")
    outputnode = pe.Node(niu.IdentityInterface(fields=['fibgz']),
                         name="outputnode")
    workflow = Workflow(name=name)
    desc = """DSI Studio Reconstruction

: """
    create_src = pe.Node(DSIStudioCreateSrc(), name="create_src")
    romdd = params.get("ratio_of_mean_diffusion_distance", 1.25)
    gqi_recon = pe.Node(
        DSIStudioGQIReconstruction(ratio_of_mean_diffusion_distance=romdd),
        name="gqi_recon")
    desc += """\
Diffusion orientation distribution functions (ODFs) were reconstructed using
generalized q-sampling imaging (GQI, @yeh2010gqi) with a ratio of mean diffusion
distance of %02f.""" % romdd

    # Resample anat mask
    resample_mask = pe.Node(afni.Resample(outputtype='NIFTI_GZ',
                                          resample_mode="NN"),
                            name='resample_mask')

    # Make a visual report of the model
    plot_peaks = pe.Node(ReconPeaksReport(subtract_iso=True),
                         name='plot_peaks')
    ds_report_peaks = pe.Node(ReconDerivativesDataSink(extension='.png',
                                                       desc="GQIODF",
                                                       suffix='peaks'),
                              name='ds_report_peaks',
                              run_without_submitting=True)

    # Plot targeted regions
    if has_transform:
        ds_report_odfs = pe.Node(ReconDerivativesDataSink(extension='.png',
                                                          desc="GQIODF",
                                                          suffix='odfs'),
                                 name='ds_report_odfs',
                                 run_without_submitting=True)
        workflow.connect(plot_peaks, 'odf_report', ds_report_odfs, 'in_file')

    workflow.connect([
        (inputnode, create_src, [('dwi_file', 'input_nifti_file'),
                                 ('bval_file', 'input_bvals_file'),
                                 ('bvec_file', 'input_bvecs_file')]),
        (inputnode, resample_mask, [('t1_brain_mask', 'in_file'),
                                    ('dwi_file', 'master')]),
        (create_src, gqi_recon, [('output_src', 'input_src_file')]),
        (resample_mask, gqi_recon, [('out_file', 'mask')]),
        (gqi_recon, outputnode, [('output_fib', 'fibgz')]),
        (gqi_recon, plot_peaks, [('output_fib', 'fib_file')]),
        (inputnode, plot_peaks, [('dwi_ref', 'background_image'),
                                 ('odf_rois', 'odf_rois')]),
        (resample_mask, plot_peaks, [('out_file', 'mask_file')]),
        (plot_peaks, ds_report_peaks, [('out_report', 'in_file')])
    ])

    if output_suffix:
        # Save the output in the outputs directory
        ds_gqi_fibgz = pe.Node(ReconDerivativesDataSink(extension='.fib.gz',
                                                        suffix=output_suffix,
                                                        compress=True),
                               name='ds_gqi_fibgz',
                               run_without_submitting=True)
        workflow.connect(gqi_recon, 'output_fib', ds_gqi_fibgz, 'in_file')
    workflow.__desc__ = desc
    return workflow
Exemplo n.º 21
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.º 22
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.º 23
0
def create_lesion_preproc(wf_name='lesion_preproc'):
    """
    The main purpose of this workflow is to process lesions masks.
    Lesion mask file is deobliqued and reoriented in the same way as the T1 in
    the anat_preproc function.

    Returns
    -------
    lesion_preproc : workflow
        Lesion preprocessing Workflow

    Workflow Inputs::
        inputspec.lesion : string
            User input lesion mask, in any of the 8 orientations

    Workflow Outputs::

        outputspec.refit : string
            Path to deobliqued anatomical image

        outputspec.reorient : string
            Path to RPI oriented anatomical image

    Order of commands:
    - Deobliqing the scans. ::
        3drefit -deoblique mprage.nii.gz

    - Re-orienting the Image into Right-to-Left Posterior-to-Anterior
    Inferior-to-Superior  (RPI) orientation ::
        3dresample -orient RPI
                   -prefix mprage_RPI.nii.gz
                   -inset mprage.nii.gz

    Examples
    --------
    >>> from CPAC.anat_preproc.lesion_preproc import create_lesion_preproc
    >>> preproc = create_lesion_preproc()
    >>> preproc.inputs.inputspec.lesion = 'sub1/anat/lesion-mask.nii.gz'
    >>> preproc.run() #doctest: +SKIP
    """

    preproc = pe.Workflow(name=wf_name)

    inputnode = pe.Node(util.IdentityInterface(fields=['lesion']),
                        name='inputspec')

    outputnode = pe.Node(util.IdentityInterface(fields=['refit', 'reorient']),
                         name='outputspec')

    lesion_deoblique = pe.Node(interface=afni.Refit(), name='lesion_deoblique')

    lesion_deoblique.inputs.deoblique = True

    lesion_inverted = pe.Node(interface=util.Function(
        input_names=['lesion_path'],
        output_names=['lesion_out'],
        function=inverse_lesion),
                              name='inverse_lesion')
    # We first check and invert the lesion if needed to be used by ANTs
    preproc.connect(inputnode, 'lesion', lesion_inverted, 'lesion_path')

    preproc.connect(lesion_inverted, 'lesion_out', lesion_deoblique, 'in_file')

    preproc.connect(lesion_deoblique, 'out_file', outputnode, 'refit')

    # Anatomical reorientation
    lesion_reorient = pe.Node(interface=afni.Resample(),
                              name='lesion_reorient')

    lesion_reorient.inputs.orientation = 'RPI'
    lesion_reorient.inputs.outputtype = 'NIFTI_GZ'

    preproc.connect(lesion_deoblique, 'out_file', lesion_reorient, 'in_file')
    preproc.connect(lesion_reorient, 'out_file', outputnode, 'reorient')

    return preproc
Exemplo n.º 24
0
# TODO_ready: erode compcor noise mask!!!!
erode_mask = pe.MapNode(fsl.ErodeImage(),
                        iterfield=['in_file'],
                        name="erode_compcor_mask")


def pickindex(vec, i):
    return [x[i] for x in vec]


myfuncproc = funcproc.FuncProc()

#create atlas matching this space
resample_atlas = pe.Node(
    interface=afni.Resample(
        outputtype='NIFTI_GZ',
        in_file="/Users/tspisak/data/atlases/MIST/Parcellations/MIST_7.nii.gz",
        master=globals._FSLDIR_ + '/data/standard/MNI152_T1_3mm_brain.nii.gz'),
    name='resample_atlas')  #default interpolation is nearest neighbour

# standardize what you need
myfunc2mni = transform.func2mni(stdreg=_regtype_,
                                carpet_plot="1_original",
                                wf_name="func2mni_1")
myfunc2mni_cc = transform.func2mni(stdreg=_regtype_,
                                   carpet_plot="2_cc",
                                   wf_name="func2mni_2_cc")
myfunc2mni_cc_bpf = transform.func2mni(stdreg=_regtype_,
                                       carpet_plot="3_cc_bpf",
                                       wf_name="func2mni_3_cc_bpf")
myfunc2mni_cc_bpf_cens = transform.func2mni(stdreg=_regtype_,
                                            carpet_plot="4_cc_bpf_cens",
Exemplo n.º 25
0
def create_denoise_pipeline(name='denoise'):
    # workflow
    denoise = Workflow(name='denoise')
    # Define nodes
    inputnode = Node(interface=util.IdentityInterface(fields=['brain_mask',
                                                              'epi_coreg',
                                                              'wmseg',
                                                              'csfseg',
                                                              'highpass_freq',
                                                              'tr']),
                     name='inputnode')
    outputnode = Node(interface=util.IdentityInterface(fields=['wmcsf_mask',
                                                               'combined_motion',
                                                               'comp_regressor',
                                                               'comp_F',
                                                               'comp_pF',
                                                               'out_betas',
                                                               'ts_fullspectrum',
                                                               'ts_filtered']),
                      name='outputnode')

    # combine tissue classes to noise mask
    wmcsf_mask = Node(fsl.BinaryMaths(operation='add',
                                      out_file='wmcsf_mask.nii'),
                      name='wmcsf_mask')
    denoise.connect([(inputnode, wmcsf_mask, [('wmseg', 'in_file'),
                                              ('csfseg', 'operand_file')])])
        
    #resample + binarize wm_csf mask to epi resolution.
   
    resample_wmcsf= Node(afni.Resample(resample_mode='NN',
    outputtype='NIFTI_GZ',
    out_file='wmcsf_mask_lowres.nii.gz'),
    name = 'resample_wmcsf')
    
    bin_wmcsf_mask=Node(fsl.utils.ImageMaths(), name="bin_wmcsf_mask")
    bin_wmcsf_mask.inputs.op_string='-nan -thr 0.99 -ero -bin'
    
    denoise.connect([(wmcsf_mask, resample_wmcsf, [('out_file', 'in_file')]),
                     (inputnode, resample_wmcsf, [('brain_mask', 'master')]),
                     (resample_wmcsf, bin_wmcsf_mask,[('out_file', 'in_file')]),
                     (bin_wmcsf_mask, outputnode, [('out_file', 'wmcsf_mask')])
                    ])
         
    #no other denoising filters created here because AROMA performs already well.
       
    compcor=Node(conf.ACompCor(), name="compcor")
    compcor.inputs.num_components=5 #https://www.sciencedirect.com/science/article/pii/S105381191400175X?via%3Dihub
    denoise.connect([
                     (inputnode, compcor, [('epi_coreg', 'realigned_file')]),
                     (bin_wmcsf_mask, compcor, [('out_file', 'mask_files')]),
                     
                     ])    
    
    def create_designs(compcor_regressors,epi_coreg,mask):
            import numpy as np
            import pandas as pd
            import os
            from nilearn.input_data import NiftiMasker
           
            brain_masker = NiftiMasker(mask_img = mask, 
                               smoothing_fwhm=None, standardize=False,
                               memory='nilearn_cache', 
                               memory_level=5, verbose=2)
    
            whole_brain = brain_masker.fit_transform(epi_coreg)
            avg_signal = np.mean(whole_brain,axis=1)
            
            all_regressors=pd.read_csv(compcor_regressors,sep='\t')
            
            #add global signal.
            all_regressors['global_signal']=avg_signal
            
            fn=os.getcwd()+'/all_regressors.txt'
            all_regressors.to_csv(fn, sep='\t', index=False)
            
            return [fn, compcor_regressors]
            
    #create a list of design to loop over.
    create_design = Node(util.Function(input_names=['compcor_regressors','epi_coreg','mask'], output_names=['reg_list'], function=create_designs),
              name='create_design')
    
    denoise.connect([
    (compcor, create_design, [('components_file', 'compcor_regressors')]),
    (inputnode, create_design, [('epi_coreg', 'epi_coreg')]),
    (inputnode, create_design, [('brain_mask', 'mask')])
    ])
    
    # regress compcor and other noise components
    filter2 = MapNode(fsl.GLM(out_f_name='F_noise.nii.gz',
                           out_pf_name='pF_noise.nii.gz',
                           out_res_name='rest2anat_denoised.nii.gz',
                           output_type='NIFTI_GZ',
                           demean=True), 
                    iterfield=['design'],
                    name='filternoise')
    filter2.plugin_args = {'submit_specs': 'request_memory = 17000'}
    
    denoise.connect([(inputnode, filter2, [('epi_coreg', 'in_file')]),
                     #(createfilter2, filter2, [('out_files', 'design')]),
                     #(compcor, filter2, [('components_file', 'design')]),
                     (create_design, filter2, [('reg_list', 'design')]),
                     (inputnode, filter2, [('brain_mask', 'mask')]),
                     (filter2, outputnode, [('out_f', 'comp_F'),
                                            ('out_pf', 'comp_pF'),
                                            ('out_file', 'out_betas'),
                                            ('out_res', 'ts_fullspectrum'),
                                            ])
                     ])



    def calc_sigma(TR,highpass):
        # https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind1205&L=FSL&P=R57592&1=FSL&9=A&I=-3&J=on&d=No+Match%3BMatch%3BMatches&z=4
        sigma=1. / (2 * TR * highpass)
        return sigma

    calc_s=Node(util.Function(input_names=['TR', 'highpass'], output_names=['sigma'], function=calc_sigma),
                  name='calc_s')
    
    
    denoise.connect(inputnode, 'tr', calc_s, 'TR')
    denoise.connect(inputnode, 'highpass_freq', calc_s, 'highpass')
    
    #use only highpass filter (because high-frequency content is already somewhat filtered in AROMA)) 
    highpass_filter = MapNode(fsl.TemporalFilter(out_file='rest_denoised_highpassed.nii'),
                           name='highpass_filter', iterfield=['in_file'])
    highpass_filter.plugin_args = {'submit_specs': 'request_memory = 17000'}
    denoise.connect([(calc_s, highpass_filter, [('sigma', 'highpass_sigma')]),
                     (filter2, highpass_filter, [('out_res', 'in_file')]),
                     (highpass_filter, outputnode, [('out_file', 'ts_filtered')])
                     ])
    
    return denoise
Exemplo n.º 26
0
def init_dipy_mapmri_recon_wf(name="dipy_mapmri_recon",
                              output_suffix="",
                              params={}):
    """Reconstruct EAPs, ODFs, using 3dSHORE (brainsuite-style basis set).

    Inputs

        *qsiprep outputs*

    Outputs

        shore_coeffs
            3dSHORE coefficients
        rtop
            Voxelwise Return-to-origin probability.
        rtap
            Voxelwise Return-to-axis probability.
        rtpp
            Voxelwise Return-to-plane probability.
        msd
            Voxelwise MSD
        qiv
            q-space inverse variance
        lapnorm
            Voxelwise norm of the Laplacian

    Params

        write_fibgz: bool
            True writes out a DSI Studio fib file
        write_mif: bool
            True writes out a MRTrix mif file with sh coefficients
        radial_order: int
            An even integer that represent the order of the basis
        laplacian_regularization: bool
            Regularize using the Laplacian of the MAP-MRI basis.
        laplacian_weighting: str or scalar
            The string 'GCV' makes it use generalized cross-validation to find
            the regularization weight. A scalar sets the regularization
            weight to that value and an array will make it selected the
            optimal weight from the values in the array.
        positivity_constraint: bool
            Constrain the propagator to be positive.
        pos_grid: int
            Grid points for estimating EAP(default=15)
        pos_radius
            Radius for EAP estimation (default=20e-03) or "adaptive"
        anisotropic_scaling : bool,
            If True, uses the standard anisotropic MAP-MRI basis. If False,
            uses the isotropic MAP-MRI basis (equal to 3D-SHORE).
        eigenvalue_threshold : float,
            Sets the minimum of the tensor eigenvalues in order to avoid
            stability problem.
        bval_threshold : float,
            Sets the b-value threshold to be used in the scale factor
            estimation. In order for the estimated non-Gaussianity to have
            meaning this value should set to a lower value (b<2000 s/mm^2)
            such that the scale factors are estimated on signal points that
            reasonably represent the spins at Gaussian diffusion.
        dti_scale_estimation : bool,
            Whether or not DTI fitting is used to estimate the isotropic scale
            factor for isotropic MAP-MRI.
            When set to False the algorithm presets the isotropic tissue
            diffusivity to static_diffusivity. This vastly increases fitting
            speed but at the cost of slightly reduced fitting quality. Can
            still be used in combination with regularization and constraints.
        static_diffusivity : float,
            the tissue diffusivity that is used when dti_scale_estimation is
            set to False. The default is that of typical white matter
            D=0.7e-3 _[5].
        cvxpy_solver : str, optional
            cvxpy solver name. Optionally optimize the positivity constraint
            with a particular cvxpy solver. See http://www.cvxpy.org/ for
            details.
            Default: None (cvxpy chooses its own solver)
    """

    inputnode = pe.Node(niu.IdentityInterface(fields=input_fields),
                        name="inputnode")
    outputnode = pe.Node(niu.IdentityInterface(fields=[
        'mapmri_coeffs', 'rtop', 'rtap', 'rtpp', 'fibgz', 'fod_sh_mif',
        'parng', 'perng', 'ng', 'qiv', 'lapnorm', 'msd'
    ]),
                         name="outputnode")

    workflow = pe.Workflow(name=name)
    recon_map = pe.Node(MAPMRIReconstruction(**params), name="recon_map")
    resample_mask = pe.Node(afni.Resample(outputtype='NIFTI_GZ',
                                          resample_mode="NN"),
                            name='resample_mask')

    workflow.connect([(inputnode, recon_map, [('dwi_file', 'dwi_file'),
                                              ('bval_file', 'bval_file'),
                                              ('bvec_file', 'bvec_file')]),
                      (inputnode, resample_mask, [('t1_brain_mask', 'in_file'),
                                                  ('dwi_file', 'master')]),
                      (resample_mask, recon_map, [('out_file', 'mask_file')]),
                      (recon_map, outputnode, [('mapmri_coeffs',
                                                'mapmri_coeffs'),
                                               ('rtop', 'rtop'),
                                               ('rtap', 'rtap'),
                                               ('rtpp', 'rtpp'),
                                               ('parng', 'parng'),
                                               ('perng', 'perng'),
                                               ('msd', 'msd'), ('ng', 'ng'),
                                               ('qiv', 'qiv'),
                                               ('lapnorm', 'lapnorm'),
                                               ('fibgz', 'fibgz'),
                                               ('fod_sh_mif', 'fod_sh_mif')])])
    if output_suffix:
        external_format_datasinks(output_suffix, params, workflow)
        connections = []
        for scalar_name in ['rtop', 'rtap', 'rtpp', 'qiv', 'msd', 'lapnorm']:
            connections += [
                (outputnode,
                 pe.Node(ReconDerivativesDataSink(desc=scalar_name,
                                                  suffix=output_suffix),
                         name='ds_%s_%s' % (name, scalar_name)), [(scalar_name,
                                                                   'in_file')])
            ]
        workflow.connect(connections)

    return workflow
Exemplo n.º 27
0
def create_qc_carpet(wf_name='qc_carpet', output_image='qc_carpet'):

    wf = pe.Workflow(name=wf_name)

    input_node = pe.Node(util.IdentityInterface(fields=[
        'functional_to_standard', 'mean_functional_to_standard',
        'anatomical_gm_mask', 'anatomical_wm_mask', 'anatomical_csf_mask'
    ]),
                         name='inputspec')

    output_node = pe.Node(util.IdentityInterface(fields=['carpet_plot']),
                          name='outputspec')

    gm_resample = pe.Node(afni.Resample(), name='gm_resample')
    gm_resample.inputs.outputtype = 'NIFTI'
    wf.connect(input_node, 'anatomical_gm_mask', gm_resample, 'in_file')
    wf.connect(input_node, 'mean_functional_to_standard', gm_resample,
               'master')

    gm_mask = pe.Node(afni.Calc(), name="gm_mask")
    gm_mask.inputs.expr = 'astep(a, 0.5)'
    gm_mask.inputs.outputtype = 'NIFTI'
    wf.connect(gm_resample, 'out_file', gm_mask, 'in_file_a')

    wm_resample = pe.Node(afni.Resample(), name='wm_resample')
    wm_resample.inputs.outputtype = 'NIFTI'
    wf.connect(input_node, 'anatomical_wm_mask', wm_resample, 'in_file')
    wf.connect(input_node, 'mean_functional_to_standard', wm_resample,
               'master')

    wm_mask = pe.Node(afni.Calc(), name="wm_mask")
    wm_mask.inputs.expr = 'astep(a, 0.5)'
    wm_mask.inputs.outputtype = 'NIFTI'
    wf.connect(wm_resample, 'out_file', wm_mask, 'in_file_a')

    csf_resample = pe.Node(afni.Resample(), name='csf_resample')
    csf_resample.inputs.outputtype = 'NIFTI'
    wf.connect(input_node, 'anatomical_csf_mask', csf_resample, 'in_file')
    wf.connect(input_node, 'mean_functional_to_standard', csf_resample,
               'master')

    csf_mask = pe.Node(afni.Calc(), name="csf_mask")
    csf_mask.inputs.expr = 'astep(a, 0.5)'
    csf_mask.inputs.outputtype = 'NIFTI'
    wf.connect(csf_resample, 'out_file', csf_mask, 'in_file_a')

    carpet_plot = pe.Node(Function(input_names=[
        'gm_mask', 'wm_mask', 'csf_mask', 'functional_to_standard', 'output'
    ],
                                   output_names=['carpet_plot'],
                                   function=gen_carpet_plt,
                                   as_module=True),
                          name='carpet_plot')

    carpet_plot.inputs.output = output_image
    wf.connect(gm_mask, 'out_file', carpet_plot, 'gm_mask')
    wf.connect(wm_mask, 'out_file', carpet_plot, 'wm_mask')
    wf.connect(csf_mask, 'out_file', carpet_plot, 'csf_mask')
    wf.connect(input_node, 'functional_to_standard', carpet_plot,
               'functional_to_standard')
    wf.connect(carpet_plot, 'carpet_plot', output_node, 'carpet_plot')

    return wf
Exemplo n.º 28
0
def init_dipy_brainsuite_shore_recon_wf(name="dipy_3dshore_recon",
                                        output_suffix="",
                                        params={}):
    """Reconstruct EAPs, ODFs, using 3dSHORE (brainsuite-style basis set).

    Inputs

        *qsiprep outputs*

    Outputs

        shore_coeffs
            3dSHORE coefficients
        rtop
            Voxelwise Return-to-origin probability.
        rtap
            Voxelwise Return-to-axis probability.
        rtpp
            Voxelwise Return-to-plane probability.


    Params

        write_fibgz: bool
            True writes out a DSI Studio fib file
        write_mif: bool
            True writes out a MRTrix mif file with sh coefficients
        convert_to_multishell: str
            either "HCP", "ABCD", "lifespan" will resample the data with this scheme
        radial_order: int
            Radial order for spherical harmonics (even)
        zeta: float
            Zeta parameter for basis set.
        tau:float
            Diffusion parameter (default= 4 * np.pi**2)
        regularization
            "L2" or "L1". Default is "L2"
        lambdaN
            LambdaN parameter for L2 regularization. (default=1e-8)
        lambdaL
            LambdaL parameter for L2 regularization. (default=1e-8)
        regularization_weighting: int or "CV"
            L1 regualrization weighting. Default "CV" (use cross-validation).
            Can specify a static value to use in all voxels.
        l1_positive_constraint: bool
            Use positivity constraint.
        l1_maxiter
            Maximum number of iterations for L1 optization. (Default=1000)
        l1_alpha
            Alpha parameter for L1 optimization. (default=1.0)
        pos_grid: int
            Grid points for estimating EAP(default=11)
        pos_radius
            Radius for EAP estimation (default=20e-03)

    """

    inputnode = pe.Node(niu.IdentityInterface(fields=input_fields),
                        name="inputnode")
    outputnode = pe.Node(niu.IdentityInterface(fields=[
        'shore_coeffs_image', 'rtop_image', 'alpha_image', 'r2_image',
        'cnr_image', 'regularization_image', 'fibgz', 'fod_sh_mif', 'dwi_file',
        'bval_file', 'bvec_file', 'b_file'
    ]),
                         name="outputnode")

    workflow = pe.Workflow(name=name)
    resample_mask = pe.Node(afni.Resample(outputtype='NIFTI_GZ',
                                          resample_mode="NN"),
                            name='resample_mask')
    recon_shore = pe.Node(BrainSuiteShoreReconstruction(**params),
                          name="recon_shore")
    doing_extrapolation = params.get("extrapolate_scheme") in ("HCP", "ABCD")

    workflow.connect([
        (inputnode, recon_shore, [('dwi_file', 'dwi_file'),
                                  ('bval_file', 'bval_file'),
                                  ('bvec_file', 'bvec_file')]),
        (inputnode, resample_mask, [('t1_brain_mask', 'in_file'),
                                    ('dwi_file', 'master')]),
        (resample_mask, recon_shore, [('out_file', 'mask_file')]),
        (recon_shore, outputnode,
         [('shore_coeffs_image', 'shore_coeffs_image'),
          ('rtop_image', 'rtop_image'), ('alpha_image', 'alpha_image'),
          ('r2_image', 'r2_image'), ('cnr_image', 'cnr_image'),
          ('regularization_image', 'regularization_image'), ('fibgz', 'fibgz'),
          ('fod_sh_mif', 'fod_sh_mif'), ('extrapolated_dwi', 'dwi_file'),
          ('extrapolated_bvals', 'bval_file'),
          ('extrapolated_bvecs', 'bvec_file'), ('extrapolated_b', 'b_file')])
    ])

    if output_suffix:
        external_format_datasinks(output_suffix, params, workflow)

        ds_rtop = pe.Node(ReconDerivativesDataSink(extension='.nii.gz',
                                                   desc="rtop",
                                                   suffix=output_suffix,
                                                   compress=True),
                          name='ds_bsshore_rtop',
                          run_without_submitting=True)
        workflow.connect(outputnode, 'rtop_image', ds_rtop, 'in_file')

        ds_coeff = pe.Node(ReconDerivativesDataSink(extension='.nii.gz',
                                                    desc="SHOREcoeff",
                                                    suffix=output_suffix,
                                                    compress=True),
                           name='ds_bsshore_coeff',
                           run_without_submitting=True)
        workflow.connect(outputnode, 'shore_coeffs_image', ds_coeff, 'in_file')

        ds_alpha = pe.Node(ReconDerivativesDataSink(extension='.nii.gz',
                                                    desc="L1alpha",
                                                    suffix=output_suffix,
                                                    compress=True),
                           name='ds_bsshore_alpha',
                           run_without_submitting=True)
        workflow.connect(outputnode, 'alpha_image', ds_alpha, 'in_file')

        ds_r2 = pe.Node(ReconDerivativesDataSink(extension='.nii.gz',
                                                 desc="r2",
                                                 suffix=output_suffix,
                                                 compress=True),
                        name='ds_bsshore_r2',
                        run_without_submitting=True)
        workflow.connect(outputnode, 'r2_image', ds_r2, 'in_file')

        ds_cnr = pe.Node(ReconDerivativesDataSink(extension='.nii.gz',
                                                  desc="CNR",
                                                  suffix=output_suffix,
                                                  compress=True),
                         name='ds_bsshore_cnr',
                         run_without_submitting=True)
        workflow.connect(outputnode, 'cnr_image', ds_cnr, 'in_file')

        ds_regl = pe.Node(ReconDerivativesDataSink(extension='.nii.gz',
                                                   desc="regularization",
                                                   suffix=output_suffix,
                                                   compress=True),
                          name='ds_bsshore_regl',
                          run_without_submitting=True)
        workflow.connect(outputnode, 'regularization_image', ds_regl,
                         'in_file')
        if doing_extrapolation:
            ds_extrap_dwi = pe.Node(ReconDerivativesDataSink(
                extension='.nii.gz',
                desc="extrapolated",
                suffix=output_suffix,
                compress=True),
                                    name='ds_extrap_dwi',
                                    run_without_submitting=True)
            workflow.connect(outputnode, 'dwi_file', ds_extrap_dwi, 'in_file')
            ds_extrap_bval = pe.Node(ReconDerivativesDataSink(
                extension='.bval', desc="extrapolated", suffix=output_suffix),
                                     name='ds_extrap_bval',
                                     run_without_submitting=True)
            workflow.connect(outputnode, 'bval_file', ds_extrap_bval,
                             'in_file')
            ds_extrap_bvec = pe.Node(ReconDerivativesDataSink(
                extension='.bvec', desc="extrapolated", suffix=output_suffix),
                                     name='ds_extrap_bvec',
                                     run_without_submitting=True)
            workflow.connect(outputnode, 'bvec_file', ds_extrap_bvec,
                             'in_file')
            ds_extrap_b = pe.Node(ReconDerivativesDataSink(
                extension='.b', desc="extrapolated", suffix=output_suffix),
                                  name='ds_extrap_b',
                                  run_without_submitting=True)
            workflow.connect(outputnode, 'b_file', ds_extrap_b, 'in_file')
    return workflow
Exemplo n.º 29
0
import nipype.interfaces.fsl as fsl

### resampling template data to 2mm

# all input/output hard coded (not good...)
myindata = '/data/pt_neuam005/sheyma/mni_icbm152_nlin_asym_09c/'

# choose a subject's EPI image with 2mm  resoltuib as 'masterfile'
masterdi = '/data/pt_neuam005/FSTIM_1_Think_preprocessed/fmriprep/sub-10/ses-01/func/'
masterte = 'sub-10_ses-01_task-future_bold_space-MNI152NLin2009cAsym_preproc.nii.gz'
masterfi = os.path.join(masterdi, masterte)

os.chdir(myindata)

# afni resample
resample = afni.Resample()
resample.inputs.in_file = 'mni_icbm152_t1_tal_nlin_asym_09c.nii'
resample.inputs.voxel_size = (2.0, 2.0, 2.0)
resample.inputs.master = masterfi
resample.inputs.outputtype = 'NIFTI'
resample.inputs.out_file = 'mni_icbm152_t1_tal_nlin_asym_09c_2mm.nii.gz'
print(resample.cmdline)
resample.run()

# transforming template mask to 2mm (fsl nonlinear transform)
aw = fsl.ApplyWarp()
aw.inputs.in_file = 'mni_icbm152_t1_tal_nlin_asym_09c_mask.nii'
aw.inputs.ref_file = 'mni_icbm152_t1_tal_nlin_asym_09c_2mm.nii.gz'
aw.inputs.out_file = 'mni_icbm152_t1_tal_nlin_asym_09c_2mm_trf.nii.gz'
print(aw.cmdline)
aw.run()
Exemplo n.º 30
0
def create_anat_preproc(method='afni',
                        already_skullstripped=False,
                        c=None,
                        wf_name='anat_preproc'):
    """The main purpose of this workflow is to process T1 scans. Raw mprage file is deobliqued, reoriented
    into RPI and skullstripped. Also, a whole brain only mask is generated from the skull stripped image
    for later use in registration.

    Returns
    -------
    anat_preproc : workflow
        Anatomical Preprocessing Workflow

    Notes
    -----
    `Source <https://github.com/FCP-INDI/C-PAC/blob/master/CPAC/anat_preproc/anat_preproc.py>`_

    Workflow Inputs::
        inputspec.anat : string
            User input anatomical (T1) Image, in any of the 8 orientations

    Workflow Outputs::

        outputspec.refit : string
            Path to deobliqued anatomical image

        outputspec.reorient : string
            Path to RPI oriented anatomical image

        outputspec.skullstrip : string
            Path to skull stripped RPI oriented mprage file with normalized intensities.

        outputspec.brain : string
            Path to skull stripped RPI brain image with original intensity values and not normalized or scaled.

    Order of commands:
    - Deobliqing the scans. ::
        3drefit -deoblique mprage.nii.gz

    - Re-orienting the Image into Right-to-Left Posterior-to-Anterior Inferior-to-Superior  (RPI) orientation ::
        3dresample -orient RPI
                   -prefix mprage_RPI.nii.gz
                   -inset mprage.nii.gz

    - Skull-Stripping the image ::
        Using AFNI ::
            3dSkullStrip -input mprage_RPI.nii.gz
                         -o_ply mprage_RPI_3dT.nii.gz
        or using BET ::
            bet mprage_RPI.nii.gz

    - The skull-stripping step modifies the intensity values. To get back the original intensity values, we do an element wise product of RPI data with step function of skull-stripped data ::
        3dcalc -a mprage_RPI.nii.gz
               -b mprage_RPI_3dT.nii.gz
               -expr 'a*step(b)'
               -prefix mprage_RPI_3dc.nii.gz

    High Level Workflow Graph:
    .. image:: ../images/anatpreproc_graph.dot.png
       :width: 500

    Detailed Workflow Graph:
    .. image:: ../images/anatpreproc_graph_detailed.dot.png
       :width: 500

    Examples
    --------
    >>> from CPAC.anat_preproc import create_anat_preproc
    >>> preproc = create_anat_preproc()
    >>> preproc.inputs.inputspec.anat = 'sub1/anat/mprage.nii.gz'
    >>> preproc.run() #doctest: +SKIP
    """

    preproc = pe.Workflow(name=wf_name)

    inputnode = pe.Node(util.IdentityInterface(fields=['anat', 'brain_mask']),
                        name='inputspec')

    outputnode = pe.Node(util.IdentityInterface(
        fields=['refit', 'reorient', 'skullstrip', 'brain', 'brain_mask']),
                         name='outputspec')

    anat_deoblique = pe.Node(interface=afni.Refit(), name='anat_deoblique')
    anat_deoblique.inputs.deoblique = True
    preproc.connect(inputnode, 'anat', anat_deoblique, 'in_file')

    preproc.connect(anat_deoblique, 'out_file', outputnode, 'refit')
    # Disable non_local_means_filtering and n4_bias_field_correction when run niworkflows-ants
    if method == 'niworkflows-ants':
        c.non_local_means_filtering = False
        c.n4_bias_field_correction = False

    if c.non_local_means_filtering and c.n4_bias_field_correction:
        denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise')
        preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image')
        n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3,
                                                          shrink_factor=2,
                                                          copy_header=True),
                     name='anat_n4')
        preproc.connect(denoise, 'output_image', n4, 'input_image')
    elif c.non_local_means_filtering and not c.n4_bias_field_correction:
        denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise')
        preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image')
    elif not c.non_local_means_filtering and c.n4_bias_field_correction:
        n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3,
                                                          shrink_factor=2,
                                                          copy_header=True),
                     name='anat_n4')
        preproc.connect(anat_deoblique, 'out_file', n4, 'input_image')

    # Anatomical reorientation
    anat_reorient = pe.Node(interface=afni.Resample(), name='anat_reorient')
    anat_reorient.inputs.orientation = 'RPI'
    anat_reorient.inputs.outputtype = 'NIFTI_GZ'

    if c.n4_bias_field_correction:
        preproc.connect(n4, 'output_image', anat_reorient, 'in_file')
    elif c.non_local_means_filtering and not c.n4_bias_field_correction:
        preproc.connect(denoise, 'output_image', anat_reorient, 'in_file')
    else:
        preproc.connect(anat_deoblique, 'out_file', anat_reorient, 'in_file')

    preproc.connect(anat_reorient, 'out_file', outputnode, 'reorient')

    if already_skullstripped:

        anat_skullstrip = pe.Node(
            interface=util.IdentityInterface(fields=['out_file']),
            name='anat_skullstrip')

        preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'out_file')

        preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip')

        preproc.connect(anat_skullstrip, 'out_file', outputnode, 'brain')

    else:

        if method == 'afni':
            # Skull-stripping using AFNI 3dSkullStrip
            inputnode_afni = pe.Node(util.IdentityInterface(fields=[
                'mask_vol', 'shrink_factor', 'var_shrink_fac',
                'shrink_fac_bot_lim', 'avoid_vent', 'niter', 'pushout',
                'touchup', 'fill_hole', 'avoid_eyes', 'use_edge', 'exp_frac',
                'smooth_final', 'push_to_edge', 'use_skull', 'perc_int',
                'max_inter_iter', 'blur_fwhm', 'fac', 'monkey'
            ]),
                                     name='AFNI_options')

            skullstrip_args = pe.Node(util.Function(
                input_names=[
                    'spat_norm', 'spat_norm_dxyz', 'mask_vol', 'shrink_fac',
                    'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent',
                    'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes',
                    'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge',
                    'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm',
                    'fac', 'monkey'
                ],
                output_names=['expr'],
                function=create_3dskullstrip_arg_string),
                                      name='anat_skullstrip_args')

            preproc.connect([(inputnode_afni, skullstrip_args,
                              [('mask_vol', 'mask_vol'),
                               ('shrink_factor', 'shrink_fac'),
                               ('var_shrink_fac', 'var_shrink_fac'),
                               ('shrink_fac_bot_lim', 'shrink_fac_bot_lim'),
                               ('avoid_vent', 'avoid_vent'),
                               ('niter', 'niter'), ('pushout', 'pushout'),
                               ('touchup', 'touchup'),
                               ('fill_hole', 'fill_hole'),
                               ('avoid_eyes', 'avoid_eyes'),
                               ('use_edge', 'use_edge'),
                               ('exp_frac', 'exp_frac'),
                               ('smooth_final', 'smooth_final'),
                               ('push_to_edge', 'push_to_edge'),
                               ('use_skull', 'use_skull'),
                               ('perc_int', 'perc_int'),
                               ('max_inter_iter', 'max_inter_iter'),
                               ('blur_fwhm', 'blur_fwhm'), ('fac', 'fac'),
                               ('monkey', 'monkey')])])

            anat_skullstrip = pe.Node(interface=afni.SkullStrip(),
                                      name='anat_skullstrip')

            anat_skullstrip.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file', anat_skullstrip,
                            'in_file')
            preproc.connect(skullstrip_args, 'expr', anat_skullstrip, 'args')

            # Generate anatomical brain mask

            anat_brain_mask = pe.Node(interface=afni.Calc(),
                                      name='anat_brain_mask')

            anat_brain_mask.inputs.expr = 'step(a)'
            anat_brain_mask.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_skullstrip, 'out_file', anat_brain_mask,
                            'in_file_a')

            # Apply skull-stripping step mask to original volume
            anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(),
                                               name='anat_skullstrip_orig_vol')

            anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)'
            anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_a')

            preproc.connect(anat_brain_mask, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_b')

            preproc.connect(anat_brain_mask, 'out_file', outputnode,
                            'brain_mask')

            preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode,
                            'brain')

        elif method == 'fsl':
            # Skull-stripping using FSL BET
            inputnode_bet = pe.Node(util.IdentityInterface(fields=[
                'frac', 'mask_boolean', 'mesh_boolean', 'outline', 'padding',
                'radius', 'reduce_bias', 'remove_eyes', 'robust', 'skull',
                'surfaces', 'threshold', 'vertical_gradient'
            ]),
                                    name='BET_options')

            anat_skullstrip = pe.Node(interface=fsl.BET(),
                                      name='anat_skullstrip')
            anat_skullstrip.inputs.output_type = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file', anat_skullstrip,
                            'in_file')

            preproc.connect([(inputnode_bet, anat_skullstrip, [
                ('frac', 'frac'),
                ('mask_boolean', 'mask'),
                ('mesh_boolean', 'mesh'),
                ('outline', 'outline'),
                ('padding', 'padding'),
                ('radius', 'radius'),
                ('reduce_bias', 'reduce_bias'),
                ('remove_eyes', 'remove_eyes'),
                ('robust', 'robust'),
                ('skull', 'skull'),
                ('surfaces', 'surfaces'),
                ('threshold', 'threshold'),
                ('vertical_gradient', 'vertical_gradient'),
            ])])

            preproc.connect(anat_skullstrip, 'out_file', outputnode,
                            'skullstrip')

            # Apply skull-stripping step mask to original volume
            anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(),
                                               name='anat_skullstrip_orig_vol')

            anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)'
            anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_a')

            preproc.connect(anat_skullstrip, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_b')

            preproc.connect(anat_skullstrip, 'mask_file', outputnode,
                            'brain_mask')

            preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode,
                            'brain')

        elif method == 'niworkflows-ants':
            # Skull-stripping using niworkflows-ants
            anat_skullstrip_ants = init_brain_extraction_wf(
                tpl_target_path=c.niworkflows_ants_template_path,
                tpl_mask_path=c.niworkflows_ants_mask_path,
                tpl_regmask_path=c.niworkflows_ants_regmask_path,
                name='anat_skullstrip_ants')

            preproc.connect(anat_reorient, 'out_file', anat_skullstrip_ants,
                            'inputnode.in_files')

            preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file',
                            outputnode, 'skullstrip')

            preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file',
                            outputnode, 'brain')

            preproc.connect(anat_skullstrip_ants,
                            'atropos_wf.copy_xform.out_mask', outputnode,
                            'brain_mask')

        elif method == 'mask':

            brain_mask_deoblique = pe.Node(interface=afni.Refit(),
                                           name='brain_mask_deoblique')
            brain_mask_deoblique.inputs.deoblique = True
            preproc.connect(inputnode, 'brain_mask', brain_mask_deoblique,
                            'in_file')

            brain_mask_reorient = pe.Node(interface=afni.Resample(),
                                          name='brain_mask_reorient')
            brain_mask_reorient.inputs.orientation = 'RPI'
            brain_mask_reorient.inputs.outputtype = 'NIFTI_GZ'
            preproc.connect(brain_mask_deoblique, 'out_file',
                            brain_mask_reorient, 'in_file')

            anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(),
                                               name='anat_skullstrip_orig_vol')
            anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)'
            anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ'

            preproc.connect(anat_reorient, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_a')

            preproc.connect(brain_mask_reorient, 'out_file',
                            anat_skullstrip_orig_vol, 'in_file_b')

            preproc.connect(brain_mask_reorient, 'out_file', outputnode,
                            'brain_mask')

            preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode,
                            'brain')

        elif method == 'unet':
            """
            UNet
            options (following numbers are default):
            input_slice: 3
            conv_block: 5
            kernel_root: 16
            rescale_dim: 256
            """
            # TODO: add options to pipeline_config
            train_model = UNet2d(dim_in=3, num_conv_block=5, kernel_root=16)
            unet_path = check_for_s3(c.unet_model)
            checkpoint = torch.load(unet_path, map_location={'cuda:0': 'cpu'})
            train_model.load_state_dict(checkpoint['state_dict'])
            model = nn.Sequential(train_model, nn.Softmax2d())

            # create a node called unet_mask
            unet_mask = pe.Node(util.Function(input_names=['model', 'cimg_in'],
                                              output_names=['out_path'],
                                              function=predict_volumes),
                                name='unet_mask')

            unet_mask.inputs.model = model
            preproc.connect(anat_reorient, 'out_file', unet_mask, 'cimg_in')
            """
            Revised mask with ANTs
            """
            # fslmaths <whole head> -mul <mask> brain.nii.gz
            unet_masked_brain = pe.Node(interface=fsl.MultiImageMaths(),
                                        name='unet_masked_brain')
            unet_masked_brain.inputs.op_string = "-mul %s"
            preproc.connect(anat_reorient, 'out_file', unet_masked_brain,
                            'in_file')
            preproc.connect(unet_mask, 'out_path', unet_masked_brain,
                            'operand_files')

            # flirt -v -dof 6 -in brain.nii.gz -ref NMT_SS_0.5mm.nii.gz -o brain_rot2atl -omat brain_rot2atl.mat -interp sinc
            # TODO change it to ANTs linear transform
            native_brain_to_template_brain = pe.Node(
                interface=fsl.FLIRT(), name='native_brain_to_template_brain')
            native_brain_to_template_brain.inputs.reference = c.template_brain_only_for_anat
            native_brain_to_template_brain.inputs.dof = 6
            native_brain_to_template_brain.inputs.interp = 'sinc'
            preproc.connect(unet_masked_brain, 'out_file',
                            native_brain_to_template_brain, 'in_file')

            # flirt -in head.nii.gz -ref NMT_0.5mm.nii.gz -o head_rot2atl -applyxfm -init brain_rot2atl.mat
            # TODO change it to ANTs linear transform
            native_head_to_template_head = pe.Node(
                interface=fsl.FLIRT(), name='native_head_to_template_head')
            native_head_to_template_head.inputs.reference = c.template_skull_for_anat
            native_head_to_template_head.inputs.apply_xfm = True
            preproc.connect(anat_reorient, 'out_file',
                            native_head_to_template_head, 'in_file')
            preproc.connect(native_brain_to_template_brain, 'out_matrix_file',
                            native_head_to_template_head, 'in_matrix_file')

            # fslmaths NMT_SS_0.5mm.nii.gz -bin templateMask.nii.gz
            template_brain_mask = pe.Node(interface=fsl.maths.MathsCommand(),
                                          name='template_brain_mask')
            template_brain_mask.inputs.in_file = c.template_brain_only_for_anat
            template_brain_mask.inputs.args = '-bin'

            # ANTS 3 -m  CC[head_rot2atl.nii.gz,NMT_0.5mm.nii.gz,1,5] -t SyN[0.25] -r Gauss[3,0] -o atl2T1rot -i 60x50x20 --use-Histogram-Matching  --number-of-affine-iterations 10000x10000x10000x10000x10000 --MI-option 32x16000
            ants_template_head_to_template = pe.Node(
                interface=ants.Registration(),
                name='template_head_to_template')
            ants_template_head_to_template.inputs.metric = ['CC']
            ants_template_head_to_template.inputs.metric_weight = [1, 5]
            ants_template_head_to_template.inputs.moving_image = c.template_skull_for_anat
            ants_template_head_to_template.inputs.transforms = ['SyN']
            ants_template_head_to_template.inputs.transform_parameters = [
                (0.25, )
            ]
            ants_template_head_to_template.inputs.interpolation = 'NearestNeighbor'
            ants_template_head_to_template.inputs.number_of_iterations = [[
                60, 50, 20
            ]]
            ants_template_head_to_template.inputs.smoothing_sigmas = [[
                0.6, 0.2, 0.0
            ]]
            ants_template_head_to_template.inputs.shrink_factors = [[4, 2, 1]]
            ants_template_head_to_template.inputs.convergence_threshold = [
                1.e-8
            ]
            preproc.connect(native_head_to_template_head, 'out_file',
                            ants_template_head_to_template, 'fixed_image')

            # antsApplyTransforms -d 3 -i templateMask.nii.gz -t atl2T1rotWarp.nii.gz atl2T1rotAffine.txt -r brain_rot2atl.nii.gz -o brain_rot2atl_mask.nii.gz
            template_head_transform_to_template = pe.Node(
                interface=ants.ApplyTransforms(),
                name='template_head_transform_to_template')
            template_head_transform_to_template.inputs.dimension = 3
            preproc.connect(template_brain_mask, 'out_file',
                            template_head_transform_to_template, 'input_image')
            preproc.connect(native_brain_to_template_brain, 'out_file',
                            template_head_transform_to_template,
                            'reference_image')
            preproc.connect(ants_template_head_to_template,
                            'forward_transforms',
                            template_head_transform_to_template, 'transforms')

            # convert_xfm -omat brain_rot2native.mat -inverse brain_rot2atl.mat
            invt = pe.Node(interface=fsl.ConvertXFM(), name='convert_xfm')
            invt.inputs.invert_xfm = True
            preproc.connect(native_brain_to_template_brain, 'out_matrix_file',
                            invt, 'in_file')

            # flirt -in brain_rot2atl_mask.nii.gz -ref brain.nii.gz -o brain_mask.nii.gz -applyxfm -init brain_rot2native.mat
            template_brain_to_native_brain = pe.Node(
                interface=fsl.FLIRT(), name='template_brain_to_native_brain')
            template_brain_to_native_brain.inputs.apply_xfm = True
            preproc.connect(template_head_transform_to_template,
                            'output_image', template_brain_to_native_brain,
                            'in_file')
            preproc.connect(unet_masked_brain, 'out_file',
                            template_brain_to_native_brain, 'reference')
            preproc.connect(invt, 'out_file', template_brain_to_native_brain,
                            'in_matrix_file')

            # fslmaths brain_mask.nii.gz -thr .5 -bin brain_mask_thr.nii.gz
            refined_mask = pe.Node(interface=fsl.Threshold(),
                                   name='refined_mask')
            refined_mask.inputs.thresh = 0.5
            preproc.connect(template_brain_to_native_brain, 'out_file',
                            refined_mask, 'in_file')

            # get a new brain with mask
            refined_brain = pe.Node(interface=fsl.MultiImageMaths(),
                                    name='refined_brain')
            refined_brain.inputs.op_string = "-mul %s"
            preproc.connect(anat_reorient, 'out_file', refined_brain,
                            'in_file')
            preproc.connect(refined_mask, 'out_file', refined_brain,
                            'operand_files')

            preproc.connect(refined_mask, 'out_file', outputnode, 'brain_mask')
            preproc.connect(refined_brain, 'out_file', outputnode, 'brain')

    return preproc