Ejemplo n.º 1
0
def nipype_bbregister(t1path):
    splitpath = t1path.split(os.sep)
    sub_fsdir = os.path.join(BIDS_DATA_DIR, "derivatives",
                             "freesurfer_{0}".format(splitpath[-3]),
                             splitpath[-4])
    if not os.path.isdir(sub_fsdir):
        os.mkdir(sub_fsdir)
    outdir = os.path.join(BIDS_DATA_DIR, "derivatives",
                          "freesurfer_projection_{0}".format(splitpath[-3]),
                          splitpath[-4])
    if not os.path.isdir(outdir):
        os.makedirs(outdir)
    funcpath = os.path.join(
        BIDS_DATA_DIR, "derivatives", "spmpreproc_{0}".format(splitpath[-3]),
        splitpath[-4],
        "wrr{0}_{1}_task-localizer_bold.nii.gz".format(splitpath[-4],
                                                       splitpath[-3]))
    assert os.path.isfile(funcpath), funcpath
    basename = os.path.basename(funcpath).replace(".nii.gz", "")
    os.environ["SUBJECTS_DIR"] = os.path.dirname(sub_fsdir)
    bbreg = freesurfer.BBRegister(
        subject_id=splitpath[-4],
        source_file=funcpath,
        init="fsl",
        contrast_type="t2",
        dof=6,
        fsldof=6,
        reg_frame=0,
        out_fsl_file=os.path.join(outdir, basename + ".fsl.mat"),
        out_reg_file=os.path.join(outdir, basename + ".reg.dat"))
    print(bbreg.cmdline)
    if PROCESS:
        bbreg.run()
Ejemplo n.º 2
0
def test_bbregister(create_files_in_directory):
    filelist, outdir = create_files_in_directory
    bbr = freesurfer.BBRegister()

    # make sure command gets called
    assert bbr.cmd == "bbregister"

    # test raising error with mandatory args absent
    with pytest.raises(ValueError):
        bbr.cmdline

    bbr.inputs.subject_id = "fsaverage"
    bbr.inputs.source_file = filelist[0]
    bbr.inputs.contrast_type = "t2"

    # Check that 'init' is mandatory in FS < 6, but not in 6+
    if Info.looseversion() < LooseVersion("6.0.0"):
        with pytest.raises(ValueError):
            bbr.cmdline
    else:
        bbr.cmdline

    bbr.inputs.init = "fsl"

    base, ext = os.path.splitext(os.path.basename(filelist[0]))
    if ext == ".gz":
        base, _ = os.path.splitext(base)

    assert bbr.cmdline == ("bbregister --t2 --init-fsl "
                           "--reg {base}_bbreg_fsaverage.dat "
                           "--mov {full} --s fsaverage".format(
                               full=filelist[0], base=base))
Ejemplo n.º 3
0
def create_bbregister_workflow(name="bbregister",
                               contrast_type="t2",
                               partial_brain=False,
                               init_with="fsl"):
    """Find a linear transformation to align the EPI file with the anatomy."""
    in_fields = ["subject_id", "timeseries"]
    if partial_brain:
        in_fields.append("whole_brain_template")
    inputnode = Node(IdentityInterface(in_fields), "inputs")

    # Take the mean over time to get a target volume
    meanvol = MapNode(fsl.MeanImage(), "in_file", "meanvol")

    # Do a rough skullstrip using BET
    skullstrip = MapNode(fsl.BET(), "in_file", "bet")

    # Estimate the registration to Freesurfer conformed space
    func2anat = MapNode(
        fs.BBRegister(contrast_type=contrast_type,
                      init=init_with,
                      epi_mask=True,
                      registered_file=True,
                      out_reg_file="func2anat_tkreg.dat",
                      out_fsl_file="func2anat_flirt.mat"), "source_file",
        "func2anat")

    # Make an image for quality control on the registration
    report = MapNode(CoregReport(), "in_file", "coreg_report")

    # Define the workflow outputs
    outputnode = Node(IdentityInterface(["tkreg_mat", "flirt_mat", "report"]),
                      "outputs")

    bbregister = Workflow(name=name)

    # Connect the registration
    bbregister.connect([
        (inputnode, func2anat, [("subject_id", "subject_id")]),
        (inputnode, report, [("subject_id", "subject_id")]),
        (inputnode, meanvol, [("timeseries", "in_file")]),
        (meanvol, skullstrip, [("out_file", "in_file")]),
        (skullstrip, func2anat, [("out_file", "source_file")]),
        (func2anat, report, [("registered_file", "in_file")]),
        (func2anat, outputnode, [("out_reg_file", "tkreg_mat")]),
        (func2anat, outputnode, [("out_fsl_file", "flirt_mat")]),
        (report, outputnode, [("out_file", "report")]),
    ])

    # Possibly connect the full_fov image
    if partial_brain:
        bbregister.connect([
            (inputnode, func2anat, [("whole_brain_template",
                                     "intermediate_file")]),
        ])

    return bbregister
Ejemplo n.º 4
0
def epi_fs_coregister(name='epi_fs_coregister'):
    
    inputnode = pe.Node(
        utility.IdentityInterface(
            fields=['fmri','subject_id','subjects_dir',
                    'roi_file','mask_file']),
        name='inputspec')

    outputnode = pe.Node(
        utility.IdentityInterface(
            fields=['fmri_mask','fmri_rois','reg_file','fsl_reg_file']),
        name='outputspec')


    n_bbregister = pe.Node(
        freesurfer.BBRegister(init='fsl', contrast_type='t2',
                              out_fsl_file=True),
        name='bbregister')

    n_fsmask2epi = pe.Node(
        freesurfer.ApplyVolTransform(inverse=True, interp='nearest',
                                     transformed_file='mask_epi.nii.gz'),
        name='fsmask2epi')

    n_fsrois2epi = pe.Node(
        freesurfer.ApplyVolTransform(inverse=True, interp='nearest',
                                     transformed_file='epi_aparc.aseg.nii.gz'),
        name='fsrois2epi')
    w=pe.Workflow(name=name)
    w.connect([
            (inputnode, n_bbregister,[('fmri','source_file'),
                                      ('subjects_dir','subjects_dir'),
                                      ('subject_id','subject_id')]),
            (n_bbregister, n_fsrois2epi,[('out_reg_file','reg_file')]),
            (inputnode, n_fsrois2epi, [('fmri','source_file'),
                                       ('roi_file','target_file')]),
            (n_bbregister, n_fsmask2epi,[('out_reg_file','reg_file')]),
            (inputnode, n_fsmask2epi, [('fmri','source_file'),
                                       ('mask_file','target_file')]),
            (n_bbregister, outputnode,[('out_reg_file','reg_file')]),
            (n_bbregister, outputnode,[('out_fsl_file','fsl_reg_file')]),
            (n_fsmask2epi, outputnode, [('transformed_file','fmri_mask')]),
            (n_fsrois2epi, outputnode, [('transformed_file','fmri_rois')]),
            ])
    return w
Ejemplo n.º 5
0
def test_bbregister():
    input_map = dict(
        args=dict(argstr='%s', ),
        contrast_type=dict(
            argstr='--%s',
            mandatory=True,
        ),
        environ=dict(),
        init=dict(
            argstr='--init-%s',
            xor=['init_reg_file'],
        ),
        init_reg_file=dict(
            xor=['init'],
            mandatory=True,
        ),
        out_reg_file=dict(argstr='--reg %s', ),
        registered_file=dict(argstr='--o %s', ),
        reg_frame=dict(argstr="--frame %d", ),
        reg_middle_frame=dict(argstr="--mid-frame", ),
        intermediate_file=dict(argstr="--int %s", ),
        source_file=dict(
            copyfile=False,
            mandatory=True,
            argstr='--mov %s',
        ),
        subject_id=dict(
            mandatory=True,
            argstr='--s %s',
        ),
        subjects_dir=dict(),
    )
    instance = freesurfer.BBRegister()
    for key, metadata in input_map.items():
        for metakey, value in metadata.items():
            yield (assert_equal, getattr(instance.inputs.traits()[key],
                                         metakey), value)
Ejemplo n.º 6
0
def min_func_preproc(subject, sessions, data_dir, fs_dir, wd, sink, TR,
                     EPI_resolution):

    #initiate min func preproc workflow
    wf = pe.Workflow(name='MPP')
    wf.base_dir = wd
    wf.config['execution']['crashdump_dir'] = wf.base_dir + "/crash_files"

    ## set fsl output type to nii.gz
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')

    # I/O nodes
    inputnode = pe.Node(util.IdentityInterface(fields=['subjid', 'fs_dir']),
                        name='inputnode')
    inputnode.inputs.subjid = subject
    inputnode.inputs.fs_dir = fs_dir

    ds = pe.Node(nio.DataSink(base_directory=sink, parameterization=False),
                 name='sink')

    ds.inputs.substitutions = [('moco.nii.gz.par', 'moco.par'),
                               ('moco.nii.gz_', 'moco_')]

    #infosource to interate over sessions: COND, EXT1, EXT2
    sessions_infosource = pe.Node(util.IdentityInterface(fields=['session']),
                                  name='session')
    sessions_infosource.iterables = [('session', sessions)]

    #select files
    templates = {
        'func_data': '{session}/func_data.nii.gz',
        'T1_brain': 'T1/T1_brain.nii.gz',
        'wmedge': 'T1/MASKS/aparc_aseg.WMedge.nii.gz'
    }

    selectfiles = pe.Node(nio.SelectFiles(templates, base_directory=data_dir),
                          name='selectfiles')

    wf.connect(sessions_infosource, 'session', selectfiles, 'session')
    wf.connect(sessions_infosource, 'session', ds, 'container')

    ##########################################################################
    ########################    START   ######################################
    ##########################################################################

    ###########################################################################
    ########################    No. 3   ######################################

    #change the data type to float
    fsl_float = pe.Node(fsl.maths.MathsCommand(output_datatype='float'),
                        name='fsl_float')

    wf.connect(selectfiles, 'func_data', fsl_float, 'in_file')

    ###########################################################################
    ########################    No. 4   ######################################

    #get FD from fsl_motion_outliers
    FD = pe.Node(fsl.MotionOutliers(out_file='func_data_FD_outliers.txt',
                                    out_metric_values='func_data_FD.txt',
                                    metric='fd'),
                 name='FD')

    wf.connect(fsl_float, 'out_file', FD, 'in_file')
    wf.connect(FD, 'out_metric_values', ds, 'QC.@FD')
    wf.connect(FD, 'out_file', ds, 'QC.@FDoutliers')

    ###########################################################################
    ########################    No. 5   ######################################

    #slice timing correction: sequential ascending
    slicetimer = pe.Node(
        fsl.SliceTimer(
            index_dir=False,
            interleaved=False,
            #slice_direction=3, #z direction
            time_repetition=TR,
            out_file='func_data_stc.nii.gz'),
        name='slicetimer')

    wf.connect(fsl_float, 'out_file', slicetimer, 'in_file')
    wf.connect(slicetimer, 'slice_time_corrected_file', ds, 'TEMP.@slicetimer')

    ###########################################################################
    ########################    No. 6   ######################################
    #do realignment to the middle or first volume
    mcflirt = pe.Node(fsl.MCFLIRT(save_mats=True,
                                  save_plots=True,
                                  save_rms=True,
                                  ref_vol=1,
                                  out_file='func_data_stc_moco.nii.gz'),
                      name='mcflirt')

    wf.connect(slicetimer, 'slice_time_corrected_file', mcflirt, 'in_file')
    wf.connect(mcflirt, 'out_file', ds, 'TEMP.@mcflirt')
    wf.connect(mcflirt, 'par_file', ds, 'MOCO.@par_file')
    wf.connect(mcflirt, 'rms_files', ds, 'MOCO.@rms_files')
    wf.connect(mcflirt, 'mat_file', ds, 'MOCO_MAT.@mcflirt')

    # plot motion parameters
    rotplotter = pe.Node(fsl.PlotMotionParams(in_source='fsl',
                                              plot_type='rotations',
                                              out_file='rotation.png'),
                         name='rotplotter')

    transplotter = pe.Node(fsl.PlotMotionParams(in_source='fsl',
                                                plot_type='translations',
                                                out_file='translation.png'),
                           name='transplotter')

    dispplotter = pe.Node(
        interface=fsl.PlotMotionParams(in_source='fsl',
                                       plot_type='displacement',
                                       out_file='displacement.png'),
        name='dispplotter')

    wf.connect(mcflirt, 'par_file', rotplotter, 'in_file')
    wf.connect(mcflirt, 'par_file', transplotter, 'in_file')
    wf.connect(mcflirt, 'rms_files', dispplotter, 'in_file')
    wf.connect(rotplotter, 'out_file', ds, 'PLOTS.@rotplot')
    wf.connect(transplotter, 'out_file', ds, 'PLOTS.@transplot')
    wf.connect(dispplotter, 'out_file', ds, 'PLOTS.@disppplot')

    #calculate tSNR and the mean

    moco_Tmean = pe.Node(fsl.maths.MathsCommand(args='-Tmean',
                                                out_file='moco_Tmean.nii.gz'),
                         name='moco_Tmean')

    moco_Tstd = pe.Node(fsl.maths.MathsCommand(args='-Tstd',
                                               out_file='moco_Tstd.nii.gz'),
                        name='moco_Tstd')

    tSNR0 = pe.Node(fsl.maths.MultiImageMaths(op_string='-div %s',
                                              out_file='moco_tSNR.nii.gz'),
                    name='moco_tSNR')

    wf.connect(mcflirt, 'out_file', moco_Tmean, 'in_file')
    wf.connect(mcflirt, 'out_file', moco_Tstd, 'in_file')
    wf.connect(moco_Tmean, 'out_file', tSNR0, 'in_file')
    wf.connect(moco_Tstd, 'out_file', tSNR0, 'operand_files')
    wf.connect(moco_Tmean, 'out_file', ds, 'TEMP.@moco_Tmean')
    wf.connect(moco_Tstd, 'out_file', ds, 'TEMP.@moco_Tstd')
    wf.connect(tSNR0, 'out_file', ds, 'TEMP.@moco_Tsnr')

    ###########################################################################
    ########################    No. 7   ######################################

    #bias field correction of mean epi for better coregistration
    bias = pe.Node(
        fsl.FAST(
            img_type=2,
            #restored_image='epi_Tmeanrestored.nii.gz',
            output_biascorrected=True,
            out_basename='moco_Tmean',
            no_pve=True,
            probability_maps=False),
        name='bias')

    wf.connect(moco_Tmean, 'out_file', bias, 'in_files')
    wf.connect(bias, 'restored_image', ds, 'TEMP.@restored_image')

    #co-registration to anat using FS BBregister and mean EPI
    bbregister = pe.Node(fs.BBRegister(
        subject_id=subject,
        subjects_dir=fs_dir,
        contrast_type='t2',
        init='fsl',
        out_fsl_file='func2anat.mat',
        out_reg_file='func2anat.dat',
        registered_file='moco_Tmean_restored2anat.nii.gz',
        epi_mask=True),
                         name='bbregister')

    wf.connect(bias, 'restored_image', bbregister, 'source_file')
    wf.connect(bbregister, 'registered_file', ds, 'TEMP.@registered_file')
    wf.connect(bbregister, 'out_fsl_file', ds, 'COREG.@out_fsl_file')
    wf.connect(bbregister, 'out_reg_file', ds, 'COREG.@out_reg_file')
    wf.connect(bbregister, 'min_cost_file', ds, 'COREG.@min_cost_file')

    #inverse func2anat mat
    inverseXFM = pe.Node(fsl.ConvertXFM(invert_xfm=True,
                                        out_file='anat2func.mat'),
                         name='inverseXFM')

    wf.connect(bbregister, 'out_fsl_file', inverseXFM, 'in_file')
    wf.connect(inverseXFM, 'out_file', ds, 'COREG.@out_fsl_file_inv')

    #plot the corregistration quality
    slicer = pe.Node(fsl.Slicer(middle_slices=True, out_file='func2anat.png'),
                     name='slicer')

    wf.connect(selectfiles, 'wmedge', slicer, 'image_edges')
    wf.connect(bbregister, 'registered_file', slicer, 'in_file')
    wf.connect(slicer, 'out_file', ds, 'PLOTS.@func2anat')

    ###########################################################################
    ########################    No. 8   ######################################
    #MOCO and COREGISTRATION

    #resample T1 to EPI resolution to use it as a reference image
    resample_T1 = pe.Node(
        fsl.FLIRT(datatype='float',
                  apply_isoxfm=EPI_resolution,
                  out_file='T1_brain_EPI.nii.gz'),
        #interp='nearestneighbour'),keep spline so it looks nicer
        name='resample_T1')

    wf.connect(selectfiles, 'T1_brain', resample_T1, 'in_file')
    wf.connect(selectfiles, 'T1_brain', resample_T1, 'reference')
    wf.connect(resample_T1, 'out_file', ds, 'COREG.@resample_T1')

    #concate matrices (moco and func2anat) volume-wise
    concat_xfm = pe.MapNode(fsl.ConvertXFM(concat_xfm=True),
                            iterfield=['in_file'],
                            name='concat_xfm')

    wf.connect(mcflirt, 'mat_file', concat_xfm, 'in_file')
    wf.connect(bbregister, 'out_fsl_file', concat_xfm, 'in_file2')
    wf.connect(concat_xfm, 'out_file', ds, 'MOCO2ANAT_MAT.@concat_out')

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

    wf.connect(slicetimer, 'slice_time_corrected_file', split, 'in_file')

    #motion correction and corregistration in one interpolation step
    flirt = pe.MapNode(fsl.FLIRT(apply_xfm=True,
                                 interp='spline',
                                 datatype='float'),
                       iterfield=['in_file', 'in_matrix_file'],
                       name='flirt')

    wf.connect(split, 'out_files', flirt, 'in_file')
    wf.connect(resample_T1, 'out_file', flirt, 'reference')
    wf.connect(concat_xfm, 'out_file', flirt, 'in_matrix_file')

    #merge the files to have 4d dataset motion corrected and co-registerd to T1
    merge = pe.Node(fsl.Merge(dimension='t',
                              merged_file='func_data_stc_moco2anat.nii.gz'),
                    name='merge')

    wf.connect(flirt, 'out_file', merge, 'in_files')
    wf.connect(merge, 'merged_file', ds, 'TEMP.@merged')

    ###########################################################################
    ########################    No. 9   ######################################

    #run BET on co-registered EPI in 1mm and get the mask
    bet = pe.Node(fsl.BET(mask=True,
                          functional=True,
                          out_file='moco_Tmean_restored2anat_BET.nii.gz'),
                  name='bet')

    wf.connect(bbregister, 'registered_file', bet, 'in_file')
    wf.connect(bet, 'out_file', ds, 'TEMP.@func_data_example')
    wf.connect(bet, 'mask_file', ds, 'TEMP.@func_data_mask')

    #resample BET mask to EPI resolution
    resample_mask = pe.Node(fsl.FLIRT(
        datatype='int',
        apply_isoxfm=EPI_resolution,
        interp='nearestneighbour',
        out_file='prefiltered_func_data_mask.nii.gz'),
                            name='resample_mask')

    wf.connect(bet, 'mask_file', resample_mask, 'in_file')
    wf.connect(resample_T1, 'out_file', resample_mask, 'reference')
    wf.connect(resample_mask, 'out_file', ds, '@mask')

    #apply the mask to 4D data to get rid of the "eyes and the rest"
    mask4D = pe.Node(fsl.maths.ApplyMask(), name='mask')

    wf.connect(merge, 'merged_file', mask4D, 'in_file')
    wf.connect(resample_mask, 'out_file', mask4D, 'mask_file')

    ###########################################################################
    ########################    No. 10   ######################################

    #get the values necessary for intensity normalization
    median = pe.Node(fsl.utils.ImageStats(op_string='-k %s -p 50'),
                     name='median')

    wf.connect(resample_mask, 'out_file', median, 'mask_file')
    wf.connect(mask4D, 'out_file', median, 'in_file')

    #compute the scaling factor
    def get_factor(val):

        factor = 10000 / val
        return factor

    get_scaling_factor = pe.Node(util.Function(input_names=['val'],
                                               output_names=['out_val'],
                                               function=get_factor),
                                 name='scaling_factor')

    #normalize the 4D func data with one scaling factor
    multiplication = pe.Node(fsl.maths.BinaryMaths(
        operation='mul', out_file='prefiltered_func_data.nii.gz'),
                             name='multiplication')

    wf.connect(median, 'out_stat', get_scaling_factor, 'val')
    wf.connect(get_scaling_factor, 'out_val', multiplication, 'operand_value')
    wf.connect(mask4D, 'out_file', multiplication, 'in_file')
    wf.connect(multiplication, 'out_file', ds, '@prefiltered_func_data')

    ###########################################################################
    ########################    No. 11   ######################################

    #calculate tSNR and the mean of the new prefiltered and detrend dataset

    tsnr_detrend = pe.Node(misc.TSNR(
        regress_poly=1,
        detrended_file='prefiltered_func_data_detrend.nii.gz',
        mean_file='prefiltered_func_data_detrend_Tmean.nii.gz',
        tsnr_file='prefiltered_func_data_detrend_tSNR.nii.gz'),
                           name='tsnr_detrend')

    wf.connect(multiplication, 'out_file', tsnr_detrend, 'in_file')
    wf.connect(tsnr_detrend, 'tsnr_file', ds, 'QC.@tsnr_detrend')
    wf.connect(tsnr_detrend, 'mean_file', ds, 'QC.@detrend_mean_file')
    wf.connect(tsnr_detrend, 'detrended_file', ds, '@detrend_file')

    #resample the EPI mask to original EPI dimensions
    convert2func = pe.Node(fsl.FLIRT(apply_xfm=True,
                                     interp='nearestneighbour',
                                     out_file='func_data_mask2func.nii.gz'),
                           name='conver2func')

    wf.connect(resample_mask, 'out_file', convert2func, 'in_file')
    wf.connect(bias, 'restored_image', convert2func, 'reference')
    wf.connect(inverseXFM, 'out_file', convert2func, 'in_matrix_file')
    wf.connect(convert2func, 'out_file', ds, 'QC.@inv')

    ###########################################################################
    ########################    RUN   ######################################
    wf.write_graph(dotfilename='wf.dot',
                   graph2use='colored',
                   format='pdf',
                   simple_form=True)
    wf.run(plugin='MultiProc', plugin_args={'n_procs': 2})
    #wf.run()
    return
Ejemplo n.º 7
0
def create_getmask_flow(name='getmask', dilate_mask=True):
    """Registers a source file to freesurfer space and create a brain mask in
source space

Requires fsl tools for initializing registration

Parameters
----------

name : string
name of workflow
dilate_mask : boolean
indicates whether to dilate mask or not

Example
-------

>>> getmask = create_getmask_flow()
>>> getmask.inputs.inputspec.source_file = 'mean.nii'
>>> getmask.inputs.inputspec.subject_id = 's1'
>>> getmask.inputs.inputspec.subjects_dir = '.'
>>> getmask.inputs.inputspec.contrast_type = 't2'


Inputs::

inputspec.source_file : reference image for mask generation
inputspec.subject_id : freesurfer subject id
inputspec.subjects_dir : freesurfer subjects directory
inputspec.contrast_type : MR contrast of reference image

Outputs::

outputspec.mask_file : binary mask file in reference image space
outputspec.reg_file : registration file that maps reference image to
freesurfer space
outputspec.reg_cost : cost of registration (useful for detecting misalignment)
"""
    import nipype.pipeline.engine as pe
    import nipype.interfaces.utility as niu
    import nipype.interfaces.freesurfer as fs
    import nipype.interfaces.io as nio
    """
Initialize the workflow
"""

    getmask = pe.Workflow(name=name)

    """
Define the inputs to the workflow.
"""

    inputnode = pe.Node(niu.IdentityInterface(fields=['source_file',
                                                      'subject_id',
                                                      'subjects_dir',
                                                      'contrast_type']),
        name='inputspec')

    """
Define all the nodes of the workflow:

fssource: used to retrieve aseg.mgz
threshold : binarize aseg
register : coregister source file to freesurfer space
voltransform: convert binarized aseg to source file space

"""

    fssource = pe.Node(nio.FreeSurferSource(),
        name = 'fssource')
    threshold = pe.Node(fs.Binarize(min=0.5, out_type='nii'),
        name='threshold')
    register = pe.MapNode(fs.BBRegister(init='fsl'),
        iterfield=['source_file'],
        name='register')
    voltransform = pe.MapNode(fs.ApplyVolTransform(inverse=True),
        iterfield=['source_file', 'reg_file'],
        name='transform')

    """
Connect the nodes
"""

    getmask.connect([
        (inputnode, fssource, [('subject_id','subject_id'),
            ('subjects_dir','subjects_dir')]),
        (inputnode, register, [('source_file', 'source_file'),
            ('subject_id', 'subject_id'),
            ('subjects_dir', 'subjects_dir'),
            ('contrast_type', 'contrast_type')]),
        (inputnode, voltransform, [('subjects_dir', 'subjects_dir'),
            ('source_file', 'source_file')]),
        (fssource, threshold, [(('aparc_aseg', get_aparc_aseg), 'in_file')]),
        (register, voltransform, [('out_reg_file','reg_file')]),
        (threshold, voltransform, [('binary_file','target_file')])
    ])


    """
Add remaining nodes and connections

dilate : dilate the transformed file in source space
threshold2 : binarize transformed file
"""

    threshold2 = pe.MapNode(fs.Binarize(min=0.5, out_type='nii'),
        iterfield=['in_file'],
        name='threshold2')
    if dilate_mask:
        threshold2.inputs.dilate = 1
    getmask.connect([
        (voltransform, threshold2, [('transformed_file', 'in_file')])
    ])

    """
Setup an outputnode that defines relevant inputs of the workflow.
"""

    outputnode = pe.Node(niu.IdentityInterface(fields=["mask_file",
                                                       "reg_file",
                                                       "reg_cost"
    ]),
        name="outputspec")
    getmask.connect([
        (register, outputnode, [("out_reg_file", "reg_file")]),
        (register, outputnode, [("min_cost_file", "reg_cost")]),
        (threshold2, outputnode, [("binary_file", "mask_file")]),
    ])
    return getmask
