예제 #1
0
def create_tbss_non_FA(name='tbss_non_FA'):
    """
    A pipeline that implement tbss_non_FA in FSL

    Example
    -------

    >>> from nipype.workflows.dmri.fsl import tbss
    >>> tbss_MD = tbss.create_tbss_non_FA()
    >>> tbss_MD.inputs.inputnode.file_list = []
    >>> tbss_MD.inputs.inputnode.field_list = []
    >>> tbss_MD.inputs.inputnode.skeleton_thresh = 0.2
    >>> tbss_MD.inputs.inputnode.groupmask = './xxx'
    >>> tbss_MD.inputs.inputnode.meanfa_file = './xxx'
    >>> tbss_MD.inputs.inputnode.distance_map = []

    Inputs::

        inputnode.file_list
        inputnode.field_list
        inputnode.skeleton_thresh
        inputnode.groupmask
        inputnode.meanfa_file
        inputnode.distance_map

    Outputs::

        outputnode.projected_nonFA_file

    """

    # Define the inputnode
    inputnode = pe.Node(interface=util.IdentityInterface(fields=[
        'file_list', 'field_list', 'skeleton_thresh', 'groupmask',
        'meanfa_file', 'distance_map'
    ]),
                        name='inputnode')

    # Apply the warpfield to the non FA image
    applywarp = pe.MapNode(interface=fsl.ApplyWarp(),
                           iterfield=['in_file', 'field_file'],
                           name="applywarp")
    if fsl.no_fsl():
        warn('NO FSL found')
    else:
        applywarp.inputs.ref_file = fsl.Info.standard_image(
            "FMRIB58_FA_1mm.nii.gz")
    # Merge the non FA files into a 4D file
    merge = pe.Node(fsl.Merge(dimension="t"), name="merge")
    #merged_file="all_FA.nii.gz"
    maskgroup = pe.Node(fsl.ImageMaths(op_string="-mas", suffix="_masked"),
                        name="maskgroup")
    projectfa = pe.Node(
        fsl.TractSkeleton(
            project_data=True,
            #projected_data = 'test.nii.gz',
            use_cingulum_mask=True),
        name="projectfa")

    tbss_non_FA = pe.Workflow(name=name)
    tbss_non_FA.connect([
        (inputnode, applywarp, [
            ('file_list', 'in_file'),
            ('field_list', 'field_file'),
        ]),
        (applywarp, merge, [("out_file", "in_files")]),
        (merge, maskgroup, [("merged_file", "in_file")]),
        (inputnode, maskgroup, [('groupmask', 'in_file2')]),
        (maskgroup, projectfa, [('out_file', 'data_file')]),
        (inputnode, projectfa, [
            ('skeleton_thresh', 'threshold'),
            ("meanfa_file", "in_file"),
            ("distance_map", "distance_map"),
        ]),
    ])

    # Define the outputnode
    outputnode = pe.Node(
        interface=util.IdentityInterface(fields=['projected_nonFA_file']),
        name='outputnode')
    tbss_non_FA.connect([
        (projectfa, outputnode, [
            ('projected_data', 'projected_nonFA_file'),
        ]),
    ])
    return tbss_non_FA
예제 #2
0
def create_tbss_4_prestats(name='tbss_4_prestats'):
    """Post-registration processing:Creating skeleton mask using a threshold
     projecting all FA data onto skeleton.
    A pipeline that does the same as tbss_4_prestats script from FSL

    Example
    -------

    >>> from nipype.workflows.dmri.fsl import tbss
    >>> tbss4 = tbss.create_tbss_4_prestats(name='tbss4')
    >>> tbss4.inputs.inputnode.skeleton_thresh = 0.2

    Inputs::

        inputnode.skeleton_thresh
        inputnode.groupmask
        inputnode.skeleton_file
        inputnode.meanfa_file
        inputnode.mergefa_file

    Outputs::

        outputnode.all_FA_skeletonised
        outputnode.mean_FA_skeleton_mask
        outputnode.distance_map
        outputnode.skeleton_file

    """
    # Create inputnode
    inputnode = pe.Node(interface=util.IdentityInterface(fields=[
        'groupmask', 'skeleton_file', 'meanfa_file', 'mergefa_file',
        'skeleton_thresh'
    ]),
                        name='inputnode')

    # Mask the skeleton at the threshold
    skeletonmask = pe.Node(fsl.ImageMaths(suffix="_mask"), name="skeletonmask")

    # Invert the brainmask then add in the tract skeleton
    invertmask = pe.Node(fsl.ImageMaths(suffix="_inv",
                                        op_string="-mul -1 -add 1 -add"),
                         name="invertmask")

    # Generate a distance map with the tract skeleton
    distancemap = pe.Node(fsl.DistanceMap(), name="distancemap")

    # Project the FA values onto the skeleton
    projectfa = pe.Node(fsl.TractSkeleton(project_data=True,
                                          skeleton_file=True,
                                          use_cingulum_mask=True),
                        name="projectfa")

    # Create tbss4 workflow
    tbss4 = pe.Workflow(name=name)
    tbss4.connect([
        (inputnode, invertmask, [("groupmask", "in_file")]),
        (inputnode, skeletonmask, [("skeleton_file", "in_file"),
                                   (('skeleton_thresh', tbss4_op_string),
                                    'op_string')]),
        (inputnode, projectfa, [('skeleton_thresh', 'threshold'),
                                ("meanfa_file", "in_file"),
                                ("mergefa_file", "data_file")]),
        (skeletonmask, invertmask, [("out_file", "in_file2")]),
        (invertmask, distancemap, [("out_file", "in_file")]),
        (distancemap, projectfa, [("distance_map", "distance_map")]),
    ])

    # Create the outputnode
    outputnode = pe.Node(interface=util.IdentityInterface(fields=[
        'projectedfa_file', 'skeleton_mask', 'distance_map', 'skeleton_file'
    ]),
                         name='outputnode')

    tbss4.connect([
        (projectfa, outputnode, [('projected_data', 'projectedfa_file'),
                                 ('skeleton_file', 'skeleton_file')]),
        (distancemap, outputnode, [('distance_map', 'distance_map')]),
        (skeletonmask, outputnode, [('out_file', 'skeleton_mask')])
    ])

    return tbss4
