Example #1
0
def dwi_prep(degibbs: Path,
             PA: Path,
             out_file: Path,
             data_type: str = "dwi",
             func=None):
    eddy_dir = Path(degibbs.parent / "eddyqc")
    if not eddy_dir.is_dir():
        print("Creating directory for eddy current correction parameters...")
    ### extract first AP volume
    AP_b0 = Path(degibbs.parent / "AP_b0.mif")
    if not AP_b0.is_file():
        mrconvert = mrt.MRConvert()
        mrconvert.inputs.in_file = degibbs
        mrconvert.inputs.out_file = AP_b0
        mrconvert.inputs.coord = [3, 0]
        print(mrconvert.cmdline)
        mrconvert.run()
    ### concatenate AP and PA
    dual_phased = Path(degibbs.parent / "b0s.mif")
    if not dual_phased.is_file():
        cmd = (
            f"mrcat {AP_b0.absolute()} {PA.absolute()} {dual_phased.absolute()} -axis 3"
        )
        os.system(cmd)
    ### initiate dwipreproc (eddy)
    args = "-rpe_pair"
    eddyqc_text = "eddyqc/"
    cmd = f"dwipreproc {degibbs.absolute()} {out_file.absolute()} -pe_dir AP {args} -se_epi {dual_phased.absolute()} -eddyqc_text {degibbs.parent}/{eddyqc_text}"
    print(cmd)
    return cmd
def DWI_prep(degibbs: str,
             PA: str,
             out_file: str,
             data_type: str = "dwi",
             func=None):
    eddy_dir = f"{os.path.dirname(degibbs)}/eddyqc"
    if not os.path.isdir(eddy_dir):
        print("Creating directory for eddy current correction parameters...")
    ### extract first AP volume

    mrconvert = mrt.MRConvert()
    mrconvert.inputs.in_file = degibbs
    mrconvert.inputs.out_file = f"{os.path.dirname(degibbs)}/AP_b0.mif"
    mrconvert.inputs.coord = [3, 0]
    print(mrconvert.cmdline)
    mrconvert.run()
    ### concatenate AP and PA
    cmd = f"mrcat {mrconvert.inputs.out_file} {PA} {os.path.dirname(degibbs)}/b0s.mif -axis 3"
    os.system(cmd)
    ### initiate dwipreproc (eddy)
    in_file = func

    args = "-rpe_pair"
    eddyqc_text = "eddyqc/"
    cmd = f"dwipreproc {in_file} {out_file} -pe_dir AP {args} -se_epi {os.path.dirname(degibbs)}/b0s.mif -eddyqc_text {os.path.dirname(degibbs)}/{eddyqc_text}"
    print(cmd)
    os.system(cmd)
    return out_file
def convert_to_mif(in_file, out_file, bvec=None, bval=None):
    mrconvert = mrt.MRConvert()
    mrconvert.inputs.in_file = in_file
    mrconvert.inputs.out_file = out_file
    if bvec and bval:
        mrconvert.inputs.args = (
            f"-json_import {mrconvert.inputs.in_file.replace('nii.gz','json')}"
        )
        mrconvert.inputs.grad_fsl = (bvec, bval)
    mrconvert.run()
    return out_file
Example #4
0
def convert_tmp_anat(in_file: str):
    if "mif" in in_file:
        out_file = f"{os.path.dirname(in_file)}/T1.nii"
    else:
        out_file = in_file.replace("nii.gz", "mif")
    if not os.path.isfile(out_file):
        mrconvert = mrt.MRConvert()
        mrconvert.inputs.in_file = in_file
        mrconvert.inputs.out_file = out_file
        mrconvert.inputs.args = "-strides +1,+2,+3"
        print(mrconvert.cmdline)
        mrconvert.run()
    return out_file
Example #5
0
def convert_to_mif(in_file, out_file, bvec=None, bval=None, anat=False):
    mrconvert = mrt.MRConvert()
    mrconvert.inputs.in_file = in_file
    mrconvert.inputs.out_file = out_file
    mrconvert.inputs.args = "-quiet"
    if bvec and bval:
        mrconvert.inputs.args = (
            f"-json_import {mrconvert.inputs.in_file.replace('nii.gz','json')}"
        )
        mrconvert.inputs.grad_fsl = (bvec, bval)
    if anat:
        mrconvert.inputs.args = "-strides +1,+2,+3 -quiet"
    mrconvert.run()
    return out_file