Ejemplo n.º 8
0
# Below is the command that runs AFNI's 3dTshift command
# this is the node that performs the slice timing correction
# I input the study func files as a list and the slice timing
# as a list of lists. I'm using a MapNode to iterate over the two.
# this should allow me to parallelize this on the HPC
tshifter = pe.MapNode(afni.TShift(),
                      iterfield=['in_file', 'slice_timing'],
                      name='tshifter')
tshifter.inputs.tr = '1.76'
tshifter.inputs.slice_timing = slice_timing_list
tshifter.inputs.outputtype = 'NIFTI_GZ'
psb6351_wf.connect(volreg, 'out_file', tshifter, 'in_file')

# Calculate the transformation matrix from EPI space to FreeSurfer space
# using the BBRegister command
fs_register = pe.Node(fs.BBRegister(init='fsl'), name='fs_register')
fs_register.inputs.contrast_type = 't2'
fs_register.inputs.out_fsl_file = True
fs_register.inputs.subject_id = f'sub-{sids[0]}'
fs_register.inputs.subjects_dir = fs_dir
psb6351_wf.connect(extractref, 'roi_file', fs_register, 'source_file')

# Add a mapnode to spatially blur the data
# save the outputs to the datasink
Blur = pe.MapNode(afni.BlurToFWHM(), iterfield=['in_file'], name='Blur')
#Blur.inputs.in_file = func_files #not needed?
Blur.inputs.fwhm = 3  #smoothing width in mm
Blur.inputs.automask = True
Blur.inputs.num_threads = 2
Blur.inputs.outputtype = 'NIFTI_GZ'
psb6351_wf.connect(tshifter, 'out_file', Blur, 'in_file')
Ejemplo n.º 9
0
intensity or movement.
"""

art = pe.Node(interface=ra.ArtifactDetect(), name="art")
art.inputs.use_differences = [True, False]
art.inputs.use_norm = True
art.inputs.norm_threshold = 1
art.inputs.zintensity_threshold = 3
art.inputs.mask_type = 'file'
art.inputs.parameter_source = 'SPM'
"""
Use :class:`nipype.interfaces.freesurfer.BBRegister` to coregister the mean
functional image generated by realign to the subjects' surfaces.
"""

surfregister = pe.Node(interface=fs.BBRegister(), name='surfregister')
surfregister.inputs.init = 'fsl'
surfregister.inputs.contrast_type = 't2'
"""
Use :class:`nipype.interfaces.io.FreeSurferSource` to retrieve various image
files that are automatically generated by the recon-all process.
"""

FreeSurferSource = pe.Node(interface=nio.FreeSurferSource(), name='fssource')
"""
Use :class:`nipype.interfaces.freesurfer.ApplyVolTransform` to convert the
brainmask generated by freesurfer into the realigned functional space.
"""

ApplyVolTransform = pe.Node(interface=fs.ApplyVolTransform(), name='applyreg')
ApplyVolTransform.inputs.inverse = True
Ejemplo n.º 10
0
def create_dti():
    # main workflow for preprocessing diffusion data
    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # Initiation of a workflow
    dwi_preproc = Workflow(name="dwi_preproc")
    # inputnode
    inputnode = Node(IdentityInterface(fields=[
        'subject_id', 'freesurfer_dir', 'aseg', 'dwi', 'dwi_ap', 'dwi_pa',
        'bvals', 'bvecs'
    ]),
                     name='inputnode')
    # output node
    outputnode = Node(IdentityInterface(fields=[
        'dwi_denoised', "dwi_unringed", "topup_corr", "topup_field",
        "topup_fieldcoef", "eddy_corr", "rotated_bvecs", 'total_movement_rms',
        'shell_params', 'cnr_maps', 'residuals', 'outlier_report',
        'shell_params', 'dti_fa', 'dti_md', 'dti_l1', 'dti_l2', 'dti_l3',
        'dti_v1', 'dti_v2', 'dti_v3', 'fa2anat', 'fa2anat_mat', 'fa2anat_dat'
    ]),
                      name='outputnode')
    '''
    workflow to run distortion correction
    -------------------------------------
    '''
    distor_corr = create_distortion_correct()

    #''
    ## upsampling #TODO: upsample with eddy directly, waiting for Alfred for the method
    #''
    #flirt = Node(fsl.FLIRT(), name='flirt')
    #flirt.inputs.apply_isoxfm = 1
    #TODO: to use this for dtifit, needed to creat another brain mask
    '''
    getting first bval/bvec files
    '''

    get_bvalsvecs = Node(util.Function(input_names=["bvals", "bvecs", "dwi"],
                                       output_names=["bval_file", "bvec_file"],
                                       function=return_list_element),
                         name="get_bvalsvecs")
    '''
    tensor fitting
    --------------
    '''
    dti = Node(fsl.DTIFit(), name='dti')

    #connecting the nodes
    dwi_preproc.connect([
        (inputnode, distor_corr, [('dwi', 'inputnode.dwi')]),
        (inputnode, distor_corr, [('dwi_ap', 'inputnode.dwi_ap')]),
        (inputnode, distor_corr, [('dwi_pa', 'inputnode.dwi_pa')]),
        (inputnode, get_bvalsvecs, [("bvals", "bvals")]),
        (inputnode, get_bvalsvecs, [("bvecs", "bvecs")]),
        (inputnode, get_bvalsvecs, [("dwi", "dwi")]),
        (get_bvalsvecs, distor_corr, [("bval_file", "inputnode.bvals")]),
        (get_bvalsvecs, distor_corr, [("bvec_file", "inputnode.bvecs")]),
        (get_bvalsvecs, dti, [("bval_file", "bvals")]),
        (distor_corr, outputnode, [('outputnode.bo_brain', 'bo_brain')]),
        (distor_corr, outputnode, [('outputnode.bo_brainmask', 'bo_brainmask')
                                   ]),
        (distor_corr, outputnode, [('outputnode.noise', 'noise')]),
        (distor_corr, outputnode, [('outputnode.dwi_denoised', 'dwi_denoised')
                                   ]),
        (distor_corr, outputnode, [('outputnode.dwi_unringed', 'dwi_unringed')
                                   ]),
        (distor_corr, outputnode, [('outputnode.topup_corr', 'topup_corr')]),
        (distor_corr, outputnode, [('outputnode.topup_field', 'topup_field')]),
        (distor_corr, outputnode, [('outputnode.topup_fieldcoef',
                                    'topup_fieldcoef')]),
        (distor_corr, outputnode, [('outputnode.eddy_corr', 'eddy_corr')]),
        (distor_corr, outputnode, [('outputnode.rotated_bvecs',
                                    'rotated_bvecs')]),
        (distor_corr, outputnode, [('outputnode.total_movement_rms',
                                    'total_movement_rms')]),
        (distor_corr, outputnode, [('outputnode.cnr_maps', 'cnr_maps')]),
        (distor_corr, outputnode, [('outputnode.residuals', 'residuals')]),
        (distor_corr, outputnode, [('outputnode.shell_params', 'shell_params')
                                   ]),
        (distor_corr, outputnode, [('outputnode.outlier_report',
                                    'outlier_report')]),
        (distor_corr, dti, [("outputnode.rotated_bvecs", "bvecs")]),
        (distor_corr, dti, [('outputnode.bo_brainmask', 'mask')]),
        #(distor_corr, flirt, [('outputnode.eddy_corr', 'in_file')]),
        #(distor_corr, flirt, [('outputnode.eddy_corr', 'reference')]),
        #(flirt, dti, [('out_file', 'dwi')]),
        (distor_corr, dti, [('outputnode.eddy_corr', 'dwi')]),
        (dti, outputnode, [('FA', 'dti_fa')]),
        (dti, outputnode, [('MD', 'dti_md')]),
        (dti, outputnode, [('L1', 'dti_l1')]),
        (dti, outputnode, [('L2', 'dti_l2')]),
        (dti, outputnode, [('L3', 'dti_l3')]),
        (dti, outputnode, [('V1', 'dti_v1')]),
        (dti, outputnode, [('V2', 'dti_v2')]),
        (dti, outputnode, [('V3', 'dti_v3')])
    ])
    '''
    coregistration of FA and T1
    ------------------------------------
    '''

    # linear registration with bbregister
    bbreg = Node(fs.BBRegister(contrast_type='t1',
                               out_fsl_file='fa2anat.mat',
                               out_reg_file='fa2anat.dat',
                               registered_file='fa2anat_bbreg.nii.gz',
                               init='fsl'),
                 name='bbregister')

    # connecting the nodes
    dwi_preproc.connect([
        (inputnode, bbreg, [('subject_id', 'subject_id')]),
        (inputnode, bbreg, [('freesurfer_dir', 'subjects_dir')]),
        (dti, bbreg, [("FA", "source_file")]),
        (bbreg, outputnode, [('out_fsl_file', 'fa2anat_mat'),
                             ('out_reg_file', 'fa2anat_dat'),
                             ('registered_file', 'fa2anat')])
    ])

    return dwi_preproc
Ejemplo n.º 11
0
def create_topup_coreg_pipeline(name='fmap_coreg'):
    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # initiate workflow
    fmap_coreg = Workflow(name='fmap_coreg')
    # inputnode
    inputnode = Node(util.IdentityInterface(fields=[
        'epi_mean', 'ap', 'pa', 'anat_head', 'anat_brain', 'fs_subject_id',
        'fs_subjects_dir', 'echo_space', 'pe_dir'
    ]),
                     name='inputnode')
    # outputnode
    outputnode = Node(util.IdentityInterface(fields=[
        'fmap', 'shiftmap', 'unwarpfield_epi2fmap', 'unwarped_mean_epi2fmap',
        'epi2anat_mat', 'epi2anat_dat', 'epi2anat_mincost', 'epi2anat',
        'epi2fmap', 'fmap_fullwarp'
    ]),
                      name='outputnode')

    #### merge epi ap and pa
    mergeToFilelist = Node(util.Merge(2),
                           infields=['in1', 'in2'],
                           name='mergeToFilelist')

    merge_appa = Node(fsl.Merge(), name='merge_appa')
    merge_appa.inputs.dimension = 't'
    merge_appa.inputs.merged_file = 'cmrr_mbep2d_se_23iso_norm.nii.gz'

    #use mean file of ap-pa acquisitions as "Mag"-image from fieldmap, only used for coregistration with mean EPI
    mean_appa = Node(fsl.MeanImage(), name='mean_appa')

    #### use topup --> creates fieldmap
    topup_prep = Node(fsl.TOPUP(), name='topup_prep')
    topup_prep.inputs.encoding_file = '/data/pt_02030/Analysis/Preprocessing/MRI/nipy1.4/functional/aquisition_params.txt'

    #multiply topup result to convert to rad/s
    convertHz_rad = Node(fsl.maths.MathsCommand(args='-mul 6.28'),
                         name='convertHz_rad')
    fmap_coreg.connect([(inputnode, mergeToFilelist, [('ap', 'in1')]),
                        (inputnode, mergeToFilelist, [('pa', 'in2')]),
                        (mergeToFilelist, merge_appa, [('out', 'in_files')]),
                        (merge_appa, mean_appa, [('merged_file', 'in_file')]),
                        (merge_appa, topup_prep, [('merged_file', 'in_file')]),
                        (topup_prep, convertHz_rad, [('out_field', 'in_file')])
                        ])

    #### unmask fieldmap #### is maybe not needed as our fieldmap is already in the whole image space?
    fmap_mask = Node(fsl.maths.MathsCommand(args='-abs -bin'),
                     name='fmap_mask')
    #    unmask = Node(fsl.FUGUE(save_unmasked_fmap=True),
    #                  name='unmask')
    fmap_coreg.connect([
        (convertHz_rad, fmap_mask, [('out_file', 'in_file')])
        #                        (fmap_mask, unmask, [('out_file', 'mask_file')]),
        #                        (convertHz_rad, unmask, [('out_file', 'fmap_in_file')]),
        #                        (inputnode, unmask, [('pe_dir', 'unwarp_direction')])
    ])

    #### register epi to fieldmap ####
    epi2fmap = Node(fsl.FLIRT(dof=6,
                              out_file='rest_mean2fmap.nii.gz',
                              interp='spline'),
                    name='epi2fmap')
    fmap_coreg.connect([(inputnode, epi2fmap, [('epi_mean', 'in_file')]),
                        (mean_appa, epi2fmap, [('out_file', 'reference')]),
                        (epi2fmap, outputnode, [('out_file', 'epi2fmap')])])

    #### unwarp epi with fieldmap ####
    unwarp = Node(fsl.FUGUE(save_shift=True), name='unwarp')
    fmap_coreg.connect([
        (epi2fmap, unwarp, [('out_file', 'in_file')]),
        (convertHz_rad, unwarp, [('out_file', 'fmap_in_file')]),
        (fmap_mask, unwarp, [('out_file', 'mask_file')]),
        (inputnode, unwarp, [('echo_space', 'dwell_time'),
                             ('pe_dir', 'unwarp_direction')]),
        (unwarp, outputnode, [('shift_out_file', 'shiftmap')])
    ])

    #### make warpfield and apply ####
    convertwarp0 = Node(fsl.utils.ConvertWarp(
        out_relwarp=True, out_file='rest_mean2fmap_unwarpfield.nii.gz'),
                        name='convertwarp0')
    applywarp0 = Node(fsl.ApplyWarp(interp='spline',
                                    relwarp=True,
                                    out_file='rest_mean2fmap_unwarped.nii.gz',
                                    datatype='float'),
                      name='applywarp0')
    fmap_coreg.connect([
        (mean_appa, convertwarp0, [('out_file', 'reference')]),
        (epi2fmap, convertwarp0, [('out_matrix_file', 'premat')]),
        (unwarp, convertwarp0, [('shift_out_file', 'shift_in_file')]),
        (inputnode, convertwarp0, [('pe_dir', 'shift_direction')]),
        (inputnode, applywarp0, [('epi_mean', 'in_file')]),
        (mean_appa, applywarp0, [('out_file', 'ref_file')]),
        (convertwarp0, applywarp0, [('out_file', 'field_file')]),
        (convertwarp0, outputnode, [('out_file', 'unwarpfield_epi2fmap')]),
        (applywarp0, outputnode, [('out_file', 'unwarped_mean_epi2fmap')])
    ])

    #### register epi to anatomy #####
    # linear registration with bbregister
    bbregister = Node(fs.BBRegister(
        contrast_type='t2',
        out_fsl_file='rest2anat.mat',
        out_reg_file='rest2anat.dat',
        registered_file='rest_mean2anat_highres.nii.gz',
        init='fsl',
        epi_mask=True),
                      name='bbregister')
    fmap_coreg.connect([
        (applywarp0, bbregister, [('out_file', 'source_file')]),
        (inputnode, bbregister, [('fs_subjects_dir', 'subjects_dir'),
                                 ('fs_subject_id', 'subject_id')]),
        (bbregister, outputnode, [('out_fsl_file', 'epi2anat_mat'),
                                  ('out_reg_file', 'epi2anat_dat'),
                                  ('registered_file', 'epi2anat'),
                                  ('min_cost_file', 'epi2anat_mincost')]),
    ])
    # make warpfield
    convertwarp = Node(fsl.utils.ConvertWarp(out_relwarp=True,
                                             out_file='fullwarpfield.nii.gz'),
                       name='convertwarp')
    fmap_coreg.connect([
        (inputnode, convertwarp, [('anat_head', 'reference')]),
        (convertwarp0, convertwarp, [('out_file', 'warp1')]),
        (bbregister, convertwarp, [('out_fsl_file', 'postmat')]),
        (convertwarp, outputnode, [('out_file', 'fmap_fullwarp')])
    ])
    return fmap_coreg
Ejemplo n.º 12
0
def create_workflow(func_runs,
                    subject_id,
                    subjects_dir,
                    fwhm,
                    slice_times,
                    highpass_frequency,
                    lowpass_frequency,
                    TR,
                    sink_directory,
                    use_fsl_bp,
                    num_components,
                    whichvol,
                    name='wmaze'):
    
    wf = pe.Workflow(name=name)

    datasource = pe.Node(nio.DataGrabber(infields=['subject_id', 'run'],
                                         outfields=['func']),
                         name='datasource')
    datasource.inputs.subject_id = subject_id
    datasource.inputs.run = func_runs
    datasource.inputs.template = '/home/data/madlab/data/mri/wmaze/%s/bold/bold_%03d/bold.nii.gz'
    datasource.inputs.sort_filelist = True
    
    # Rename files in case they are named identically
    name_unique = pe.MapNode(util.Rename(format_string='wmaze_%(run)02d'),
                             iterfield = ['in_file', 'run'],
                             name='rename')
    name_unique.inputs.keep_ext = True
    name_unique.inputs.run = func_runs
    wf.connect(datasource, 'func', name_unique, 'in_file')

    # Define the outputs for the preprocessing workflow
    output_fields = ['reference',
                     'motion_parameters',
                     'motion_parameters_plusDerivs',
                     'motionandoutlier_noise_file',
                     'noise_components',
                     'realigned_files',
                     'motion_plots',
                     'mask_file',
                     'smoothed_files',
                     'bandpassed_files',
                     'reg_file',
                     'reg_cost',
                     'reg_fsl_file',
                     'artnorm_files',
                     'artoutlier_files',
                     'artdisplacement_files',
                     'tsnr_file']
        
    outputnode = pe.Node(util.IdentityInterface(fields=output_fields),
                         name='outputspec')

    # Convert functional images to float representation
    img2float = pe.MapNode(fsl.ImageMaths(out_data_type='float',
                                        op_string = '',
                                        suffix='_dtype'),
                           iterfield=['in_file'],
                           name='img2float')
    wf.connect(name_unique, 'out_file', img2float, 'in_file')

    # Run AFNI's despike. This is always run, however, whether this is fed to
    # realign depends on the input configuration
    despiker = pe.MapNode(afni.Despike(outputtype='NIFTI_GZ'),
                          iterfield=['in_file'],
                          name='despike')
    num_threads = 4
    despiker.inputs.environ = {'OMP_NUM_THREADS': '%d' % num_threads}
    despiker.plugin_args = {'bsub_args': '-n %d' % num_threads}
    despiker.plugin_args = {'bsub_args': '-R "span[hosts=1]"'}
    wf.connect(img2float, 'out_file', despiker, 'in_file')

    # Extract the first volume of the first run as the reference 
    extractref = pe.Node(fsl.ExtractROI(t_size=1),
                         iterfield=['in_file'],
                         name = "extractref")
    wf.connect(despiker, ('out_file', pickfirst), extractref, 'in_file')
    wf.connect(despiker, ('out_file', pickvol, 0, whichvol), extractref, 't_min')
    wf.connect(extractref, 'roi_file', outputnode, 'reference')

    if slice_times is not None:
        # Simultaneous motion and slice timing correction with Nipy algorithm
        motion_correct = pe.Node(nipy.SpaceTimeRealigner(), name='motion_correct')
        motion_correct.inputs.tr = TR
        motion_correct.inputs.slice_times = slice_times
        motion_correct.inputs.slice_info = 2
        motion_correct.plugin_args = {'bsub_args': '-n %s' %os.environ['MKL_NUM_THREADS']}
        motion_correct.plugin_args = {'bsub_args': '-R "span[hosts=1]"'}
        wf.connect(despiker, 'out_file', motion_correct, 'in_file')
        wf.connect(motion_correct, 'par_file', outputnode, 'motion_parameters')
        wf.connect(motion_correct, 'out_file', outputnode, 'realigned_files')
    else:
        # Motion correct functional runs to the reference (1st volume of 1st run)
        motion_correct =  pe.MapNode(fsl.MCFLIRT(save_mats = True,
                                                 save_plots = True,
                                                 interpolation = 'sinc'),
                                     name = 'motion_correct',
                                     iterfield = ['in_file'])
        wf.connect(despiker, 'out_file', motion_correct, 'in_file')
        wf.connect(extractref, 'roi_file', motion_correct, 'ref_file')
        wf.connect(motion_correct, 'par_file', outputnode, 'motion_parameters')
        wf.connect(motion_correct, 'out_file', outputnode, 'realigned_files')

    # Compute TSNR on realigned data regressing polynomials upto order 2
    tsnr = pe.MapNode(TSNR(regress_poly=2), iterfield=['in_file'], name='tsnr')
    wf.connect(motion_correct, 'out_file', tsnr, 'in_file')
    wf.connect(tsnr, 'tsnr_file', outputnode, 'tsnr_file')

    # Plot the estimated motion parameters
    plot_motion = pe.MapNode(fsl.PlotMotionParams(in_source='fsl'),
                             name='plot_motion',
                             iterfield=['in_file'])
    plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
    wf.connect(motion_correct, 'par_file', plot_motion, 'in_file')
    wf.connect(plot_motion, 'out_file', outputnode, 'motion_plots')

    # Register a source file to fs space and create a brain mask in source space
    fssource = pe.Node(nio.FreeSurferSource(),
                       name ='fssource')
    fssource.inputs.subject_id = subject_id
    fssource.inputs.subjects_dir = subjects_dir

    # Extract aparc+aseg brain mask and binarize
    fs_threshold = pe.Node(fs.Binarize(min=0.5, out_type='nii'),
                           name ='fs_threshold')
    wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), fs_threshold, 'in_file')

    # Calculate the transformation matrix from EPI space to FreeSurfer space
    # using the BBRegister command
    fs_register = pe.MapNode(fs.BBRegister(init='fsl'),
                             iterfield=['source_file'],
                             name ='fs_register')
    fs_register.inputs.contrast_type = 't2'
    fs_register.inputs.out_fsl_file = True
    fs_register.inputs.subject_id = subject_id
    fs_register.inputs.subjects_dir = subjects_dir
    wf.connect(extractref, 'roi_file', fs_register, 'source_file')
    wf.connect(fs_register, 'out_reg_file', outputnode, 'reg_file')
    wf.connect(fs_register, 'min_cost_file', outputnode, 'reg_cost')
    wf.connect(fs_register, 'out_fsl_file', outputnode, 'reg_fsl_file')

    # Extract wm+csf, brain masks by eroding freesurfer lables
    wmcsf = pe.MapNode(fs.Binarize(), 
                       iterfield=['match', 'binary_file', 'erode'], name='wmcsfmask')
    #wmcsf.inputs.wm_ven_csf = True
    wmcsf.inputs.match = [[2, 41], [4, 5, 14, 15, 24, 31, 43, 44, 63]]
    wmcsf.inputs.binary_file = ['wm.nii.gz', 'csf.nii.gz']
    wmcsf.inputs.erode = [2, 2] #int(np.ceil(slice_thickness))
    wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), wmcsf, 'in_file')

    # Now transform the wm and csf masks to 1st volume of 1st run
    wmcsftransform = pe.MapNode(fs.ApplyVolTransform(inverse=True,
                                                     interp='nearest'),
                                iterfield=['target_file'],
                                name='wmcsftransform')
    wmcsftransform.inputs.subjects_dir = subjects_dir
    wf.connect(extractref, 'roi_file', wmcsftransform, 'source_file')
    wf.connect(fs_register, ('out_reg_file', pickfirst), wmcsftransform, 'reg_file')
    wf.connect(wmcsf, 'binary_file', wmcsftransform, 'target_file')

    # Transform the binarized aparc+aseg file to the 1st volume of 1st run space
    fs_voltransform = pe.MapNode(fs.ApplyVolTransform(inverse=True),
                                 iterfield = ['source_file', 'reg_file'],
                                 name='fs_transform')
    fs_voltransform.inputs.subjects_dir = subjects_dir
    wf.connect(extractref, 'roi_file', fs_voltransform, 'source_file')
    wf.connect(fs_register, 'out_reg_file', fs_voltransform, 'reg_file')
    wf.connect(fs_threshold, 'binary_file', fs_voltransform, 'target_file')

    # Dilate the binarized mask by 1 voxel that is now in the EPI space
    fs_threshold2 = pe.MapNode(fs.Binarize(min=0.5, out_type='nii'),
                               iterfield=['in_file'],
                               name='fs_threshold2')
    fs_threshold2.inputs.dilate = 1
    wf.connect(fs_voltransform, 'transformed_file', fs_threshold2, 'in_file')
    wf.connect(fs_threshold2, 'binary_file', outputnode, 'mask_file')
    
    # Use RapidART to detect motion/intensity outliers
    art = pe.MapNode(ra.ArtifactDetect(use_differences = [True, False],
                                       use_norm = True,
                                       zintensity_threshold = 3,
                                       norm_threshold = 1,
                                       bound_by_brainmask=True,
                                       mask_type = "file"),
                     iterfield=["realignment_parameters","realigned_files"],
                     name="art")
    if slice_times is not None:
        art.inputs.parameter_source = "NiPy"
    else:
        art.inputs.parameter_source = "FSL"
    wf.connect(motion_correct, 'par_file', art, 'realignment_parameters')
    wf.connect(motion_correct, 'out_file', art, 'realigned_files')
    wf.connect(fs_threshold2, ('binary_file', pickfirst), art, 'mask_file')
    wf.connect(art, 'norm_files', outputnode, 'artnorm_files')
    wf.connect(art, 'outlier_files', outputnode, 'artoutlier_files')
    wf.connect(art, 'displacement_files', outputnode, 'artdisplacement_files')

    # Compute motion regressors (save file with 1st and 2nd derivatives)
    motreg = pe.Node(util.Function(input_names=['motion_params', 'order',
                                                'derivatives'],
                                   output_names=['out_files'],
                                   function=motion_regressors,
                                   imports=imports),
                     name='getmotionregress')
    wf.connect(motion_correct, 'par_file', motreg, 'motion_params')
    wf.connect(motreg, 'out_files', outputnode, 'motion_parameters_plusDerivs')

    # Create a filter text file to remove motion (+ derivatives), art confounds,
    # and 1st, 2nd, and 3rd order legendre polynomials.
    createfilter1 = pe.Node(util.Function(input_names=['motion_params', 'comp_norm',
                                                       'outliers', 'detrend_poly'],
                                          output_names=['out_files'],
                                          function=build_filter1,
                                          imports=imports),
                            name='makemotionbasedfilter')
    createfilter1.inputs.detrend_poly = 3
    wf.connect(motreg, 'out_files', createfilter1, 'motion_params')
    wf.connect(art, 'norm_files', createfilter1, 'comp_norm')
    wf.connect(art, 'outlier_files', createfilter1, 'outliers')
    wf.connect(createfilter1, 'out_files', outputnode, 'motionandoutlier_noise_file')

    # Create a filter to remove noise components based on white matter and CSF
    createfilter2 = pe.MapNode(util.Function(input_names=['realigned_file', 'mask_file',
                                                          'num_components',
                                                          'extra_regressors'],
                                             output_names=['out_files'],
                                             function=extract_noise_components,
                                             imports=imports),
                               iterfield=['realigned_file', 'extra_regressors'],
                               name='makecompcorrfilter')
    createfilter2.inputs.num_components = num_components
    wf.connect(createfilter1, 'out_files', createfilter2, 'extra_regressors')
    wf.connect(motion_correct, 'out_file', createfilter2, 'realigned_file')
    wf.connect(wmcsftransform, 'transformed_file', createfilter2, 'mask_file')
    wf.connect(createfilter2, 'out_files', outputnode, 'noise_components')

    # Mask the functional runs with the extracted mask
    maskfunc = pe.MapNode(fsl.ImageMaths(suffix='_bet',
                                         op_string='-mas'),
                          iterfield=['in_file'],
                          name = 'maskfunc')
    wf.connect(motion_correct, 'out_file', maskfunc, 'in_file')
    wf.connect(fs_threshold2, ('binary_file', pickfirst), maskfunc, 'in_file2')
    
    # Smooth each run using SUSAn with the brightness threshold set to 75%
    # of the median value for each run and a mask constituting the mean functional
    smooth_median = pe.MapNode(fsl.ImageStats(op_string='-k %s -p 50'),
                               iterfield = ['in_file'],
                               name='smooth_median')
    wf.connect(maskfunc, 'out_file', smooth_median, 'in_file')
    wf.connect(fs_threshold2, ('binary_file', pickfirst), smooth_median, 'mask_file')
    
    smooth_meanfunc = pe.MapNode(fsl.ImageMaths(op_string='-Tmean',
                                                suffix='_mean'),
                                 iterfield=['in_file'],
                                 name='smooth_meanfunc')
    wf.connect(maskfunc, 'out_file', smooth_meanfunc, 'in_file')

    smooth_merge = pe.Node(util.Merge(2, axis='hstack'),
                           name='smooth_merge')
    wf.connect(smooth_meanfunc, 'out_file', smooth_merge, 'in1')
    wf.connect(smooth_median, 'out_stat', smooth_merge, 'in2')

    smooth = pe.MapNode(fsl.SUSAN(),
                        iterfield=['in_file', 'brightness_threshold', 'usans'],
                        name='smooth')
    smooth.inputs.fwhm=fwhm
    wf.connect(maskfunc, 'out_file', smooth, 'in_file')
    wf.connect(smooth_median, ('out_stat', getbtthresh), smooth, 'brightness_threshold')
    wf.connect(smooth_merge, ('out', getusans), smooth, 'usans')
    
    # Mask the smoothed data with the dilated mask
    maskfunc2 = pe.MapNode(fsl.ImageMaths(suffix='_mask',
                                          op_string='-mas'),
                           iterfield=['in_file'],
                           name='maskfunc2')
    wf.connect(smooth, 'smoothed_file', maskfunc2, 'in_file')
    wf.connect(fs_threshold2, ('binary_file', pickfirst), maskfunc2, 'in_file2')
    wf.connect(maskfunc2, 'out_file', outputnode, 'smoothed_files')

    # Band-pass filter the timeseries
    if use_fsl_bp == 'True':
        determine_bp_sigmas = pe.Node(util.Function(input_names=['tr',
                                                                 'highpass_freq',
                                                                 'lowpass_freq'],
                                                    output_names = ['out_sigmas'],
                                                    function=calc_fslbp_sigmas),
                                      name='determine_bp_sigmas')
        determine_bp_sigmas.inputs.tr = float(TR)
        determine_bp_sigmas.inputs.highpass_freq = float(highpass_frequency)
        determine_bp_sigmas.inputs.lowpass_freq = float(lowpass_frequency)

        bandpass = pe.MapNode(fsl.ImageMaths(suffix='_tempfilt'),
                              iterfield=["in_file"],
                              name="bandpass")
        wf.connect(determine_bp_sigmas, ('out_sigmas', highpass_operand), bandpass, 'op_string')
        wf.connect(maskfunc2, 'out_file', bandpass, 'in_file')
        wf.connect(bandpass, 'out_file', outputnode, 'bandpassed_files')
    else:
        bandpass = pe.Node(util.Function(input_names=['files',
                                                      'lowpass_freq',
                                                      'highpass_freq',
                                                      'fs'],
                                         output_names=['out_files'],
                                         function=bandpass_filter,
                                         imports=imports),
                           name='bandpass')
        bandpass.inputs.fs = 1./TR
        if highpass_frequency < 0:
            bandpass.inputs.highpass_freq = -1
        else:
            bandpass.inputs.highpass_freq = highpass_frequency
        if lowpass_frequency < 0:
            bandpass.inputs.lowpass_freq = -1
        else:
            bandpass.inputs.lowpass_freq = lowpass_frequency
        wf.connect(maskfunc2, 'out_file', bandpass, 'files')
        wf.connect(bandpass, 'out_files', outputnode, 'bandpassed_files')

    # Save the relevant data into an output directory
    datasink = pe.Node(nio.DataSink(), name="datasink")
    datasink.inputs.base_directory = sink_directory
    datasink.inputs.container = subject_id
    wf.connect(outputnode, 'reference', datasink, 'ref')
    wf.connect(outputnode, 'motion_parameters', datasink, 'motion')
    wf.connect(outputnode, 'realigned_files', datasink, 'func.realigned')
    wf.connect(outputnode, 'motion_plots', datasink, 'motion.@plots')
    wf.connect(outputnode, 'mask_file', datasink, 'ref.@mask')
    wf.connect(outputnode, 'smoothed_files', datasink, 'func.smoothed_fullspectrum')
    wf.connect(outputnode, 'bandpassed_files', datasink, 'func.smoothed_bandpassed')
    wf.connect(outputnode, 'reg_file', datasink, 'bbreg.@reg')
    wf.connect(outputnode, 'reg_cost', datasink, 'bbreg.@cost')
    wf.connect(outputnode, 'reg_fsl_file', datasink, 'bbreg.@regfsl')
    wf.connect(outputnode, 'artnorm_files', datasink, 'art.@norm_files')
    wf.connect(outputnode, 'artoutlier_files', datasink, 'art.@outlier_files')
    wf.connect(outputnode, 'artdisplacement_files', datasink, 'art.@displacement_files')
    wf.connect(outputnode, 'motion_parameters_plusDerivs', datasink, 'noise.@motionplusDerivs')
    wf.connect(outputnode, 'motionandoutlier_noise_file', datasink, 'noise.@motionplusoutliers')
    wf.connect(outputnode, 'noise_components', datasink, 'compcor')
    wf.connect(outputnode, 'tsnr_file', datasink, 'tsnr')    

    return wf
Ejemplo n.º 13
0
func_tstat = pe.MapNode(interface=e_afni.ThreedTstat(),
                        name='func_tstat',
                        iterfield=["in_file"])
func_tstat.inputs.args = "-mean"
func_tstat.inputs.out_file = 'rest_ro_mean.nii.gz'

func_volreg = pe.MapNode(interface=e_afni.Threedvolreg(),
                         name='func_volreg',
                         iterfield=["in_file", "basefile"])
func_volreg.inputs.other = '-Fourier -twopass'
func_volreg.inputs.zpad = '4'
func_volreg.inputs.oned_file = 'rest_mc.1D'
func_volreg.inputs.out_file = 'rest_mc.nii.gz'

func_bbreg = pe.MapNode(interface=fs.BBRegister(init='fsl',
                                                contrast_type='t2',
                                                registered_file=True,
                                                out_fsl_file=True),
                        name='func_bbreg',
                        iterfield=["source_file"])

func_sampler_lh = pe.MapNode(interface=fs.SampleToSurface(hemi="lh"),
                             name='func_sampler_lh',
                             iterfield=["source_file", "reg_file"])
func_sampler_lh.inputs.no_reshape = True
func_sampler_lh.inputs.interp_method = 'trilinear'
func_sampler_lh.inputs.sampling_method = "point"
func_sampler_lh.inputs.sampling_range = 0.5
func_sampler_lh.inputs.sampling_units = "frac"

func_sampler_rh = pe.MapNode(interface=fs.SampleToSurface(hemi="rh"),
                             name='func_sampler_rh',
Ejemplo n.º 14
0
def create_epi_to_T1_workflow(name='epi_to_T1', use_FS=True, do_FAST=True):
    """Registers session's EPI space to subject's T1 space
    uses either FLIRT or, when a FS segmentation is present, BBRegister
    Requires fsl and freesurfer tools

    Parameters
    ----------
    name : string
        name of workflow
    use_FS : bool
        whether to use freesurfer's segmentation and BBRegister
    Example
    -------
    >>> epi_to_T1 = create_epi_to_T1_workflow('epi_to_T1', use_FS = True)
    >>> epi_to_T1.inputs.inputspec.EPI_space_file = 'example_Func.nii.gz'
    >>> epi_to_T1.inputs.inputspec.T1_file = 'T1.nii.gz'
    >>> epi_to_T1.inputs.inputspec.freesurfer_subject_ID = 'sub_01'
    >>> epi_to_T1.inputs.inputspec.freesurfer_subject_dir = '$SUBJECTS_DIR'
 
    Inputs::
          inputspec.T1_file : T1 anatomy file
          inputspec.EPI_space_file : EPI session file
          inputspec.freesurfer_subject_ID : FS subject ID
          inputspec.freesurfer_subject_dir : $SUBJECTS_DIR
    Outputs::
           outputspec.EPI_T1_register_file : BBRegister registration file that maps EPI space to T1
           outputspec.EPI_T1_matrix_file : FLIRT registration file that maps EPI space to T1
           outputspec.T1_EPI_matrix_file : FLIRT registration file that maps T1 space to EPI
    """

    input_node = pe.Node(IdentityInterface(fields=[
        'EPI_space_file', 'output_directory', 'freesurfer_subject_ID',
        'freesurfer_subject_dir', 'T1_file'
    ]),
                         name='inputspec')

    # Idea: also output FAST outputs for later use?
    output_node = pe.Node(IdentityInterface(fields=('EPI_T1_matrix_file',
                                                    'T1_EPI_matrix_file',
                                                    'EPI_T1_register_file')),
                          name='outputspec')

    epi_to_T1_workflow = pe.Workflow(name=name)

    if use_FS:  # do BBRegister
        bbregister_N = pe.Node(freesurfer.BBRegister(init='fsl',
                                                     contrast_type='t2',
                                                     out_fsl_file=True),
                               name='bbregister_N')

        epi_to_T1_workflow.connect(input_node, 'EPI_space_file', bbregister_N,
                                   'source_file')
        epi_to_T1_workflow.connect(input_node, 'freesurfer_subject_ID',
                                   bbregister_N, 'subject_id')
        epi_to_T1_workflow.connect(input_node, 'freesurfer_subject_dir',
                                   bbregister_N, 'subjects_dir')

        epi_to_T1_workflow.connect(bbregister_N, 'out_fsl_file', output_node,
                                   'EPI_T1_matrix_file')
        epi_to_T1_workflow.connect(bbregister_N, 'out_reg_file', output_node,
                                   'EPI_T1_register_file')

        # the final invert node
        invert_EPI_N = pe.Node(fsl.ConvertXFM(invert_xfm=True),
                               name='invert_EPI_N')
        epi_to_T1_workflow.connect(bbregister_N, 'out_fsl_file', invert_EPI_N,
                                   'in_file')
        epi_to_T1_workflow.connect(invert_EPI_N, 'out_file', output_node,
                                   'T1_EPI_matrix_file')

    else:  # do FAST + FLIRT

        flirt_e2t = pe.Node(fsl.FLIRT(cost_func='bbr',
                                      output_type='NIFTI_GZ',
                                      dof=12,
                                      interp='sinc'),
                            name='flirt_e2t')

        epi_to_T1_workflow.connect(input_node, 'EPI_space_file', flirt_e2t,
                                   'in_file')

        if do_FAST:
            fast = pe.Node(fsl.FAST(no_pve=True, img_type=1, segments=True),
                           name='fast')

            epi_to_T1_workflow.connect(input_node, 'T1_file', fast, 'in_files')
            epi_to_T1_workflow.connect(fast, ('tissue_class_files', pick_last),
                                       flirt_e2t, 'wm_seg')
        elif not do_FAST and flirt_e2t.inputs.cost_func == 'bbr':
            print(
                'You indicated not wanting to do FAST, but still wanting to do a'
                ' BBR epi-to-T1 registration. That is probably not going to work ...'
            )

        epi_to_T1_workflow.connect(input_node, 'T1_file', flirt_e2t,
                                   'reference')
        epi_to_T1_workflow.connect(flirt_e2t, 'out_matrix_file', output_node,
                                   'EPI_T1_matrix_file')

        # the final invert node
        invert_EPI_N = pe.Node(fsl.ConvertXFM(invert_xfm=True),
                               name='invert_EPI_N')
        epi_to_T1_workflow.connect(flirt_e2t, 'out_matrix_file', invert_EPI_N,
                                   'in_file')
        epi_to_T1_workflow.connect(invert_EPI_N, 'out_file', output_node,
                                   'T1_EPI_matrix_file')

    return epi_to_T1_workflow
Ejemplo n.º 15
0
 def create_workflow(self, flow, inputnode, outputnode):        
     # Extract first volume and resample it to 1x1x1mm3
     if self.config.pipeline == "Diffusion":
         extract_first = pe.Node(interface=fsl.ExtractROI(t_min=0,t_size=1,roi_file='first.nii.gz'),name='extract_first')
         flow.connect([
                       (inputnode,extract_first,[("target","in_file")])
                     ])
         fs_mriconvert = pe.Node(interface=fs.MRIConvert(out_file="target_first.nii.gz",vox_size=(1,1,1)),name="target_resample")
         flow.connect([(extract_first, fs_mriconvert,[('roi_file','in_file')])])
     elif self.config.pipeline == "fMRI":
         fmri_bet = pe.Node(interface=fsl.BET(),name="fMRI_skullstrip")
         T1_bet = pe.Node(interface=fsl.BET(),name="T1_skullstrip")
         flow.connect([
                     (inputnode,fmri_bet,[("target","in_file")]),
                     (inputnode,T1_bet,[("T1","in_file")])
                     ])
     
     if self.config.registration_mode == 'Linear (FSL)':
         fsl_flirt = pe.Node(interface=fsl.FLIRT(out_file='T1-TO-TARGET.nii.gz',out_matrix_file='T1-TO-TARGET.mat'),name="linear_registration")
         fsl_flirt.inputs.uses_qform = self.config.uses_qform
         fsl_flirt.inputs.dof = self.config.dof
         fsl_flirt.inputs.cost = self.config.cost
         fsl_flirt.inputs.no_search = self.config.no_search
         fsl_flirt.inputs.args = self.config.flirt_args
         
         fsl_applyxfm_wm = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="wm_mask_registered.nii.gz"),name="apply_registration_wm")
         fsl_applyxfm_rois = pe.Node(interface=ApplymultipleXfm(),name="apply_registration_roivs")           
         
         flow.connect([
                     (inputnode, fsl_applyxfm_wm, [('wm_mask','in_file')]),
                     (fsl_flirt,outputnode,[("out_file","T1_registered")]),
                     (fsl_flirt, fsl_applyxfm_wm, [('out_matrix_file','in_matrix_file')]),
                     (fsl_applyxfm_wm, outputnode, [('out_file','wm_mask_registered')]),
                     (inputnode, fsl_applyxfm_rois, [('roi_volumes','in_files')]),
                     (fsl_flirt, fsl_applyxfm_rois, [('out_matrix_file','xfm_file')]),
                     (fsl_applyxfm_rois, outputnode, [('out_files','roi_volumes_registered')])
                     ])
         
         if self.config.pipeline == "fMRI":
             flow.connect([
                         (T1_bet, fsl_flirt, [('out_file','in_file')]),
                         (fmri_bet, fsl_flirt, [('out_file','reference')]),
                         (fmri_bet, fsl_applyxfm_wm, [('out_file','reference')]),
                         (fmri_bet, fsl_applyxfm_rois, [('out_file','reference')])
                         ])
             fsl_applyxfm_eroded_wm = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="eroded_wm_registered.nii.gz"),name="apply_registration_wm_eroded")
             if self.config.apply_to_eroded_csf:
                 fsl_applyxfm_eroded_csf = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="eroded_csf_registered.nii.gz"),name="apply_registration_csf_eroded")
                 flow.connect([
                               (inputnode, fsl_applyxfm_eroded_csf, [('eroded_csf','in_file')]),
                               (fmri_bet, fsl_applyxfm_eroded_csf, [('out_file','reference')]),
                               (fsl_flirt, fsl_applyxfm_eroded_csf, [('out_matrix_file','in_matrix_file')]),
                               (fsl_applyxfm_eroded_csf, outputnode, [('out_file','eroded_csf_registered')])
                             ])
             if self.config.apply_to_eroded_brain:
                 fsl_applyxfm_eroded_brain = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="eroded_brain_registered.nii.gz"),name="apply_registration_brain_eroded")
                 flow.connect([
                               (inputnode, fsl_applyxfm_eroded_brain, [('eroded_brain','in_file')]),
                               (fmri_bet, fsl_applyxfm_eroded_brain, [('out_file','reference')]),
                               (fsl_flirt, fsl_applyxfm_eroded_brain, [('out_matrix_file','in_matrix_file')]),
                               (fsl_applyxfm_eroded_brain, outputnode, [('out_file','eroded_brain_registered')])
                             ])
             flow.connect([
                         (inputnode, fsl_applyxfm_eroded_wm, [('eroded_wm','in_file')]),
                         (fmri_bet, fsl_applyxfm_eroded_wm, [('out_file','reference')]),
                         (fsl_flirt, fsl_applyxfm_eroded_wm, [('out_matrix_file','in_matrix_file')]),
                         (fsl_applyxfm_eroded_wm, outputnode, [('out_file','eroded_wm_registered')])
                         ])
         else:
             flow.connect([
                         (inputnode, fsl_flirt, [('T1','in_file')]),
                         (fs_mriconvert, fsl_flirt, [('out_file','reference')]),
                         (fs_mriconvert, fsl_applyxfm_wm, [('out_file','reference')]),
                         (fs_mriconvert, fsl_applyxfm_rois, [('out_file','reference')]),
                         ])
             
     if self.config.registration_mode == 'BBregister (FS)':
         fs_bbregister = pe.Node(interface=fs.BBRegister(out_fsl_file="target-TO-orig.mat"),name="bbregister")
         fs_bbregister.inputs.init = self.config.init
         fs_bbregister.inputs.contrast_type = self.config.contrast_type
         
         fsl_invertxfm = pe.Node(interface=fsl.ConvertXFM(invert_xfm=True),name="fsl_invertxfm")
         
         fs_source = pe.Node(interface=fs.preprocess.FreeSurferSource(),name="get_fs_files")
         
         fs_tkregister2 = pe.Node(interface=Tkregister2(regheader=True,noedit=True),name="fs_tkregister2")
         fs_tkregister2.inputs.reg_out = 'T1-TO-orig.dat'
         fs_tkregister2.inputs.fslreg_out = 'T1-TO-orig.mat'
         
         fsl_concatxfm = pe.Node(interface=fsl.ConvertXFM(concat_xfm=True),name="fsl_concatxfm")
         
         fsl_applyxfm = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,out_file="T1-TO-TARGET.nii.gz"),name="linear_registration")
         fsl_applyxfm_wm = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="wm_mask_registered.nii.gz"),name="apply_registration_wm")
         fsl_applyxfm_rois = pe.Node(interface=ApplymultipleXfm(),name="apply_registration_roivs")
         
         flow.connect([
                     (inputnode, fs_bbregister, [(('subjects_dir',unicode2str),'subjects_dir'),(('subject_id',os.path.basename),'subject_id')]),
                     (fs_bbregister, fsl_invertxfm, [('out_fsl_file','in_file')]),
                     (fsl_invertxfm, fsl_concatxfm, [('out_file','in_file2')]),
                     (inputnode,fs_source,[("subjects_dir","subjects_dir"),(("subject_id",os.path.basename),"subject_id")]),
                     (inputnode, fs_tkregister2, [('subjects_dir','subjects_dir'),(('subject_id',os.path.basename),'subject_id')]),
                     (fs_source,fs_tkregister2,[("orig","target_file"),("rawavg","in_file")]),
                     (fs_tkregister2, fsl_concatxfm, [('fslregout_file','in_file')]),
                     (inputnode, fsl_applyxfm, [('T1','in_file')]),
                     (fsl_concatxfm, fsl_applyxfm, [('out_file','in_matrix_file')]),
                     (fsl_applyxfm,outputnode,[("out_file","T1_registered")]),
                     (inputnode, fsl_applyxfm_wm, [('wm_mask','in_file')]),
                     (fsl_concatxfm, fsl_applyxfm_wm, [('out_file','in_matrix_file')]),
                     (fsl_applyxfm_wm, outputnode, [('out_file','wm_mask_registered')]),
                     (inputnode, fsl_applyxfm_rois, [('roi_volumes','in_files')]),
                     (fsl_concatxfm, fsl_applyxfm_rois, [('out_file','xfm_file')]),
                     (fsl_applyxfm_rois, outputnode, [('out_files','roi_volumes_registered')])
                     ])
         
         if self.config.pipeline == "fMRI":
             flow.connect([
                         (inputnode, fs_bbregister, [('target','source_file')]),
                         (inputnode, fsl_applyxfm, [('target','reference')]),
                         (inputnode, fsl_applyxfm_wm, [('target','reference')]),
                         (inputnode, fsl_applyxfm_rois, [('target','reference')]),
                         ])
             fsl_applyxfm_eroded_wm = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="eroded_wm_registered.nii.gz"),name="apply_registration_wm_eroded")
             if self.config.apply_to_eroded_csf:
                 fsl_applyxfm_eroded_csf = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="eroded_csf_registered.nii.gz"),name="apply_registration_csf_eroded")
                 flow.connect([
                               (inputnode, fsl_applyxfm_eroded_csf, [('eroded_csf','in_file')]),
                               (inputnode, fsl_applyxfm_eroded_csf, [('target','reference')]),
                               (fsl_concatxfm, fsl_applyxfm_eroded_csf, [('out_file','in_matrix_file')]),
                               (fsl_applyxfm_eroded_csf, outputnode, [('out_file','eroded_csf_registered')])
                             ])
             if self.config.apply_to_eroded_brain:
                 fsl_applyxfm_eroded_brain = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True,interp="nearestneighbour",out_file="eroded_brain_registered.nii.gz"),name="apply_registration_brain_eroded")
                 flow.connect([
                               (inputnode, fsl_applyxfm_eroded_brain, [('eroded_brain','in_file')]),
                               (inputnode, fsl_applyxfm_eroded_brain, [('target','reference')]),
                               (fsl_concatxfm, fsl_applyxfm_eroded_brain, [('out_file','in_matrix_file')]),
                               (fsl_applyxfm_eroded_brain, outputnode, [('out_file','eroded_brain_registered')])
                             ])
             flow.connect([
                         (inputnode, fsl_applyxfm_eroded_wm, [('eroded_wm','in_file')]),
                         (inputnode, fsl_applyxfm_eroded_wm, [('target','reference')]),
                         (fsl_concatxfm, fsl_applyxfm_eroded_wm, [('out_file','in_matrix_file')]),
                         (fsl_applyxfm_eroded_wm, outputnode, [('out_file','eroded_wm_registered')])
                         ])
         else:
             flow.connect([
                         (fs_mriconvert, fs_bbregister, [('out_file','source_file')]),
                         (fs_mriconvert, fsl_applyxfm, [('out_file','reference')]),
                         (fs_mriconvert, fsl_applyxfm_wm, [('out_file','reference')]),
                         (fs_mriconvert, fsl_applyxfm_rois, [('out_file','reference')]),
                         ])
             
         
     if self.config.registration_mode == 'Nonlinear (FSL)':
         # [SUB-STEP 1] LINEAR register "T2" onto "Target_resampled
         # [1.1] linear register "T1" onto "T2"
         fsl_flirt_1 = pe.Node(interface=fsl.FLIRT(out_file='T1-TO-T2.nii.gz',out_matrix_file='T1-TO-T2.mat'),name="t1tot2_lin_registration")
         fsl_flirt_1.inputs.dof = 6
         fsl_flirt_1.inputs.cost = "mutualinfo"
         fsl_flirt_1.inputs.no_search = True
         #[1.2] -> linear register "T2" onto "target_resampled"
         fsl_flirt_2 = pe.Node(interface=fsl.FLIRT(out_file='T2-TO-TARGET.nii.gz',out_matrix_file='T2-TO-TARGET.mat'),name="t2totarget_lin_registration")
         fsl_flirt_2.inputs.dof = 12
         fsl_flirt_2.inputs.cost = "normmi"
         fsl_flirt_2.inputs.no_search = True
         #[1.3] -> apply the linear registration "T1" --> "target" (for comparison)
         fsl_concatxfm = pe.Node(interface=fsl.ConvertXFM(concat_xfm=True),name="fsl_concatxfm")
         fsl_applyxfm = pe.Node(interface=fsl.ApplyXfm(apply_xfm=True, interp="sinc",out_file='T1-TO-target.nii.gz',out_matrix_file='T1-TO-TARGET.mat'),name="linear_registration")
         #"[SUB-STEP 2] Create BINARY MASKS for nonlinear registration"
         # [2.1] -> create a T2 brain mask
         fsl_bet_1 = pe.Node(interface=fsl.BET(out_file='T2-brain',mask=True,no_output=True,robust=True),name="t2_brain_mask")
         fsl_bet_1.inputs.frac = 0.35
         fsl_bet_1.inputs.vertical_gradient = 0.15
         #[2.2] -> create a DSI_target brain mask
         fsl_bet_2 = pe.Node(interface=fsl.BET(out_file='target-brain',mask=True,no_output=True,robust=True),name="target_brain_mask")
         fsl_bet_2.inputs.frac = 0.2
         fsl_bet_2.inputs.vertical_gradient = 0.2
         # [SUB-STEP 3] NONLINEAR register "T2" onto "target_resampled"
         # [3.1] 'Started FNIRT to find 'T2 --> target' nonlinear transformation at
         fsl_fnirt = pe.Node(interface=fsl.FNIRT(field_file='T2-TO-target_warp.nii.gz'),name="t2totarget_nlin_registration")
         fsl_fnirt.inputs.subsampling_scheme = [8,4,2,2]
         fsl_fnirt.inputs.max_nonlin_iter = [5,5,5,5]
         fsl_fnirt.inputs.regularization_lambda = [240,120,90,30]
         fsl_fnirt.inputs.spline_order = 3
         fsl_fnirt.inputs.apply_inmask = [0,0,1,1]
         fsl_fnirt.inputs.apply_refmask = [0,0,1,1]
         #[3.2] -> apply the warp found for "T2" also onto "T1"
         fsl_applywarp = pe.Node(interface=fsl.ApplyWarp(out_file='T1_warped.nii.gz'),name="nonlinear_registration")
         fsl_applywarp_wm = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="wm_mask_registered.nii.gz"),name="apply_registration_wm")
         fsl_applywarp_rois = pe.Node(interface=Applynlinmultiplewarps(),name="apply_registration_roivs") # TO FIX: Applynlinmultiplewarps() done because applying MapNode to fsl.ApplyWarp crashes
         #fsl_applywarp_rois = pe.MapNode(interface=fsl.ApplyWarp(interp="nn"),name="apply_registration_roivs",iterfield=["in_file"])
         
         flow.connect([
                 (inputnode,fsl_flirt_1,[('T1','in_file'),('T2','reference')]),
                 (inputnode,fsl_flirt_2,[('T2','in_file')]),
                 (fsl_flirt_1,fsl_concatxfm,[('out_matrix_file','in_file')]),
                 (fsl_flirt_2,fsl_concatxfm,[('out_matrix_file','in_file2')]),
                 (inputnode,fsl_applyxfm,[('T1','in_file')]),
                 (fsl_concatxfm,fsl_applyxfm,[('out_file','in_matrix_file')]),
                 (inputnode,fsl_bet_1,[('T2','in_file')]),
                 (inputnode,fsl_fnirt,[('T2','in_file')]),
                 (fsl_flirt_2,fsl_fnirt,[('out_matrix_file','affine_file')]),
                 (fsl_bet_1,fsl_fnirt,[('mask_file','inmask_file')]),
                 (fsl_bet_2,fsl_fnirt,[('mask_file','refmask_file')]),
                 (inputnode,fsl_applywarp,[('T1','in_file')]),
                 (fsl_flirt_1,fsl_applywarp,[('out_matrix_file','premat')]),
                 (fsl_fnirt,fsl_applywarp,[('field_file','field_file')]),
                 (inputnode, fsl_applywarp_wm, [('wm_mask','in_file')]),
                 (fsl_flirt_1, fsl_applywarp_wm, [('out_matrix_file','premat')]),
                 (fsl_fnirt,fsl_applywarp_wm,[('field_file','field_file')]),
                 (fsl_applywarp_wm, outputnode, [('out_file','wm_mask_registered')]),
                 (inputnode, fsl_applywarp_rois, [('roi_volumes','in_files')]),
                 (fsl_flirt_1, fsl_applywarp_rois, [('out_matrix_file','premat_file')]),
                 (fsl_fnirt,fsl_applywarp_rois,[('field_file','field_file')]),
                 (fsl_applywarp_rois, outputnode, [('warped_files','roi_volumes_registered')])
                 ])
         if self.config.pipeline == "fMRI":
             flow.connect([
                         (inputnode,fsl_flirt_2,[('target','reference')]),
                         (inputnode,fsl_applyxfm,[('target','reference')]),
                         (inputnode,fsl_bet_2,[('target','in_file')]),
                         (inputnode,fsl_fnirt,[('target','ref_file')]),
                         (inputnode,fsl_applywarp,[('target','ref_file')]),
                         (inputnode, fsl_applywarp_wm, [('target','ref_file')]),
                         (inputnode, fsl_applywarp_rois, [('target','ref_file')]),
                         ])
             fsl_applywarp_eroded_wm = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="eroded_wm_registered.nii.gz"),name="apply_registration_eroded_wm")
             if self.config.apply_to_eroded_csf:
                 fsl_applywarp_eroded_csf = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="eroded_csf_registered.nii.gz"),name="apply_registration_eroded_csf")
                 flow.connect([
                               (inputnode, fsl_applywarp_eroded_csf, [('eroded_csf','in_file')]),
                               (inputnode, fsl_applywarp_eroded_csf, [('target','ref_file')]),
                               (fsl_flirt_1, fsl_applywarp_eroded_csf, [('out_matrix_file','premat')]),
                               (fsl_fnirt,fsl_applywarp_eroded_csf,[('field_file','field_file')]),
                               (fsl_applywarp_eroded_csf, outputnode, [('out_file','eroded_csf_registered')])
                             ])
             if self.config.apply_to_eroded_brain:
                 fsl_applywarp_eroded_brain = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="eroded_brain_registered.nii.gz"),name="apply_registration_eroded_brain")
                 flow.connect([
                               (inputnode, fsl_applywarp_eroded_brain, [('eroded_brain','in_file')]),
                               (inputnode, fsl_applywarp_eroded_brain, [('target','ref_file')]),
                               (fsl_flirt_1, fsl_applywarp_eroded_brain, [('out_matrix_file','premat')]),
                               (fsl_fnirt,fsl_applywarp_eroded_brain,[('field_file','field_file')]),
                               (fsl_applywarp_eroded_brain, outputnode, [('out_file','eroded_brain_registered')])
                             ])
             flow.connect([
                         (inputnode, fsl_applywarp_eroded_wm, [('eroded_wm','in_file')]),
                         (inputnode, fsl_applywarp_eroded_wm, [('target','ref_file')]),
                         (fsl_flirt_1, fsl_applywarp_eroded_wm, [('out_matrix_file','premat')]),
                         (fsl_fnirt,fsl_applywarp_eroded_wm,[('field_file','field_file')]),
                         (fsl_applywarp_eroded_wm, outputnode, [('out_file','eroded_wm_registered')])
                         ])
         else:
             flow.connect([
                         (fs_mriconvert,fsl_flirt_2,[('out_file','reference')]),
                         (fs_mriconvert,fsl_applyxfm,[('out_file','reference')]),
                         (fs_mriconvert,fsl_bet_2,[('out_file','in_file')]),
                         (fs_mriconvert,fsl_fnirt,[('out_file','ref_file')]),
                         (fs_mriconvert,fsl_applywarp,[('out_file','ref_file')]),
                         (fs_mriconvert, fsl_applywarp_wm, [('out_file','ref_file')]),
                         (fs_mriconvert, fsl_applywarp_rois, [('out_file','ref_file')]),
                         ])
Ejemplo n.º 16
0
def create_fmap_coreg_pipeline(name='fmap_coreg'):

    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')

    # initiate workflow
    fmap_coreg = Workflow(name='fmap_coreg')

    #inputnode
    inputnode = Node(util.IdentityInterface(fields=[
        'epi_mean', 'mag', 'phase', 'anat_head', 'anat_brain', 'fs_subject_id',
        'fs_subjects_dir', 'echo_space', 'te_diff', 'pe_dir'
    ]),
                     name='inputnode')

    # outputnode
    outputnode = Node(util.IdentityInterface(fields=[
        'fmap', 'shiftmap', 'unwarpfield_epi2fmap', 'unwarped_mean_epi2fmap',
        'epi2anat_mat', 'epi2anat_dat', 'epi2anat_mincost', 'epi2anat',
        'epi2fmap', 'fmap_fullwarp'
    ]),
                      name='outputnode')

    #### prepare fieldmap ####
    # split first magnitude image from mag input
    split = Node(fsl.ExtractROI(t_min=0, t_size=1), name='split')
    fmap_coreg.connect(inputnode, 'mag', split, 'in_file')

    # strip magnitude image and erode even further
    bet = Node(fsl.BET(frac=0.5, mask=True), name='bet')
    fmap_coreg.connect(split, 'roi_file', bet, 'in_file')

    erode = Node(fsl.maths.ErodeImage(kernel_shape='sphere',
                                      kernel_size=3,
                                      args=''),
                 name='erode')
    fmap_coreg.connect(bet, 'out_file', erode, 'in_file')

    # prepare fieldmap
    prep_fmap = Node(fsl.epi.PrepareFieldmap(), name='prep_fmap')
    fmap_coreg.connect([(erode, prep_fmap, [('out_file', 'in_magnitude')]),
                        (inputnode, prep_fmap, [('phase', 'in_phase'),
                                                ('te_diff', 'delta_TE')]),
                        (prep_fmap, outputnode, [('out_fieldmap', 'fmap')])])

    #### unmask fieldmap ####
    fmap_mask = Node(fsl.maths.MathsCommand(args='-abs -bin'),
                     name='fmap_mask')

    unmask = Node(fsl.FUGUE(save_unmasked_fmap=True), name='unmask')

    fmap_coreg.connect([(prep_fmap, fmap_mask, [('out_fieldmap', 'in_file')]),
                        (fmap_mask, unmask, [('out_file', 'mask_file')]),
                        (prep_fmap, unmask, [('out_fieldmap', 'fmap_in_file')
                                             ]),
                        (inputnode, unmask, [('pe_dir', 'unwarp_direction')])])

    #### register epi to fieldmap ####
    epi2fmap = Node(fsl.FLIRT(dof=6,
                              out_file='rest_mean2fmap.nii.gz',
                              interp='spline'),
                    name='epi2fmap')

    fmap_coreg.connect([(inputnode, epi2fmap, [('epi_mean', 'in_file')]),
                        (split, epi2fmap, [('roi_file', 'reference')]),
                        (epi2fmap, outputnode, [('out_file', 'epi2fmap')])])

    #### unwarp epi with fieldmap ####
    unwarp = Node(fsl.FUGUE(save_shift=True), name='unwarp')

    fmap_coreg.connect([(epi2fmap, unwarp, [('out_file', 'in_file')]),
                        (unmask, unwarp, [('fmap_out_file', 'fmap_in_file')]),
                        (fmap_mask, unwarp, [('out_file', 'mask_file')]),
                        (inputnode, unwarp, [('echo_space', 'dwell_time'),
                                             ('pe_dir', 'unwarp_direction')]),
                        (unwarp, outputnode, [('shift_out_file', 'shiftmap')])
                        ])

    #### make warpfield and apply ####
    convertwarp0 = Node(fsl.utils.ConvertWarp(
        out_relwarp=True, out_file='rest_mean2fmap_unwarpfield.nii.gz'),
                        name='convertwarp0')

    applywarp0 = Node(fsl.ApplyWarp(interp='spline',
                                    relwarp=True,
                                    out_file='rest_mean2fmap_unwarped.nii.gz',
                                    datatype='float'),
                      name='applywarp0')

    fmap_coreg.connect([
        (split, convertwarp0, [('roi_file', 'reference')]),
        (epi2fmap, convertwarp0, [('out_matrix_file', 'premat')]),
        (unwarp, convertwarp0, [('shift_out_file', 'shift_in_file')]),
        (inputnode, convertwarp0, [('pe_dir', 'shift_direction')]),
        (inputnode, applywarp0, [('epi_mean', 'in_file')]),
        (split, applywarp0, [('roi_file', 'ref_file')]),
        (convertwarp0, applywarp0, [('out_file', 'field_file')]),
        (convertwarp0, outputnode, [('out_file', 'unwarpfield_epi2fmap')]),
        (applywarp0, outputnode, [('out_file', 'unwarped_mean_epi2fmap')])
    ])

    #### register epi to anatomy #####
    # linear registration with bbregister
    bbregister = Node(fs.BBRegister(
        contrast_type='t2',
        out_fsl_file='rest2anat.mat',
        out_reg_file='rest2anat.dat',
        registered_file='rest_mean2anat_highres.nii.gz',
        init='fsl',
        epi_mask=True),
                      name='bbregister')

    fmap_coreg.connect([
        (applywarp0, bbregister, [('out_file', 'source_file')]),
        (inputnode, bbregister, [('fs_subjects_dir', 'subjects_dir'),
                                 ('fs_subject_id', 'subject_id')]),
        (bbregister, outputnode, [('out_fsl_file', 'epi2anat_mat'),
                                  ('out_reg_file', 'epi2anat_dat'),
                                  ('registered_file', 'epi2anat'),
                                  ('min_cost_file', 'epi2anat_mincost')]),
    ])

    # make warpfield
    convertwarp = Node(fsl.utils.ConvertWarp(out_relwarp=True,
                                             out_file='fullwarpfield.nii.gz'),
                       name='convertwarp')

    fmap_coreg.connect([
        (inputnode, convertwarp, [('anat_head', 'reference')]),
        (convertwarp0, convertwarp, [('out_file', 'warp1')]),
        (bbregister, convertwarp, [('out_fsl_file', 'postmat')]),
        (convertwarp, outputnode, [('out_file', 'fmap_fullwarp')])
    ])

    return fmap_coreg
Ejemplo n.º 17
0
def create_epi_t1_nonlinear_pipeline(name='epi_t1_nonlinear'):
    """Creates a pipeline that performs nonlinear EPI to T1 registration using 
    the antsRegistration tool. Beforehand, the T1 image has to be processed in 
    freesurfer and the EPI timeseries should be realigned.

    Example
    -------

    >>> nipype_epi_t1_nonlin = create_epi_t1_nonlinear_pipeline('nipype_epi_t1_nonlin')
    >>> nipype_epi_t1_nonlin.inputs.inputnode.fs_subject_id = '123456'
    >>> nipype_epi_t1_nonlin.inputs.inputnode.fs_subjects_dir = '/project/data/freesurfer'
    >>> nipype_epi_t1_nonlin.inputs.inputnode.realigned_epi = 'mcflirt.nii.gz'
    >>> nipype_epi_t1_nonlin.run()

    Inputs::

        inputnode.fs_subject_id    # subject id used in freesurfer
        inputnode.fs_subjects_dir  # path to freesurfer output
        inputnode.realigned_epi    # realigned EPI timeseries

    Outputs::

        outputnode.lin_epi2anat     # ITK format
        outputnode.lin_anat2epi     # ITK format
        outputnode.nonlin_epi2anat  # ANTs specific 5D deformation field
        outputnode.nonlin_anat2epi  # ANTs specific 5D deformation field

    """

    nonreg = Workflow(name='epi_t1_nonlinear')

    # input
    inputnode = Node(interface=util.IdentityInterface(
        fields=['fs_subject_id', 'fs_subjects_dir', 'realigned_epi']),
                     name='inputnode')

    # calculate the temporal mean image of the realigned timeseries
    tmean = Node(interface=fsl.maths.MeanImage(dimension='T',
                                               output_type='NIFTI_GZ'),
                 name='tmean')

    nonreg.connect(inputnode, 'realigned_epi', tmean, 'in_file')

    # import brain.mgz and ribbon.mgz from freesurfer directory
    fs_import = Node(interface=nio.FreeSurferSource(),
                     name='freesurfer_import')

    nonreg.connect(inputnode, 'fs_subjects_dir', fs_import, 'subjects_dir')
    nonreg.connect(inputnode, 'fs_subject_id', fs_import, 'subject_id')

    # convert brain.mgz to niigz
    mriconvert = Node(interface=fs.MRIConvert(out_type='niigz'),
                      name='mriconvert')

    nonreg.connect(fs_import, 'brain', mriconvert, 'in_file')

    # calculate rigid transformation of mean epi to t1 with bbregister
    bbregister = Node(interface=fs.BBRegister(init='fsl',
                                              contrast_type='t2',
                                              out_fsl_file=True),
                      name='bbregister')

    nonreg.connect(inputnode, 'fs_subjects_dir', bbregister, 'subjects_dir')
    nonreg.connect(inputnode, 'fs_subject_id', bbregister, 'subject_id')
    nonreg.connect(tmean, 'out_file', bbregister, 'source_file')

    # convert linear transformation to itk format compatible with ants
    itk = Node(interface=c3.C3dAffineTool(fsl2ras=True,
                                          itk_transform='epi2anat_affine.txt'),
               name='itk')

    nonreg.connect(tmean, 'out_file', itk, 'source_file')
    nonreg.connect(mriconvert, 'out_file', itk, 'reference_file')
    nonreg.connect(bbregister, 'out_fsl_file', itk, 'transform_file')

    # get aparc aseg mask
    # create brainmask from aparc+aseg
    def get_aparc_aseg(files):
        for name in files:
            if 'aparc+aseg' in name:
                return name

    aparc_aseg_mask = Node(fs.Binarize(min=0.1,
                                       dilate=10,
                                       erode=7,
                                       out_type='nii.gz',
                                       binary_file='aparc_aseg_mask.nii.gz'),
                           name='aparc_aseg_mask')

    # fill holes in mask
    fillholes = Node(fsl.maths.MathsCommand(args='-fillh'), name='fillholes')

    nonreg.connect([(fs_import, aparc_aseg_mask, [
        (('aparc_aseg', get_aparc_aseg), 'in_file')
    ]), (aparc_aseg_mask, fillholes, [('binary_file', 'in_file')])])

    #create bounding box mask and rigidly transform into anatomical (fs) space
    fov = Node(interface=fs.model.Binarize(min=0.0, out_type='nii.gz'),
               name='fov')

    nonreg.connect(tmean, 'out_file', fov, 'in_file')

    fov_trans = Node(interface=ants.resampling.ApplyTransforms(
        dimension=3, interpolation='NearestNeighbor'),
                     name='fov_trans')

    nonreg.connect(itk, ('itk_transform', filename_to_list), fov_trans,
                   'transforms')
    nonreg.connect(fov, 'binary_file', fov_trans, 'input_image')
    nonreg.connect(fillholes, 'out_file', fov_trans, 'reference_image')
    #nonreg.connect(ribbon, 'binary_file', fov_trans, 'reference_image')

    # intersect both masks
    intersect = Node(interface=fsl.maths.BinaryMaths(operation='mul'),
                     name='intersect')

    nonreg.connect(fillholes, 'out_file', intersect, 'in_file')
    #nonreg.connect(ribbon, 'binary_file', intersect, 'in_file')
    nonreg.connect(fov_trans, 'output_image', intersect, 'operand_file')

    # inversly transform mask and mask original epi
    mask_trans = Node(interface=ants.resampling.ApplyTransforms(
        dimension=3,
        interpolation='NearestNeighbor',
        invert_transform_flags=[True]),
                      name='mask_trans')

    nonreg.connect(itk, ('itk_transform', filename_to_list), mask_trans,
                   'transforms')
    nonreg.connect(intersect, 'out_file', mask_trans, 'input_image')
    nonreg.connect(tmean, 'out_file', mask_trans, 'reference_image')

    maskepi = Node(interface=fs.utils.ApplyMask(), name='maskepi')

    nonreg.connect(mask_trans, 'output_image', maskepi, 'mask_file')
    nonreg.connect(tmean, 'out_file', maskepi, 'in_file')

    # mask anatomical image (brain)
    maskanat = Node(interface=fs.utils.ApplyMask(), name='maskanat')

    nonreg.connect(intersect, 'out_file', maskanat, 'mask_file')
    nonreg.connect(mriconvert, 'out_file', maskanat, 'in_file')

    # invert masked anatomical image
    anat_min_max = Node(interface=fsl.utils.ImageStats(op_string='-R'),
                        name='anat_min_max')
    epi_min_max = Node(interface=fsl.utils.ImageStats(op_string='-r'),
                       name='epi_min_max')

    nonreg.connect(maskanat, 'out_file', anat_min_max, 'in_file')
    nonreg.connect(tmean, 'out_file', epi_min_max, 'in_file')

    def calc_inversion(anat_min_max, epi_min_max):
        mul = -(epi_min_max[1] - epi_min_max[0]) / (anat_min_max[1] -
                                                    anat_min_max[0])
        add = abs(anat_min_max[1] * mul) + epi_min_max[0]
        return mul, add

    calcinv = Node(interface=Function(
        input_names=['anat_min_max', 'epi_min_max'],
        output_names=['mul', 'add'],
        function=calc_inversion),
                   name='calcinv')

    nonreg.connect(anat_min_max, 'out_stat', calcinv, 'anat_min_max')
    nonreg.connect(epi_min_max, 'out_stat', calcinv, 'epi_min_max')

    mulinv = Node(interface=fsl.maths.BinaryMaths(operation='mul'),
                  name='mulinv')
    addinv = Node(interface=fsl.maths.BinaryMaths(operation='add'),
                  name='addinv')

    nonreg.connect(maskanat, 'out_file', mulinv, 'in_file')
    nonreg.connect(calcinv, 'mul', mulinv, 'operand_value')
    nonreg.connect(mulinv, 'out_file', addinv, 'in_file')
    nonreg.connect(calcinv, 'add', addinv, 'operand_value')

    # nonlinear transformation of masked anat to masked epi with ants
    antsreg = Node(interface=ants.registration.Registration(
        dimension=3,
        invert_initial_moving_transform=True,
        metric=['CC'],
        metric_weight=[1.0],
        radius_or_number_of_bins=[4],
        sampling_strategy=['None'],
        transforms=['SyN'],
        args='-g .1x1x.1',
        transform_parameters=[(0.10, 3, 0)],
        number_of_iterations=[[10, 5]],
        convergence_threshold=[1e-06],
        convergence_window_size=[10],
        shrink_factors=[[2, 1]],
        smoothing_sigmas=[[1, 0.5]],
        sigma_units=['vox'],
        use_estimate_learning_rate_once=[True],
        use_histogram_matching=[True],
        collapse_output_transforms=True,
        output_inverse_warped_image=True,
        output_warped_image=True),
                   name='antsreg')

    nonreg.connect(itk, 'itk_transform', antsreg, 'initial_moving_transform')
    nonreg.connect(maskepi, 'out_file', antsreg, 'fixed_image')
    nonreg.connect(addinv, 'out_file', antsreg, 'moving_image')

    # output

    def second_element(file_list):
        return file_list[1]

    def first_element(file_list):
        return file_list[0]

    outputnode = Node(interface=util.IdentityInterface(fields=[
        'lin_epi2anat', 'lin_anat2epi', 'nonlin_epi2anat', 'nonlin_anat2epi'
    ]),
                      name='outputnode')

    nonreg.connect(itk, 'itk_transform', outputnode, 'lin_epi2anat')
    nonreg.connect(antsreg, ('forward_transforms', first_element), outputnode,
                   'lin_anat2epi')
    nonreg.connect(antsreg, ('forward_transforms', second_element), outputnode,
                   'nonlin_anat2epi')
    nonreg.connect(antsreg, ('reverse_transforms', second_element), outputnode,
                   'nonlin_epi2anat')

    return nonreg
Ejemplo n.º 18
0
def create_fmap_coreg_pipeline(name='fmap_coreg'):
    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # initiate workflow
    fmap_coreg = Workflow(name='fmap_coreg')
    # inputnode
    inputnode = Node(util.IdentityInterface(fields=[
        'epi_mean', 'ap', 'pa', 'anat_head', 'anat_brain', 'fs_subject_id',
        'fs_subjects_dir', 'echo_space', 'pe_dir'
    ]),
                     name='inputnode')
    # outputnode
    outputnode = Node(util.IdentityInterface(fields=[
        'fmap', 'shiftmap', 'unwarpfield_epi2fmap', 'unwarped_mean_epi2fmap',
        'epi2anat_mat', 'epi2anat_dat', 'epi2anat_mincost', 'epi2anat',
        'epi2fmap', 'fmap_fullwarp'
    ]),
                      name='outputnode')

    #### merge epi ap and pa
    merge_appa = Node(fsl.Merge(), name='merge_appa')
    merge_appa.inputs.dimension = 't'

    #use mean file of ap-pa acquisitions as "Mag"-image from fieldmap
    mean_appa = Node(fsl.MeanImage())

    #### use topup --> creates fieldmap
    topup_prep = Node(fsl.TOPUP(), name='topup_prep')
    topup_prep.inputs.encoding_file = '/home/raid1/fbeyer/Documents/Scripts/rs_preprocessing/RSV/topup-version/topup_file.txt'
    #multiply topup result to convert to rad/s

    convertHz_rad = Node(fsl.maths.MathsCommand(args='-mul 6.28'),
                         name='convertHz_rad')
    fmap_coreg.connect([(inputnode, merge_appa, [('ap', 'in_files')]),
                        (inputnode, merge_appa, [('pa', 'in_files')]),
                        (merge_appa, mean_appa, [('merged_file', 'in_file')]),
                        (merge_appa, topup_prep, [
                            ('merged_file', 'in_files')
                        ])(topup_prep, convertHz_rad,
                           [('out_field', 'in_file')])])

    #only needed when using PrepareFieldmap() command
    # split first magnitude image from mag input
    #split = Node(fsl.ExtractROI(t_min=0, t_size=1), name='split')
    #fmap_coreg.connect(inputnode, 'mag', split, 'in_file')

    # strip magnitude image and erode even further
    #bet = Node(fsl.BET(frac=0.5, mask=True), name='bet')
    #fmap_coreg.connect(split, 'roi_file', bet, 'in_file')
    #erode = Node(fsl.maths.ErodeImage(kernel_shape='sphere', kernel_size=3, args=''), name='erode')
    #fmap_coreg.connect(bet, 'out_file', erode, 'in_file')

    # prepare fieldmap
    #prep_fmap = Node(fsl.epi.PrepareFieldmap(), name='prep_fmap')
    #fmap_coreg.connect([(erode, prep_fmap, [('out_file', 'in_magnitude')]),
    #                    (inputnode, prep_fmap, [('phase', 'in_phase'), ('te_diff', 'delta_TE')]),
    #                    (prep_fmap, outputnode, [('out_fieldmap', 'fmap')])
    #                    ])

    #### unmask fieldmap ####
    fmap_mask = Node(fsl.maths.MathsCommand(args='-abs -bin'),
                     name='fmap_mask')
    unmask = Node(fsl.FUGUE(save_unmasked_fmap=True), name='unmask')
    fmap_coreg.connect([(convertHz_rad, fmap_mask, [('out_file', 'in_file')]),
                        (fmap_mask, unmask, [('out_file', 'mask_file')]),
                        (convertHz_rad, unmask, [('out_file', 'fmap_in_file')
                                                 ]),
                        (inputnode, unmask, [('pe_dir', 'unwarp_direction')])])

    #### register epi to fieldmap ####
    epi2fmap = Node(fsl.FLIRT(dof=6,
                              out_file='rest_mean2fmap.nii.gz',
                              interp='spline'),
                    name='epi2fmap')
    fmap_coreg.connect([(inputnode, epi2fmap, [('epi_mean', 'in_file')]),
                        (mean_appa, epi2fmap, [('out_file', 'reference')]),
                        (epi2fmap, outputnode, [('out_file', 'epi2fmap')])])

    #### unwarp epi with fieldmap ####
    unwarp = Node(fsl.FUGUE(save_shift=True), name='unwarp')
    fmap_coreg.connect([(epi2fmap, unwarp, [('out_file', 'in_file')]),
                        (unmask, unwarp, [('fmap_out_file', 'fmap_in_file')]),
                        (fmap_mask, unwarp, [('out_file', 'mask_file')]),
                        (inputnode, unwarp, [('echo_space', 'dwell_time'),
                                             ('pe_dir', 'unwarp_direction')]),
                        (unwarp, outputnode, [('shift_out_file', 'shiftmap')])
                        ])

    #### make warpfield and apply ####
    convertwarp0 = Node(fsl.utils.ConvertWarp(
        out_relwarp=True, out_file='rest_mean2fmap_unwarpfield.nii.gz'),
                        name='convertwarp0')
    applywarp0 = Node(fsl.ApplyWarp(interp='spline',
                                    relwarp=True,
                                    out_file='rest_mean2fmap_unwarped.nii.gz',
                                    datatype='float'),
                      name='applywarp0')
    fmap_coreg.connect([
        (mean_appa, convertwarp0, [('roi_file', 'reference')]),
        (epi2fmap, convertwarp0, [('out_matrix_file', 'premat')]),
        (unwarp, convertwarp0, [('shift_out_file', 'shift_in_file')]),
        (inputnode, convertwarp0, [('pe_dir', 'shift_direction')]),
        (inputnode, applywarp0, [('epi_mean', 'in_file')]),
        (mean_appa, applywarp0, [('roi_file', 'ref_file')]),
        (convertwarp0, applywarp0, [('out_file', 'field_file')]),
        (convertwarp0, outputnode, [('out_file', 'unwarpfield_epi2fmap')]),
        (applywarp0, outputnode, [('out_file', 'unwarped_mean_epi2fmap')])
    ])

    #### register epi to anatomy #####
    # linear registration with bbregister
    bbregister = Node(fs.BBRegister(
        contrast_type='t2',
        out_fsl_file='rest2anat.mat',
        out_reg_file='rest2anat.dat',
        registered_file='rest_mean2anat_highres.nii.gz',
        init='fsl',
        epi_mask=True),
                      name='bbregister')
    fmap_coreg.connect([
        (applywarp0, bbregister, [('out_file', 'source_file')]),
        (inputnode, bbregister, [('fs_subjects_dir', 'subjects_dir'),
                                 ('fs_subject_id', 'subject_id')]),
        (bbregister, outputnode, [('out_fsl_file', 'epi2anat_mat'),
                                  ('out_reg_file', 'epi2anat_dat'),
                                  ('registered_file', 'epi2anat'),
                                  ('min_cost_file', 'epi2anat_mincost')]),
    ])
    # make warpfield
    convertwarp = Node(fsl.utils.ConvertWarp(out_relwarp=True,
                                             out_file='fullwarpfield.nii.gz'),
                       name='convertwarp')
    fmap_coreg.connect([
        (inputnode, convertwarp, [('anat_head', 'reference')]),
        (convertwarp0, convertwarp, [('out_file', 'warp1')]),
        (bbregister, convertwarp, [('out_fsl_file', 'postmat')]),
        (convertwarp, outputnode, [('out_file', 'fmap_fullwarp')])
    ])
    return fmap_coreg
Ejemplo n.º 19
0
                   't_min')
preproc_wf.connect(extractref, 'roi_file', outputspec, 'reference')

# Motion correction with Nipy algorithm
motion_correct = pe.Node(nipy.SpaceTimeRealigner(), name='motion_correct')
motion_correct.plugin_args = {'bsub_args': '-n 12'}
motion_correct.plugin_args = {'bsub_args': '-R "span[hosts=1]"'}
preproc_wf.connect(datasource, 'mri_files', motion_correct, 'in_file')
preproc_wf.connect(motion_correct, 'par_file', outputspec, 'motion_parameters')
preproc_wf.connect(motion_correct, 'out_file', outputspec,
                   'motion_corrected_files')

# Calculate the transformation matrix from EPI space to FreeSurfer space
# using the BBRegister command
coregister = pe.Node(fs.BBRegister(subjects_dir=subjects_dir,
                                   contrast_type='t2',
                                   init='fsl',
                                   out_fsl_file=True),
                     name='coregister')
preproc_wf.connect(subj_iterable, 'subject_id', coregister, 'subject_id')
preproc_wf.connect(motion_correct, ('out_file', pickfirst), coregister,
                   'source_file')
preproc_wf.connect(coregister, 'out_reg_file', outputspec, 'reg_file')
preproc_wf.connect(coregister, 'out_fsl_file', outputspec, 'fsl_reg_file')
preproc_wf.connect(coregister, 'min_cost_file', outputspec, 'reg_cost')

# Register a source file to fs space
fssource = pe.Node(nio.FreeSurferSource(subjects_dir=subjects_dir),
                   name='fssource')
preproc_wf.connect(subj_iterable, 'subject_id', fssource, 'subject_id')

# Extract aparc+aseg brain mask and binarize
Ejemplo n.º 20
0
def create_bbregister_workflow(name="bbregister", contrast_type="t2"):

    # Define the workflow inputs
    inputnode = pe.Node(
        util.IdentityInterface(fields=["subject_id", "source_file"]),
        name="inputs")

    # Estimate the registration to Freesurfer conformed space
    func2anat = pe.MapNode(fs.BBRegister(contrast_type=contrast_type,
                                         init="fsl",
                                         epi_mask=True,
                                         registered_file=True,
                                         out_fsl_file=True),
                           iterfield=["source_file"],
                           name="func2anat")

    # Set up a node to grab the target from the subjects directory
    fssource = pe.Node(io.FreeSurferSource(subjects_dir=fs.Info.subjectsdir()),
                       name="fssource")
    # Always overwrite the grab; shouldn't cascade unless the underlying image changes
    fssource.overwrite = True

    # Convert the target to nifti
    convert = pe.Node(fs.MRIConvert(out_type="niigz"), name="convertbrain")

    # Swap dimensions so stuff looks nice in the report
    flipbrain = pe.Node(fsl.SwapDimensions(new_dims=("RL", "PA", "IS")),
                        name="flipbrain")

    flipfunc = pe.MapNode(fsl.SwapDimensions(new_dims=("RL", "PA", "IS")),
                          iterfield=["in_file"],
                          name="flipfunc")

    # Slice up the registration
    func2anatpng = pe.MapNode(fsl.Slicer(middle_slices=True,
                                         show_orientation=False,
                                         scaling=.6,
                                         label_slices=False),
                              iterfield=["in_file"],
                              name="func2anatpng")

    # Rename some files
    pngname = pe.MapNode(util.Rename(format_string="func2anat.png"),
                         iterfield=["in_file"],
                         name="pngname")

    costname = pe.MapNode(util.Rename(format_string="func2anat_cost.dat"),
                          iterfield=["in_file"],
                          name="costname")

    tkregname = pe.MapNode(util.Rename(format_string="func2anat_tkreg.dat"),
                           iterfield=["in_file"],
                           name="tkregname")

    flirtname = pe.MapNode(util.Rename(format_string="func2anat_flirt.mat"),
                           iterfield=["in_file"],
                           name="flirtname")

    # Merge the slicer png and cost file into a report list
    report = pe.Node(util.Merge(2, axis="hstack"), name="report")

    # Define the workflow outputs
    outputnode = pe.Node(
        util.IdentityInterface(fields=["tkreg_mat", "flirt_mat", "report"]),
        name="outputs")

    bbregister = pe.Workflow(name=name)

    # Connect the registration
    bbregister.connect([
        (inputnode, func2anat, [("subject_id", "subject_id"),
                                ("source_file", "source_file")]),
        (inputnode, fssource, [("subject_id", "subject_id")]),
        (func2anat, flipfunc, [("registered_file", "in_file")]),
        (flipfunc, func2anatpng, [("out_file", "in_file")]),
        (fssource, convert, [("brain", "in_file")]),
        (convert, flipbrain, [("out_file", "in_file")]),
        (flipbrain, func2anatpng, [("out_file", "image_edges")]),
        (func2anatpng, pngname, [("out_file", "in_file")]),
        (func2anat, tkregname, [("out_reg_file", "in_file")]),
        (func2anat, flirtname, [("out_fsl_file", "in_file")]),
        (func2anat, costname, [("min_cost_file", "in_file")]),
        (costname, report, [("out_file", "in1")]),
        (pngname, report, [("out_file", "in2")]),
        (tkregname, outputnode, [("out_file", "tkreg_mat")]),
        (flirtname, outputnode, [("out_file", "flirt_mat")]),
        (report, outputnode, [("out", "report")]),
    ])

    return bbregister
Ejemplo n.º 21
0
def create_surface_registration(wf_name='surface_registration'):
    """
    Workflow to generate surface from anatomical data and register 
    the structural data to FreeSurfer anatomical and assign it 
    to a surface vertex. 
    
    Parameters
    ----------
    wf_name : string
        name of the workflow
    
    Returns 
    -------
    wflow : workflow object
        workflow object
        
    Notes
    -----
    `Source <https://github.com/FCP-INDI/C-PAC/blob/master/CPAC/timeseries/timeseries_analysis.py>`_
        
    Workflow Inputs::
        
        inputspec.rest : string  (nifti file)
            path to input functional data
        inputspec.brain : string (nifti file)
            path to skull stripped anatomical image
        inputspec.recon_subjects : string
            path to subjects directory
        inputspec.subject_id : string
            subject id 
            
    Workflow Outputs::
    
        outputspec.reconall_subjects_dir : string
            freesurfer subjects directory
        outputspec.reconall_subjects_id : string
            subject id for which anatomical data is taken
        outputspec.out_reg_file : string
            path to bbregister output registration file
        outputspec.lh_surface_file : string (mgz file)
            path to left hemisphere cortical surface file 
        outputspec.rh_surface_file : string (mgz file)
            path to right hemisphere cortical surface file 
    
    Order of commands:
     
    - Generate surfaces and rois of structural data from T1 anatomical Image using FreeSurfer's reconall . For details see `ReconAll <https://surfer.nmr.mgh.harvard.edu/fswiki/recon-all>`_::

        recon-all -all -subjid 0010001 -sd working_dir/SurfaceRegistration/anat_reconall
        
    - Register input volume to the FreeSurfer anatomical using FreeSurfer's bbregister. The input is the output of the recon-all command. For details see `BBRegister <http://surfer.nmr.mgh.harvard.edu/fswiki/bbregister>`_::
        
        bbregister --t2 --init -fsl --reg structural_bbreg_me.dat --mov structural.nii --s 0010001
        
    - Assign values from a volume to each surface vertex using FreeSurfer's mri_vol2surf . For details see `mri_vol2surf <http://surfer.nmr.mgh.harvard.edu/fswiki/mri_vol2surf>`_::
       
        For left hemisphere
        mri_vol2surf --mov structural.nii --reg structural_bbreg_me.dat --interp trilin --projfrac 0.5 --hemi lh --o surface_file.nii.gz 

        For right hemisphere        
        mri_vol2surf --mov structural.nii --reg structural_bbreg_me.dat --interp trilin --projfrac 0.5 --hemi rh --o surface_file.nii.gz
    
    
    High Level Workflow Graph:
    
    .. image:: ../images/surface_registration.dot.png
       :width: 1000
    
    
    Detailed Workflow Graph:
    
    .. image:: ../images/surface_registration_detailed.dot.png
       :width: 1000
       
    Example
    -------
    >>> import CPAC.timeseries.timeseries_analysis as t
    >>> wf = t.create_surface_registration()
    >>> wf.inputs.inputspec.rest = '/home/data/sub001/rest.nii.gz'
    >>> wf.inputs.inputspec.brain = '/home/data/sub001/anat.nii.gz'
    >>> wf.inputs.inputspec.recon_subjects = '/home/data/working_dir/SurfaceRegistration/anat_reconall'
    >>> wf.inputs.inputspec.subject_id = 'sub001'
    >>> wf.base_dir = './'
    >>> wf.run() 
        
    """
    wflow = pe.Workflow(name=wf_name)

    inputNode = pe.Node(util.IdentityInterface(fields=['recon_subjects',
                                                       'brain',
                                                       'subject_id',
                                                       'rest']),
                        name='inputspec')

    outputNode = pe.Node(util.IdentityInterface(fields=['reconall_subjects_dir',
                                                         'reconall_subjects_id',
                                                         'out_reg_file',
                                                         'lh_surface_file',
                                                         'rh_surface_file']),
                         name='outputspec')


    reconall = pe.Node(interface=fs.ReconAll(),
                       name="reconall")
    reconall.inputs.directive = 'all'


    wflow.connect(inputNode, 'brain',
                  reconall, 'T1_files')
    wflow.connect(inputNode, 'subject_id',
                  reconall, 'subject_id')
    wflow.connect(inputNode, 'recon_subjects',
                  reconall, 'subjects_dir')

    wflow.connect(reconall, 'subjects_dir',
                  outputNode, 'reconall_subjects_dir')
    wflow.connect(reconall, 'subject_id',
                  outputNode, 'reconall_subjects_id')


    bbregister = pe.Node(interface=fs.BBRegister(init='fsl',
                                                 contrast_type='t2',
                                                 registered_file=True,
                                                 out_fsl_file=True),
                        name='bbregister')

    wflow.connect(inputNode, 'rest',
                  bbregister, 'source_file')
    wflow.connect(reconall, 'subjects_dir',
                  bbregister, 'subjects_dir')
    wflow.connect(reconall, 'subject_id',
                  bbregister, 'subject_id')

    wflow.connect(bbregister, 'out_reg_file',
                  outputNode, 'out_reg_file')


    sample_to_surface_lh = pe.Node(interface=fs.SampleToSurface(hemi="lh"),
                                    name='sample_to_surface_lh')
    sample_to_surface_lh.inputs.no_reshape = True
    sample_to_surface_lh.inputs.interp_method = 'trilinear'
    sample_to_surface_lh.inputs.sampling_method = "point"
    sample_to_surface_lh.inputs.sampling_range = 0.5
    sample_to_surface_lh.inputs.sampling_units = "frac"

    wflow.connect(bbregister, 'out_reg_file',
                  sample_to_surface_lh, 'reg_file')
    wflow.connect(inputNode, 'rest',
                  sample_to_surface_lh, 'source_file')

    wflow.connect(sample_to_surface_lh, 'out_file',
               outputNode, 'lh_surface_file')


    sample_to_surface_rh = pe.Node(interface=fs.SampleToSurface(hemi="rh"),
                                    name='sample_to_surface_rh')
    sample_to_surface_rh.inputs.no_reshape = True
    sample_to_surface_rh.inputs.interp_method = 'trilinear'
    sample_to_surface_rh.inputs.sampling_method = "point"
    sample_to_surface_rh.inputs.sampling_range = 0.5
    sample_to_surface_rh.inputs.sampling_units = "frac"

    wflow.connect(bbregister, 'out_reg_file',
                  sample_to_surface_rh, 'reg_file')
    wflow.connect(inputNode, 'rest',
                  sample_to_surface_rh, 'source_file')

    wflow.connect(sample_to_surface_rh, 'out_file',
               outputNode, 'rh_surface_file')

    return wflow
Ejemplo n.º 22
0
def get_dmriprep_pe_workflow():
    """Return the dmriprep (phase encoded) nipype workflow

    Parameters
    ----------


    Returns
    -------
    wf : nipype.pipeline.engine.Workflow
        Nipype dmriprep workflow

    Notes
    -----
    This assumes that there are scans with phase-encode directions AP/PA for
    topup.
    """
    import nipype.interfaces.freesurfer as fs
    import nipype.interfaces.fsl as fsl
    import nipype.interfaces.io as nio
    import nipype.interfaces.utility as niu
    import nipype.pipeline.engine as pe
    from nipype.interfaces.dipy import DTI
    from nipype.workflows.dmri.fsl.artifacts import all_fsl_pipeline

    inputspec = pe.Node(niu.IdentityInterface(fields=[
        'subject_id', 'dwi_file', 'dwi_file_ap', 'dwi_file_pa', 'bvec_file',
        'bval_file', 'subjects_dir', 'out_dir', 'eddy_niter',
        'slice_outlier_threshold'
    ]),
                        name="inputspec")

    # AK: watch out, other datasets might be encoded LR
    epi_ap = {'echospacing': 66.5e-3, 'enc_dir': 'y-'}
    epi_pa = {'echospacing': 66.5e-3, 'enc_dir': 'y'}
    prep = all_fsl_pipeline(epi_params=epi_ap, altepi_params=epi_pa)

    # initialize an overall workflow
    wf = pe.Workflow(name="dmriprep")

    wf.connect(inputspec, 'dwi_file', prep, 'inputnode.in_file')
    wf.connect(inputspec, 'bvec_file', prep, 'inputnode.in_bvec')
    wf.connect(inputspec, 'bval_file', prep, 'inputnode.in_bval')
    wf.connect(inputspec, 'eddy_niter', prep, 'fsl_eddy.niter')

    eddy = prep.get_node('fsl_eddy')
    eddy.inputs.repol = True
    eddy.inputs.cnr_maps = True
    eddy.inputs.residuals = True
    import multiprocessing
    eddy.inputs.num_threads = multiprocessing.cpu_count()

    topup = prep.get_node('peb_correction.topup')
    topup.inputs.checksize = True

    applytopup = prep.get_node('peb_correction.unwarp')
    applytopup.inputs.checksize = True

    eddy.inputs.checksize = True

    eddy_quad = pe.Node(fsl.EddyQuad(verbose=True, checksize=True),
                        name="eddy_quad")
    get_path = lambda x: x.split('.nii.gz')[0].split('_fix')[0]
    wf.connect(prep, ('fsl_eddy.out_corrected', get_path), eddy_quad,
               "base_name")
    wf.connect(inputspec, 'bval_file', eddy_quad, 'bval_file')
    wf.connect(prep, 'Rotate_Bvec.out_file', eddy_quad, 'bvec_file')
    wf.connect(prep, 'peb_correction.topup.out_field', eddy_quad, 'field')
    wf.connect(prep, 'gen_index.out_file', eddy_quad, 'idx_file')
    wf.connect(prep, 'peb_correction.topup.out_enc_file', eddy_quad,
               'param_file')

    # need a mask file for eddy_quad. lets get it from the B0.
    def get_b0_mask_fn(b0_file):
        import nibabel as nib
        from nipype.utils.filemanip import fname_presuffix
        from dipy.segment.mask import median_otsu
        import os

        mask_file = fname_presuffix(b0_file,
                                    suffix="_mask",
                                    newpath=os.path.abspath('.'))
        img = nib.load(b0_file)
        data, aff = img.get_data(), img.affine
        _, mask = median_otsu(data, 2, 1)
        nib.Nifti1Image(mask.astype(float), aff).to_filename(mask_file)
        return mask_file

    def id_outliers_fn(outlier_report, threshold, dwi_file):
        """Get list of scans that exceed threshold for number of outliers

        Parameters
        ----------
        outlier_report: string
            Path to the fsl_eddy outlier report

        threshold: int or float
            If threshold is an int, it is treated as number of allowed outlier
            slices. If threshold is a float between 0 and 1 (exclusive), it is
            treated the fraction of allowed outlier slices before we drop the
            whole volume.

        dwi_file: string
            Path to nii dwi file to determine total number of slices

        Returns
        -------
        drop_scans: numpy.ndarray
            List of scan indices to drop
        """
        import nibabel as nib
        import numpy as np
        import os.path as op
        import parse

        with open(op.abspath(outlier_report), 'r') as fp:
            lines = fp.readlines()

        p = parse.compile(
            "Slice {slice:d} in scan {scan:d} is an outlier with "
            "mean {mean_sd:f} standard deviations off, and mean "
            "squared {mean_sq_sd:f} standard deviations off.")

        outliers = [p.parse(l).named for l in lines]
        scans = {d['scan'] for d in outliers}

        def num_outliers(scan, outliers):
            return len([d for d in outliers if d['scan'] == scan])

        if 0 < threshold < 1:
            img = nib.load(dwi_file)
            try:
                threshold *= img.header.get_n_slices()
            except nib.spatialimages.HeaderDataError:
                print(
                    'WARNING. We are not sure which dimension has the '
                    'slices in this image. So we are using the 3rd dim.',
                    img.shape)
                threshold *= img.shape[2]

        drop_scans = np.array(
            [s for s in scans if num_outliers(s, outliers) > threshold])

        outpath = op.abspath("dropped_scans.txt")
        np.savetxt(outpath, drop_scans, fmt="%d")

        return drop_scans, outpath

    id_outliers_node = pe.Node(niu.Function(
        input_names=["outlier_report", "threshold", "dwi_file"],
        output_names=["drop_scans", "outpath"],
        function=id_outliers_fn),
                               name="id_outliers_node")

    wf.connect(inputspec, 'dwi_file', id_outliers_node, 'dwi_file')
    wf.connect(inputspec, 'slice_outlier_threshold', id_outliers_node,
               'threshold')

    wf.connect(prep, "fsl_eddy.out_outlier_report", id_outliers_node,
               "outlier_report")

    list_merge = pe.Node(niu.Merge(numinputs=2), name="list_merge")
    wf.connect(inputspec, 'dwi_file_ap', list_merge, 'in1')
    wf.connect(inputspec, 'dwi_file_pa', list_merge, 'in2')

    merge = pe.Node(fsl.Merge(dimension='t'), name="mergeAPPA")
    wf.connect(merge, 'merged_file', prep, 'inputnode.alt_file')
    wf.connect(list_merge, 'out', merge, 'in_files')

    fslroi = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="fslroi")
    wf.connect(prep, "outputnode.out_file", fslroi, "in_file")

    b0mask_node = pe.Node(niu.Function(input_names=['b0_file'],
                                       output_names=['mask_file'],
                                       function=get_b0_mask_fn),
                          name="getB0Mask")
    wf.connect(fslroi, 'roi_file', b0mask_node, 'b0_file')
    wf.connect(b0mask_node, 'mask_file', eddy_quad, 'mask_file')

    bbreg = pe.Node(
        fs.BBRegister(
            contrast_type="t2",
            init="coreg",
            out_fsl_file=True,
            # subjects_dir=subjects_dir,
            epi_mask=True),
        name="bbreg")
    bbreg.inputs.subject_id = 'freesurfer'  # bids_sub_name
    wf.connect(fslroi, "roi_file", bbreg, "source_file")
    wf.connect(inputspec, 'subjects_dir', bbreg, 'subjects_dir')

    def drop_outliers_fn(in_file, in_bval, in_bvec, drop_scans):
        """Drop outlier volumes from dwi file

        Parameters
        ----------
        in_file: string
            Path to nii dwi file to drop outlier volumes from

        in_bval: string
            Path to bval file to drop outlier volumes from

        in_bvec: string
            Path to bvec file to drop outlier volumes from

        drop_scans: numpy.ndarray
            List of scan indices to drop

        Returns
        -------
        out_file: string
            Path to "thinned" output dwi file

        out_bval: string
            Path to "thinned" output bval file

        out_bvec: string
            Path to "thinned" output bvec file
        """
        import nibabel as nib
        import numpy as np
        import os.path as op
        from nipype.utils.filemanip import fname_presuffix

        img = nib.load(op.abspath(in_file))
        img_data = img.get_data()
        img_data_thinned = np.delete(img_data, drop_scans, axis=3)
        if isinstance(img, nib.nifti1.Nifti1Image):
            img_thinned = nib.Nifti1Image(img_data_thinned.astype(np.float64),
                                          img.affine,
                                          header=img.header)
        elif isinstance(img, nib.nifti2.Nifti2Image):
            img_thinned = nib.Nifti2Image(img_data_thinned.astype(np.float64),
                                          img.affine,
                                          header=img.header)
        else:
            raise TypeError("in_file does not contain Nifti image datatype.")

        out_file = fname_presuffix(in_file,
                                   suffix="_thinned",
                                   newpath=op.abspath('.'))
        nib.save(img_thinned, op.abspath(out_file))

        bval = np.loadtxt(in_bval)
        bval_thinned = np.delete(bval, drop_scans, axis=0)
        out_bval = fname_presuffix(in_bval,
                                   suffix="_thinned",
                                   newpath=op.abspath('.'))
        np.savetxt(out_bval, bval_thinned)

        bvec = np.loadtxt(in_bvec)
        bvec_thinned = np.delete(bvec, drop_scans, axis=1)
        out_bvec = fname_presuffix(in_bvec,
                                   suffix="_thinned",
                                   newpath=op.abspath('.'))
        np.savetxt(out_bvec, bvec_thinned)

        return out_file, out_bval, out_bvec

    drop_outliers_node = pe.Node(niu.Function(
        input_names=["in_file", "in_bval", "in_bvec", "drop_scans"],
        output_names=["out_file", "out_bval", "out_bvec"],
        function=drop_outliers_fn),
                                 name="drop_outliers_node")

    # Align the output of drop_outliers_node & also the eddy corrected version to the anatomical space
    # without resampling. and then for aparc+aseg & the mask, resample to the larger voxel size of the B0 image from
    # fslroi. Also we need to apply the transformation to both bvecs (dropped & eddied) and I think we can just load
    # the affine from bbreg (sio.loadmat) and np.dot(coord, aff) for each coord in bvec

    def get_orig(subjects_dir, sub='freesurfer'):
        import os.path as op
        return op.join(subjects_dir, sub, "mri", "orig.mgz")

    def get_aparc_aseg(subjects_dir, sub='freesurfer'):
        import os.path as op
        return op.join(subjects_dir, sub, "mri", "aparc+aseg.mgz")

    # transform the dropped volume version to anat space w/ out resampling
    voltransform = pe.Node(fs.ApplyVolTransform(no_resample=True),
                           iterfield=['source_file', 'reg_file'],
                           name='transform')

    wf.connect(inputspec, 'subjects_dir', voltransform, 'subjects_dir')
    wf.connect(inputspec, ('subjects_dir', get_aparc_aseg), voltransform,
               'target_file')
    wf.connect(prep, "outputnode.out_file", voltransform, "source_file")
    wf.connect(bbreg, "out_reg_file", voltransform, "reg_file")

    def apply_transform_to_bvecs_fn(bvec_file, reg_mat_file):
        import numpy as np
        import nipype.utils.filemanip as fm
        import os
        aff = np.loadtxt(reg_mat_file)
        bvecs = np.loadtxt(bvec_file)
        bvec_trans = []
        for bvec in bvecs.T:
            coord = np.hstack((bvec, [1]))
            coord_trans = np.dot(coord, aff)[:-1]
            bvec_trans.append(coord_trans)
        out_bvec = fm.fname_presuffix(bvec_file,
                                      suffix="anat_space",
                                      newpath=os.path.abspath('.'))
        np.savetxt(out_bvec, np.asarray(bvec_trans).T)
        return out_bvec

    apply_transform_to_bvecs_node = pe.Node(niu.Function(
        input_names=['bvec_file', 'reg_mat_file'],
        output_names=['out_bvec'],
        function=apply_transform_to_bvecs_fn),
                                            name="applyTransformToBvecs")
    wf.connect(bbreg, 'out_fsl_file', apply_transform_to_bvecs_node,
               'reg_mat_file')
    wf.connect(prep, 'outputnode.out_bvec', apply_transform_to_bvecs_node,
               'bvec_file')

    # ok cool, now lets do the thresholding.

    wf.connect(id_outliers_node, "drop_scans", drop_outliers_node,
               "drop_scans")
    wf.connect(voltransform, "transformed_file", drop_outliers_node, "in_file")
    wf.connect(inputspec, 'bval_file', drop_outliers_node, 'in_bval')
    wf.connect(apply_transform_to_bvecs_node, "out_bvec", drop_outliers_node,
               "in_bvec")

    # lets compute the tensor on both the dropped volume scan
    # and also the original, eddy corrected one.
    get_tensor = pe.Node(DTI(), name="dipy_tensor")
    wf.connect(drop_outliers_node, "out_file", get_tensor, "in_file")
    wf.connect(drop_outliers_node, "out_bval", get_tensor, "in_bval")
    wf.connect(drop_outliers_node, "out_bvec", get_tensor, "in_bvec")

    get_tensor_eddy = get_tensor.clone('dipy_tensor_eddy')
    wf.connect(voltransform, 'transformed_file', get_tensor_eddy, "in_file")
    wf.connect(apply_transform_to_bvecs_node, 'out_bvec', get_tensor_eddy,
               "in_bvec")
    wf.connect(inputspec, 'bval_file', get_tensor_eddy, 'in_bval')

    # AK: What is this, some vestigal node from a previous workflow?
    # I'm not sure why the tensor gets scaled. but i guess lets scale it for
    # both the dropped & eddy corrected versions.
    scale_tensor = pe.Node(name='scale_tensor', interface=fsl.BinaryMaths())
    scale_tensor.inputs.operation = 'mul'
    scale_tensor.inputs.operand_value = 1000
    wf.connect(get_tensor, 'out_file', scale_tensor, 'in_file')

    scale_tensor_eddy = scale_tensor.clone('scale_tensor_eddy')
    wf.connect(get_tensor_eddy, 'out_file', scale_tensor_eddy, 'in_file')

    # OK now that anatomical stuff (segmentation & mask)
    # We'll need:
    # 1. the B0 image in anat space (fslroi the 'transformed file' of voltransform
    # 2. the aparc aseg resampled-like the B0 image (mri_convert)
    # 3. the resample aparc_aseg binarized to be the mask image.

    def binarize_aparc(aparc_aseg):
        import nibabel as nib
        from nipype.utils.filemanip import fname_presuffix
        import os.path as op
        img = nib.load(aparc_aseg)
        data, aff = img.get_data(), img.affine
        outfile = fname_presuffix(aparc_aseg,
                                  suffix="bin.nii.gz",
                                  newpath=op.abspath("."),
                                  use_ext=False)
        nib.Nifti1Image((data > 0).astype(float), aff).to_filename(outfile)
        return outfile

    create_mask = pe.Node(niu.Function(input_names=["aparc_aseg"],
                                       output_names=["outfile"],
                                       function=binarize_aparc),
                          name="bin_aparc")

    get_b0_anat = fslroi.clone('get_b0_anat')
    wf.connect(voltransform, 'transformed_file', get_b0_anat, 'in_file')

    # reslice the anat-space aparc+aseg to the DWI resolution
    reslice_to_dwi = pe.Node(fs.MRIConvert(resample_type="nearest"),
                             name="reslice_to_dwi")
    wf.connect(get_b0_anat, 'roi_file', reslice_to_dwi, 'reslice_like')
    wf.connect(inputspec, ('subjects_dir', get_aparc_aseg), reslice_to_dwi,
               'in_file')

    # also reslice the orig i suppose
    reslice_orig_to_dwi = reslice_to_dwi.clone('resliceT1wToDwi')
    wf.connect(inputspec, ('subjects_dir', get_orig), reslice_orig_to_dwi,
               'in_file')
    # reslice_orig_to_dwi.inputs.in_file = get_orig(subjects_dir, 'freesurfer')
    reslice_orig_to_dwi.inputs.out_type = 'niigz'
    wf.connect(get_b0_anat, 'roi_file', reslice_orig_to_dwi, 'reslice_like')

    # we assume the freesurfer is the output of BIDS
    # so the freesurfer output is in /path/to/derivatives/sub-whatever/freesurfer
    # which means the subject_dir is /path/to/derivatives/sub-whatever
    # reslice_to_dwi.inputs.in_file = get_aparc_aseg(subjects_dir, 'freesurfer')

    # now we have a nice aparc+aseg still in anat space but resliced like the dwi file
    # lets create a mask file from it.

    wf.connect(reslice_to_dwi, 'out_file', create_mask, 'aparc_aseg')

    # save all the things
    datasink = pe.Node(nio.DataSink(), name="sinker")
    wf.connect(inputspec, 'out_dir', datasink, 'base_directory')
    wf.connect(inputspec, 'subject_id', datasink, 'container')

    wf.connect(drop_outliers_node, "out_file", datasink,
               "dmriprep.dwi.@thinned")
    wf.connect(drop_outliers_node, "out_bval", datasink,
               "dmriprep.dwi.@bval_thinned")
    wf.connect(drop_outliers_node, "out_bvec", datasink,
               "dmriprep.dwi.@bvec_thinned")

    # eddy corrected files
    wf.connect(prep, "outputnode.out_file", datasink,
               "dmriprep.dwi_eddy.@corrected")
    wf.connect(prep, "outputnode.out_bvec", datasink,
               "dmriprep.dwi_eddy.@rotated")
    wf.connect(inputspec, 'bval_file', datasink, 'dmriprep.dwi_eddy.@bval')

    # all the eddy stuff except the corrected files
    wf.connect(prep, "fsl_eddy.out_movement_rms", datasink,
               "dmriprep.qc.@eddyparamsrms")
    wf.connect(prep, "fsl_eddy.out_outlier_report", datasink,
               "dmriprep.qc.@eddyparamsreport")
    wf.connect(prep, "fsl_eddy.out_restricted_movement_rms", datasink,
               "dmriprep.qc.@eddyparamsrestrictrms")
    wf.connect(prep, "fsl_eddy.out_shell_alignment_parameters", datasink,
               "dmriprep.qc.@eddyparamsshellalign")
    wf.connect(prep, "fsl_eddy.out_parameter", datasink,
               "dmriprep.qc.@eddyparams")
    wf.connect(prep, "fsl_eddy.out_cnr_maps", datasink,
               "dmriprep.qc.@eddycndr")
    wf.connect(prep, "fsl_eddy.out_residuals", datasink,
               "dmriprep.qc.@eddyresid")

    # the file that told us which volumes to drop
    wf.connect(id_outliers_node, "outpath", datasink,
               "dmriprep.qc.@droppedscans")

    # the tensors of the dropped volumes dwi
    wf.connect(get_tensor, "out_file", datasink, "dmriprep.dti.@tensor")
    wf.connect(get_tensor, "fa_file", datasink, "dmriprep.dti.@fa")
    wf.connect(get_tensor, "md_file", datasink, "dmriprep.dti.@md")
    wf.connect(get_tensor, "ad_file", datasink, "dmriprep.dti.@ad")
    wf.connect(get_tensor, "rd_file", datasink, "dmriprep.dti.@rd")
    wf.connect(get_tensor, "color_fa_file", datasink, "dmriprep.dti.@colorfa")
    wf.connect(scale_tensor, "out_file", datasink,
               "dmriprep.dti.@scaled_tensor")

    # the tensors of the eddied volumes dwi
    wf.connect(get_tensor_eddy, "out_file", datasink,
               "dmriprep.dti_eddy.@tensor")
    wf.connect(get_tensor_eddy, "fa_file", datasink, "dmriprep.dti_eddy.@fa")
    wf.connect(get_tensor_eddy, "md_file", datasink, "dmriprep.dti_eddy.@md")
    wf.connect(get_tensor_eddy, "ad_file", datasink, "dmriprep.dti_eddy.@ad")
    wf.connect(get_tensor_eddy, "rd_file", datasink, "dmriprep.dti_eddy.@rd")
    wf.connect(get_tensor_eddy, "color_fa_file", datasink,
               "dmriprep.dti_eddy.@colorfa")
    wf.connect(scale_tensor_eddy, "out_file", datasink,
               "dmriprep.dti_eddy.@scaled_tensor")

    # all the eddy_quad stuff
    wf.connect(eddy_quad, 'out_qc_json', datasink,
               "dmriprep.qc.@eddyquad_json")
    wf.connect(eddy_quad, 'out_qc_pdf', datasink, "dmriprep.qc.@eddyquad_pdf")
    wf.connect(eddy_quad, 'out_avg_b_png', datasink,
               "dmriprep.qc.@eddyquad_bpng")
    wf.connect(eddy_quad, 'out_avg_b0_pe_png', datasink,
               "dmriprep.qc.@eddyquad_b0png")
    wf.connect(eddy_quad, 'out_cnr_png', datasink, "dmriprep.qc.@eddyquad_cnr")
    wf.connect(eddy_quad, 'out_vdm_png', datasink, "dmriprep.qc.@eddyquad_vdm")
    wf.connect(eddy_quad, 'out_residuals', datasink,
               'dmriprep.qc.@eddyquad_resid')

    # anatomical registration stuff
    wf.connect(bbreg, "min_cost_file", datasink, "dmriprep.reg.@mincost")
    wf.connect(bbreg, "out_fsl_file", datasink, "dmriprep.reg.@fslfile")
    wf.connect(bbreg, "out_reg_file", datasink, "dmriprep.reg.@reg")

    # anatomical files resliced
    wf.connect(reslice_to_dwi, 'out_file', datasink,
               'dmriprep.anat.@segmentation')
    wf.connect(create_mask, 'outfile', datasink, 'dmriprep.anat.@mask')
    wf.connect(reslice_orig_to_dwi, 'out_file', datasink, 'dmriprep.anat.@T1w')

    def report_fn(dwi_corrected_file, eddy_rms, eddy_report, color_fa_file,
                  anat_mask_file, outlier_indices, eddy_qc_file):
        from dmriprep.qc import create_report_json

        report = create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
                                    color_fa_file, anat_mask_file,
                                    outlier_indices, eddy_qc_file)
        return report

    report_node = pe.Node(niu.Function(input_names=[
        'dwi_corrected_file', 'eddy_rms', 'eddy_report', 'color_fa_file',
        'anat_mask_file', 'outlier_indices', 'eddy_qc_file'
    ],
                                       output_names=['report'],
                                       function=report_fn),
                          name="reportJSON")

    # for the report, lets show the eddy corrected (full volume) image
    wf.connect(voltransform, "transformed_file", report_node,
               'dwi_corrected_file')
    wf.connect(eddy_quad, 'out_qc_json', report_node, 'eddy_qc_file')

    # add the rms movement output from eddy
    wf.connect(prep, "fsl_eddy.out_movement_rms", report_node, 'eddy_rms')
    wf.connect(prep, "fsl_eddy.out_outlier_report", report_node, 'eddy_report')
    wf.connect(id_outliers_node, 'drop_scans', report_node, 'outlier_indices')

    # the mask file to check our registration, and the colorFA file go in the report
    wf.connect(create_mask, "outfile", report_node, 'anat_mask_file')
    wf.connect(get_tensor, "color_fa_file", report_node, 'color_fa_file')

    # save that report!
    wf.connect(report_node, 'report', datasink, 'dmriprep.report.@report')

    # this part is done last, to get the filenames *just right*
    # its super annoying.
    def name_files_nicely(dwi_file, subject_id):
        import os.path as op
        dwi_fname = op.split(dwi_file)[1].split(".nii.gz")[0]
        substitutions = [
            ("vol0000_flirt_merged.nii.gz", dwi_fname + '.nii.gz'),
            ("stats.vol0000_flirt_merged.txt", dwi_fname + ".art.json"),
            ("motion_parameters.par", dwi_fname + ".motion.txt"),
            ("_rotated.bvec", ".bvec"),
            ("art.vol0000_flirt_merged_outliers.txt",
             dwi_fname + ".outliers.txt"), ("vol0000_flirt_merged", dwi_fname),
            ("_roi_bbreg_freesurfer", "_register"),
            ("dwi/eddy_corrected", "dwi/%s" % dwi_fname),
            ("dti/eddy_corrected", "dti/%s" % dwi_fname.replace("_dwi", "")),
            ("reg/eddy_corrected", "reg/%s" % dwi_fname.replace("_dwi", "")),
            ("aparc+aseg_outbin", dwi_fname.replace("_dwi", "_mask")),
            ("aparc+aseg_out", dwi_fname.replace("_dwi", "_aparc+aseg")),
            ("art.eddy_corrected_outliers",
             dwi_fname.replace("dwi", "outliers")), ("color_fa", "colorfa"),
            ("orig_out", dwi_fname.replace("_dwi", "_T1w")),
            ("stats.eddy_corrected", dwi_fname.replace("dwi", "artStats")),
            ("eddy_corrected.eddy_parameters", dwi_fname + ".eddy_parameters"),
            ("qc/eddy_corrected", "qc/" + dwi_fname),
            ("derivatives/dmriprep",
             "derivatives/{}/dmriprep".format(subject_id)),
            ("_rotatedanat_space_thinned", ""), ("_thinned", ""),
            ("eddy_corrected", dwi_fname), ("_warped", ""),
            ("_maths", "_scaled"),
            ("dropped_scans", dwi_fname.replace("_dwi", "_dwi_dropped_scans")),
            ("report.json", dwi_fname.replace("_dwi", "_dwi_report.json"))
        ]
        return substitutions

    node_name_files_nicely = pe.Node(niu.Function(
        input_names=['dwi_file', 'subject_id'],
        output_names=['substitutions'],
        function=name_files_nicely),
                                     name="name_files_nicely")
    wf.connect(inputspec, 'dwi_file', node_name_files_nicely, 'dwi_file')
    wf.connect(inputspec, 'subject_id', node_name_files_nicely, 'subject_id')
    wf.connect(node_name_files_nicely, 'substitutions', datasink,
               'substitutions')

    return wf
Ejemplo n.º 23
0
def define_preproc_workflow(info, subjects, sessions, qc=True):

    # --- Workflow parameterization and data input

    scan_info = info.scan_info
    experiment = info.experiment_name

    iterables = generate_iterables(scan_info, experiment, subjects, sessions)
    subject_iterables, session_iterables, run_iterables = iterables

    subject_iterables = subjects

    subject_source = Node(IdentityInterface(["subject"]),
                          name="subject_source",
                          iterables=("subject", subject_iterables))

    session_source = Node(IdentityInterface(["subject", "session"]),
                          name="session_source",
                          itersource=("subject_source", "subject"),
                          iterables=("session", session_iterables))

    run_source = Node(IdentityInterface(["subject", "session", "run"]),
                      name="run_source",
                      itersource=("session_source", "session"),
                      iterables=("run", run_iterables))

    session_input = Node(SessionInput(data_dir=info.data_dir,
                                      proc_dir=info.proc_dir,
                                      fm_template=info.fm_template,
                                      phase_encoding=info.phase_encoding),
                         "session_input")

    run_input = Node(RunInput(experiment=experiment,
                              data_dir=info.data_dir,
                              proc_dir=info.proc_dir,
                              sb_template=info.sb_template,
                              ts_template=info.ts_template,
                              crop_frames=info.crop_frames),
                     name="run_input")

    # --- Warpfield estimation using topup

    # Distortion warpfield estimation
    #  TODO figure out how to parameterize for testing
    # topup_config = op.realpath(op.join(__file__, "../../../topup_fast.cnf"))
    topup_config = "b02b0.cnf"
    estimate_distortions = Node(fsl.TOPUP(config=topup_config),
                                "estimate_distortions")

    # Post-process the TOPUP outputs
    finalize_unwarping = Node(FinalizeUnwarping(), "finalize_unwarping")

    # --- Registration of SE-EPI (without distortions) to Freesurfer anatomy

    fm2anat = Node(fs.BBRegister(init="fsl",
                                 contrast_type="t2",
                                 registered_file=True,
                                 out_fsl_file="sess2anat.mat",
                                 out_reg_file="sess2anat.dat"),
                   "fm2anat")

    fm2anat_qc = Node(AnatRegReport(data_dir=info.data_dir), "fm2anat_qc")

    # --- Registration of SBRef to SE-EPI (with distortions)

    sb2fm = Node(fsl.FLIRT(dof=6, interp="spline"), "sb2fm")

    sb2fm_qc = Node(CoregGIF(out_file="coreg.gif"), "sb2fm_qc")

    # --- Motion correction of time series to SBRef (with distortions)

    ts2sb = Node(fsl.MCFLIRT(save_mats=True, save_plots=True),
                 "ts2sb")

    ts2sb_qc = Node(RealignmentReport(), "ts2sb_qc")

    # --- Combined motion correction, unwarping, and template registration

    # Combine pre-and post-warp linear transforms
    combine_premats = MapNode(fsl.ConvertXFM(concat_xfm=True),
                              "in_file", "combine_premats")

    combine_postmats = Node(fsl.ConvertXFM(concat_xfm=True),
                            "combine_postmats")

    # Transform Jacobian images into the template space
    transform_jacobian = Node(fsl.ApplyWarp(relwarp=True),
                              "transform_jacobian")

    # Apply rigid transforms and nonlinear warpfield to time series frames
    restore_timeseries = MapNode(fsl.ApplyWarp(interp="spline", relwarp=True),
                                 ["in_file", "premat"],
                                 "restore_timeseries")

    # Apply rigid transforms and nonlinear warpfield to template frames
    restore_template = MapNode(fsl.ApplyWarp(interp="spline", relwarp=True),
                               ["in_file", "premat", "field_file"],
                               "restore_template")

    # Perform final preprocessing operations on timeseries
    finalize_timeseries = Node(FinalizeTimeseries(experiment=experiment),
                               "finalize_timeseries")

    # Perform final preprocessing operations on template
    finalize_template = JoinNode(FinalizeTemplate(experiment=experiment),
                                 name="finalize_template",
                                 joinsource="run_source",
                                 joinfield=["mean_files", "tsnr_files",
                                            "mask_files", "noise_files"])

    # --- Workflow ouptut

    save_info = Node(SaveInfo(info_dict=info.trait_get()), "save_info")

    template_output = Node(DataSink(base_directory=info.proc_dir,
                                    parameterization=False),
                           "template_output")

    timeseries_output = Node(DataSink(base_directory=info.proc_dir,
                                      parameterization=False),
                             "timeseries_output")

    # === Assemble pipeline

    cache_base = op.join(info.cache_dir, info.experiment_name)
    workflow = Workflow(name="preproc", base_dir=cache_base)

    # Connect processing nodes

    processing_edges = [

        (subject_source, session_source,
            [("subject", "subject")]),
        (subject_source, run_source,
            [("subject", "subject")]),
        (session_source, run_source,
            [("session", "session")]),
        (session_source, session_input,
            [("session", "session")]),
        (run_source, run_input,
            [("run", "run")]),

        # Phase-encode distortion estimation

        (session_input, estimate_distortions,
            [("fm_file", "in_file"),
             ("phase_encoding", "encoding_direction"),
             ("readout_times", "readout_times")]),
        (session_input, finalize_unwarping,
            [("fm_file", "raw_file"),
             ("phase_encoding", "phase_encoding")]),
        (estimate_distortions, finalize_unwarping,
            [("out_corrected", "corrected_file"),
             ("out_warps", "warp_files"),
             ("out_jacs", "jacobian_files")]),

        # Registration of corrected SE-EPI to anatomy

        (session_input, fm2anat,
            [("subject", "subject_id")]),
        (finalize_unwarping, fm2anat,
            [("corrected_file", "source_file")]),

        # Registration of each frame to SBRef image

        (run_input, ts2sb,
            [("ts_file", "in_file"),
             ("sb_file", "ref_file")]),
        (ts2sb, finalize_timeseries,
            [("par_file", "mc_file")]),

        # Registration of SBRef volume to SE-EPI fieldmap

        (run_input, sb2fm,
            [("sb_file", "in_file")]),
        (finalize_unwarping, sb2fm,
            [("raw_file", "reference"),
             ("mask_file", "ref_weight")]),

        # Single-interpolation spatial realignment and unwarping

        (ts2sb, combine_premats,
            [("mat_file", "in_file")]),
        (sb2fm, combine_premats,
            [("out_matrix_file", "in_file2")]),
        (fm2anat, combine_postmats,
            [("out_fsl_file", "in_file")]),
        (session_input, combine_postmats,
            [("reg_file", "in_file2")]),

        (run_input, transform_jacobian,
            [("anat_file", "ref_file")]),
        (finalize_unwarping, transform_jacobian,
            [("jacobian_file", "in_file")]),
        (combine_postmats, transform_jacobian,
            [("out_file", "premat")]),

        (run_input, restore_timeseries,
            [("ts_frames", "in_file")]),
        (run_input, restore_timeseries,
            [("anat_file", "ref_file")]),
        (combine_premats, restore_timeseries,
            [("out_file", "premat")]),
        (finalize_unwarping, restore_timeseries,
            [("warp_file", "field_file")]),
        (combine_postmats, restore_timeseries,
            [("out_file", "postmat")]),
        (run_input, finalize_timeseries,
            [("run_tuple", "run_tuple"),
             ("anat_file", "anat_file"),
             ("seg_file", "seg_file"),
             ("mask_file", "mask_file")]),
        (transform_jacobian, finalize_timeseries,
            [("out_file", "jacobian_file")]),
        (restore_timeseries, finalize_timeseries,
            [("out_file", "in_files")]),

        (session_input, restore_template,
            [("fm_frames", "in_file"),
             ("anat_file", "ref_file")]),
        (estimate_distortions, restore_template,
            [("out_mats", "premat"),
             ("out_warps", "field_file")]),
        (combine_postmats, restore_template,
            [("out_file", "postmat")]),
        (session_input, finalize_template,
            [("session_tuple", "session_tuple"),
             ("seg_file", "seg_file"),
             ("anat_file", "anat_file")]),
        (transform_jacobian, finalize_template,
            [("out_file", "jacobian_file")]),
        (restore_template, finalize_template,
            [("out_file", "in_files")]),

        (finalize_timeseries, finalize_template,
            [("mean_file", "mean_files"),
             ("tsnr_file", "tsnr_files"),
             ("mask_file", "mask_files"),
             ("noise_file", "noise_files")]),

        # --- Persistent data storage

        # Ouputs associated with each scanner run

        (finalize_timeseries, timeseries_output,
            [("output_path", "container"),
             ("out_file", "@func"),
             ("mean_file", "@mean"),
             ("mask_file", "@mask"),
             ("tsnr_file", "@tsnr"),
             ("noise_file", "@noise"),
             ("mc_file", "@mc")]),

        # Ouputs associated with the session template

        (finalize_template, template_output,
            [("output_path", "container"),
             ("out_file", "@func"),
             ("mean_file", "@mean"),
             ("tsnr_file", "@tsnr"),
             ("mask_file", "@mask"),
             ("noise_file", "@noise")]),

    ]
    workflow.connect(processing_edges)

    # Optionally connect QC nodes

    qc_edges = [

        # Registration of each frame to SBRef image

        (run_input, ts2sb_qc,
            [("sb_file", "target_file")]),
        (ts2sb, ts2sb_qc,
            [("par_file", "realign_params")]),

        # Registration of corrected SE-EPI to anatomy

        (session_input, fm2anat_qc,
            [("subject", "subject_id")]),
        (fm2anat, fm2anat_qc,
            [("registered_file", "in_file"),
             ("min_cost_file", "cost_file")]),

        # Registration of SBRef volume to SE-EPI fieldmap

        (sb2fm, sb2fm_qc,
            [("out_file", "in_file")]),
        (finalize_unwarping, sb2fm_qc,
            [("raw_file", "ref_file")]),

        # Ouputs associated with each scanner run

        (run_source, save_info,
            [("run", "parameterization")]),
        (save_info, timeseries_output,
            [("info_file", "qc.@info_json")]),

        (run_input, timeseries_output,
            [("ts_plot", "qc.@raw_gif")]),
        (sb2fm_qc, timeseries_output,
            [("out_file", "qc.@sb2fm_gif")]),
        (ts2sb_qc, timeseries_output,
            [("params_plot", "qc.@params_plot"),
             ("target_plot", "qc.@target_plot")]),
        (finalize_timeseries, timeseries_output,
            [("out_gif", "qc.@ts_gif"),
             ("out_png", "qc.@ts_png"),
             ("mask_plot", "qc.@mask_plot"),
             ("mean_plot", "qc.@ts_mean_plot"),
             ("tsnr_plot", "qc.@ts_tsnr_plot"),
             ("noise_plot", "qc.@noise_plot")]),

        # Outputs associated with the session template

        (finalize_unwarping, template_output,
            [("warp_plot", "qc.@warp_png"),
             ("unwarp_gif", "qc.@unwarp_gif")]),
        (fm2anat_qc, template_output,
            [("out_file", "qc.@reg_png")]),
        (finalize_template, template_output,
            [("out_plot", "qc.@func_png"),
             ("mean_plot", "qc.@mean"),
             ("tsnr_plot", "qc.@tsnr"),
             ("mask_plot", "qc.@mask"),
             ("noise_plot", "qc.@noise")]),

    ]

    if qc:
        workflow.connect(qc_edges)

    return workflow
Ejemplo n.º 24
0
def run_dmriprep(dwi_file, bvec_file, bval_file, subjects_dir, working_dir,
                 out_dir):
    """
    Runs dmriprep for acquisitions with just one PE direction.

    """
    from glob import glob
    import nibabel as nib
    import nipype.interfaces.freesurfer as fs
    import nipype.interfaces.fsl as fsl
    import nipype.interfaces.io as nio
    import nipype.interfaces.utility as niu
    import nipype.pipeline.engine as pe
    import numpy as np
    from nipype.algorithms.rapidart import ArtifactDetect
    from nipype.interfaces.dipy import DTI
    from nipype.interfaces.fsl.utils import AvScale
    from nipype.utils.filemanip import fname_presuffix
    from nipype.workflows.dmri.fsl.epi import create_dmri_preprocessing

    wf = create_dmri_preprocessing(name='dmriprep',
                                   use_fieldmap=False,
                                   fieldmap_registration=False)
    wf.inputs.inputnode.ref_num = 0
    wf.inputs.inputnode.in_file = dwi_file
    wf.inputs.inputnode.in_bvec = bvec_file

    dwi_fname = op.split(dwi_file)[1].split(".nii.gz")[0]
    bids_sub_name = dwi_fname.split("_")[0]
    assert bids_sub_name.startswith("sub-")

    # inputnode = wf.get_node("inputnode")
    outputspec = wf.get_node("outputnode")

    # QC: FLIRT translation and rotation parameters
    flirt = wf.get_node("motion_correct.coregistration")
    # flirt.inputs.save_mats = True

    get_tensor = pe.Node(DTI(), name="dipy_tensor")
    wf.connect(outputspec, "dmri_corrected", get_tensor, "in_file")
    # wf.connect(inputspec2,"bvals", get_tensor, "in_bval")
    get_tensor.inputs.in_bval = bval_file
    wf.connect(outputspec, "bvec_rotated", get_tensor, "in_bvec")

    scale_tensor = pe.Node(name='scale_tensor', interface=fsl.BinaryMaths())
    scale_tensor.inputs.operation = 'mul'
    scale_tensor.inputs.operand_value = 1000
    wf.connect(get_tensor, 'out_file', scale_tensor, 'in_file')

    fslroi = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="fslroi")
    wf.connect(outputspec, "dmri_corrected", fslroi, "in_file")

    bbreg = pe.Node(fs.BBRegister(contrast_type="t2",
                                  init="fsl",
                                  out_fsl_file=True,
                                  subjects_dir=subjects_dir,
                                  epi_mask=True),
                    name="bbreg")
    # wf.connect(inputspec2,"fsid", bbreg,"subject_id")
    bbreg.inputs.subject_id = 'freesurfer'  # bids_sub_name
    wf.connect(fslroi, "roi_file", bbreg, "source_file")

    voltransform = pe.Node(fs.ApplyVolTransform(inverse=True),
                           iterfield=['source_file', 'reg_file'],
                           name='transform')
    voltransform.inputs.subjects_dir = subjects_dir

    vt2 = voltransform.clone("transform_aparcaseg")
    vt2.inputs.interp = "nearest"

    def binarize_aparc(aparc_aseg):
        img = nib.load(aparc_aseg)
        data, aff = img.get_data(), img.affine
        outfile = fname_presuffix(aparc_aseg,
                                  suffix="bin.nii.gz",
                                  newpath=op.abspath("."),
                                  use_ext=False)
        nib.Nifti1Image((data > 0).astype(float), aff).to_filename(outfile)
        return outfile

    # wf.connect(inputspec2, "mask_nii", voltransform, "target_file")
    create_mask = pe.Node(niu.Function(input_names=["aparc_aseg"],
                                       output_names=["outfile"],
                                       function=binarize_aparc),
                          name="bin_aparc")

    def get_aparc_aseg(subjects_dir, sub):
        return op.join(subjects_dir, sub, "mri", "aparc+aseg.mgz")

    create_mask.inputs.aparc_aseg = get_aparc_aseg(subjects_dir, 'freesurfer')
    wf.connect(create_mask, "outfile", voltransform, "target_file")

    wf.connect(fslroi, "roi_file", voltransform, "source_file")
    wf.connect(bbreg, "out_reg_file", voltransform, "reg_file")

    vt2.inputs.target_file = get_aparc_aseg(subjects_dir, 'freesurfer')
    # wf.connect(inputspec2, "aparc_aseg", vt2, "target_file")
    wf.connect(fslroi, "roi_file", vt2, "source_file")
    wf.connect(bbreg, "out_reg_file", vt2, "reg_file")

    # AK (2017): THIS NODE MIGHT NOT BE NECESSARY
    # AK (2018) doesn't know why she said that above..
    threshold2 = pe.Node(fs.Binarize(min=0.5, out_type='nii.gz', dilate=1),
                         iterfield=['in_file'],
                         name='threshold2')
    wf.connect(voltransform, "transformed_file", threshold2, "in_file")

    # wf.connect(getmotion, "motion_params", datasink, "dti.@motparams")

    def get_flirt_motion_parameters(flirt_out_mats):
        def get_params(A):
            """This is a copy of spm's spm_imatrix where
            we already know the rotations and translations matrix,
            shears and zooms (as outputs from fsl FLIRT/avscale)
            Let A = the 4x4 rotation and translation matrix
            R = [          c5*c6,           c5*s6, s5]
                [-s4*s5*c6-c4*s6, -s4*s5*s6+c4*c6, s4*c5]
                [-c4*s5*c6+s4*s6, -c4*s5*s6-s4*c6, c4*c5]
            """
            def rang(b):
                a = min(max(b, -1), 1)
                return a

            Ry = np.arcsin(A[0, 2])
            # Rx = np.arcsin(A[1, 2] / np.cos(Ry))
            # Rz = np.arccos(A[0, 1] / np.sin(Ry))

            if (abs(Ry) - np.pi / 2)**2 < 1e-9:
                Rx = 0
                Rz = np.arctan2(-rang(A[1, 0]), rang(-A[2, 0] / A[0, 2]))
            else:
                c = np.cos(Ry)
                Rx = np.arctan2(rang(A[1, 2] / c), rang(A[2, 2] / c))
                Rz = np.arctan2(rang(A[0, 1] / c), rang(A[0, 0] / c))

            rotations = [Rx, Ry, Rz]
            translations = [A[0, 3], A[1, 3], A[2, 3]]

            return rotations, translations

        motion_params = open(op.abspath('motion_parameters.par'), 'w')
        for mat in flirt_out_mats:
            res = AvScale(mat_file=mat).run()
            A = np.asarray(res.outputs.rotation_translation_matrix)
            rotations, translations = get_params(A)
            for i in rotations + translations:
                motion_params.write('%f ' % i)
            motion_params.write('\n')
        motion_params.close()
        motion_params = op.abspath('motion_parameters.par')
        return motion_params

    getmotion = pe.Node(niu.Function(input_names=["flirt_out_mats"],
                                     output_names=["motion_params"],
                                     function=get_flirt_motion_parameters),
                        name="get_motion_parameters",
                        iterfield="flirt_out_mats")

    wf.connect(flirt, "out_matrix_file", getmotion, "flirt_out_mats")

    art = pe.Node(interface=ArtifactDetect(), name="art")
    art.inputs.use_differences = [True, True]
    art.inputs.save_plot = False
    art.inputs.use_norm = True
    art.inputs.norm_threshold = 3
    art.inputs.zintensity_threshold = 9
    art.inputs.mask_type = 'spm_global'
    art.inputs.parameter_source = 'FSL'

    wf.connect(getmotion, "motion_params", art, "realignment_parameters")
    wf.connect(outputspec, "dmri_corrected", art, "realigned_files")

    datasink = pe.Node(nio.DataSink(), name="sinker")
    datasink.inputs.base_directory = out_dir
    datasink.inputs.substitutions = [
        ("vol0000_flirt_merged.nii.gz", dwi_fname + '.nii.gz'),
        ("stats.vol0000_flirt_merged.txt", dwi_fname + ".art.json"),
        ("motion_parameters.par", dwi_fname + ".motion.txt"),
        ("_rotated.bvec", ".bvec"),
        ("aparc+aseg_warped_out", dwi_fname.replace("_dwi", "_aparc+aseg")),
        ("art.vol0000_flirt_merged_outliers.txt", dwi_fname + ".outliers.txt"),
        ("vol0000_flirt_merged", dwi_fname),
        ("_roi_bbreg_freesurfer", "_register"),
        ("aparc+asegbin_warped_thresh", dwi_fname.replace("_dwi", "_mask")),
        ("derivatives/dmriprep",
         "derivatives/{}/dmriprep".format(bids_sub_name))
    ]

    wf.connect(art, "statistic_files", datasink, "dmriprep.art.@artstat")
    wf.connect(art, "outlier_files", datasink, "dmriprep.art.@artoutlier")
    wf.connect(outputspec, "dmri_corrected", datasink,
               "dmriprep.dwi.@corrected")
    wf.connect(outputspec, "bvec_rotated", datasink, "dmriprep.dwi.@rotated")
    wf.connect(getmotion, "motion_params", datasink, "dmriprep.art.@motion")

    wf.connect(get_tensor, "out_file", datasink, "dmriprep.dti.@tensor")
    wf.connect(get_tensor, "fa_file", datasink, "dmriprep.dti.@fa")
    wf.connect(get_tensor, "md_file", datasink, "dmriprep.dti.@md")
    wf.connect(get_tensor, "ad_file", datasink, "dmriprep.dti.@ad")
    wf.connect(get_tensor, "rd_file", datasink, "dmriprep.dti.@rd")
    wf.connect(get_tensor, "out_file", datasink, "dmriprep.dti.@scaled_tensor")

    wf.connect(bbreg, "min_cost_file", datasink, "dmriprep.reg.@mincost")
    wf.connect(bbreg, "out_fsl_file", datasink, "dmriprep.reg.@fslfile")
    wf.connect(bbreg, "out_reg_file", datasink, "dmriprep.reg.@reg")
    wf.connect(threshold2, "binary_file", datasink, "dmriprep.anat.@mask")
    # wf.connect(vt2, "transformed_file", datasink, "dwi.@aparc_aseg")

    convert = pe.Node(fs.MRIConvert(out_type="niigz"), name="convert2nii")
    wf.connect(vt2, "transformed_file", convert, "in_file")
    wf.connect(convert, "out_file", datasink, "dmriprep.anat.@aparc_aseg")

    wf.base_dir = working_dir
    wf.run()

    copyfile(
        bval_file,
        op.join(out_dir, bids_sub_name, "dmriprep", "dwi",
                op.split(bval_file)[1]))

    dmri_corrected = glob(op.join(out_dir, '*/dmriprep/dwi', '*.nii.gz'))[0]
    bvec_rotated = glob(op.join(out_dir, '*/dmriprep/dwi', '*.bvec'))[0]
    bval_file = glob(op.join(out_dir, '*/dmriprep/dwi', '*.bval'))[0]
    art_file = glob(op.join(out_dir, '*/dmriprep/art', '*.art.json'))[0]
    motion_file = glob(op.join(out_dir, '*/dmriprep/art', '*.motion.txt'))[0]
    outlier_file = glob(op.join(out_dir, '*/dmriprep/art',
                                '*.outliers.txt'))[0]
    return dmri_corrected, bvec_rotated, art_file, motion_file, outlier_file
Ejemplo n.º 25
0
def create_coreg_pipeline(name='coreg'):

    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')

    # initiate workflow
    coreg = Workflow(name='coreg')

    #inputnode
    inputnode = Node(util.IdentityInterface(fields=[
        'epi_median',
        'fs_subjects_dir',
        'fs_subject_id',
        'uni_highres',
    ]),
                     name='inputnode')

    # outputnode
    outputnode = Node(util.IdentityInterface(fields=[
        'uni_lowres', 'epi2lowres', 'epi2lowres_mat', 'epi2lowres_dat',
        'highres2lowres', 'highres2lowres_mat', 'highres2lowres_dat',
        'epi2highres_lin', 'epi2highres_lin_mat', 'epi2highres_lin_itk'
    ]),
                      name='outputnode')

    # convert mgz head file for reference
    fs_import = Node(interface=nio.FreeSurferSource(), name='fs_import')

    brain_convert = Node(fs.MRIConvert(out_type='niigz',
                                       out_file='uni_lowres.nii.gz'),
                         name='brain_convert')

    coreg.connect([(inputnode, fs_import, [('fs_subjects_dir', 'subjects_dir'),
                                           ('fs_subject_id', 'subject_id')]),
                   (fs_import, brain_convert, [('brain', 'in_file')]),
                   (brain_convert, outputnode, [('out_file', 'uni_lowres')])])

    # linear registration epi median to lowres mp2rage with bbregister
    bbregister_epi = Node(fs.BBRegister(contrast_type='t2',
                                        out_fsl_file='epi2lowres.mat',
                                        out_reg_file='epi2lowres.dat',
                                        registered_file='epi2lowres.nii.gz',
                                        init='fsl',
                                        epi_mask=True),
                          name='bbregister_epi')

    coreg.connect([
        (inputnode, bbregister_epi, [('fs_subjects_dir', 'subjects_dir'),
                                     ('fs_subject_id', 'subject_id'),
                                     ('epi_median', 'source_file')]),
        (bbregister_epi, outputnode, [('out_fsl_file', 'epi2lowres_mat'),
                                      ('out_reg_file', 'epi2lowres_dat'),
                                      ('registered_file', 'epi2lowres')])
    ])

    # linear register highres mp2rage to lowres mp2rage
    bbregister_anat = Node(fs.BBRegister(
        contrast_type='t1',
        out_fsl_file='highres2lowres.mat',
        out_reg_file='highres2lowres.dat',
        registered_file='highres2lowres.nii.gz',
        init='fsl'),
                           name='bbregister_anat')

    coreg.connect([
        (inputnode, bbregister_anat, [('fs_subjects_dir', 'subjects_dir'),
                                      ('fs_subject_id', 'subject_id'),
                                      ('uni_highres', 'source_file')]),
        (bbregister_anat, outputnode, [('out_fsl_file', 'highres2lowres_mat'),
                                       ('out_reg_file', 'highres2lowres_dat'),
                                       ('registered_file', 'highres2lowres')])
    ])

    # invert highres2lowres transform
    invert = Node(fsl.ConvertXFM(invert_xfm=True), name='invert')
    coreg.connect([(bbregister_anat, invert, [('out_fsl_file', 'in_file')])])

    # concatenate epi2highres transforms
    concat = Node(fsl.ConvertXFM(concat_xfm=True,
                                 out_file='epi2highres_lin.mat'),
                  name='concat')
    coreg.connect([(bbregister_epi, concat, [('out_fsl_file', 'in_file')]),
                   (invert, concat, [('out_file', 'in_file2')]),
                   (concat, outputnode, [('out_file', 'epi2higres_lin_mat')])])

    # convert epi2highres transform into itk format
    itk = Node(interface=c3.C3dAffineTool(fsl2ras=True,
                                          itk_transform='epi2highres_lin.txt'),
               name='itk')

    coreg.connect([(inputnode, itk, [('epi_median', 'source_file'),
                                     ('uni_highres', 'reference_file')]),
                   (concat, itk, [('out_file', 'transform_file')]),
                   (itk, outputnode, [('itk_transform', 'epi2highres_lin_itk')
                                      ])])

    # transform epi to highres
    epi2highres = Node(ants.ApplyTransforms(
        dimension=3,
        output_image='epi2highres_lin.nii.gz',
        interpolation='BSpline',
    ),
                       name='epi2highres')

    coreg.connect([
        (inputnode, epi2highres, [('uni_highres', 'reference_image'),
                                  ('epi_median', 'input_image')]),
        (itk, epi2highres, [('itk_transform', 'transforms')]),
        (epi2highres, outputnode, [('output_image', 'epi2highres_lin')])
    ])

    return coreg
Ejemplo n.º 26
0
def create_dti():
    # main workflow for preprocessing diffusion data
    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # Initiation of a workflow
    dwi_preproc = Workflow(name="dwi_preproc")
    # inputnode
    inputnode = Node(IdentityInterface(fields=[
        'subject_id',
        'freesurfer_dir',
        'aseg',
        'dwi',
        'dwi_ap',
        'dwi_pa',
        'bvals',
        'bvecs'
    ]),
        name='inputnode')
    # output node
    outputnode = Node(IdentityInterface(fields=[
        'dwi_denoised',
        "dwi_unringed",
        "topup_corr",
        "topup_field",
        "bo_brain",
        "bo_brainmask",
        "topup_fieldcoef",
        "eddy_corr",
        "eddy_params",
        "rotated_bvecs",
        "total_movement_rms",
        "shell_alignment_parameters",
        'outlier_report',
        "cnr_maps",
        "residuals",
        'dti_fa',
        'dti_md',
        'dti_l1',
        'dti_l2',
        'dti_l3',
        'dti_v1',
        'dti_v2',
        'dti_v3',
        'fa2anat',
        'fa2anat_mat',
        'fa2anat_dat'
    ]),
        name='outputnode')

    
    '''
    workflow to run distortion correction
    -------------------------------------
    '''
    distor_corr = create_distortion_correct()


    '''
    tensor fitting
    --------------
    '''
    dti = Node(fsl.DTIFit(), name='dti')

    #connecting the nodes
    dwi_preproc.connect([

        (inputnode, distor_corr, [('dwi', 'inputnode.dwi')]),
        (inputnode, distor_corr, [('dwi_ap', 'inputnode.dwi_ap')]),
        (inputnode, distor_corr, [('dwi_pa', 'inputnode.dwi_pa')]),
        (inputnode, distor_corr, [("bvals", "inputnode.bvals")]),
        (inputnode, distor_corr, [("bvecs", "inputnode.bvecs")]),
        (inputnode, dti, [("bvals", "bvals")]),
        (distor_corr, outputnode, [('outputnode.bo_brain', 'bo_brain')]),
        (distor_corr, outputnode, [('outputnode.bo_brainmask', 'bo_brainmask')]),
        (distor_corr, outputnode, [('outputnode.noise', 'noise')]),
        (distor_corr, outputnode, [('outputnode.dwi_denoised', 'dwi_denoised')]),
        (distor_corr, outputnode, [('outputnode.dwi_unringed', 'dwi_unringed')]),
        (distor_corr, outputnode, [('outputnode.topup_corr', 'topup_corr')]),
        (distor_corr, outputnode, [('outputnode.topup_field', 'topup_field')]),
        (distor_corr, outputnode, [('outputnode.topup_fieldcoef', 'topup_fieldcoef')]),
        (distor_corr, outputnode, [('outputnode.eddy_corr', 'eddy_corr')]),
        (distor_corr, outputnode, [('outputnode.rotated_bvecs', 'rotated_bvecs')]),
        (distor_corr, outputnode, [('outputnode.total_movement_rms', 'total_movement_rms')]),
        (distor_corr, outputnode, [('outputnode.outlier_report', 'outlier_report')]),
        (distor_corr, outputnode, [('outputnode.shell_params', "shell_alignment_parameters",)]),
        (distor_corr, outputnode, [('outputnode.cnr_maps', 'cnr_maps')]),
        (distor_corr, outputnode, [('outputnode.residuals', 'residuals')]),
        (distor_corr, outputnode, [('outputnode.eddy_params', 'eddy_params')]),
        (distor_corr, dti, [("outputnode.rotated_bvecs", "bvecs")]),
        (distor_corr, dti, [('outputnode.bo_brainmask', 'mask')]),
        #(distor_corr, flirt, [('outputnode.eddy_corr', 'in_file')]),
        #(distor_corr, flirt, [('outputnode.eddy_corr', 'reference')]),
        #(flirt, dti, [('out_file', 'dwi')]),
        (distor_corr, dti, [('outputnode.eddy_corr', 'dwi')]),
        (dti, outputnode, [('FA', 'dti_fa')]),
        (dti, outputnode, [('MD', 'dti_md')]),
        (dti, outputnode, [('L1', 'dti_l1')]),
        (dti, outputnode, [('L2', 'dti_l2')]),
        (dti, outputnode, [('L3', 'dti_l3')]),
        (dti, outputnode, [('V1', 'dti_v1')]),
        (dti, outputnode, [('V2', 'dti_v2')]),
        (dti, outputnode, [('V3', 'dti_v3')])

    ])


    '''
    coregistration of FA and T1
    ------------------------------------
    '''
    #have to rename subject for fu (but now structural wf is connected to dwi
    #and its not necessary to rename again.)
    #def rename_subject_for_fu(input_id):
    #    output_id=input_id+"_fu"
    #    return output_id

    #modify subject name so it can be saved in the same folder as other LIFE- freesurfer data
    #rename=Node(util.Function(input_names=['input_id'],
    #                        output_names=['output_id'],
    #                        function = rename_subject_for_fu), name="rename")
    
    # linear registration with bbregister
    bbreg = Node(fs.BBRegister(contrast_type='t1',
    out_fsl_file='fa2anat.mat',
    out_reg_file='fa2anat.dat',
    registered_file='fa2anat_bbreg.nii.gz',
    init='fsl'
    ),
    name='bbregister')

    # connecting the nodes
    dwi_preproc.connect([

        (inputnode, bbreg, [('subject_id', 'subject_id')]),
        (inputnode, bbreg, [('freesurfer_dir', 'subjects_dir')]),
        (dti, bbreg, [("FA", "source_file")]),
        (bbreg, outputnode, [('out_fsl_file', 'fa2anat_mat'),
                             ('out_reg_file', 'fa2anat_dat'),
                             ('registered_file', 'fa2anat')])

    ])

    return dwi_preproc
def create_reg_workflow(name='registration'):
    """Create a FEAT preprocessing workflow together with freesurfer

    Parameters
    ----------

        name : name of workflow (default: 'registration')

    Inputs::

        inputspec.source_files : files (filename or list of filenames to register)
        inputspec.mean_image : reference image to use
        inputspec.anatomical_image : anatomical image to coregister to
        inputspec.target_image : registration target

    Outputs::

        outputspec.func2anat_transform : FLIRT transform
        outputspec.anat2target_transform : FLIRT+FNIRT transform
        outputspec.transformed_files : transformed files in target space
        outputspec.transformed_mean : mean image in target space
    """

    register = Workflow(name=name)

    inputnode = Node(interface=IdentityInterface(fields=[
        'source_files', 'mean_image', 'subject_id', 'subjects_dir',
        'target_image'
    ]),
                     name='inputspec')

    outputnode = Node(interface=IdentityInterface(fields=[
        'func2anat_transform', 'out_reg_file', 'anat2target_transform',
        'transforms', 'transformed_mean', 'segmentation_files', 'anat2target',
        'aparc'
    ]),
                      name='outputspec')

    # Get the subject's freesurfer source directory
    fssource = Node(FreeSurferSource(), name='fssource')
    fssource.run_without_submitting = True
    register.connect(inputnode, 'subject_id', fssource, 'subject_id')
    register.connect(inputnode, 'subjects_dir', fssource, 'subjects_dir')

    convert = Node(freesurfer.MRIConvert(out_type='nii'), name="convert")
    register.connect(fssource, 'T1', convert, 'in_file')

    # Coregister the median to the surface
    bbregister = Node(freesurfer.BBRegister(), name='bbregister')
    bbregister.inputs.init = 'fsl'
    bbregister.inputs.contrast_type = 't2'
    bbregister.inputs.out_fsl_file = True
    bbregister.inputs.epi_mask = True
    register.connect(inputnode, 'subject_id', bbregister, 'subject_id')
    register.connect(inputnode, 'mean_image', bbregister, 'source_file')
    register.connect(inputnode, 'subjects_dir', bbregister, 'subjects_dir')
    """
    Estimate the tissue classes from the anatomical image. But use spm's segment
    as FSL appears to be breaking.
    """

    stripper = Node(fsl.BET(), name='stripper')
    register.connect(convert, 'out_file', stripper, 'in_file')
    fast = Node(fsl.FAST(), name='fast')
    register.connect(stripper, 'out_file', fast, 'in_files')
    """
    Binarize the segmentation
    """

    binarize = MapNode(fsl.ImageMaths(op_string='-nan -thr 0.9 -ero -bin'),
                       iterfield=['in_file'],
                       name='binarize')
    register.connect(fast, 'partial_volume_files', binarize, 'in_file')
    """
    Apply inverse transform to take segmentations to functional space
    """

    applyxfm = MapNode(freesurfer.ApplyVolTransform(inverse=True,
                                                    interp='nearest'),
                       iterfield=['target_file'],
                       name='inverse_transform')
    register.connect(inputnode, 'subjects_dir', applyxfm, 'subjects_dir')
    register.connect(bbregister, 'out_reg_file', applyxfm, 'reg_file')
    register.connect(binarize, 'out_file', applyxfm, 'target_file')
    register.connect(inputnode, 'mean_image', applyxfm, 'source_file')
    """
    Apply inverse transform to aparc file
    """

    aparcxfm = Node(freesurfer.ApplyVolTransform(inverse=True,
                                                 interp='nearest'),
                    name='aparc_inverse_transform')
    register.connect(inputnode, 'subjects_dir', aparcxfm, 'subjects_dir')
    register.connect(bbregister, 'out_reg_file', aparcxfm, 'reg_file')
    register.connect(fssource, ('aparc_aseg', get_aparc_aseg), aparcxfm,
                     'target_file')
    register.connect(inputnode, 'mean_image', aparcxfm, 'source_file')
    """
    Convert the BBRegister transformation to ANTS ITK format
    """

    convert2itk = Node(C3dAffineTool(), name='convert2itk')
    convert2itk.inputs.fsl2ras = True
    convert2itk.inputs.itk_transform = True
    register.connect(bbregister, 'out_fsl_file', convert2itk, 'transform_file')
    register.connect(inputnode, 'mean_image', convert2itk, 'source_file')
    register.connect(stripper, 'out_file', convert2itk, 'reference_file')
    """
    Compute registration between the subject's structural and MNI template
    This is currently set to perform a very quick registration. However, the
    registration can be made significantly more accurate for cortical
    structures by increasing the number of iterations
    All parameters are set using the example from:
    #https://github.com/stnava/ANTs/blob/master/Scripts/newAntsExample.sh
    """

    reg = Node(ants.Registration(), name='antsRegister')
    reg.inputs.output_transform_prefix = "output_"
    reg.inputs.transforms = ['Rigid', 'Affine', 'SyN']
    reg.inputs.transform_parameters = [(0.1, ), (0.1, ), (0.2, 3.0, 0.0)]
    reg.inputs.number_of_iterations = [[10000, 11110, 11110]] * 2 + [[
        100, 30, 20
    ]]
    reg.inputs.dimension = 3
    reg.inputs.write_composite_transform = True
    reg.inputs.collapse_output_transforms = True
    reg.inputs.initial_moving_transform_com = True
    reg.inputs.metric = ['Mattes'] * 2 + [['Mattes', 'CC']]
    reg.inputs.metric_weight = [1] * 2 + [[0.5, 0.5]]
    reg.inputs.radius_or_number_of_bins = [32] * 2 + [[32, 4]]
    reg.inputs.sampling_strategy = ['Regular'] * 2 + [[None, None]]
    reg.inputs.sampling_percentage = [0.3] * 2 + [[None, None]]
    reg.inputs.convergence_threshold = [1.e-8] * 2 + [-0.01]
    reg.inputs.convergence_window_size = [20] * 2 + [5]
    reg.inputs.smoothing_sigmas = [[4, 2, 1]] * 2 + [[1, 0.5, 0]]
    reg.inputs.sigma_units = ['vox'] * 3
    reg.inputs.shrink_factors = [[3, 2, 1]] * 2 + [[4, 2, 1]]
    reg.inputs.use_estimate_learning_rate_once = [True] * 3
    reg.inputs.use_histogram_matching = [False] * 2 + [True]
    reg.inputs.winsorize_lower_quantile = 0.005
    reg.inputs.winsorize_upper_quantile = 0.995
    reg.inputs.float = True
    reg.inputs.output_warped_image = 'output_warped_image.nii.gz'
    reg.inputs.num_threads = 4
    reg.plugin_args = {'qsub_args': '-l nodes=1:ppn=4'}
    register.connect(stripper, 'out_file', reg, 'moving_image')
    register.connect(inputnode, 'target_image', reg, 'fixed_image')
    """
    Concatenate the affine and ants transforms into a list
    """

    merge = Node(Merge(2), iterfield=['in2'], name='mergexfm')
    register.connect(convert2itk, 'itk_transform', merge, 'in2')
    register.connect(reg, 'composite_transform', merge, 'in1')
    """
    Transform the mean image. First to anatomical and then to target
    """

    warpmean = Node(ants.ApplyTransforms(), name='warpmean')
    warpmean.inputs.input_image_type = 3
    warpmean.inputs.interpolation = 'Linear'
    warpmean.inputs.invert_transform_flags = [False, False]
    warpmean.inputs.terminal_output = 'file'
    warpmean.inputs.args = '--float'
    warpmean.inputs.num_threads = 4

    register.connect(inputnode, 'target_image', warpmean, 'reference_image')
    register.connect(inputnode, 'mean_image', warpmean, 'input_image')
    register.connect(merge, 'out', warpmean, 'transforms')
    """
    Assign all the output files
    """

    register.connect(reg, 'warped_image', outputnode, 'anat2target')
    register.connect(warpmean, 'output_image', outputnode, 'transformed_mean')
    register.connect(applyxfm, 'transformed_file', outputnode,
                     'segmentation_files')
    register.connect(aparcxfm, 'transformed_file', outputnode, 'aparc')
    register.connect(bbregister, 'out_fsl_file', outputnode,
                     'func2anat_transform')
    register.connect(bbregister, 'out_reg_file', outputnode, 'out_reg_file')
    register.connect(reg, 'composite_transform', outputnode,
                     'anat2target_transform')
    register.connect(merge, 'out', outputnode, 'transforms')

    return register
Ejemplo n.º 28
0
def make_fs_fieldmap(name='make_fs_fieldmap'):

    inputnode = pe.Node(utility.IdentityInterface(fields=[
        'complex_image', 'magnitude_image', 'subject_id',
        'freesurfer_subject_dir', 't1_mask', 'delta_TE'
    ]),
                        run_without_submitting=True,
                        name='inputspec')
    outputnode = pe.Node(
        utility.IdentityInterface(fields=['fieldmap', 'fieldmap_mask']),
        run_without_submitting=True,
        name='outputspec')

    n_fieldmap_to_t1_bbr = pe.Node(freesurfer.BBRegister(init='header',
                                                         reg_frame=0,
                                                         out_fsl_file=True,
                                                         registered_file=True,
                                                         contrast_type='t1'),
                                   name='fieldmap_to_t1_bbr')
    """
    n_fieldmap_to_t1 = pe.Node(
        fsl.FLIRT(cost='mutualinfo',
                  dof=6,
                  no_search=True,
                  uses_qform=True),
        name='fieldmap_to_t1')
        """
    n_reg_to_mni = pe.Node(freesurfer.preprocess.Tkregister(
        no_edit=True, xfm_out='%s_xfm.mat'),
                           run_without_submitting=True,
                           name='reg_to_mni')

    n_resamp_complex = pe.Node(utility.Function(
        input_names=['mat_file', 'cplx_file', 'ref_file'],
        output_names=['out_file'],
        function=fs_resamp_complex),
                               name='resamp_complex')

    n_phase_mag = pe.Node(utility.Function(
        input_names=['complex_in_file', 'mask_file'],
        output_names=['magnitude_out_file', 'phase_out_file'],
        function=complex_to_mag_phase),
                          name='phase_mag')

    n_unwrap_phases = pe.Node(fsl.PRELUDE(process3d=True),
                              name='unwrap_phases')

    n_make_fieldmap = pe.Node(
        fsl.FUGUE(smooth3d=3, unwarp_direction='z'),
        iterfield=['fmap_out_file', 'mask_file', 'fmap_in_file'],
        name='make_fieldmap')

    w = pe.Workflow(name=name)

    w.connect([
        #       (inputnode, n_fieldmap_to_t1, [('magnitude_image','in_file'),
        #                                      ('t1_mag','reference')]),
        #(n_fieldmap_to_t1, n_flirt_complex, [('out_matrix_file','mat_file'),]),
        (inputnode, n_fieldmap_to_t1_bbr, [('magnitude_image', 'source_file'),
                                           ('freesurfer_subject_dir',
                                            'subjects_dir'),
                                           ('subject_id', 'subject_id')]),
        (n_fieldmap_to_t1_bbr, n_reg_to_mni, [('out_reg_file', 'reg_file')]),
        (inputnode, n_reg_to_mni, [
            ('magnitude_image', 'mov'),
            ('freesurfer_subject_dir', 'subjects_dir'),
        ]),
        (n_reg_to_mni, n_resamp_complex, [
            ('xfm_out', 'mat_file'),
        ]),
        (inputnode, n_resamp_complex, [('complex_image', 'cplx_file'),
                                       ('t1_mask', 'ref_file')]),
        (n_resamp_complex, n_phase_mag, [('out_file', 'complex_in_file')]),
        (inputnode, n_phase_mag, [('t1_mask', 'mask_file')]),
        (n_phase_mag, n_unwrap_phases, [('phase_out_file', 'phase_file')]),
        (n_phase_mag, n_unwrap_phases, [('magnitude_out_file',
                                         'magnitude_file')]),
        (inputnode, n_unwrap_phases, [('t1_mask', 'mask_file')]),
        (n_unwrap_phases, n_make_fieldmap, [('unwrapped_phase_file',
                                             'phasemap_file')]),
        (inputnode, n_make_fieldmap,
         [('delta_TE', 'asym_se_time'), ('t1_mask', 'mask_file'),
          (('complex_image', fname_presuffix_basename, '', '_fieldmap'),
           'fmap_out_file')]),
    ])

    return w
Ejemplo n.º 29
0
datasource = pe.Node(nio.DataGrabber(infields=['subject_id'],
                                     outfields=['filtered_func',
                                                'mean_image']),
                     name='datasource')
datasource.inputs.base_directory = datadir
datasource.inputs.template = '%s/*%s.nii.gz'
datasource.inputs.template_args = dict(
    filtered_func=[['subject_id', 'filtered']],
    mean_image=[['subject_id', 'mean']])

roiproc.connect(inputnode, 'subject_id', datasource, 'subject_id')

fssource = pe.Node(nio.FreeSurferSource(), name='fssource')
fssource.inputs.subjects_dir = surfacedir

register = pe.Node(fs.BBRegister(init='fsl', contrast_type='t2'),
                   name='register')
register.inputs.subjects_dir = surfacedir

voltransform = pe.Node(fs.ApplyVolTransform(inverse=True, interp='nearest'),
                       name='transform')
voltransform.inputs.subjects_dir = surfacedir


def choose_aseg(aparc_files):
    from glob import glob
    import os
    all_files = glob(os.path.join(aparc_files[0].split('aparc')[0], '*yeo*'))
    for fname in all_files:
        if 'aparc+yeo17' in fname:
            return fname
Ejemplo n.º 30
0
def create_dti():
    # main workflow for preprocessing diffusion data
    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # Initiation of a workflow
    dwi_preproc = Workflow(name="dwi_preproc")
    # inputnode
    inputnode = Node(IdentityInterface(fields=[
        'subject_id', 'freesurfer_dir', 'aseg', 'dwi', 'dwi_b0', 'dwi_mag',
        'dwi_ph', 'bvals', 'bvecs', 'dwi_dwelltime', 'te_diff'
    ]),
                     name='inputnode')
    # output node
    outputnode = Node(IdentityInterface(fields=[
        'bo_brain', "bo_brainmask", 'dwi_denoised', 'dwi_unringed',
        "mag2b0mat", "mag2b0", "fmap", "eddy_corr", "rotated_bvecs",
        "total_movement_rms", "outlier_report", "cnr_maps", "residuals",
        "shell_params", "eddy_params", 'dti_fa', 'dti_md', 'dti_l1', 'dti_l2',
        'dti_l3', 'dti_v1', 'dti_v2', 'dti_v3', 'fa2anat', 'fa2anat_mat',
        'fa2anat_dat'
    ]),
                      name='outputnode')
    '''
    workflow to run distortion correction
    -------------------------------------
    '''
    distor_corr = create_distortion_correct()
    '''
    tensor fitting
    --------------
    '''
    dti = Node(fsl.DTIFit(), name='dti')

    #connecting the nodes
    dwi_preproc.connect([
        (inputnode, distor_corr, [('dwi', 'inputnode.dwi')]),
        (inputnode, distor_corr, [('dwi_b0', 'inputnode.dwi_b0')]),
        (inputnode, distor_corr, [('dwi_mag', 'inputnode.dwi_mag')]),
        (inputnode, distor_corr, [('dwi_ph', 'inputnode.dwi_ph')]),
        (inputnode, distor_corr, [("bvals", "inputnode.bvals")]),
        (inputnode, distor_corr, [("bvecs", "inputnode.bvecs")]),
        (inputnode, distor_corr, [("dwi_dwelltime", "inputnode.dwi_dwelltime")
                                  ]),
        (inputnode, distor_corr, [("te_diff", "inputnode.te_diff")]),
        (distor_corr, outputnode, [('outputnode.bo_brain', 'bo_brain')]),
        (distor_corr, outputnode, [('outputnode.bo_brainmask', 'bo_brainmask')
                                   ]),
        (distor_corr, outputnode, [('outputnode.dwi_denoised', 'dwi_denoised')
                                   ]),
        (distor_corr, outputnode, [('outputnode.dwi_unringed', 'dwi_unringed')
                                   ]),
        (distor_corr, outputnode, [('outputnode.fmap', 'fmap')]),
        (distor_corr, outputnode, [('outputnode.mag2b0mat', 'mag2b0mat')]),
        (distor_corr, outputnode, [('outputnode.mag2b0', 'mag2b0')]),
        (distor_corr, outputnode, [('outputnode.eddy_corr', 'eddy_corr')]),
        (distor_corr, outputnode, [('outputnode.rotated_bvecs',
                                    'rotated_bvecs')]),
        (distor_corr, outputnode, [('outputnode.total_movement_rms',
                                    'total_movement_rms')]),
        (distor_corr, outputnode, [('outputnode.cnr_maps', 'cnr_maps')]),
        (distor_corr, outputnode, [('outputnode.residuals', 'residuals')]),
        (distor_corr, outputnode, [('outputnode.shell_params', 'shell_params')
                                   ]),
        (distor_corr, outputnode, [('outputnode.eddy_params', 'eddy_params')]),
        (distor_corr, outputnode, [('outputnode.outlier_report',
                                    'outlier_report')]),
        (distor_corr, dti, [("outputnode.rotated_bvecs", "bvecs")]),
        (distor_corr, dti, [('outputnode.bo_brainmask', 'mask')]),
        (distor_corr, dti, [('outputnode.eddy_corr', 'dwi')]),
        (distor_corr, dti, [("outputnode.bvals", "bvals")]),
        (dti, outputnode, [('FA', 'dti_fa')]),
        (dti, outputnode, [('MD', 'dti_md')]),
        (dti, outputnode, [('L1', 'dti_l1')]),
        (dti, outputnode, [('L2', 'dti_l2')]),
        (dti, outputnode, [('L3', 'dti_l3')]),
        (dti, outputnode, [('V1', 'dti_v1')]),
        (dti, outputnode, [('V2', 'dti_v2')]),
        (dti, outputnode, [('V3', 'dti_v3')])
    ])
    '''
    coregistration of FA and T1
    ------------------------------------
    '''

    # linear registration with bbregister
    bbreg = Node(fs.BBRegister(contrast_type='t1',
                               out_fsl_file='fa2anat.mat',
                               out_reg_file='fa2anat.dat',
                               registered_file='fa2anat_bbreg.nii.gz',
                               init='fsl'),
                 name='bbregister')

    # connecting the nodes
    dwi_preproc.connect([
        (inputnode, bbreg, [('subject_id', 'subject_id')]),
        (inputnode, bbreg, [('freesurfer_dir', 'subjects_dir')]),
        (dti, bbreg, [("FA", "source_file")]),
        (bbreg, outputnode, [('out_fsl_file', 'fa2anat_mat'),
                             ('out_reg_file', 'fa2anat_dat'),
                             ('registered_file', 'fa2anat')])
    ])

    return dwi_preproc