예제 #3
0
def create_tbss_3_postreg(name='tbss_3_postreg', estimate_skeleton=True):
    """Post-registration processing: derive mean_FA and mean_FA_skeleton from
    mean of all subjects in study. Target is assumed to be FMRIB58_FA_1mm.
    A pipeline that does the same as 'tbss_3_postreg -S' script from FSL
    Setting 'estimate_skeleton to False will use precomputed FMRIB58_FA-skeleton_1mm
    skeleton (same as 'tbss_3_postreg -T').

    Example
    -------

    >>> from nipype.workflows.dmri.fsl import tbss
    >>> tbss3 = tbss.create_tbss_3_postreg()
    >>> tbss3.inputs.inputnode.fa_list = ['s1_wrapped_FA.nii', 's2_wrapped_FA.nii', 's3_wrapped_FA.nii']

    Inputs::

        inputnode.field_list
        inputnode.fa_list

    Outputs::

        outputnode.groupmask
        outputnode.skeleton_file
        outputnode.meanfa_file
        outputnode.mergefa_file

    """

    # Create the inputnode
    inputnode = pe.Node(
        interface=util.IdentityInterface(fields=['field_list', 'fa_list']),
        name='inputnode')

    # Apply the warpfield to the masked FA image
    applywarp = pe.MapNode(interface=fsl.ApplyWarp(),
                           iterfield=['in_file', 'field_file'],
                           name="applywarp")
    if fsl.no_fsl():
        warn('NO FSL found')
    else:
        applywarp.inputs.ref_file = fsl.Info.standard_image(
            "FMRIB58_FA_1mm.nii.gz")

    # Merge the FA files into a 4D file
    mergefa = pe.Node(fsl.Merge(dimension="t"), name="mergefa")

    # Get a group mask
    groupmask = pe.Node(fsl.ImageMaths(op_string="-max 0 -Tmin -bin",
                                       out_data_type="char",
                                       suffix="_mask"),
                        name="groupmask")

    maskgroup = pe.Node(fsl.ImageMaths(op_string="-mas", suffix="_masked"),
                        name="maskgroup")

    tbss3 = pe.Workflow(name=name)
    tbss3.connect([
        (inputnode, applywarp, [("fa_list", "in_file"),
                                ("field_list", "field_file")]),
        (applywarp, mergefa, [("out_file", "in_files")]),
        (mergefa, groupmask, [("merged_file", "in_file")]),
        (mergefa, maskgroup, [("merged_file", "in_file")]),
        (groupmask, maskgroup, [("out_file", "in_file2")]),
    ])

    # Create outputnode
    outputnode = pe.Node(interface=util.IdentityInterface(
        fields=['groupmask', 'skeleton_file', 'meanfa_file', 'mergefa_file']),
                         name='outputnode')

    if estimate_skeleton:
        # Take the mean over the fourth dimension
        meanfa = pe.Node(fsl.ImageMaths(op_string="-Tmean", suffix="_mean"),
                         name="meanfa")

        # Use the mean FA volume to generate a tract skeleton
        makeskeleton = pe.Node(fsl.TractSkeleton(skeleton_file=True),
                               name="makeskeleton")
        tbss3.connect([
            (maskgroup, meanfa, [("out_file", "in_file")]),
            (meanfa, makeskeleton, [("out_file", "in_file")]),
            (groupmask, outputnode, [('out_file', 'groupmask')]),
            (makeskeleton, outputnode, [('skeleton_file', 'skeleton_file')]),
            (meanfa, outputnode, [('out_file', 'meanfa_file')]),
            (maskgroup, outputnode, [('out_file', 'mergefa_file')])
        ])
    else:
        #$FSLDIR/bin/fslmaths $FSLDIR/data/standard/FMRIB58_FA_1mm -mas mean_FA_mask mean_FA
        maskstd = pe.Node(fsl.ImageMaths(op_string="-mas", suffix="_masked"),
                          name="maskstd")
        maskstd.inputs.in_file = fsl.Info.standard_image(
            "FMRIB58_FA_1mm.nii.gz")

        #$FSLDIR/bin/fslmaths mean_FA -bin mean_FA_mask
        binmaskstd = pe.Node(fsl.ImageMaths(op_string="-bin"),
                             name="binmaskstd")

        #$FSLDIR/bin/fslmaths all_FA -mas mean_FA_mask all_FA
        maskgroup2 = pe.Node(fsl.ImageMaths(op_string="-mas",
                                            suffix="_masked"),
                             name="maskgroup2")

        tbss3.connect([(groupmask, maskstd, [("out_file", "in_file2")]),
                       (maskstd, binmaskstd, [("out_file", "in_file")]),
                       (maskgroup, maskgroup2, [("out_file", "in_file")]),
                       (binmaskstd, maskgroup2, [("out_file", "in_file2")])])

        outputnode.inputs.skeleton_file = fsl.Info.standard_image(
            "FMRIB58_FA-skeleton_1mm.nii.gz")
        tbss3.connect([(binmaskstd, outputnode, [('out_file', 'groupmask')]),
                       (maskstd, outputnode, [('out_file', 'meanfa_file')]),
                       (maskgroup2, outputnode, [('out_file', 'mergefa_file')])
                       ])
    return tbss3