Example #6
0
    def preprocess_dwi_data(self,
                            data,
                            index,
                            acqp,
                            atlas2use,
                            ResponseSD_algorithm='tournier',
                            fod_algorithm='csd',
                            tract_algorithm='iFOD2',
                            streamlines_number='10M'):
        '''
        preprocessing of dwi data and connectome extraction

        Parameters
        ----------

        subjects_dir = path to the subjects' folders
        data: tuple |
            a tuple having the path to dwi, bvecs and bvals files. It is obtained
            using the function grab_data()
        index: str |
            Name of text file specifying the relationship between the images in
            --imain and the information in --acqp and --topup. E.g. index.txt
        acqp: str |
            Name of text file with information about the acquisition of the images
            in --imain
        atlas2use: str |
             The input node parcellation image
        ResponseSD_algorithm (optional): str |
             Select the algorithm to be used to complete the script operation;
             Options are: dhollander, fa, manual, msmt_5tt, tax, tournier
             (Default is 'tournier')
        fod_algorithm (optional): str |
             The algorithm to use for FOD estimation. (options are: csd,msmt_csd)
             (Default is 'csd')
        tract_algorithm (optional): str |
            specify the tractography algorithm to use. Valid choices are: FACT,
            iFOD1, iFOD2, Nulldist1, Nulldist2, SD_Stream, Seedtest, Tensor_Det,
            Tensor_Prob (Default is 'iFOD2')
        streamlines_number (optional): str |
            set the desired number of streamlines (Default is '10M')
    '''

        if len(data[0]) != len(data[1]):
            raise ValueError(
                'dwi datas do not have the same shape of bvec files')
        if len(data[0]) != len(data[2]):
            raise ValueError(
                'dwi datas do not have the same shape of bval files')
        if len(data[1]) != len(data[2]):
            raise ValueError(
                'bvec files do not have the same shape of bvec files')

        for subj in range(len(data[0])):
            print('Extracting B0 volume for subject', subj)
            self.roi = fsl.ExtractROI(
                in_file=data[0][subj],
                roi_file=os.path.join(
                    os.path.split(data[0][subj])[0] + '/' +
                    os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                    '_nodiff.nii.gz'),
                t_min=0,
                t_size=1)
            self.roi.run()

            print('Converting into .mif for subject', subj)
            self.mrconvert = mrt.MRConvert()
            self.mrconvert.inputs.in_file = data[0][subj]
            self.mrconvert.inputs.grad_fsl = (data[1][subj], data[2][subj])
            self.mrconvert.inputs.out_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] + '_dwi.mif')
            self.mrconvert.run()

            print('Denoising data for subject', subj)
            self.denoise = mrt.DWIDenoise()
            self.denoise.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] + '_dwi.mif')
            self.denoise.inputs.noise = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_noise.mif')
            self.denoise.inputs.out_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised.mif')
            self.denoise.run()

            self.denoise_convert = mrt.MRConvert()
            self.denoise_convert.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised.mif')
            self.denoise_convert.inputs.out_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised.nii.gz')
            self.denoise_convert.run()

            print('Skull stripping for subject', subj)
            self.mybet = fsl.BET()
            self.mybet.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_nodiff.nii.gz')
            self.mybet.inputs.out_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_denoised_brain.nii.gz')
            self.mybet.inputs.frac = 0.1
            self.mybet.inputs.robust = True
            self.mybet.inputs.mask = True
            self.mybet.run()

            print('Running Eddy for subject', subj)
            self.eddy = Eddy()
            self.eddy.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised.nii.gz')
            self.eddy.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_denoised_brain_mask.nii.gz')
            self.eddy.inputs.in_acqp = acqp
            self.eddy.inputs.in_bvec = data[1][subj]
            self.eddy.inputs.in_bval = data[2][subj]
            self.eddy.inputs.out_base = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised_eddy.nii.gz')
            self.eddy.run()

            print('Running Bias Correction for subject', subj)
            self.bias_correct = mrt.DWIBiasCorrect()
            self.bias_correct.inputs.use_ants = True
            self.bias_correct.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised_eddy.nii.gz')
            self.bias_correct.inputs.grad_fsl = (os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised_eddy.eddy_rotated_bvecs.bvec'), data[2][subj])
            self.bias_correct.inputs.bias = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] + '_bias.mif')
            self.bias_correct.inputs.out_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised_eddy_unbiased.mif')
            self.bias_correct.run()

            print('Calculating Response function for subject', subj)
            self.resp = mrt.ResponseSD()
            self.resp.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised_eddy_unbiased.mif')
            self.resp.inputs.algorithm = ResponseSD_algorithm
            self.resp.inputs.grad_fsl = (os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised_eddy.eddy_rotated_bvecs.bvec'), data[2][subj])
            self.resp.inputs.wm_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_response.txt')
            self.resp.run()

            print('Estimating FOD for subject', subj)
            self.fod = mrt.EstimateFOD()
            self.fod.inputs.algorithm = fod_algorithm
            self.fod.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_dwi_denoised_eddy_unbiased.mif')
            self.fod.inputs.wm_txt = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_response.txt')
            self.fod.inputs.mask_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_denoised_brain_mask.nii.gz')
            self.fod.inputs.grad_fsl = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_response.txt')
            self.fod.run()

            print('Extracting whole brain tract for subject', subj)
            self.tk = mrt.Tractography()
            self.tk.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] + 'fods.mif')
            self.tk.inputs.roi_mask = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_denoised_brain_mask.nii.gz')
            self.tk.inputs.algorithm = tract_algorithm
            self.tk.inputs.seed_image = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_denoised_brain_mask.nii.gz')
            self.tk.inputs.select = streamlines_number
            self.tk.inputs.out_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_whole_brain_' + streamlines_number + '.tck')
            self.tk.run()

            print('Extracting connectome for subject', subj)
            self.mat = mrt.BuildConnectome()
            self.mat.inputs.in_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_whole_brain_' + streamlines_number + '.tck')
            self.mat.inputs.in_parc = atlas2use
            self.mat.inputs.out_file = os.path.join(
                os.path.split(data[0][subj])[0] + '/' +
                os.path.split(data[0][0])[1].split(".nii.gz")[0] +
                '_connectome.csv')
            self.mat.run()