예제 #4
0
 def tbss4d(self, tbss_dir, oDir, template, **kwargs):
     """
     python function to generate 4d nii files for randomise from TBSS.
     
     Required arguments:
         tbss_dir --- where the 'FA' and 'stats' folder exists.  This by default on knicr servers is here:
         /Volumes/rbraid/mr_data_idc/aug2013_final/dti/tbss
     
         oDir --- this is where you want the 4d files to go. This should be specific to the analysis you are doing
         e.g., /home/tonya/my_data/tbss/dysregulation_analysis/
     
 
     Default is to assume scalars FA, MD, RD, AD are all processed.
     Also assumes the subject files are named as such:
     
         idc_#_SCALAR_to_FMRIB58_FA_2mm_nonlinear.nii.gz
         
     
     Optional Arguments:
         
         tbss_pfix --- default is "idc_"
         This is what goes before the subject id
         String type
         
         tbss_sfix --- default is "_to_FMRIB58_FA_2mm_nonlin.nii.gz"
         This is what goes after the subject id and scalar name (eg FA, MD)
         String type
         
         Scalars --- List of Scalars 
         default is: [FA, MD, RD, AD] 
         List type
         
         opfix --- prefix for the 4d output file. suffix will be the scalar type.
         default is tbss_all_
         string type.
         
         
     """
     tbss_pfix = 'idc_'
     tbss_sfix = '_to_FMRIB58_FA_2mm_nonlin.nii.gz'
     scalars = ['FA', 'MD', 'RD', 'AD']
     opfix = 'tbss_all_'
     threshold = 0.2
     for i in kwargs.keys():
         if i == 'tbss_pfix':
             tbss_pfix = kwargs[i]
         elif i == 'tbss_sfix':
             tbss_sfix = kwargs[i]
         elif i == 'opfix':
             opfix = kwargs[i]
         elif i == 'scalars':
             scalars = kwargs[i]
             if not type(scalars) is list:
                 print 'ERROR....scalar option must be a LIST!'
                 print 'Resetting scalars to be FA only...'
                 scalars = ['FA']
         elif i == 'threshold':
             threshold = kwarg[i]
     for scalar in scalars:
         print 'writing out 4d file for component: ', scalar
         fourDlist = []
         for s in range(0, self.subj_list.shape[0]):
             subj = str(int(self.subj_list[s][0]))
             tbss_file = os.path.join(
                 tbss_dir, 'FA',
                 tbss_pfix + subj + '_' + scalar + tbss_sfix)
             if not os.path.exists(tbss_file):
                 print 'CANNOT FIND tbss data for :', subj, scalar
                 print 'Looked here: ', tbss_file
                 print 'Cannot continue...must exit...'
                 sys.exit(0)
             fourDlist.append(tbss_file)
         #merge the file
         logFile = os.path.join(oDir, 'tbss_nonFA.log')
         merged4d = os.path.join(oDir, opfix + scalar + '.nii.gz')
         if not os.path.exists(merged4d):
             fslmerge = fsl.Merge(dimension='t',
                                  terminal_output='stream',
                                  in_files=fourDlist,
                                  merged_file=merged4d,
                                  output_type='NIFTI_GZ')
             fslmerge.run()
             write_log(fslmerge.cmdline, logFile)
             subjinfo = merged4d.replace('.nii.gz', '_mergeInfo.csv')
             write_txt(fourDlist, subjinfo)
         if scalar.endswith('_FA'):
             #next we make the mean FA image
             op_str = '-max 0 -Tmin -bin'
             fslmaths = fsl.ImageMaths(in_file=merged4d,
                                       op_string=op_str,
                                       out_file=os.path.join(
                                           oDir, 'mean_FA_mask.nii.gz'),
                                       output_type='NIFTI_GZ',
                                       out_data_type='char')
             fslmaths.run()
             write_log(fslmaths.cmdline, logFile)
             op_str = '-mas ' + os.path.join(oDir, 'mean_FA_mask.nii.gz')
             fslmaths = fsl.ImageMaths(in_file=merged4d,
                                       op_string=op_str,
                                       out_file=merged4d.replace(
                                           '.nii.gz', '_masked.nii.gz'),
                                       output_type='NIFTI_GZ')
             fslmaths.run()
             write_log(fslmaths.cmdline, logFile)
             op_str = '-Tmean'
             fslmaths = fsl.ImageMaths(
                 in_file=merged4d.replace('.nii.gz', '_masked.nii.gz'),
                 op_string=op_str,
                 out_file=os.path.join(oDir, 'mean_FA.nii.gz'),
                 output_type='NIFTI_GZ')
             fslmaths.run()
             write_log(fslmaths.cmdline, logFile)
             #now make the initial skeleton
             tbss_skeleton = fsl.TractSkeleton(
                 in_file=os.path.join(oDir, 'mean_FA.nii.gz'),
                 skeleton_file=os.path.join(oDir,
                                            'mean_FA_skeleton.nii.gz'))
             tbss_skeleton.run()
             write_log(tbss_skeleton.cmdline, logFile)
             print 'Creating Skeleton Mask using threshold', str(threshold)
             op_str = '-thr ' + str(threshold) + ' -bin'
             fslmaths = fsl.ImageMaths(
                 in_file=os.path.join(oDir, 'mean_FA_skeleton.nii.gz'),
                 op_string=op_str,
                 out_file=os.path.join(oDir,
                                       'mean_FA_skeleton_mask.nii.gz'),
                 output_type='NIFTI_GZ')
             fslmaths.run()
             write_log(fslmaths.cmdline, logFile)
             print 'Creating skeleton distancemap (for use in projection search)'
             op_str = '-mul 1 -add 1 -add ' + os.path.join(
                 oDir, 'mean_FA_skeleton_mask.nii.gz')
             fslmaths = fsl.ImageMaths(
                 in_file=os.path.join(oDir, 'mean_FA_mask.nii.gz'),
                 op_string=op_str,
                 out_file=os.path.join(oDir,
                                       'mean_FA_skeleton_mask_dst.nii.gz'),
                 output_type='NIFTI_GZ')
             fslmaths.run()
             write_log(fslmaths.cmdline, logFile)
             distancemap = fsl.DistanceMap(
                 in_file=os.path.join(oDir,
                                      'mean_FA_skeleton_mask_dst.nii.gz'),
                 distance_map=os.path.join(
                     oDir, 'mean_FA_skeleton_mask_dst.nii.gz'))
             distancemap.run()
             write_log(distancemap.cmdline, logFile)
             #to make things easier below, make a generic-named copy of the 4d fa map. needed for skeletonization.
             shutil.copyfile(merged4d.replace('.nii.gz', '_masked.nii.gz'),
                             os.path.join(oDir, 'all_FA.nii.gz'))
         else:
             if not os.path.exists(os.path.join(oDir,
                                                'mean_FA_mask.nii.gz')):
                 print oDir, 'mean_FA_mask.nii.gz does not exist'
                 print 'Make sure FA is the first scalar in your list. Must exit'
                 sys.exit(0)
             #mask other scalars
             op_str = '-mas ' + os.path.join(oDir, 'mean_FA_mask.nii.gz')
             fslmaths = fsl.ImageMaths(in_file=merged4d,
                                       op_string=op_str,
                                       out_file=merged4d.replace(
                                           '.nii.gz', '_masked.nii.gz'),
                                       output_type='NIFTI_GZ')
             fslmaths.run()
             write_log(fslmaths.cmdline, logFile)
         #skeletenize
         nb_template = nb.load(template)
         x = abs(nb_template.get_affine()[0][0])
         y = abs(nb_template.get_affine()[1][1])
         z = abs(nb_template.get_affine()[2][2])
         cing_file1mm = os.path.join(os.environ['FSLDIR'], 'data',
                                     'standard', 'LowerCingulum_1mm.nii.gz')
         if x == 1 and y == 1 and z == 1:
             cing_file = cing_file1mm
         elif x == 2 and y == 2 and z == 2:
             cing_file = os.path.join(os.environ['FSLDIR'], 'data',
                                      'standard',
                                      'LowerCingulum_2mm.nii.gz')
             if not os.path.exists(cing_file):
                 cing_file = os.path.join(oDir, 'LowerCingulum_2mm.nii.gz')
                 flirt = fsl.FLIRT(in_file=cing_file1mm,
                                   reference=os.path.join(
                                       os.environ['FSLDIR'], 'data',
                                       'standard', 'MNI152_T1_2mm.nii.gz'),
                                   out_file=cing_file,
                                   args='-applyisoxfm 2')
                 flirt.run()
                 write_log(flirt.cmdline, logFile)
         else:
             cing_file = False
         if not cing_file:
             print 'Cannot find cingulum file.'
             return
         print 'Projecting all FA data onto Skeleton'
         #run the tbss skeletonize thing
         if not os.path.exists(os.path.join(oDir, 'mean_FA_mask.nii.gz')):
             print oDir, 'mean_FA_mask.nii.gz does not exist'
             print 'Make sure FA is the first scalar in your list. Must exit'
             sys.exit(0)
         final4d = merged4d.replace('.nii.gz', '_skeletonized.nii.gz')
         tbss_skeleton = fsl.TractSkeleton(
             threshold=threshold,
             distance_map=os.path.join(oDir,
                                       'mean_FA_skeleton_mask_dst.nii.gz'),
             alt_data_file=merged4d.replace('.nii.gz', '_masked.nii.gz'),
             data_file=os.path.join(oDir, 'all_FA.nii.gz'),
             projected_data=final4d,
             in_file=os.path.join(oDir, 'mean_FA.nii.gz'),
             project_data=True)
         tbss_skeleton.inputs.use_cingulum_mask = Undefined
         tbss_skeleton.inputs.search_mask_file = cing_file
         tbss_skeleton.run()
         write_log(tbss_skeleton.cmdline, logFile)