import os 
from os.path import abspath
from datetime import datetime
from IPython.display import Image
import pydot
from nipype import Workflow, Node, MapNode, Function, config
from nipype.interfaces.fsl import TOPUP, ApplyTOPUP, BET, ExtractROI,  Eddy, FLIRT, FUGUE
from nipype.interfaces.fsl.maths import MathsCommand
import nipype.interfaces.utility as util 
import nipype.interfaces.mrtrix3 as mrt
#Requirements for the workflow to run smoothly: All files as in NIfTI-format and named according to the following standard: 
#Images are from the tonotopy DKI sequences on the 7T Philips Achieva scanner in Lund. It should work with any DKI sequence and possibly also a standard DTI but the setting for B0-corrections, epi-distortion corrections and eddy current corrections will be wrong. 
#DKI file has a base name shared with bvec and bval in FSL format. E.g. "DKI.nii.gz" "DKI.bvec" and "DKI.bval". 
#There is one b0-volume with reversed (P->A) phase encoding called DKIbase+_revenc. E.g. "DKI_revenc.nii.gz". 
#Philips B0-map magnitude and phase offset (in Hz) images. 
#One input file for topup describing the images as specified by topup. 
#Set nbrOfThreads to number of available CPU threads to run the analyses. 
### Need to make better revenc for the 15 version if we choose to use it (i.e. same TE and TR)
#Set to relevant directory/parameters
datadir=os.path.abspath("/Users/ling-men/Documents/MRData/testDKI")
rawDKI_base='DKI_15' 
B0map_base = 'B0map'
nbrOfThreads=6
print_graph = True 
acqparam_file = os.path.join(datadir,'acqparams.txt')
index_file = os.path.join(datadir,'index.txt')
####
#config.enable_debug_mode()
DKI_nii=os.path.join(datadir, rawDKI_base+'.nii.gz')
DKI_bval=os.path.join(datadir, rawDKI_base+'.bval')
Example #8
0
import sys
import nipype
import nipype.pipeline as pe

import nipype.interfaces.io as io
import nipype.interfaces.mrtrix3 as mrtrix3

#Generic datagrabber module that wraps around glob in an
io_data_grabber = pe.Node(io.DataGrabber(outfields=["outfiles"]),
                          name='io_data_grabber')
io_data_grabber.inputs.sort_filelist = True
io_data_grabber.inputs.template = "/Users/bsms9gep/data/*.nii"

#Wraps the executable command ``mrconvert``.
mrtrix3_mrconvert = pe.Node(interface=mrtrix3.MRConvert(),
                            name='mrtrix3_mrconvert')
mrtrix3_mrconvert.inputs.grad_fsl = ("/Users/bsms9gep/data/bvecs",
                                     "/Users/bsms9gep/data/bvals")

#Wraps the executable command ``dwi2mask``.
mrtrix3_brain_mask = pe.Node(interface=mrtrix3.BrainMask(),
                             name='mrtrix3_brain_mask')

#Wraps the executable command ``dwibiascorrect``.
mrtrix3_dwibias_correct = pe.Node(interface=mrtrix3.DWIBiasCorrect(),
                                  name='mrtrix3_dwibias_correct')
mrtrix3_dwibias_correct.inputs.out_file = 'dwi_unbiased.mif'

#Wraps the executable command ``dwi2response``.
mrtrix3_response_sd = pe.Node(interface=mrtrix3.ResponseSD(),
"""
Diffusion-weighted MRI data processing pipeline:
In construction:
"""

# pipeline engine of nipype
import nipype.pipeline.engine as pe

# python interface to mrtrix3 (mrtrix3 need to be installed in your computer)
from nipype.interfaces import mrtrix3
from dwi_nodes import sift_filtering, rigid_transform_estimation, apply_linear_transform

# Elementary bricks

# Data conversion from .nii to .mif file (allows to embed diffusion bvals et bvecs)
mrconvert = pe.Node(interface=mrtrix3.MRConvert(), name="mrconvert")

# Bias correction of the diffusion MRI data (for more quantitative approach)
dwibiascorrect = pe.Node(interface=mrtrix3.preprocess.DWIBiasCorrect(),
                         name="dwibiascorrect")
dwibiascorrect.use_ants = True

# gross brain mask stemming from DWI data
dwi2mask = pe.Node(interface=mrtrix3.utils.BrainMask(), name="dwi2mask")

# tensor coefficients estimation
dwi2tensor = pe.Node(interface=mrtrix3.reconst.FitTensor(), name="dwi2tensor")

# derived FA contrast for registration
tensor2fa = pe.Node(interface=mrtrix3.TensorMetrics(), name="tensor2fa")
Example #10
0
def dholl_preproc_wf(shells=[0, 1000, 2000],
                     lmax=[0, 8, 8],
                     sshell=False,
                     noreorient=False,
                     template_dir=None,
                     template_label=None,
                     wdir=None,
                     nthreads=1,
                     name='dholl_preproc_wf'):
    """
    Set up Dhollander response preproc workflow
    No assumption of registration to T1w space is made
    """

    if template_dir is None or template_label is None:
        print("Missing template info")
        raise IOError

    # Grab template data
    templateGrabber = io.getTemplate(template_dir=template_dir,
                                     template_label=template_label,
                                     wdir=wdir)

    # Convert nii to mif
    dwiConvert = pe.Node(mrt.MRConvert(), name='dwiConvert')
    dwiConvert.base_dir = wdir
    dwiConvert.inputs.nthreads = nthreads
    dwiConvert.interface.num_threads = nthreads

    # dwi2response - included but not used
    dwi2response = pe.Node(mrt.ResponseSD(), name='dwi2response')
    dwi2response.base_dir = wdir
    dwi2response.inputs.algorithm = 'dhollander'
    dwi2response.inputs.wm_file = 'space-dwi_model-CSD_WMResp.txt'
    dwi2response.inputs.gm_file = 'space-dwi_model-CSD_GMResp.txt'
    dwi2response.inputs.csf_file = 'space-dwi_model-CSD_CSFResp.txt'
    dwi2response.inputs.max_sh = lmax
    dwi2response.inputs.shell = shells
    dwi2response.inputs.nthreads = nthreads
    dwi2response.interface.num_threads = nthreads

    # Convert mask (nii) to mif
    maskConvert = pe.Node(mrt.MRConvert(), name='maskConvert')
    maskConvert.base_dir = wdir
    maskConvert.inputs.nthreads = nthreads
    maskConvert.interface.num_threads = nthreads

    # dwi2fod
    dwi2fod = pe.Node(mrt.EstimateFOD(), name='dwi2fod')
    dwi2fod.base_dir = wdir
    dwi2fod.inputs.algorithm = 'msmt_csd'
    dwi2fod.inputs.shell = shells
    dwi2fod.inputs.wm_odf = 'space-dwi_model-CSD_WMFOD.mif'
    if sshell is False:
        dwi2fod.inputs.gm_odf = 'space-dwi_model-CSD_GMFOD.mif'
    dwi2fod.inputs.csf_odf = 'space-dwi_model-CSD_CSFFOD.mif'
    dwi2fod.inputs.nthreads = nthreads
    dwi2fod.interface.num_threads = nthreads

    # mtnormalise
    mtnormalise = pe.Node(mrt.MTNormalise(), name='mtnormalise')
    mtnormalise.base_dir = wdir
    mtnormalise.inputs.out_wm = 'space-dwi_model-CSD_WMFODNorm.mif'
    if sshell is False:
        mtnormalise.inputs.out_gm = 'space-dwi_model-CSD_GMFODNorm.mif'
    mtnormalise.inputs.out_csf = 'space-dwi_model-CSD_CSFFODNorm.mif'
    mtnormalise.inputs.nthreads = nthreads
    mtnormalise.interface.num_threads = nthreads

    # Registration
    MRRegister = pe.Node(mrt.MRRegister(), name='MRRegister')
    MRRegister.base_dir = wdir
    # MRRegister.inputs.ref_file = template
    MRRegister.inputs.nl_warp = [
        'from-dwi_to-Template_xfm.mif', 'from-Template_to-dwi_xfm.mif'
    ]
    if noreorient is not False:
        MRRegister.inputs.noreorientation = noreorient
    MRRegister.inputs.nthreads = nthreads
    MRRegister.interface.num_threads = nthreads

    # Transforms
    WarpSelect1 = pe.Node(niu.Select(), name='WarpSelect1')
    WarpSelect1.base_dir = wdir
    WarpSelect1.inputs.index = [0]
    WarpSelect1.interface.num_threads = nthreads

    WarpSelect2 = pe.Node(niu.Select(), name='WarpSelect2')
    WarpSelect2.base_dir = wdir
    WarpSelect2.inputs.index = [1]
    WarpSelect2.interface.num_threads = nthreads

    # Warp data
    MaskTransform = pe.Node(mrt.MRTransform(), name='MaskTransform')
    MaskTransform.base_dir = wdir
    MaskTransform.inputs.out_file = 'space-Template_brainmask.mif'
    MaskTransform.inputs.nthreads = nthreads
    MaskTransform.interface.num_threads = nthreads

    FODTransform = pe.Node(mrt.MRTransform(), name='FODTransform')
    FODTransform.base_dir = wdir
    FODTransform.inputs.out_file = 'space-Template_model-CSD_WMFODNorm.mif'
    FODTransform.inputs.nthreads = nthreads
    FODTransform.interface.num_threads = nthreads

    # Tensor processing
    DWINormalise = pe.Node(mrt.DWINormalise(), name='DWINormalise')
    DWINormalise.base_dir = wdir
    DWINormalise.inputs.out_file = 'space-dwi_dwiNorm.mif'
    DWINormalise.inputs.nthreads = nthreads
    DWINormalise.interface.num_threads = nthreads

    DWITransform = pe.Node(mrt.MRTransform(), name='DWITransform')
    DWITransform.base_dir = wdir
    DWITransform.inputs.out_file = 'space-Template_dwiNorm.mif'
    DWITransform.inputs.nthreads = nthreads
    DWITransform.interface.num_threads = nthreads

    FitTensor = pe.Node(mrt.FitTensor(), name='FitTensor')
    FitTensor.base_dir = wdir
    FitTensor.inputs.out_file = 'space-Template_desc-WLS_model-DTI_tensor.mif'
    FitTensor.inputs.nthreads = nthreads
    FitTensor.interface.num_threads = nthreads

    TensorMetrics = pe.Node(mrt.TensorMetrics(), name='TensorMetrics')
    TensorMetrics.base_dir = wdir
    TensorMetrics.inputs.out_fa = 'space-Template_model-DTI_FA.mif'
    TensorMetrics.inputs.out_adc = 'space-Template_model-DTI_MD.mif'
    TensorMetrics.inputs.out_ad = 'space-Template_model-DTI_AD.mif'
    TensorMetrics.inputs.out_rd = 'space-Template_model-DTI_RD.mif'
    TensorMetrics.inputs.nthreads = nthreads
    TensorMetrics.interface.num_threads = nthreads

    # Build workflow
    workflow = pe.Workflow(name=name)

    # Single shell
    if sshell is True:
        workflow.connect([
            # Compute FOD
            (dwiConvert, dwi2response, [('out_file', 'in_file')]),
            (dwiConvert, dwi2fod, [('out_file', 'in_file')]),
            (dwi2response, dwi2fod, [('wm_file', 'wm_txt'),
                                     ('csf_file', 'csf_txt')]),
            (dwi2fod, mtnormalise, [('wm_odf', 'in_wm'),
                                    ('csf_odf', 'in_csf')]),
            (maskConvert, dwi2response, [('out_file', 'in_mask')]),
            (maskConvert, dwi2fod, [('out_file', 'mask_file')]),
            (maskConvert, mtnormalise, [('out_file', 'mask')]),
            (maskConvert, MRRegister, [('out_file', 'mask1')]),
            (templateGrabber, MRRegister, [('wm_fod', 'ref_file'),
                                           ('mask', 'mask2')]),
            (mtnormalise, MRRegister, [('out_wm', 'in_file')]),
            (MRRegister, WarpSelect1, [('nl_warp', 'inlist')]),
            (MRRegister, WarpSelect2, [('nl_warp', 'inlist')]),
            (maskConvert, MaskTransform, [('out_file', 'in_file')]),
            (WarpSelect1, MaskTransform, [('out', 'warp')]),
            (mtnormalise, FODTransform, [('out_wm', 'in_file')]),
            (WarpSelect1, FODTransform, [('out', 'warp')]),
            # Compute tensors
            (dwiConvert, DWINormalise, [('out_file', 'in_file')]),
            (maskConvert, DWINormalise, [('out_file', 'in_mask')]),
            (DWINormalise, DWITransform, [('out_file', 'in_file')]),
            (WarpSelect1, DWITransform, [('out', 'warp')]),
            (DWITransform, FitTensor, [('out_file', 'in_file')]),
            (MaskTransform, FitTensor, [('out_file', 'in_mask')]),
            (FitTensor, TensorMetrics, [('out_file', 'in_file')]),
            (MaskTransform, TensorMetrics, [('out_file', 'in_mask')])
        ])

    # For multi-shell
    else:
        workflow.connect([
            # Compute FOD
            (dwiConvert, dwi2response, [('out_file', 'in_file')]),
            (dwiConvert, dwi2fod, [('out_file', 'in_file')]),
            (dwi2response, dwi2fod, [('wm_file', 'wm_txt'),
                                     ('gm_file', 'gm_txt'),
                                     ('csf_file', 'csf_txt')]),
            (dwi2fod, mtnormalise, [('wm_odf', 'in_wm'), ('gm_odf', 'in_gm'),
                                    ('csf_odf', 'in_csf')]),
            (maskConvert, dwi2response, [('out_file', 'in_mask')]),
            (maskConvert, dwi2fod, [('out_file', 'mask_file')]),
            (maskConvert, mtnormalise, [('out_file', 'mask')]),
            (maskConvert, MRRegister, [('out_file', 'mask1')]),
            (templateGrabber, MRRegister, [('wm_fod', 'ref_file'),
                                           ('mask', 'mask2')]),
            (mtnormalise, MRRegister, [('out_wm', 'in_file')]),
            (MRRegister, WarpSelect1, [('nl_warp', 'inlist')]),
            (MRRegister, WarpSelect2, [('nl_warp', 'inlist')]),
            (maskConvert, MaskTransform, [('out_file', 'in_file')]),
            (WarpSelect1, MaskTransform, [('out', 'warp')]),
            (mtnormalise, FODTransform, [('out_wm', 'in_file')]),
            (WarpSelect1, FODTransform, [('out', 'warp')]),
            # Compute tensors
            (dwiConvert, DWINormalise, [('out_file', 'in_file')]),
            (maskConvert, DWINormalise, [('out_file', 'in_mask')]),
            (DWINormalise, DWITransform, [('out_file', 'in_file')]),
            (WarpSelect1, DWITransform, [('out', 'warp')]),
            (DWITransform, FitTensor, [('out_file', 'in_file')]),
            (MaskTransform, FitTensor, [('out_file', 'in_mask')]),
            (FitTensor, TensorMetrics, [('out_file', 'in_file')]),
            (MaskTransform, TensorMetrics, [('out_file', 'in_mask')])
        ])

    return workflow
Example #11
0
def create_dwi_processing_pipeline():
    # Nodes
    inputnode = pe.Node(
        utility.IdentityInterface(
            fields=[
                "diffusion_volume",
                "bvals",
                "bvecs",
                "t1_volume",
                "nb_tracks",
                "min_length",
                "max_length",
            ],
            mandatory_inputs=False,
        ),
        name="inputnode",
    )
    # Data conversion from .nii to .mif file (allows to embed diffusion bvals et bvecs)
    mrconvert = pe.Node(interface=mrtrix3.MRConvert(), name="mrconvert")
    # Main processing steps
    core_pipeline = create_core_dwi_processing_pipeline()
    # Outputs params
    outputnode = pe.Node(
        utility.IdentityInterface(
            fields=[
                "corrected_diffusion_volume",
                "wm_fod",
                "tractogram",
                "diffusion_to_t1_transform",
            ],
            mandatory_inputs=False,
        ),
        name="outputnode",
    )

    dwi_processing_pipeline = pe.Workflow(name="dwi_processing_pipeline")
    dwi_processing_pipeline.connect([(
        inputnode,
        mrconvert,
        [
            ("diffusion_volume", "in_file"),
            ("bvals", "in_bval"),
            ("bvecs", "in_bvec"),
        ],
    )])
    dwi_processing_pipeline.connect([(
        inputnode,
        core_pipeline,
        [
            ("t1_volume", "inputnode.t1_volume"),
            ("nb_tracks", "inputnode.nb_tracks"),
            ("min_length", "inputnode.min_length"),
            ("max_length", "inputnode.max_length"),
        ],
    )])
    dwi_processing_pipeline.connect(mrconvert, "out_file", core_pipeline,
                                    "inputnode.diffusion_volume")
    dwi_processing_pipeline.connect(
        core_pipeline,
        "outputnode.corrected_diffusion_volume",
        outputnode,
        "corrected_diffusion_volume",
    )
    dwi_processing_pipeline.connect(core_pipeline, "outputnode.wm_fod",
                                    outputnode, "wm_fod")
    dwi_processing_pipeline.connect(core_pipeline, "outputnode.tractogram",
                                    outputnode, "tractogram")
    dwi_processing_pipeline.connect(
        core_pipeline,
        "outputnode.diffusion_to_t1_transform",
        outputnode,
        "diffusion_to_t1_transform",
    )

    return dwi_processing_pipeline