예제 #5
0
def create_tbss_3_postreg(name='tbss_3_postreg'):
    """Post-registration processing: derive mean_FA and mean_FA_skeleton from 
    mean of all subjects in study.
    A pipeline that does the same as tbss_3_postreg script from FSL
    
    Example
    --------
    
    >>>tbss3 = create_tbss_3_postreg(name='tbss3')
    >>>...
    
    Inputs::
    
        inputnode.wraped_fa_list
    
    Outputs::
    
        outputnode.groupmask
        outputnode.skeleton_file
        outputnode.meanfa_file
        outputnode.mergefa_file

    """
    
    # Create the inputnode
    inputnode = pe.Node(interface = util.IdentityInterface(fields=['field_list',
                                                                'fa_list',
                                                                'target']),
                        name='inputnode')
    
    # Apply the warpfield to the masked FA image
    applywarp = pe.MapNode(interface=fsl.ApplyWarp(),
                           iterfield=['in_file','field_file'],
                        name="applywarp")
    
    # Merge the FA files into a 4D file
    mergefa = pe.Node(fsl.Merge(dimension="t", merged_file="all_FA.nii.gz"),
                    name="mergefa")
    
    # Get a group mask
    groupmask = pe.Node(fsl.ImageMaths(op_string="-max 0 -Tmin -bin",
                                       out_data_type="char",
                                       suffix="_mask"),
                        name="groupmask")
    
    maskgroup = pe.Node(fsl.ImageMaths(op_string="-mas",
                                       suffix="_masked"),
                        name="maskgroup")
    
    # Take the mean over the fourth dimension
    meanfa = pe.Node(fsl.ImageMaths(op_string="-Tmean",
                                     suffix="_mean"),
                      name="meanfa")
    
    # Use the mean FA volume to generate a tract skeleton
    makeskeleton = pe.Node(fsl.TractSkeleton(skeleton_file=True),
                           name="makeskeleton")
    tbss3 = pe.Workflow(name=name)
    tbss3.connect([
        (inputnode,applywarp,[("fa_list", "in_file"),
                              ("target","ref_file"),
                              ("field_list", "field_file")]),
        (applywarp, mergefa, [("out_file", "in_files")]),
        (mergefa, groupmask, [("merged_file", "in_file")]),
        (mergefa, maskgroup, [("merged_file", "in_file")]),
        (groupmask, maskgroup, [("out_file", "in_file2")]),
        (maskgroup, meanfa, [("out_file", "in_file")]),
        (meanfa, makeskeleton, [("out_file", "in_file")])
        ])
    
    # Create outputnode
    outputnode = pe.Node(interface = util.IdentityInterface(fields=['groupmask',
                                                                'skeleton_file',
                                                                'meanfa_file',
                                                                'mergefa_file']),
                         name='outputnode')
    tbss3.connect([
            (groupmask, outputnode,[('out_file', 'groupmask')]),
            (makeskeleton, outputnode,[('skeleton_file', 'skeleton_file')]),
            (meanfa, outputnode,[('out_file', 'meanfa_file')]),
            (maskgroup, outputnode,[('out_file', 'mergefa_file')])
            ])
    return tbss3
예제 #6
0
def create_cross_sectional_tbss_pipeline(in_files,
                                         output_dir,
                                         name='cross_sectional_tbss',
                                         skeleton_threshold=0.2,
                                         design_mat=None,
                                         design_con=None):
    workflow = pe.Workflow(name=name)
    workflow.base_dir = output_dir
    workflow.base_output_dir = name

    # Create the dtitk groupwise registration workflow
    groupwise_dtitk = create_dtitk_groupwise_workflow(in_files=in_files,
                                                      name="dtitk_groupwise",
                                                      rig_iteration=3,
                                                      aff_iteration=3,
                                                      nrr_iteration=6)

    # Create the average FA map
    mean_fa = pe.Node(interface=dtitk.TVtool(), name="mean_fa")
    workflow.connect(groupwise_dtitk, 'output_node.out_template', mean_fa,
                     'in_file')
    mean_fa.inputs.operation = 'fa'

    # Register the FMRIB58_FA_1mm.nii.gz atlas to the mean FA map
    reg_atlas = pe.Node(interface=niftyreg.RegAladin(), name='reg_atlas')
    workflow.connect(mean_fa, 'out_file', reg_atlas, 'ref_file')
    reg_atlas.inputs.flo_file = os.path.join(os.environ['FSLDIR'], 'data',
                                             'standard',
                                             'FMRIB58_FA_1mm.nii.gz')

    # Apply the transformation to the lower cingulum image
    war_atlas = pe.Node(interface=niftyreg.RegResample(), name='war_atlas')
    workflow.connect(mean_fa, 'out_file', war_atlas, 'ref_file')
    war_atlas.inputs.flo_file = os.path.join(os.environ['FSLDIR'], 'data',
                                             'standard',
                                             'LowerCingulum_1mm.nii.gz')
    workflow.connect(reg_atlas, 'aff_file', war_atlas, 'trans_file')
    war_atlas.inputs.inter_val = 'LIN'

    # Threshold the propagated lower cingulum
    thr_atlas = pe.Node(interface=niftyseg.BinaryMaths(), name='thr_atlas')
    workflow.connect(war_atlas, 'out_file', thr_atlas, 'in_file')
    thr_atlas.inputs.operation = 'thr'
    thr_atlas.inputs.operand_value = 0.5

    # Binarise the propagated lower cingulum
    bin_atlas = pe.Node(interface=niftyseg.UnaryMaths(), name='bin_atlas')
    workflow.connect(thr_atlas, 'out_file', bin_atlas, 'in_file')
    bin_atlas.inputs.operation = 'bin'

    # Create all the individual FA maps
    individual_fa = pe.MapNode(interface=dtitk.TVtool(),
                               name="individual_fa",
                               iterfield=['in_file'])
    workflow.connect(groupwise_dtitk, 'output_node.out_res', individual_fa,
                     'in_file')
    individual_fa.inputs.operation = 'fa'

    # Create all the individual MD maps
    individual_md = pe.MapNode(interface=dtitk.TVtool(),
                               name="individual_md",
                               iterfield=['in_file'])
    workflow.connect(groupwise_dtitk, 'output_node.out_res', individual_md,
                     'in_file')
    individual_md.inputs.operation = 'tr'

    # Create all the individual RD maps
    individual_rd = pe.MapNode(interface=dtitk.TVtool(),
                               name="individual_rd",
                               iterfield=['in_file'])
    workflow.connect(groupwise_dtitk, 'output_node.out_res', individual_rd,
                     'in_file')
    individual_rd.inputs.operation = 'rd'

    # Create all the individual RD maps
    individual_ad = pe.MapNode(interface=dtitk.TVtool(),
                               name="individual_ad",
                               iterfield=['in_file'])
    workflow.connect(groupwise_dtitk, 'output_node.out_res', individual_ad,
                     'in_file')
    individual_ad.inputs.operation = 'ad'

    # Combine all the warped FA images into a 4D image
    merged_4d_fa = pe.Node(interface=fsl.Merge(), name='merged_4d_fa')
    merged_4d_fa.inputs.dimension = 't'
    workflow.connect(individual_fa, 'out_file', merged_4d_fa, 'in_files')

    # Combine all the warped MD images into a 4D image
    merged_4d_md = pe.Node(interface=fsl.Merge(), name='merged_4d_md')
    merged_4d_md.inputs.dimension = 't'
    workflow.connect(individual_md, 'out_file', merged_4d_md, 'in_files')

    # Combine all the warped RD images into a 4D image
    merged_4d_rd = pe.Node(interface=fsl.Merge(), name='merged_4d_rd')
    merged_4d_rd.inputs.dimension = 't'
    workflow.connect(individual_rd, 'out_file', merged_4d_rd, 'in_files')

    # Combine all the warped AD images into a 4D image
    merged_4d_ad = pe.Node(interface=fsl.Merge(), name='merged_4d_ad')
    merged_4d_ad.inputs.dimension = 't'
    workflow.connect(individual_ad, 'out_file', merged_4d_ad, 'in_files')

    # Threshold the 4D FA image to 0
    merged_4d_fa_thresholded = pe.Node(interface=niftyseg.BinaryMaths(),
                                       name='merged_4d_fa_thresholded')
    merged_4d_fa_thresholded.inputs.operation = 'thr'
    merged_4d_fa_thresholded.inputs.operand_value = 0
    workflow.connect(merged_4d_fa, 'merged_file', merged_4d_fa_thresholded,
                     'in_file')

    # Extract the min value from the 4D FA image
    minimal_value_across_all_fa = pe.Node(interface=niftyseg.UnaryMaths(),
                                          name='minimal_value_across_all_fa')
    minimal_value_across_all_fa.inputs.operation = 'tmin'
    workflow.connect(merged_4d_fa_thresholded, 'out_file',
                     minimal_value_across_all_fa, 'in_file')

    # Create the mask image
    fa_mask = pe.Node(interface=niftyseg.UnaryMaths(), name='fa_mask')
    fa_mask.inputs.operation = 'bin'
    fa_mask.inputs.output_datatype = 'char'
    workflow.connect(minimal_value_across_all_fa, 'out_file', fa_mask,
                     'in_file')

    # Mask the mean FA image
    masked_mean_fa = pe.Node(interface=fsl.ApplyMask(), name='masked_mean_fa')
    workflow.connect(mean_fa, 'out_file', masked_mean_fa, 'in_file')
    workflow.connect(fa_mask, 'out_file', masked_mean_fa, 'mask_file')

    # Create the skeleton image
    skeleton = pe.Node(interface=fsl.TractSkeleton(), name='skeleton')
    skeleton.inputs.skeleton_file = True
    workflow.connect(masked_mean_fa, 'out_file', skeleton, 'in_file')

    # Threshold the skeleton image
    thresholded_skeleton = pe.Node(interface=niftyseg.BinaryMaths(),
                                   name='thresholded_skeleton')
    thresholded_skeleton.inputs.operation = 'thr'
    thresholded_skeleton.inputs.operand_value = skeleton_threshold
    workflow.connect(skeleton, 'skeleton_file', thresholded_skeleton,
                     'in_file')

    # Binarise the skeleton image
    binarised_skeleton = pe.Node(interface=niftyseg.UnaryMaths(),
                                 name='binarised_skeleton')
    binarised_skeleton.inputs.operation = 'bin'
    workflow.connect(thresholded_skeleton, 'out_file', binarised_skeleton,
                     'in_file')

    # Create skeleton distance map
    invert_mask1 = pe.Node(interface=niftyseg.BinaryMaths(),
                           name='invert_mask1')
    invert_mask1.inputs.operation = 'mul'
    invert_mask1.inputs.operand_value = -1
    workflow.connect(fa_mask, 'out_file', invert_mask1, 'in_file')
    invert_mask2 = pe.Node(interface=niftyseg.BinaryMaths(),
                           name='invert_mask2')
    invert_mask2.inputs.operation = 'add'
    invert_mask2.inputs.operand_value = 1
    workflow.connect(invert_mask1, 'out_file', invert_mask2, 'in_file')
    invert_mask3 = pe.Node(interface=niftyseg.BinaryMaths(),
                           name='invert_mask3')
    invert_mask3.inputs.operation = 'add'
    workflow.connect(invert_mask2, 'out_file', invert_mask3, 'in_file')
    workflow.connect(binarised_skeleton, 'out_file', invert_mask3,
                     'operand_file')
    distance_map = pe.Node(interface=fsl.DistanceMap(), name='distance_map')
    workflow.connect(invert_mask3, 'out_file', distance_map, 'in_file')

    # Project the FA values onto the skeleton
    all_fa_projected = pe.Node(interface=fsl.TractSkeleton(),
                               name='all_fa_projected')
    all_fa_projected.inputs.threshold = skeleton_threshold
    all_fa_projected.inputs.project_data = True
    workflow.connect(masked_mean_fa, 'out_file', all_fa_projected, 'in_file')
    workflow.connect(distance_map, 'distance_map', all_fa_projected,
                     'distance_map')
    workflow.connect(merged_4d_fa, 'merged_file', all_fa_projected,
                     'data_file')
    workflow.connect(bin_atlas, 'out_file', all_fa_projected,
                     'search_mask_file')

    # Project the MD values onto the skeleton
    all_md_projected = pe.Node(interface=fsl.TractSkeleton(),
                               name='all_md_projected')
    all_md_projected.inputs.threshold = skeleton_threshold
    all_md_projected.inputs.project_data = True
    workflow.connect(masked_mean_fa, 'out_file', all_md_projected, 'in_file')
    workflow.connect(distance_map, 'distance_map', all_md_projected,
                     'distance_map')
    workflow.connect(merged_4d_fa, 'merged_file', all_md_projected,
                     'data_file')
    workflow.connect(merged_4d_md, 'merged_file', all_md_projected,
                     'alt_data_file')
    workflow.connect(bin_atlas, 'out_file', all_md_projected,
                     'search_mask_file')

    # Project the RD values onto the skeleton
    all_rd_projected = pe.Node(interface=fsl.TractSkeleton(),
                               name='all_rd_projected')
    all_rd_projected.inputs.threshold = skeleton_threshold
    all_rd_projected.inputs.project_data = True
    workflow.connect(masked_mean_fa, 'out_file', all_rd_projected, 'in_file')
    workflow.connect(distance_map, 'distance_map', all_rd_projected,
                     'distance_map')
    workflow.connect(merged_4d_fa, 'merged_file', all_rd_projected,
                     'data_file')
    workflow.connect(merged_4d_rd, 'merged_file', all_rd_projected,
                     'alt_data_file')
    workflow.connect(bin_atlas, 'out_file', all_rd_projected,
                     'search_mask_file')

    # Project the RD values onto the skeleton
    all_ad_projected = pe.Node(interface=fsl.TractSkeleton(),
                               name='all_ad_projected')
    all_ad_projected.inputs.threshold = skeleton_threshold
    all_ad_projected.inputs.project_data = True
    workflow.connect(masked_mean_fa, 'out_file', all_ad_projected, 'in_file')
    workflow.connect(distance_map, 'distance_map', all_ad_projected,
                     'distance_map')
    workflow.connect(merged_4d_fa, 'merged_file', all_ad_projected,
                     'data_file')
    workflow.connect(merged_4d_ad, 'merged_file', all_ad_projected,
                     'alt_data_file')
    workflow.connect(bin_atlas, 'out_file', all_ad_projected,
                     'search_mask_file')

    # Create an output node
    output_node = pe.Node(interface=niu.IdentityInterface(fields=[
        'mean_fa', 'all_fa_skeletonised', 'all_md_skeletonised',
        'all_rd_skeletonised', 'all_ad_skeletonised', 'skeleton',
        'skeleton_bin', 't_contrast_raw_stat', 't_contrast_uncorrected_pvalue',
        't_contrast_corrected_pvalue'
    ]),
                          name='output_node')

    # Connect the workflow to the output node
    workflow.connect(masked_mean_fa, 'out_file', output_node, 'mean_fa')
    workflow.connect(all_fa_projected, 'projected_data', output_node,
                     'all_fa_skeletonised')
    workflow.connect(all_md_projected, 'projected_data', output_node,
                     'all_md_skeletonised')
    workflow.connect(all_rd_projected, 'projected_data', output_node,
                     'all_rd_skeletonised')
    workflow.connect(all_ad_projected, 'projected_data', output_node,
                     'all_ad_skeletonised')
    workflow.connect(skeleton, 'skeleton_file', output_node, 'skeleton')
    workflow.connect(binarised_skeleton, 'out_file', output_node,
                     'skeleton_bin')

    # Run randomise if required and connect its output to the output node
    if design_mat is not None and design_con is not None:
        randomise = pe.Node(interface=fsl.Randomise(), name='randomise')
        randomise.inputs.base_name = 'stats_tbss'
        randomise.inputs.tfce2D = True
        randomise.inputs.num_perm = 5000
        workflow.connect(all_fa_projected, 'projected_data', randomise,
                         'in_file')
        randomise.inputs.design_mat = design_mat
        randomise.inputs.design_con = design_con
        workflow.connect(binarised_skeleton, 'out_file', randomise, 'mask')

        workflow.connect(randomise, 'tstat_files', output_node,
                         't_contrast_raw_stat')
        workflow.connect(randomise, 't_p_files', output_node,
                         't_contrast_uncorrected_pvalue')
        workflow.connect(randomise, 't_corrected_p_files', output_node,
                         't_contrast_corrected_pvalue')

    # Create nodes to rename the outputs
    mean_fa_renamer = pe.Node(interface=niu.Rename(
        format_string='tbss_mean_fa', keep_ext=True),
                              name='mean_fa_renamer')
    workflow.connect(output_node, 'mean_fa', mean_fa_renamer, 'in_file')

    mean_sk_renamer = pe.Node(interface=niu.Rename(
        format_string='tbss_mean_fa_skeleton', keep_ext=True),
                              name='mean_sk_renamer')
    workflow.connect(output_node, 'skeleton', mean_sk_renamer, 'in_file')

    bin_ske_renamer = pe.Node(interface=niu.Rename(
        format_string='tbss_mean_fa_skeleton_mask', keep_ext=True),
                              name='bin_ske_renamer')
    workflow.connect(output_node, 'skeleton_bin', bin_ske_renamer, 'in_file')

    fa_skel_renamer = pe.Node(interface=niu.Rename(
        format_string='tbss_all_fa_skeletonised', keep_ext=True),
                              name='fa_skel_renamer')
    workflow.connect(output_node, 'all_fa_skeletonised', fa_skel_renamer,
                     'in_file')
    md_skel_renamer = pe.Node(interface=niu.Rename(
        format_string='tbss_all_md_skeletonised', keep_ext=True),
                              name='md_skel_renamer')
    workflow.connect(output_node, 'all_md_skeletonised', md_skel_renamer,
                     'in_file')
    rd_skel_renamer = pe.Node(interface=niu.Rename(
        format_string='tbss_all_rd_skeletonised', keep_ext=True),
                              name='rd_skel_renamer')
    workflow.connect(output_node, 'all_rd_skeletonised', rd_skel_renamer,
                     'in_file')
    ad_skel_renamer = pe.Node(interface=niu.Rename(
        format_string='tbss_all_ad_skeletonised', keep_ext=True),
                              name='ad_skel_renamer')
    workflow.connect(output_node, 'all_ad_skeletonised', ad_skel_renamer,
                     'in_file')

    # Create a data sink
    ds = pe.Node(nio.DataSink(parameterization=False), name='data_sink')
    ds.inputs.base_directory = os.path.abspath(output_dir)

    # Connect the data sink
    workflow.connect(mean_fa_renamer, 'out_file', ds, '@mean_fa')
    workflow.connect(mean_sk_renamer, 'out_file', ds, '@skel_fa')
    workflow.connect(bin_ske_renamer, 'out_file', ds, '@bkel_fa')
    workflow.connect(fa_skel_renamer, 'out_file', ds, '@all_fa')
    workflow.connect(md_skel_renamer, 'out_file', ds, '@all_md')
    workflow.connect(rd_skel_renamer, 'out_file', ds, '@all_rd')
    workflow.connect(ad_skel_renamer, 'out_file', ds, '@all_ad')

    if design_mat is not None and design_con is not None:
        workflow.connect(output_node, 't_contrast_raw_stat', ds,
                         '@t_contrast_raw_stat')
        workflow.connect(output_node, 't_contrast_uncorrected_pvalue', ds,
                         '@t_contrast_uncorrected_pvalue')
        workflow.connect(output_node, 't_contrast_corrected_pvalue', ds,
                         '@t_contrast_corrected_pvalue')

    return workflow