def create_moco_pipeline(name='motion_correction'):
    # initiate workflow
    moco = Workflow(name='motion_correction')
    # set fsl output
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # inputnode
    inputnode = Node(util.IdentityInterface(fields=['epi']), name='inputnode')
    # outputnode
    outputnode = Node(util.IdentityInterface(fields=[
        'epi_moco', 'par_moco', 'mat_moco', 'rms_moco', 'epi_mean', 'rotplot',
        'transplot', 'dispplots', 'tsnr_file'
    ]),
                      name='outputnode')
    # mcflirt motion correction to 1st volume
    mcflirt = Node(fsl.MCFLIRT(save_mats=True,
                               save_plots=True,
                               save_rms=True,
                               ref_vol=1,
                               out_file='rest_realigned.nii.gz'),
                   name='mcflirt')
    # plot motion parameters
    rotplotter = Node(fsl.PlotMotionParams(in_source='fsl',
                                           plot_type='rotations',
                                           out_file='rotation_plot.png'),
                      name='rotplotter')
    transplotter = Node(fsl.PlotMotionParams(in_source='fsl',
                                             plot_type='translations',
                                             out_file='translation_plot.png'),
                        name='transplotter')
    dispplotter = MapNode(interface=fsl.PlotMotionParams(
        in_source='fsl',
        plot_type='displacement',
    ),
                          name='dispplotter',
                          iterfield=['in_file'])
    dispplotter.iterables = ('plot_type', ['displacement'])
    # calculate tmean
    tmean = Node(fsl.maths.MeanImage(dimension='T',
                                     out_file='rest_realigned_mean.nii.gz'),
                 name='tmean')
    # calculate tsnr
    tsnr = Node(confounds.TSNR(), name='tsnr')
    # create connections
    moco.connect([(inputnode, mcflirt, [('epi', 'in_file')]),
                  (mcflirt, tmean, [('out_file', 'in_file')]),
                  (mcflirt, rotplotter, [('par_file', 'in_file')]),
                  (mcflirt, transplotter, [('par_file', 'in_file')]),
                  (mcflirt, dispplotter, [('rms_files', 'in_file')]),
                  (tmean, outputnode, [('out_file', 'epi_mean')]),
                  (mcflirt, outputnode, [('out_file', 'epi_moco'),
                                         ('par_file', 'par_moco'),
                                         ('mat_file', 'mat_moco'),
                                         ('rms_files', 'rms_moco')]),
                  (rotplotter, outputnode, [('out_file', 'rotplot')]),
                  (transplotter, outputnode, [('out_file', 'transplot')]),
                  (dispplotter, outputnode, [('out_file', 'dispplots')]),
                  (mcflirt, tsnr, [('out_file', 'in_file')]),
                  (tsnr, outputnode, [('tsnr_file', 'tsnr_file')])])
    return moco
Beispiel #2
0
def MCORRECTOR():
	#--- 1)  Import modules
	import nipype.pipeline.engine as pe
	import os
	os.system('clear')
	from glob import glob
	import nipype.interfaces.fsl as fsl
	import nipype.interfaces.utility as util

	#--- 2)  Record intial working directory

	INITDIR=os.getcwd();

	#--- 3) Prompt user for directory containing DICOM FILES

	NIFTIFILE=raw_input('Please drag in the nifti\n file you wish to motion correct\n(ensure there is no blank space at the end)\n')
	os.system('clear')
	print '---\n'
	NIFTIFILE=NIFTIFILE.strip('\'"')
	NIFTIDIR=os.path.split(NIFTIFILE)[0]
	#--- 3) Move to directory

	os.chdir(NIFTIDIR)


	#--- 4) Set up motion correction node

	motion_correct = pe.Node(interface=fsl.MCFLIRT(save_mats=True,save_plots=True,interpolation='spline'),name='MCORRECTED')
	motion_correct.inputs.in_file=NIFTIFILE

	#--- 5) Set up plotting node
	plot_motion = pe.Node(interface=fsl.PlotMotionParams(in_source='fsl'),name='PLOTTED')
	plot_motion.iterables = ('plot_type', ['rotations', 'translations'])

	#--- 5) Utility output node
	outputnode = pe.Node(interface=util.IdentityInterface(fields=['mcorrected_files']),name='outputnode')

	
	#--- 6) Set up workflow

	workflow = pe.Workflow(name='MCORRECTOR')
	workflow.base_dir = NIFTIDIR


	#--- 7) Connect nodes.

	workflow.connect(motion_correct, 'par_file', plot_motion, 'in_file')
	workflow.connect(motion_correct,'out_file', outputnode,'mcorrected_files')


	workflow.write_graph(graph2use='exec')

	#--- 8) Run workflow

	result=workflow.run()


	print "Node completed. Returning to intital directory\n"

	os.chdir(INITDIR)
Beispiel #3
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
Beispiel #4
0
def FUNCPIPE():
	#--- 1)  Import modules

	import os                                    # system functions
	os.system('clear')
	import nipype.interfaces.dcm2nii as dcm2nii
	import nipype.interfaces.io as nio           # Data i/o
	import nipype.interfaces.fsl as fsl          # fsl
	import nipype.interfaces.utility as util     # utility
	import nipype.pipeline.engine as pe          # pypeline engine
	import nipype.interfaces.fsl.utils as fslu
	import nipype.interfaces.fsl.preprocess as fslp
	from nipype.interfaces import afni as afni
	from nipype.interfaces.utility import Function
	import matplotlib
	from nilearn import plotting
	from nilearn import image
	import os
	import nipype.interfaces.fsl as fsl          # fsl
	import nipype.interfaces.utility as util     # utility
	import nipype.pipeline.engine as pe          # pypeline engine
	import nipype.interfaces.freesurfer as fs    # freesurfer


	tolist = lambda x: [x]
	highpass_operand = lambda x:'-bptf %.10f -1'%x

	#--- 2) Prompt user for directory containing DICOM FILES

	INITDIR=os.getcwd();

	#--- 3) Prompt user for inputs.

	DICOMDIR=raw_input('Please drag in the directory of\nDICOM files you wish to pre-process\n(ensure there is no blank space at the end)\n')
	os.system('clear')
	print ('---\n')
	DICOMDIR=DICOMDIR.strip('\'"')
	frac=float(input('Please enter the fractional anisotropy threshold [0 - 1] \n'))
	os.system('clear')
	print ('---\n')
	grad=float(input('Please enter the threshold gradient [-1 - 1] \n'))
	os.system('clear')
	print ('---\n')
	FWHM=float(input('Please enter the FWHM of the smoother (mm) \n'))
	os.system('clear')
	print ('---\n')
	HIGHPASS=float(input('Please enter the High Pass filter cutoff (s)\n'))
	os.system('clear')
	print ('---\n')
	TR=float(input('Please enter the TR (s)\n'))
	os.system('clear')
	print ('---\n')





	#--- 4) Define workflow and input node.

	workflow = pe.Workflow(name='FUNCPIPE')
	inputnode = pe.Node(interface=util.IdentityInterface(fields=['fwhm','highpass','TR']),name='inputspec')

	inputnode.inputs.fwhm=FWHM
	inputnode.inputs.TR=TR
	inputnode.inputs.highpass=float(HIGHPASS/(inputnode.inputs.TR*2.5))


	#--- 5) Move to directory
	os.chdir(DICOMDIR)


	#--- 6) Set up converter node for conversion to nifti
	converter=pe.Node(interface=dcm2nii.Dcm2nii(),name='CONVERTED')
	converter.inputs.source_dir=DICOMDIR
	converter.inputs.gzip_output=bool(1)


	#--- 7) Set up realigner node to match orientation of MNI 152
	realigner=pe.Node(interface=fslu.Reorient2Std(),name='REORIENTED')
	realigner.inputs.output_type='NIFTI_GZ'

	workflow.connect(converter,'converted_files',realigner,'in_file')


	#--- 8) Set up a slice timing node
	slicetimer=pe.Node(interface=fslp.SliceTimer(),name='SLICETIMED')
	slicetimer.inputs.interleaved = True

	workflow.connect(inputnode, 'TR', slicetimer, 'time_repetition')
	workflow.connect(realigner, 'out_file', slicetimer, 'in_file')


	#--- 9) Convert to float.
	img2float = pe.Node(interface=fsl.ImageMaths(out_data_type='float',op_string='',suffix='_dtype'),name='IMG2FLOATED')

	workflow.connect(slicetimer,'slice_time_corrected_file',img2float,'in_file')

	#--- 10) Motion correct.
	motion_correct = pe.Node(interface=fsl.MCFLIRT(save_mats=True,save_plots=True,interpolation='spline'),name='MCORRECTED')

	workflow.connect(img2float, 'out_file', motion_correct, 'in_file')


	#--- 11) Despike
	despiker=pe.Node(interface=afni.Despike(),name='DESPIKED')
	despiker.inputs.outputtype = 'NIFTI_GZ'

	workflow.connect(motion_correct,'out_file',despiker,'in_file')

	#--- 12) Plot motion.
	plot_motion = pe.Node(interface=fsl.PlotMotionParams(in_source='fsl'),name='MOTIONPLOTTED')
	plot_motion.iterables = ('plot_type', ['rotations', 'translations'])

	workflow.connect(motion_correct, 'par_file', plot_motion, 'in_file')

	#--- 13) Extract
	extracter=pe.Node(interface=fsl.BET(),name='EXTRACTED')
	extracter.inputs.frac=float(frac)
	extracter.inputs.vertical_gradient=float(grad)
	extracter.inputs.mask=bool(1)
	extracter.inputs.functional=bool(1)

	workflow.connect(despiker, 'out_file', extracter, 'in_file')


	#--- 14) Smooth
	smoother=pe.MapNode(interface=afni.BlurInMask(),name='SMOOTHED',iterfield=['fwhm'])
	smoother.inputs.outputtype='NIFTI_GZ'

	workflow.connect(inputnode, 'fwhm', smoother, 'fwhm')
	workflow.connect(extracter, 'out_file', smoother, 'in_file')
	workflow.connect(extracter, 'mask_file', smoother, 'mask')


	#--- 15) Highpass filter

	# Filtering node
	highpass = pe.MapNode(interface=fsl.ImageMaths(suffix='_tempfilt'),name='HIGHPASSED',iterfield=['in_file'])

	workflow.connect(inputnode, ('highpass', highpass_operand), highpass, 'op_string')
	workflow.connect(smoother, 'out_file', highpass, 'in_file')

	#--- 16) Mean functional volume
	# Need to add back the mean removed by FSL
	meanfunc = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',suffix='_mean'),name='meanfunc',iterfield=['in_file'])
	workflow.connect(smoother, 'out_file', meanfunc, 'in_file')

	#--- 17) Add mean back to highpassed data (FINAL OUTPUT)
	addmean = pe.MapNode(interface=fsl.BinaryMaths(operation='add'),name='PREPROCESSED',iterfield=['in_file','operand_file'])

	workflow.connect(highpass, 'out_file', addmean, 'in_file')
	workflow.connect(meanfunc, 'out_file', addmean, 'operand_file')

	outputnode = pe.Node(interface=util.IdentityInterface(fields=['highpassed_files']),name='outputnode')

	workflow.connect(addmean, 'out_file', outputnode, 'highpassed_files')



	# Utility function for plotting extraction
	def bplot(in_file,in_file2,in_file3):
		from nilearn import image
		from nilearn import plotting
		import matplotlib
		niftifiledim=len(image.load_img(in_file).shape)
		firstim=image.index_img(in_file, 0)
		firstim2=image.index_img(in_file2, 0)
		display=plotting.plot_anat(firstim2)	
		display.add_contours(firstim,filled=True, alpha=0.5,levels=[0.2], colors='b')
		display.add_edges(in_file3)
		matplotlib.pyplot.show()
		return niftifiledim

	#--- 18) Show extraction
	showextract= pe.Node(Function(input_names=['in_file','in_file2','in_file3'],output_names=['niftifiledim'],function=bplot),name='SHOWEXTRACT')

	workflow.connect(despiker,'out_file', showextract,'in_file2')
	workflow.connect(extracter,'out_file', showextract,'in_file')
	workflow.connect(extracter,'mask_file', showextract,'in_file3')

	# Utility function for plotting extraction
	def splot(in_file):
		from nilearn import image
		from nilearn import plotting
		import matplotlib
		niftifiledim=len(image.load_img(in_file).shape)
		firstim=image.index_img(in_file, 0)
		display=plotting.plot_anat(firstim,display_mode='z',cut_coords=10)
		matplotlib.pyplot.show()	
		return niftifiledim

	#--- 19) Show smoothing
	showsmooth= pe.MapNode(Function(input_names=['in_file'],output_names=['niftifiledim'],function=splot),iterfield=['in_file'],name='SHOWSMOOTH')

	workflow.connect(smoother,'out_file', showsmooth,'in_file')



	#--- 20) Mean functional volume (for plotting stats)
	meanfunc2 = pe.Node(interface=fsl.ImageMaths(op_string='-Tmean',suffix='_mean'),name='MEANFUNCTIONAL')
	workflow.connect(extracter, 'out_file', meanfunc2, 'in_file')
	workflow.connect(meanfunc2, 'out_file', outputnode, 'mean_functional_volume')

	#--- 21) Plot workflow
	workflow.base_dir = DICOMDIR
	workflow.write_graph(graph2use='exec')

	#--- 22) Plot workflow
	result=workflow.run()

	#--- 23) Show plots
	

	#--- 24) Return to initial working directory
	print ("Workflow completed. Returning to intital directory\n")
	os.chdir(INITDIR)
Beispiel #5
0
realign_flow = Workflow(name='realign_flow')
realign_inputnode = Node(IdentityInterface(fields=['func']), name='inputspec')
realign_outputnode = Node(IdentityInterface(fields=[
    'realigned_file', 'transformation_matrices', 'motion_parameters',
    'displacement_parameters', 'motion_plots'
]),
                          name='outputspec')

realigner = Node(fsl.MCFLIRT(save_mats=True, stats_imgs=True, save_plots=True),
                 name='realigner')
splitter = Node(fsl.Split(dimension='t'), name='splitter')
warper = MapNode(fsl.ApplyWarp(interp='spline'),
                 iterfield=['in_file', 'premat'],
                 name='warper')
joiner = Node(fsl.Merge(dimension='t'), name='joiner')
plot_motion = Node(fsl.PlotMotionParams(in_source='fsl'), name='plot_motion')
plot_motion.iterables = ('plot_type', ['rotations', 'translations'])

realign_flow.connect(realign_inputnode, 'func', realigner, 'in_file')
realign_flow.connect(realign_inputnode, ('func', select_volume, 'middle'),
                     realigner, 'ref_vol')
realign_flow.connect(realigner, 'out_file', splitter, 'in_file')
realign_flow.connect(realigner, 'mat_file', warper, 'premat')
realign_flow.connect(realigner, 'variance_img', warper, 'ref_file')
realign_flow.connect(realigner, 'par_file', plot_motion, 'in_file')
realign_flow.connect(splitter, 'out_files', warper, 'in_file')
realign_flow.connect(warper, 'out_file', joiner, 'in_files')
realign_flow.connect(joiner, 'merged_file', realign_outputnode,
                     'realigned_file')
realign_flow.connect(realigner, 'mat_file', realign_outputnode,
                     'transformation_matrices')
Beispiel #6
0
def func_preproc_fsl(wf_name='func_preproc'):

    featpreproc = pe.Workflow(name=wf_name)
    """
        Set up a node to define all inputs required for the preprocessing workflow

    """

    inputnode = pe.Node(interface=util.IdentityInterface(
        fields=['in_file', 'anat_brain'], mandatory_inputs=True),
                        name='inputspec')

    # preprocessed_func: upscaled, brain-extracted and motion corrected functional data
    outputnode = pe.Node(interface=util.IdentityInterface(
        fields=[
            'preprocessed_func', 'example_func', 'func_brain_mask',
            'motion_plots', 'func2anat_mat'
        ],
        mandatory_inputs=True),
                         name='outputspec')
    """
        Reorient data to match Paxinos

    """

    reorient = pe.MapNode(interface=fsl.utils.SwapDimensions(new_dims=("RL",
                                                                       "AP",
                                                                       "IS")),
                          name='reorient',
                          iterfield=['in_file'])
    featpreproc.connect(inputnode, 'in_file', reorient, 'in_file')
    """
    Upscale data to human range

    """

    upscaler = mine.upscale()
    featpreproc.connect(reorient, 'out_file', upscaler, 'inputspec.in_file')
    """
    Convert functional images to float representation. Since there can
    be more than one functional run we use a MapNode to convert each
    run.
    """

    img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float',
                                                    op_string='',
                                                    suffix='_dtype'),
                           iterfield=['in_file'],
                           name='img2float')
    featpreproc.connect(upscaler, 'outputspec.out_file', img2float, 'in_file')
    """
    Extract the first volume of the first run as the reference
    """

    extract_ref = pe.MapNode(interface=fsl.ExtractROI(t_size=1),
                             iterfield=['in_file', 't_min'],
                             name='extractref')

    featpreproc.connect(img2float, 'out_file', extract_ref, 'in_file')
    featpreproc.connect(img2float, ('out_file', pickmiddle), extract_ref,
                        't_min')
    featpreproc.connect(extract_ref, 'roi_file', outputnode, 'example_func')
    """
    Realign the functional runs to the reference (1st volume of first run)
    """

    motion_correct = pe.MapNode(interface=fsl.MCFLIRT(save_mats=True,
                                                      save_plots=True),
                                name='motioncorr',
                                iterfield=['in_file', 'ref_file'])
    featpreproc.connect(img2float, 'out_file', motion_correct, 'in_file')
    featpreproc.connect(extract_ref, 'roi_file', motion_correct, 'ref_file')
    featpreproc.connect(motion_correct, 'par_file', outputnode,
                        'motion_parameters')
    featpreproc.connect(motion_correct, 'out_file', outputnode,
                        'realigned_files')
    """
    Plot the estimated motion parameters
    """

    plot_motion = pe.MapNode(interface=fsl.PlotMotionParams(in_source='fsl'),
                             name='plot_motion',
                             iterfield=['in_file'])
    plot_motion.iterables = ('plot_type',
                             ['displacement', 'rotations', 'translations'])
    featpreproc.connect(motion_correct, 'par_file', plot_motion, 'in_file')
    featpreproc.connect(plot_motion, 'out_file', outputnode, 'motion_plots')
    """
    Extract the mean volume of the first functional run
    """

    meanfunc = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',
                                                   suffix='_mean'),
                          iterfield=['in_file'],
                          name='meanfunc')
    featpreproc.connect(motion_correct, 'out_file', meanfunc, 'in_file')
    """
    estimate func2anat matrix
    """
    f2a = pe.MapNode(util.Function(input_names=['in_file', 'like'],
                                   output_names=['out_mat'],
                                   function=myfsl.utils.run_resample),
                     name='func2anat',
                     iterfield=['in_file', 'like'])

    featpreproc.connect(meanfunc, 'out_file', f2a, 'in_file')
    featpreproc.connect(inputnode, 'anat_brain', f2a, 'like')
    featpreproc.connect(f2a, 'out_mat', outputnode, 'func2anat_mat')
    """
    Invert func2anat matrix
    """

    invertmat = pe.MapNode(interface=fsl.ConvertXFM(invert_xfm=True),
                           iterfield=['in_file'],
                           name='invertmat')

    featpreproc.connect(f2a, 'out_mat', invertmat, 'in_file')
    """
    Resample the anatomical brain mask to the space of functional image
    """

    resamplemask = pe.MapNode(
        interface=fsl.ApplyXfm(interp='nearestneighbour'),
        iterfield=['reference', 'in_file', 'in_matrix_file'],
        name='resamplemask')

    featpreproc.connect(inputnode, 'anat_brain', resamplemask, 'in_file')
    featpreproc.connect(meanfunc, 'out_file', resamplemask, 'reference')
    featpreproc.connect(invertmat, 'out_file', resamplemask, 'in_matrix_file')
    """
    Mask the functional runs with the resampled mask
    """

    maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet',
                                                   op_string='-mas'),
                          iterfield=['in_file', 'in_file2'],
                          name='maskfunc')
    featpreproc.connect(motion_correct, 'out_file', maskfunc, 'in_file')
    featpreproc.connect(resamplemask, 'out_file', maskfunc, 'in_file2')
    """
    Determine the 2nd and 98th percentile intensities of each functional run
    """

    getthresh = pe.MapNode(interface=fsl.ImageStats(op_string='-p 2 -p 98'),
                           iterfield=['in_file'],
                           name='getthreshold')
    featpreproc.connect(maskfunc, 'out_file', getthresh, 'in_file')
    """
    Threshold the first run of the functional data at 10% of the 98th percentile
    """

    threshold = pe.MapNode(interface=fsl.ImageMaths(out_data_type='char',
                                                    suffix='_thresh'),
                           iterfield=['in_file', 'op_string'],
                           name='threshold')
    featpreproc.connect(maskfunc, 'out_file', threshold, 'in_file')
    """
    Define a function to get 10% of the intensity
    """

    featpreproc.connect(getthresh, ('out_stat', getthreshop), threshold,
                        'op_string')
    featpreproc.connect(threshold, 'out_file', outputnode, 'func_brain_mask')

    #"""
    #Determine the median value of the functional runs using the mask
    #"""

    #medianval = pe.MapNode(interface=fsl.ImageStats(op_string='-k %s -p 50'),
    #                       iterfield=['in_file', 'mask_file'],
    #                       name='medianval')
    #featpreproc.connect(motion_correct, 'out_file', medianval, 'in_file')
    #featpreproc.connect(threshold, 'out_file', medianval, 'mask_file')

    #"""
    #Dilate the mask
    #"""

    #dilatemask = pe.MapNode(interface=fsl.ImageMaths(suffix='_dil',
    #                                                 op_string='-dilF'),
    #                        iterfield=['in_file'],
    #                        name='dilatemask')
    #featpreproc.connect(threshold, 'out_file', dilatemask, 'in_file')
    """
    Mask the motion corrected functional runs with the dilated mask
    """

    maskfunc2 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                           iterfield=['in_file', 'in_file2'],
                           name='maskfunc2')
    featpreproc.connect(motion_correct, 'out_file', maskfunc2, 'in_file')
    featpreproc.connect(threshold, 'out_file', maskfunc2, 'in_file2')
    #featpreproc.connect(dilatemask, 'out_file', maskfunc2, 'in_file2')

    featpreproc.connect(maskfunc2, 'out_file', outputnode, 'preprocessed_func')

    return featpreproc
Beispiel #7
0
def mc_workflow_fsl(reference_vol="mid",
                    FD_mode="Power",
                    SinkTag="func_preproc",
                    wf_name="motion_correction_fsl"):
    """
    Modified version of CPAC.func_preproc.func_preproc and CPAC.generate_motion_statistics.generate_motion_statistics:

    `source: https://fcp-indi.github.io/docs/developer/_modules/CPAC/func_preproc/func_preproc.html`
    `source: https://fcp-indi.github.io/docs/developer/_modules/CPAC/generate_motion_statistics/generate_motion_statistics.html`

    Use FSL MCFLIRT to do the motion correction of the 4D functional data and use the 6df rigid body motion parameters to calculate friston24 parameters
    for later nuissance regression step.

    Workflow inputs:
        :param func: The reoriented functional file.
        :param reference_vol: Either "first", "mid", "last", "mean", or the index of the volume which the rigid body registration (motion correction) will use as reference.
        default: "mid"
        :param FD_mode Eiher "Power" or "Jenkinson"
        :param SinkDir:
        :param SinkTag: The output directory in which the returned images (see workflow outputs) could be found in a subdirectory directory specific for this workflow..

    Workflow outputs:




        :return: mc_workflow - workflow




    Balint Kincses
    [email protected]
    2018


    """
    # TODO_ready nipype has the ability to calculate FD: the function from CPAC calculates it correctly
    # import relevant packages
    import sys
    import os
    import nipype
    import nipype.pipeline as pe
    import nipype.interfaces.utility as utility
    import nipype.interfaces.fsl as fsl
    import nipype.algorithms.confounds as conf
    import PUMI.func_preproc.info.info_get as info_get
    import nipype.interfaces.io as io
    import PUMI.utils.utils_math as utils_math
    import PUMI.utils.utils_convert as utils_convert
    import PUMI.utils.globals as globals
    import PUMI.utils.QC as qc

    SinkDir = os.path.abspath(globals._SinkDir_ + "/" + SinkTag)
    if not os.path.exists(SinkDir):
        os.makedirs(SinkDir)
    QCDir = os.path.abspath(globals._SinkDir_ + "/" + globals._QCDir_)
    if not os.path.exists(QCDir):
        os.makedirs(QCDir)

    # Basic interface class generates identity mappings
    inputspec = pe.Node(utility.IdentityInterface(
        fields=['func', 'ref_vol', 'save_plots', 'stats_imgs']),
                        name='inputspec')
    inputspec.inputs.save_plots = True
    inputspec.inputs.stats_imgs = True
    inputspec.inputs.ref_vol = reference_vol

    # todo_ready: make parametrizable: the reference_vol variable is an argumentum of the mc_workflow

    # extract reference volume
    refvol = pe.MapNode(utility.Function(input_names=['refvol', 'func'],
                                         output_names=['refvol'],
                                         function=getRefVol),
                        iterfield=['func'],
                        name='getRefVol')

    # Wraps command **mcflirt**
    mcflirt = pe.MapNode(
        interface=fsl.MCFLIRT(
            interpolation="spline",
            stats_imgs=False),  # stages=4), #stages 4: more accurate but slow
        iterfield=['in_file',
                   'ref_file'],  # , 'ref_vol'], # make parametrizable
        name='mcflirt')

    if (reference_vol == "mean"):
        mcflirt = pe.MapNode(
            interface=fsl.MCFLIRT(interpolation="spline", stats_imgs=False),
            # stages=4), #stages 4: more accurate but slow
            iterfield=['in_file'],  # , 'ref_vol'], # make parametrizable
            name='mcflirt')
        mcflirt.inputs.mean_vol = True
    else:
        mcflirt = pe.MapNode(
            interface=fsl.MCFLIRT(interpolation="spline", stats_imgs=False),
            # stages=4), #stages 4: more accurate but slow
            iterfield=['in_file',
                       'ref_file'],  # , 'ref_vol'], # make parametrizable
            name='mcflirt')

    mcflirt.inputs.dof = 6
    mcflirt.inputs.save_mats = True
    mcflirt.inputs.save_plots = True
    mcflirt.inputs.save_rms = True
    mcflirt.inputs.stats_imgs = False

    myqc = qc.timecourse2png("timeseries", tag="010_motioncorr")

    # Calculate Friston24 parameters
    calc_friston = pe.MapNode(utility.Function(
        input_names=['in_file'],
        output_names=['out_file'],
        function=calc_friston_twenty_four),
                              iterfield=['in_file'],
                              name='calc_friston')

    # Calculate FD based on Power's method
    if FD_mode == "Power":
        calculate_FD = pe.MapNode(conf.FramewiseDisplacement(
            parameter_source='FSL', save_plot=True),
                                  iterfield=['in_file'],
                                  name='calculate_FD_Power')
    elif FD_mode == "Jenkinson":
        calculate_FD = pe.MapNode(utility.Function(input_names=['in_file'],
                                                   output_names=['out_file'],
                                                   function=calculate_FD_J),
                                  iterfield=['in_file'],
                                  name='calculate_FD_Jenkinson')

    # compute mean and max FD
    meanFD = pe.MapNode(interface=utils_math.Txt2meanTxt,
                        iterfield=['in_file'],
                        name='meanFD')
    meanFD.inputs.axis = 0  # global mean
    meanFD.inputs.header = True  # global mean

    maxFD = pe.MapNode(interface=utils_math.Txt2maxTxt,
                       iterfield=['in_file'],
                       name='maxFD')
    maxFD.inputs.axis = 0  # global mean
    maxFD.inputs.header = True

    pop_FD = pe.Node(interface=utils_convert.List2TxtFileOpen, name='pop_FD')
    pop_FDmax = pe.Node(interface=utils_convert.List2TxtFileOpen,
                        name='pop_FDmax')

    # save data out with Datasink
    ds_fd = pe.Node(interface=io.DataSink(), name='ds_pop_fd')
    ds_fd.inputs.regexp_substitutions = [("(\/)[^\/]*$", "FD.txt")]
    ds_fd.inputs.base_directory = SinkDir

    # save data out with Datasink
    ds_fd_max = pe.Node(interface=io.DataSink(), name='ds_pop_fd_max')
    ds_fd_max.inputs.regexp_substitutions = [("(\/)[^\/]*$", "FD_max.txt")]
    ds_fd_max.inputs.base_directory = SinkDir

    plot_motion_rot = pe.MapNode(
        interface=fsl.PlotMotionParams(in_source='fsl'),
        name='plot_motion_rot',
        iterfield=['in_file'])
    plot_motion_rot.inputs.plot_type = 'rotations'

    plot_motion_tra = pe.MapNode(
        interface=fsl.PlotMotionParams(in_source='fsl'),
        name='plot_motion_trans',
        iterfield=['in_file'])
    plot_motion_tra.inputs.plot_type = 'translations'

    # Basic interface class generates identity mappings
    outputspec = pe.Node(utility.IdentityInterface(fields=[
        'func_out_file', 'first24_file', 'mat_file', 'mc_par_file', 'FD_file'
    ]),
                         name='outputspec')

    # save data out with Datasink
    ds_nii = pe.Node(interface=io.DataSink(), name='ds_nii')
    ds_nii.inputs.regexp_substitutions = [("(\/)[^\/]*$", ".nii.gz")]
    ds_nii.inputs.base_directory = SinkDir

    # save data out with Datasink
    ds_text = pe.Node(interface=io.DataSink(), name='ds_txt')
    ds_text.inputs.regexp_substitutions = [("(\/)[^\/]*$", ".txt")]
    ds_text.inputs.base_directory = SinkDir

    # Save outputs which are important
    ds_qc_fd = pe.Node(interface=io.DataSink(), name='ds_qc_fd')
    ds_qc_fd.inputs.base_directory = QCDir
    ds_qc_fd.inputs.regexp_substitutions = [("(\/)[^\/]*$", "_FD.pdf")]

    # Save outputs which are important
    ds_qc_rot = pe.Node(interface=io.DataSink(), name='ds_qc_rot')
    ds_qc_rot.inputs.base_directory = QCDir
    ds_qc_rot.inputs.regexp_substitutions = [("(\/)[^\/]*$", "_rot.png")]

    # Save outputs which are important
    ds_qc_tra = pe.Node(interface=io.DataSink(), name='ds_qc_tra')
    ds_qc_tra.inputs.base_directory = QCDir
    ds_qc_tra.inputs.regexp_substitutions = [("(\/)[^\/]*$", "_trans.png")]

    #TODO_ready set the proper images which has to be saved in a the datasink specified directory
    # Create a workflow to connect all those nodes
    analysisflow = nipype.Workflow(wf_name)
    analysisflow.connect(inputspec, 'func', mcflirt, 'in_file')
    analysisflow.connect(inputspec, 'func', refvol, 'func')
    analysisflow.connect(inputspec, 'ref_vol', refvol, 'refvol')
    if (reference_vol != "mean"):
        analysisflow.connect(refvol, 'refvol', mcflirt, 'ref_file')
    analysisflow.connect(mcflirt, 'par_file', calc_friston, 'in_file')
    analysisflow.connect(mcflirt, 'par_file', calculate_FD, 'in_file')

    analysisflow.connect(mcflirt, 'out_file', outputspec, 'func_out_file')
    analysisflow.connect(mcflirt, 'mat_file', outputspec, 'mat_file')
    analysisflow.connect(mcflirt, 'par_file', outputspec, 'mc_par_file')
    analysisflow.connect(mcflirt, 'out_file', ds_nii, 'mc_func')
    analysisflow.connect(mcflirt, 'par_file', ds_text, 'mc_par')
    #analysisflow.connect(mcflirt, 'std_img', ds, 'mc.@std_img')
    analysisflow.connect(mcflirt, 'rms_files', ds_text, 'mc_rms')
    #analysisflow.connect(mcflirt, 'variance_img', ds, 'mc.@variance_img')
    analysisflow.connect(calc_friston, 'out_file', outputspec, 'first24_file')
    analysisflow.connect(calc_friston, 'out_file', ds_text, 'mc_first24')
    analysisflow.connect(calculate_FD, 'out_file', outputspec, 'FD_file')
    analysisflow.connect(mcflirt, 'par_file', plot_motion_rot, 'in_file')
    analysisflow.connect(mcflirt, 'par_file', plot_motion_tra, 'in_file')
    analysisflow.connect(plot_motion_rot, 'out_file', ds_qc_rot,
                         'motion_correction')
    analysisflow.connect(plot_motion_tra, 'out_file', ds_qc_tra,
                         'motion_correction')
    analysisflow.connect(mcflirt, 'out_file', myqc, 'inputspec.func')
    # pop-level mean FD
    analysisflow.connect(calculate_FD, 'out_file', meanFD, 'in_file')
    analysisflow.connect(calculate_FD, 'out_file', ds_text, 'mc_fd')
    analysisflow.connect(calculate_FD, 'out_figure', ds_qc_fd, 'FD')
    analysisflow.connect(meanFD, 'mean_file', pop_FD, 'in_list')
    analysisflow.connect(pop_FD, 'txt_file', ds_fd, 'pop')

    analysisflow.connect(calculate_FD, 'out_file', maxFD, 'in_file')
    analysisflow.connect(maxFD, 'max_file', pop_FDmax, 'in_list')
    analysisflow.connect(pop_FDmax, 'txt_file', ds_fd_max, 'pop')

    return analysisflow
Beispiel #8
0
def create_fsl_fs_preproc(name='preproc', highpass=True, whichvol='middle'):
    """Create a FEAT preprocessing workflow together with freesurfer

    Parameters
    ----------

    ::

        name : name of workflow (default: preproc)
        highpass : boolean (default: True)
        whichvol : which volume of the first run to register to ('first', 'middle', 'mean')

    Inputs::

        inputspec.func : functional runs (filename or list of filenames)
        inputspec.fwhm : fwhm for smoothing with SUSAN
        inputspec.highpass : HWHM in TRs (if created with highpass=True)
        inputspec.subject_id : freesurfer subject id
        inputspec.subjects_dir : freesurfer subjects dir

    Outputs::

        outputspec.reference : volume to which runs are realigned
        outputspec.motion_parameters : motion correction parameters
        outputspec.realigned_files : motion corrected files
        outputspec.motion_plots : plots of motion correction parameters
        outputspec.mask_file : mask file used to mask the brain
        outputspec.smoothed_files : smoothed functional data
        outputspec.highpassed_files : highpassed functional data (if highpass=True)
        outputspec.reg_file : bbregister registration files
        outputspec.reg_cost : bbregister registration cost files

    Example
    -------

    >>> preproc = create_fsl_fs_preproc(whichvol='first')
    >>> preproc.inputs.inputspec.highpass = 128./(2*2.5)
    >>> preproc.inputs.inputspec.func = ['f3.nii', 'f5.nii']
    >>> preproc.inputs.inputspec.subjects_dir = '.'
    >>> preproc.inputs.inputspec.subject_id = 's1'
    >>> preproc.inputs.inputspec.fwhm = 6
    >>> preproc.run() # doctest: +SKIP
    """

    featpreproc = pe.Workflow(name=name)

    """
    Set up a node to define all inputs required for the preprocessing workflow

    """

    if highpass:
        inputnode = pe.Node(interface=util.IdentityInterface(fields=['func',
                                                                     'fwhm',
                                                                     'subject_id',
                                                                     'subjects_dir',
                                                                     'highpass']),
                            name='inputspec')
        outputnode = pe.Node(interface=util.IdentityInterface(fields=['reference',
                                                                  'motion_parameters',
                                                                  'realigned_files',
                                                                  'motion_plots',
                                                                  'mask_file',
                                                                  'smoothed_files',
                                                                  'highpassed_files',
                                                                  'reg_file',
                                                                  'reg_cost'
                                                                  ]),
                         name='outputspec')
    else:
        inputnode = pe.Node(interface=util.IdentityInterface(fields=['func',
                                                                     'fwhm',
                                                                     'subject_id',
                                                                     'subjects_dir'
                                                                     ]),
                            name='inputspec')
        outputnode = pe.Node(interface=util.IdentityInterface(fields=['reference',
                                                                  'motion_parameters',
                                                                  'realigned_files',
                                                                  'motion_plots',
                                                                  'mask_file',
                                                                  'smoothed_files',
                                                                  'reg_file',
                                                                  'reg_cost'
                                                                  ]),
                         name='outputspec')

    """
    Set up a node to define outputs for the preprocessing workflow

    """

    """
    Convert functional images to float representation. Since there can
    be more than one functional run we use a MapNode to convert each
    run.
    """

    img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float',
                                                 op_string = '',
                                                 suffix='_dtype'),
                           iterfield=['in_file'],
                           name='img2float')
    featpreproc.connect(inputnode, 'func', img2float, 'in_file')


    """
    Extract the first volume of the first run as the reference
    """

    if whichvol != 'mean':
        extract_ref = pe.Node(interface=fsl.ExtractROI(t_size=1),
                                 iterfield=['in_file'],
                                 name = 'extractref')
        featpreproc.connect(img2float, ('out_file', pickfirst), extract_ref, 'in_file')
        featpreproc.connect(img2float, ('out_file', pickvol, 0, whichvol), extract_ref, 't_min')
        featpreproc.connect(extract_ref, 'roi_file', outputnode, 'reference')


    """
    Realign the functional runs to the reference (1st volume of first run)
    """

    motion_correct = pe.MapNode(interface=fsl.MCFLIRT(save_mats = True,
                                                      save_plots = True,
                                                      interpolation = 'sinc'),
                                name='realign',
                                iterfield = ['in_file'])
    featpreproc.connect(img2float, 'out_file', motion_correct, 'in_file')
    if whichvol != 'mean':
        featpreproc.connect(extract_ref, 'roi_file', motion_correct, 'ref_file')
    else:
        motion_correct.inputs.mean_vol = True
        featpreproc.connect(motion_correct, 'mean_img', outputnode, 'reference')

    featpreproc.connect(motion_correct, 'par_file', outputnode, 'motion_parameters')
    featpreproc.connect(motion_correct, 'out_file', outputnode, 'realigned_files')

    """
    Plot the estimated motion parameters
    """

    plot_motion = pe.MapNode(interface=fsl.PlotMotionParams(in_source='fsl'),
                            name='plot_motion',
                            iterfield=['in_file'])
    plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
    featpreproc.connect(motion_correct, 'par_file', plot_motion, 'in_file')
    featpreproc.connect(plot_motion, 'out_file', outputnode, 'motion_plots')

    """Get the mask from subject for each run
    """

    maskflow = create_getmask_flow()
    featpreproc.connect([(inputnode, maskflow, [('subject_id','inputspec.subject_id'),
                                             ('subjects_dir', 'inputspec.subjects_dir')])])
    maskflow.inputs.inputspec.contrast_type = 't2'
    if whichvol != 'mean':
        featpreproc.connect(extract_ref, 'roi_file', maskflow, 'inputspec.source_file')
    else:
        featpreproc.connect(motion_correct, ('mean_img', pickfirst), maskflow, 'inputspec.source_file')


    """
    Mask the functional runs with the extracted mask
    """

    maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet',
                                                   op_string='-mas'),
                          iterfield=['in_file'],
                          name = 'maskfunc')
    featpreproc.connect(motion_correct, 'out_file', maskfunc, 'in_file')
    featpreproc.connect(maskflow, ('outputspec.mask_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 consituting the mean
    functional
    """

    smooth = create_susan_smooth(separate_masks=False)

    featpreproc.connect(inputnode, 'fwhm', smooth, 'inputnode.fwhm')
    featpreproc.connect(maskfunc, 'out_file', smooth, 'inputnode.in_files')
    featpreproc.connect(maskflow, ('outputspec.mask_file', pickfirst), smooth, 'inputnode.mask_file')

    """
    Mask the smoothed data with the dilated mask
    """

    maskfunc3 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                          iterfield=['in_file'],
                          name='maskfunc3')
    featpreproc.connect(smooth, 'outputnode.smoothed_files', maskfunc3, 'in_file')
    featpreproc.connect(maskflow, ('outputspec.mask_file', pickfirst), maskfunc3, 'in_file2')


    concatnode = pe.Node(interface=util.Merge(2),
                         name='concat')
    featpreproc.connect(maskfunc, ('out_file', tolist), concatnode, 'in1')
    featpreproc.connect(maskfunc3, ('out_file', tolist), concatnode, 'in2')

    """
    The following nodes select smooth or unsmoothed data depending on the
    fwhm. This is because SUSAN defaults to smoothing the data with about the
    voxel size of the input data if the fwhm parameter is less than 1/3 of the
    voxel size.
    """
    selectnode = pe.Node(interface=util.Select(),name='select')

    featpreproc.connect(concatnode, 'out', selectnode, 'inlist')

    featpreproc.connect(inputnode, ('fwhm', chooseindex), selectnode, 'index')
    featpreproc.connect(selectnode, 'out', outputnode, 'smoothed_files')


    """
    Scale the median value of the run is set to 10000
    """

    meanscale = pe.MapNode(interface=fsl.ImageMaths(suffix='_gms'),
                          iterfield=['in_file','op_string'],
                          name='meanscale')
    featpreproc.connect(selectnode, 'out', meanscale, 'in_file')

    """
    Determine the median value of the functional runs using the mask
    """

    medianval = pe.MapNode(interface=fsl.ImageStats(op_string='-k %s -p 50'),
                           iterfield = ['in_file'],
                           name='medianval')
    featpreproc.connect(motion_correct, 'out_file', medianval, 'in_file')
    featpreproc.connect(maskflow, ('outputspec.mask_file', pickfirst), medianval, 'mask_file')

    """
    Define a function to get the scaling factor for intensity normalization
    """

    featpreproc.connect(medianval, ('out_stat', getmeanscale), meanscale, 'op_string')

    """
    Perform temporal highpass filtering on the data
    """

    if highpass:
        highpass = pe.MapNode(interface=fsl.ImageMaths(suffix='_tempfilt'),
                              iterfield=['in_file'],
                              name='highpass')
        featpreproc.connect(inputnode, ('highpass', highpass_operand), highpass, 'op_string')
        featpreproc.connect(meanscale, 'out_file', highpass, 'in_file')
        featpreproc.connect(highpass, 'out_file', outputnode, 'highpassed_files')

    featpreproc.connect(maskflow, ('outputspec.mask_file', pickfirst), outputnode, 'mask_file')
    featpreproc.connect(maskflow, 'outputspec.reg_file', outputnode, 'reg_file')
    featpreproc.connect(maskflow, 'outputspec.reg_cost', outputnode, 'reg_cost')

    return featpreproc
Beispiel #9
0
def create_moco_pipeline(working_dir, ds_dir, name='motion_correction'):
    """
    Workflow for motion correction to 1st volume
    based on https://github.com/NeuroanatomyAndConnectivity/pipelines/blob/master/src/lsd_lemon/func_preproc/moco.py
    """

    # initiate workflow
    moco_wf = Workflow(name=name)
    moco_wf.base_dir = os.path.join(working_dir, 'LeiCA_resting',
                                    'rsfMRI_preprocessing')

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

    # I/O NODES
    inputnode = Node(util.IdentityInterface(fields=['epi', 'vols_to_drop']),
                     name='inputnode')

    outputnode = Node(util.IdentityInterface(fields=[
        'epi_moco', 'par_moco', 'mat_moco', 'rms_moco',
        'initial_mean_epi_moco', 'rotplot', 'transplot', 'dispplots',
        'tsnr_file', 'epi_mask'
    ]),
                      name='outputnode')

    ds = Node(nio.DataSink(base_directory=ds_dir), name='ds')
    ds.inputs.substitutions = [('_TR_id_', 'TR_')]

    # REMOVE FIRST VOLUMES
    drop_vols = Node(util.Function(input_names=['in_file', 't_min'],
                                   output_names=['out_file'],
                                   function=strip_rois_func),
                     name='remove_vol')

    moco_wf.connect(inputnode, 'epi', drop_vols, 'in_file')
    moco_wf.connect(inputnode, 'vols_to_drop', drop_vols, 't_min')

    # MCFILRT MOCO TO 1st VOLUME
    mcflirt = Node(fsl.MCFLIRT(save_mats=True,
                               save_plots=True,
                               save_rms=True,
                               ref_vol=0,
                               out_file='rest_realigned.nii.gz'),
                   name='mcflirt')

    moco_wf.connect(drop_vols, 'out_file', mcflirt, 'in_file')
    moco_wf.connect([(mcflirt, ds, [('par_file', 'realign.par.@par'),
                                    ('mat_file', 'realign.MAT.@mat'),
                                    ('rms_files', 'realign.plots.@rms')])])
    moco_wf.connect([(mcflirt, outputnode, [('out_file', 'epi_moco'),
                                            ('par_file', 'par_moco'),
                                            ('mat_file', 'mat_moco'),
                                            ('rms_files', 'rms_moco')])])

    # CREATE MEAN EPI (INTENSITY NORMALIZED)
    initial_mean_epi_moco = Node(fsl.maths.MeanImage(
        dimension='T', out_file='initial_mean_epi_moco.nii.gz'),
                                 name='initial_mean_epi_moco')
    moco_wf.connect(mcflirt, 'out_file', initial_mean_epi_moco, 'in_file')
    moco_wf.connect(initial_mean_epi_moco, 'out_file', outputnode,
                    'initial_mean_epi_moco')
    moco_wf.connect(initial_mean_epi_moco, 'out_file', ds,
                    'QC.initial_mean_epi_moco')

    # PLOT MOTION PARAMETERS
    rotplotter = Node(fsl.PlotMotionParams(in_source='fsl',
                                           plot_type='rotations',
                                           out_file='rotation_plot.png'),
                      name='rotplotter')

    moco_wf.connect(mcflirt, 'par_file', rotplotter, 'in_file')
    moco_wf.connect(rotplotter, 'out_file', ds, 'realign.plots.@rotplot')

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

    moco_wf.connect(mcflirt, 'par_file', transplotter, 'in_file')
    moco_wf.connect(transplotter, 'out_file', ds, 'realign.plots.@transplot')

    dispplotter = MapNode(interface=fsl.PlotMotionParams(
        in_source='fsl', plot_type='displacement'),
                          name='dispplotter',
                          iterfield=['in_file'])
    dispplotter.iterables = ('plot_type', ['displacement'])

    moco_wf.connect(mcflirt, 'rms_files', dispplotter, 'in_file')
    moco_wf.connect(dispplotter, 'out_file', ds, 'realign.plots.@dispplots')

    moco_wf.write_graph(dotfilename=moco_wf.name,
                        graph2use='flat',
                        format='pdf')

    return moco_wf
#Wraps command **flirt**
NodeHash_8f61130 = pe.MapNode(interface = fsl.FLIRT(), name = 'NodeName_8f61130', iterfield = ['in_file', 'in_matrix_file', 'reference', 'wm_seg'])
NodeHash_8f61130.inputs.cost = 'bbr'
NodeHash_8f61130.inputs.dof = 6
NodeHash_8f61130.inputs.no_resample = True

#Wraps command **mcflirt**
NodeHash_c3ef3c0 = pe.MapNode(interface = fsl.MCFLIRT(), name = 'NodeName_c3ef3c0', iterfield = ['in_file', 'ref_file'])
NodeHash_c3ef3c0.inputs.interpolation = 'spline'
NodeHash_c3ef3c0.inputs.save_mats = True
NodeHash_c3ef3c0.inputs.save_plots = True
NodeHash_c3ef3c0.inputs.save_rms = True

#Wraps command **fsl_tsplot**
NodeHash_c4a9c30 = pe.MapNode(interface = fsl.PlotMotionParams(), name = 'NodeName_c4a9c30', iterfield = ['in_file'])
NodeHash_c4a9c30.inputs.args = '-a x,y,z -w 640 -h 144'
NodeHash_c4a9c30.inputs.in_source = 'fsl'
NodeHash_c4a9c30.iterables = [('plot_type', ['rotations', 'translations'])]

#Wraps command **fslmaths**
NodeHash_1040c610 = pe.MapNode(interface = fsl.MeanImage(), name = 'NodeName_1040c610', iterfield = ['in_file'])
NodeHash_1040c610.inputs.dimension = 'T'

#Wraps command **bet**
NodeHash_1212d0d0 = pe.MapNode(interface = fsl.BET(), name = 'NodeName_1212d0d0', iterfield = ['in_file'])
NodeHash_1212d0d0.inputs.frac = 0.3
NodeHash_1212d0d0.inputs.mask = True
NodeHash_1212d0d0.inputs.no_output = True

#Wraps command **fslmaths**
Beispiel #11
0
def create_motion_correction_workflow(name='moco',
                                      method='AFNI',
                                      extend_moco_params=False):
    """uses sub-workflows to perform different registration steps.
    Requires fsl and freesurfer tools
    Parameters
    ----------
    name : string
        name of workflow

    Example
    -------
    >>> motion_correction_workflow = create_motion_correction_workflow('motion_correction_workflow')
    >>> motion_correction_workflow.inputs.inputspec.output_directory = '/data/project/raw/BIDS/sj_1/'
    >>> motion_correction_workflow.inputs.inputspec.in_files = ['sub-001.nii.gz','sub-002.nii.gz']
    >>> motion_correction_workflow.inputs.inputspec.which_file_is_EPI_space = 'middle'

    Inputs::
          inputspec.output_directory : directory in which to sink the result files
          inputspec.in_files : list of functional files
          inputspec.which_file_is_EPI_space : determines which file is the 'standard EPI space'
    Outputs::
           outputspec.EPI_space_file : standard EPI space file, one timepoint
           outputspec.motion_corrected_files : motion corrected files
           outputspec.motion_correction_plots : motion correction plots
           outputspec.motion_correction_parameters : motion correction parameters
    """

    ### NODES
    input_node = pe.Node(IdentityInterface(fields=[
        'in_files', 'output_directory', 'which_file_is_EPI_space', 'sub_id',
        'tr'
    ]),
                         name='inputspec')
    output_node = pe.Node(IdentityInterface(fields=([
        'motion_corrected_files', 'EPI_space_file', 'mask_EPI_space_file',
        'motion_correction_plots', 'motion_correction_parameters',
        'extended_motion_correction_parameters',
        'new_motion_correction_parameters'
    ])),
                          name='outputspec')

    ########################################################################################
    # Invariant nodes
    ########################################################################################

    EPI_file_selector_node = pe.Node(interface=EPI_file_selector,
                                     name='EPI_file_selector_node')
    mean_bold = pe.Node(interface=fsl.maths.MeanImage(dimension='T'),
                        name='mean_space')
    rename_mean_bold = pe.Node(niu.Rename(format_string='session_EPI_space',
                                          keep_ext=True),
                               name='rename_mean_bold')

    ########################################################################################
    # Workflow
    ########################################################################################

    motion_correction_workflow = pe.Workflow(name=name)
    motion_correction_workflow.connect(input_node, 'which_file_is_EPI_space',
                                       EPI_file_selector_node, 'which_file')
    motion_correction_workflow.connect(input_node, 'in_files',
                                       EPI_file_selector_node, 'in_files')

    ########################################################################################
    # outputs via datasink
    ########################################################################################
    datasink = pe.Node(nio.DataSink(), name='sinker')
    datasink.inputs.parameterization = False

    # first link the workflow's output_directory into the datasink.
    motion_correction_workflow.connect(input_node, 'output_directory',
                                       datasink, 'base_directory')
    motion_correction_workflow.connect(input_node, 'sub_id', datasink,
                                       'container')

    ########################################################################################
    # FSL MCFlirt
    ########################################################################################
    # new approach, which should aid in the joint motion correction of
    # multiple sessions together, by pre-registering each run.
    # the strategy would be to, for each run, take the first TR
    # and FLIRT-align (6dof) it to the EPI_space file.
    # then we can use this as an --infile argument to mcflirt.

    if method == 'FSL':

        rename_motion_files = pe.MapNode(
            niu.Rename(keep_ext=False),
            name='rename_motion_files',
            iterfield=['in_file', 'format_string'])

        remove_niigz_ext = pe.MapNode(interface=Remove_extension,
                                      name='remove_niigz_ext',
                                      iterfield=['in_file'])

        motion_correct_EPI_space = pe.Node(interface=fsl.MCFLIRT(
            cost='normcorr', interpolation='sinc', mean_vol=True),
                                           name='motion_correct_EPI_space')

        motion_correct_all = pe.MapNode(interface=fsl.MCFLIRT(
            save_mats=True,
            save_plots=True,
            cost='normcorr',
            interpolation='sinc',
            stats_imgs=True),
                                        name='motion_correct_all',
                                        iterfield=['in_file'])

        plot_motion = pe.MapNode(
            interface=fsl.PlotMotionParams(in_source='fsl'),
            name='plot_motion',
            iterfield=['in_file'])

        if extend_moco_params:
            # make extend_motion_pars node here
            # extend_motion_pars = pe.MapNode(Function(input_names=['moco_par_file', 'tr'], output_names=['new_out_file', 'ext_out_file'],
            # function=_extend_motion_parameters), name='extend_motion_pars', iterfield = ['moco_par_file'])
            pass

        # create reference:
        motion_correction_workflow.connect(EPI_file_selector_node, 'out_file',
                                           motion_correct_EPI_space, 'in_file')
        motion_correction_workflow.connect(motion_correct_EPI_space,
                                           'out_file', mean_bold, 'in_file')
        motion_correction_workflow.connect(mean_bold, 'out_file',
                                           motion_correct_all, 'ref_file')

        # motion correction across runs
        motion_correction_workflow.connect(input_node, 'in_files',
                                           motion_correct_all, 'in_file')
        #motion_correction_workflow.connect(motion_correct_all, 'out_file', output_node, 'motion_corrected_files')
        # motion_correction_workflow.connect(motion_correct_all, 'par_file', extend_motion_pars, 'moco_par_file')
        # motion_correction_workflow.connect(input_node, 'tr', extend_motion_pars, 'tr')
        # motion_correction_workflow.connect(extend_motion_pars, 'ext_out_file', output_node, 'extended_motion_correction_parameters')
        # motion_correction_workflow.connect(extend_motion_pars, 'new_out_file', output_node, 'new_motion_correction_parameters')

        ########################################################################################
        # Plot the estimated motion parameters
        ########################################################################################

        # rename:
        motion_correction_workflow.connect(mean_bold, 'out_file',
                                           rename_mean_bold, 'in_file')
        motion_correction_workflow.connect(motion_correct_all, 'par_file',
                                           rename_motion_files, 'in_file')
        motion_correction_workflow.connect(motion_correct_all, 'par_file',
                                           remove_niigz_ext, 'in_file')
        motion_correction_workflow.connect(remove_niigz_ext, 'out_file',
                                           rename_motion_files,
                                           'format_string')

        # plots:
        plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
        motion_correction_workflow.connect(rename_motion_files, 'out_file',
                                           plot_motion, 'in_file')
        motion_correction_workflow.connect(plot_motion, 'out_file',
                                           output_node,
                                           'motion_correction_plots')

        # output node:
        motion_correction_workflow.connect(mean_bold, 'out_file', output_node,
                                           'EPI_space_file')
        motion_correction_workflow.connect(rename_motion_files, 'out_file',
                                           output_node,
                                           'motion_correction_parameters')
        motion_correction_workflow.connect(motion_correct_all, 'out_file',
                                           output_node,
                                           'motion_corrected_files')

        # datasink:
        motion_correction_workflow.connect(rename_mean_bold, 'out_file',
                                           datasink, 'reg')
        motion_correction_workflow.connect(motion_correct_all, 'out_file',
                                           datasink, 'mcf')
        motion_correction_workflow.connect(rename_motion_files, 'out_file',
                                           datasink, 'mcf.motion_pars')
        motion_correction_workflow.connect(plot_motion, 'out_file', datasink,
                                           'mcf.motion_plots')
        # motion_correction_workflow.connect(extend_motion_pars, 'ext_out_file', datasink, 'mcf.ext_motion_pars')
        # motion_correction_workflow.connect(extend_motion_pars, 'new_out_file', datasink, 'mcf.new_motion_pars')

    ########################################################################################
    # AFNI 3DVolReg
    ########################################################################################
    # for speed, we use AFNI's 3DVolReg brute-force.
    # this loses plotting of motion parameters but increases speed
    # we hold on to the same setup, first moco the selected run
    # and then moco everything to that image, but without the
    # intermediate FLIRT step.

    if method == 'AFNI':
        motion_correct_EPI_space = pe.Node(
            interface=afni.Volreg(
                outputtype='NIFTI_GZ',
                zpad=5,
                args=' -cubic '  # -twopass -Fourier
            ),
            name='motion_correct_EPI_space')

        motion_correct_all = pe.MapNode(
            interface=afni.Volreg(
                outputtype='NIFTI_GZ',
                zpad=5,
                args=' -cubic '  # -twopass
            ),
            name='motion_correct_all',
            iterfield=['in_file'])

        # for renaming *_volreg.nii.gz to *_mcf.nii.gz
        set_postfix_mcf = pe.MapNode(interface=Set_postfix,
                                     name='set_postfix_mcf',
                                     iterfield=['in_file'])
        set_postfix_mcf.inputs.postfix = 'mcf'

        rename_volreg = pe.MapNode(interface=Rename(keep_ext=True),
                                   name='rename_volreg',
                                   iterfield=['in_file', 'format_string'])

        # curate for moco between sessions
        motion_correction_workflow.connect(EPI_file_selector_node, 'out_file',
                                           motion_correct_EPI_space, 'in_file')
        motion_correction_workflow.connect(motion_correct_EPI_space,
                                           'out_file', mean_bold, 'in_file')

        # motion correction across runs
        motion_correction_workflow.connect(input_node, 'in_files',
                                           motion_correct_all, 'in_file')
        motion_correction_workflow.connect(mean_bold, 'out_file',
                                           motion_correct_all, 'basefile')
        # motion_correction_workflow.connect(mean_bold, 'out_file', motion_correct_all, 'rotparent')
        # motion_correction_workflow.connect(mean_bold, 'out_file', motion_correct_all, 'gridparent')

        # output node:
        motion_correction_workflow.connect(mean_bold, 'out_file', output_node,
                                           'EPI_space_file')
        motion_correction_workflow.connect(motion_correct_all, 'md1d_file',
                                           output_node,
                                           'max_displacement_info')
        motion_correction_workflow.connect(motion_correct_all, 'oned_file',
                                           output_node,
                                           'motion_correction_parameter_info')
        motion_correction_workflow.connect(
            motion_correct_all, 'oned_matrix_save', output_node,
            'motion_correction_parameter_matrix')
        motion_correction_workflow.connect(input_node, 'in_files',
                                           set_postfix_mcf, 'in_file')
        motion_correction_workflow.connect(set_postfix_mcf, 'out_file',
                                           rename_volreg, 'format_string')
        motion_correction_workflow.connect(motion_correct_all, 'out_file',
                                           rename_volreg, 'in_file')
        motion_correction_workflow.connect(rename_volreg, 'out_file',
                                           output_node,
                                           'motion_corrected_files')

        # datasink:
        motion_correction_workflow.connect(mean_bold, 'out_file',
                                           rename_mean_bold, 'in_file')
        motion_correction_workflow.connect(rename_mean_bold, 'out_file',
                                           datasink, 'reg')
        motion_correction_workflow.connect(rename_volreg, 'out_file', datasink,
                                           'mcf')
        motion_correction_workflow.connect(motion_correct_all, 'md1d_file',
                                           datasink,
                                           'mcf.max_displacement_info')
        motion_correction_workflow.connect(motion_correct_all, 'oned_file',
                                           datasink, 'mcf.parameter_info')
        motion_correction_workflow.connect(motion_correct_all,
                                           'oned_matrix_save', datasink,
                                           'mcf.motion_pars')

    return motion_correction_workflow
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
Beispiel #13
0
def create_preprocess_mag_wf():
    preprocmag = pe.Workflow(name="preprocmag")
    preprocmag.config['execution']['remove_unnecessary_outputs'] = False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return preprocmag
    def __motion_correct_file__(
            self,
            input_file,
            output_file,
            subject,
            directory,
            use_example_pp=False):
        # Check whether motion correction has already been completed

        print ">>>> Working on {}".format(input_file)

        if use_example_pp:
            pp.preproc.inputs.inputspec.func = input_file
            pp.preproc.inputs.inputspec.struct = os.path.join(
                subject.anatomical_dir(), 'highres001.nii.gz')
            pp.preproc.base_dir = directory

            pp.preproc.run()
            # TODO: copy motion correction photos as well
            intnorm_file = output_file.replace('.nii.gz', '_intnorm.nii.gz')
            shutil.copy(
                os.path.join(
                    directory,
                    'preproc',
                    'intnorm',
                    'mapflow',
                    '_intnorm0',
                    'bold_dtype_mcf_mask_intnorm.nii.gz'),
                intnorm_file)
            shutil.copy(
                os.path.join(
                    directory,
                    'preproc',
                    'maskfunc2',
                    'mapflow',
                    '_maskfunc20',
                    'bold_dtype_mcf_mask.nii.gz'),
                output_file)
            cmd = "eog {}".format(
                os.path.join(
                    directory,
                    'preproc',
                    'realign',
                    'mapflow',
                    '_realign0',
                    'bold_dtype_mcf.nii.gz_rot.png'))
            subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                shell=True,
                preexec_fn=os.setsid)
            cmd = "eog {}".format(
                os.path.join(
                    directory,
                    'preproc',
                    'realign',
                    'mapflow',
                    '_realign0',
                    'bold_dtype_mcf.nii.gz_trans.png'))
            subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                shell=True,
                preexec_fn=os.setsid)

        else:
            mcflt = fsl.MCFLIRT(
                in_file=input_file,
                out_file=output_file,
                save_plots=True)
            result = mcflt.run()

            pmp = fsl.PlotMotionParams(
                in_file=result.outputs.par_file, in_source='fsl')

            pmp.inputs.plot_type = 'rotations'
            pmp.run()
            pmp.inputs.plot_type = 'translations'
            pmp.run()
    iterfield=['in_file', 'in_matrix_file', 'reference', 'wm_seg'])
NodeHash_a9682a0.inputs.cost = 'bbr'
NodeHash_a9682a0.inputs.dof = 6
NodeHash_a9682a0.inputs.no_resample = True

#Wraps command **mcflirt**
NodeHash_de46680 = pe.MapNode(interface=fsl.MCFLIRT(),
                              name='NodeName_de46680',
                              iterfield=['in_file', 'ref_file'])
NodeHash_de46680.inputs.interpolation = 'spline'
NodeHash_de46680.inputs.save_mats = True
NodeHash_de46680.inputs.save_plots = True
NodeHash_de46680.inputs.save_rms = True

#Wraps command **fsl_tsplot**
NodeHash_e827000 = pe.MapNode(interface=fsl.PlotMotionParams(),
                              name='NodeName_e827000',
                              iterfield=['in_file'])
NodeHash_e827000.inputs.args = '-a x,y,z -w 640 -h 144'
NodeHash_e827000.inputs.in_source = 'fsl'
NodeHash_e827000.iterables = [('plot_type', ['rotations', 'translations'])]

#Wraps command **fslmaths**
NodeHash_12ef2460 = pe.MapNode(interface=fsl.MeanImage(),
                               name='NodeName_12ef2460',
                               iterfield=['in_file'])
NodeHash_12ef2460.inputs.dimension = 'T'

#Wraps command **bet**
NodeHash_131f40e0 = pe.MapNode(interface=fsl.BET(),
                               name='NodeName_131f40e0',
Beispiel #16
0
def create_featreg_preproc(name='featpreproc',
                           whichvol='middle',
                           deletetimepoints=4):
    """Create a FEAT preprocessing workflow with registration to one volume of the first run

    Parameters
    ----------

    name : name of workflow (default: featpreproc)
    whichvol : which volume of the first run to register to ('first', 'middle', 'mean')

    Inputs::

        inputspec.func : functional runs (filename or list of filenames)
        inputspec.fwhm : fwhm for smoothing with SUSAN
        inputspec.highpass : HWHM in TRs (if created with highpass=True)

    Outputs::

        outputspec.reference : volume to which runs are realigned
        outputspec.motion_parameters : motion correction parameters
        outputspec.realigned_files : motion corrected files
        outputspec.motion_plots : plots of motion correction parameters
        outputspec.mask : mask file used to mask the brain
        outputspec.smoothed_files : smoothed functional data
        outputspec.meanscaled_files : meanscaled data

    Example
    -------

    >>> from nipype.workflows.fsl import create_featreg_preproc
    >>> import os
    >>> preproc = create_featreg_preproc()
    >>> preproc.inputs.inputspec.func = ['f3.nii', 'f5.nii']
    >>> preproc.inputs.inputspec.fwhm = 5
    >>> preproc.inputs.inputspec.highpass = 128./(2*2.5)
    >>> preproc.base_dir = '/tmp'
    >>> preproc.run() # doctest: +SKIP

    >>> preproc = create_featreg_preproc(highpass=False, whichvol='mean')
    >>> preproc.inputs.inputspec.func = 'f3.nii'
    >>> preproc.inputs.inputspec.fwhm = 5
    >>> preproc.base_dir = '/tmp'
    >>> preproc.run() # doctest: +SKIP
    """

    featpreproc = pe.Workflow(name=name)

    # Set up a node to define all inputs and outputs required for the
    # preprocessing workflow

    inputnode = pe.Node(interface=util.IdentityInterface(fields=[
        'func',
        'fwhm',
    ]),
                        name='inputspec')
    outputnode = pe.Node(interface=util.IdentityInterface(fields=[
        'reference',
        'motion_parameters',
        'realigned_files',
        'motion_rot_plots',
        'motion_trans_plots',
        'mask',
        'maskfunc_files',
        'smoothed_files',
        'meanscaled_files',
    ]),
                         name='outputspec')

    # Convert functional images to float representation. Since there can
    # be more than one functional run we use a MapNode to convert each
    # run.

    deletevol = pe.MapNode(interface=fsl.ExtractROI(t_min=deletetimepoints),
                           iterfield=['in_file', 't_size'],
                           name='deletevol')
    img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float',
                                                    op_string='',
                                                    suffix='_dtype'),
                           iterfield=['in_file'],
                           name='img2float')
    featpreproc.connect(inputnode, 'func', deletevol, 'in_file')
    featpreproc.connect(inputnode, ('func', getTTP, deletetimepoints),
                        deletevol, 't_size')
    featpreproc.connect(deletevol, 'roi_file', img2float, 'in_file')

    # Extract the first volume of the each run as the reference

    if whichvol != 'mean':
        extract_ref = pe.MapNode(interface=fsl.ExtractROI(t_size=1),
                                 iterfield=['in_file'],
                                 name='extractref')
        featpreproc.connect(img2float, 'out_file', extract_ref, 'in_file')
        featpreproc.connect(img2float, ('out_file', pickvol, 0, whichvol),
                            extract_ref, 't_min')
        featpreproc.connect(extract_ref, 'roi_file', outputnode, 'reference')

    # Realign the functional runs to the reference (1st volume of first run)

    motion_correct = pe.MapNode(interface=fsl.MCFLIRT(save_mats=True,
                                                      save_plots=True,
                                                      save_rms=True,
                                                      interpolation='sinc'),
                                name='realign',
                                iterfield=['in_file', 'ref_file'])
    featpreproc.connect(img2float, 'out_file', motion_correct, 'in_file')
    if whichvol != 'mean':
        featpreproc.connect(extract_ref, 'roi_file', motion_correct,
                            'ref_file')
    else:
        motion_correct.inputs.mean_vol = True
        featpreproc.connect(motion_correct, 'mean_img', outputnode,
                            'reference')

    featpreproc.connect(motion_correct, 'par_file', outputnode,
                        'motion_parameters')
    featpreproc.connect(motion_correct, 'out_file', outputnode,
                        'realigned_files')

    # Plot the estimated motion parameters

    plot_rotations = pe.MapNode(interface=fsl.PlotMotionParams(
        in_source='fsl', plot_type='rotations'),
                                name='plot_rotations',
                                iterfield=['in_file'])
    plot_translations = pe.MapNode(interface=fsl.PlotMotionParams(
        in_source='fsl', plot_type='translations'),
                                   name='plot_translations',
                                   iterfield=['in_file'])

    # plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
    featpreproc.connect(motion_correct, 'par_file', plot_rotations, 'in_file')
    featpreproc.connect(motion_correct, 'par_file', plot_translations,
                        'in_file')
    featpreproc.connect(plot_rotations, 'out_file', outputnode,
                        'motion_rot_plots')
    featpreproc.connect(plot_translations, 'out_file', outputnode,
                        'motion_trans_plots')

    # Extract the mean volume of the first functional run

    meanfunc = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',
                                                   suffix='_mean'),
                          iterfield=['in_file'],
                          name='meanfunc')
    featpreproc.connect(motion_correct, 'out_file', meanfunc, 'in_file')

    # Strip the skull from the mean functional to generate a mask

    meanfuncmask = pe.MapNode(interface=fsl.BET(mask=True,
                                                no_output=True,
                                                frac=0.3),
                              iterfield=['in_file'],
                              name='meanfuncmask')

    featpreproc.connect(meanfunc, 'out_file', meanfuncmask, 'in_file')

    # Mask the functional runs with the extracted mask

    maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet',
                                                   op_string='-mas'),
                          iterfield=['in_file', 'in_file2'],
                          name='maskfunc')
    featpreproc.connect(motion_correct, 'out_file', maskfunc, 'in_file')
    featpreproc.connect(meanfuncmask, 'mask_file', maskfunc, 'in_file2')

    # Determine the 2nd and 98th percentile intensities of each functional run

    getthresh = pe.MapNode(interface=fsl.ImageStats(op_string='-p 2 -p 98'),
                           iterfield=['in_file'],
                           name='getthreshold')
    featpreproc.connect(maskfunc, 'out_file', getthresh, 'in_file')

    # Threshold the first run of the functional data at 10% of the 98th percentile

    threshold = pe.MapNode(interface=fsl.ImageMaths(out_data_type='char',
                                                    suffix='_thresh'),
                           iterfield=['in_file', 'op_string'],
                           name='threshold')
    featpreproc.connect(maskfunc, 'out_file', threshold, 'in_file')

    # Define a function to get 10% of the intensity

    featpreproc.connect(getthresh, ('out_stat', getthreshop), threshold,
                        'op_string')

    # Determine the median value of the functional runs using the mask

    medianval = pe.MapNode(interface=fsl.ImageStats(op_string='-k %s -p 50'),
                           iterfield=['in_file', 'mask_file'],
                           name='medianval')
    featpreproc.connect(motion_correct, 'out_file', medianval, 'in_file')
    featpreproc.connect(threshold, 'out_file', medianval, 'mask_file')

    # Dilate the mask

    dilatemask = pe.MapNode(interface=fsl.ImageMaths(suffix='_dil',
                                                     op_string='-dilF'),
                            iterfield=['in_file'],
                            name='dilatemask')
    featpreproc.connect(threshold, 'out_file', dilatemask, 'in_file')
    featpreproc.connect(dilatemask, 'out_file', outputnode, 'mask')

    # Mask the motion corrected functional runs with the dilated mask

    maskfunc2 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                           iterfield=['in_file', 'in_file2'],
                           name='maskfunc2')
    featpreproc.connect(motion_correct, 'out_file', maskfunc2, 'in_file')
    featpreproc.connect(dilatemask, 'out_file', maskfunc2, 'in_file2')
    featpreproc.connect(maskfunc2, 'out_file', outputnode, 'maskfunc_files')

    # Smooth each run using SUSAN with the brightness threshold set to 75%
    # of the median value for each run and a mask consituting the mean
    # functional

    smooth = create_susan_smooth()

    featpreproc.connect(inputnode, 'fwhm', smooth, 'inputnode.fwhm')
    featpreproc.connect(maskfunc2, 'out_file', smooth, 'inputnode.in_files')
    featpreproc.connect(dilatemask, 'out_file', smooth, 'inputnode.mask_file')

    # Mask the smoothed data with the dilated mask

    maskfunc3 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                           iterfield=['in_file', 'in_file2'],
                           name='maskfunc3')
    featpreproc.connect(smooth, 'outputnode.smoothed_files', maskfunc3,
                        'in_file')

    featpreproc.connect(dilatemask, 'out_file', maskfunc3, 'in_file2')

    concatnode = pe.Node(interface=util.Merge(2), name='concat')
    featpreproc.connect(maskfunc2, ('out_file', tolist), concatnode, 'in1')
    featpreproc.connect(maskfunc3, ('out_file', tolist), concatnode, 'in2')

    # The following nodes select smooth or unsmoothed data depending on the
    # fwhm. This is because SUSAN defaults to smoothing the data with about the
    # voxel size of the input data if the fwhm parameter is less than 1/3 of the
    # voxel size.

    selectnode = pe.Node(interface=util.Select(), name='select')

    featpreproc.connect(concatnode, 'out', selectnode, 'inlist')

    featpreproc.connect(inputnode, ('fwhm', chooseindex), selectnode, 'index')
    featpreproc.connect(selectnode, 'out', outputnode, 'smoothed_files')

    # Scale the median value of the run is set to 10000

    meanscale = pe.MapNode(interface=fsl.ImageMaths(suffix='_gms'),
                           iterfield=['in_file', 'op_string'],
                           name='meanscale')

    featpreproc.connect(selectnode, 'out', meanscale, 'in_file')
    featpreproc.connect(medianval, ('out_stat', getmeanscale), meanscale,
                        'op_string')

    # Mask the scaled data with the dilated mask

    maskfunc4 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                           iterfield=['in_file', 'in_file2'],
                           name='maskfunc4')

    featpreproc.connect(meanscale, 'out_file', maskfunc4, 'in_file')
    featpreproc.connect(dilatemask, 'out_file', maskfunc4, 'in_file2')
    featpreproc.connect(maskfunc4, 'out_file', outputnode, 'meanscaled_files')

    return featpreproc
Beispiel #17
0
def create_featreg_preproc(name='featpreproc',
                           highpass=True,
                           whichvol='middle',
                           whichrun=0):
    """Create a FEAT preprocessing workflow with registration to one volume of
    the first run. If whichvol = None and/or whichrun = None, no motion
    correction will be performed and the FEAT preprocessing workflow will not
    return outputspec.reference, outputspec.realigned_files, and
    outputspec.motion_plots.

    Parameters
    ----------

    ::

        name : name of workflow (default: featpreproc)
        highpass : boolean (default: True)
        whichvol : which volume of the first run to register to ('first', 'middle', 'last', 'mean', None)
        whichrun : which run to draw reference volume from (integer index or 'first', 'middle', 'last' or None)

    Inputs::

        inputspec.func : functional runs (filename or list of filenames)
        inputspec.fwhm : fwhm for smoothing with SUSAN
        inputspec.highpass : HWHM in TRs (if created with highpass=True)

    Outputs::

        outputspec.reference : volume to which runs are realigned
        outputspec.motion_parameters : motion correction parameters
        outputspec.realigned_files : motion corrected files
        outputspec.motion_plots : plots of motion correction parameters
        outputspec.mask : mask file used to mask the brain
        outputspec.smoothed_files : smoothed functional data
        outputspec.highpassed_files : highpassed functional data (if highpass=True)
        outputspec.mean : mean file

    Example
    -------

    >>> preproc = create_featreg_preproc()
    >>> preproc.inputs.inputspec.func = ['f3.nii', 'f5.nii']
    >>> preproc.inputs.inputspec.fwhm = 5
    >>> preproc.inputs.inputspec.highpass = 128./(2*2.5)
    >>> preproc.base_dir = '/tmp'
    >>> preproc.run() # doctest: +SKIP

    >>> preproc = create_featreg_preproc(highpass=False, whichvol='mean')
    >>> preproc.inputs.inputspec.func = 'f3.nii'
    >>> preproc.inputs.inputspec.fwhm = 5
    >>> preproc.base_dir = '/tmp'
    >>> preproc.run() # doctest: +SKIP
    """

    version = 0
    if fsl.Info.version() and \
            LooseVersion(fsl.Info.version()) > LooseVersion('5.0.6'):
        version = 507

    featpreproc = pe.Workflow(name=name)
    """
    Derive boolean motion correction parameter from the given parameters
    """
    if (whichrun != None) & (whichvol != None):
        motion_corr = True
    else:
        motion_corr = False
    """
    Set up a node to define all inputs required for the preprocessing workflow

    """
    output_fields = ['mask', 'smoothed_files', 'mean', 'functional_files']

    input_fields = ['func', 'fwhm']

    if highpass:
        output_fields += ['highpassed_files']
        input_fields += ['highpass']
        inputnode = pe.Node(
            interface=util.IdentityInterface(fields=input_fields),
            name='inputspec')

        if motion_corr:
            output_fields += [
                'reference', 'motion_parameters', 'realigned_files'
            ]
            outputnode = pe.Node(
                interface=util.IdentityInterface(fields=output_fields),
                name='outputspec')

        else:
            outputnode = pe.Node(
                interface=util.IdentityInterface(fields=output_fields),
                name='outputspec')

    else:
        inputnode = pe.Node(
            interface=util.IdentityInterface(fields=input_fields),
            name='inputspec')

        if motion_corr:
            output_fields += [
                'reference', 'motion_parameters', 'realigned_files'
            ]
        outputnode = pe.Node(
            interface=util.IdentityInterface(fields=output_fields),
            name='outputspec')
    """
    Set up a node to define outputs for the preprocessing workflow

    """
    """
    Convert functional images to float representation. Since there can
    be more than one functional run we use a MapNode to convert each
    run.
    """

    img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float',
                                                    op_string='',
                                                    suffix='_dtype'),
                           iterfield=['in_file'],
                           name='img2float')
    featpreproc.connect(inputnode, 'func', img2float, 'in_file')

    if motion_corr:
        """
        Extract the middle (or what whichvol points to) volume of the first run as the reference
        """

        if whichvol != 'mean':
            extract_ref = pe.Node(interface=fsl.ExtractROI(t_size=1),
                                  iterfield=['in_file'],
                                  name='extractref')
            featpreproc.connect(img2float, ('out_file', pickrun, whichrun),
                                extract_ref, 'in_file')
            featpreproc.connect(img2float, ('out_file', pickvol, 0, whichvol),
                                extract_ref, 't_min')
            featpreproc.connect(extract_ref, 'roi_file', outputnode,
                                'reference')
        """
        Realign the functional runs to the reference (`whichvol` volume of first run)
        """

        motion_correct = pe.MapNode(interface=fsl.MCFLIRT(
            save_mats=True, save_plots=True, interpolation='spline'),
                                    name='realign',
                                    iterfield=['in_file'])
        featpreproc.connect(img2float, 'out_file', motion_correct, 'in_file')
        if whichvol != 'mean':
            featpreproc.connect(extract_ref, 'roi_file', motion_correct,
                                'ref_file')
        else:
            motion_correct.inputs.mean_vol = True
            featpreproc.connect(motion_correct,
                                ('mean_img', pickrun, whichrun), outputnode,
                                'reference')

        featpreproc.connect(motion_correct, 'par_file', outputnode,
                            'motion_parameters')
        featpreproc.connect(motion_correct, 'out_file', outputnode,
                            'realigned_files')
        """
        Plot the estimated motion parameters
        """

        plot_motion = pe.MapNode(
            interface=fsl.PlotMotionParams(in_source='fsl'),
            name='plot_motion',
            iterfield=['in_file'])
        plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
        featpreproc.connect(motion_correct, 'par_file', plot_motion, 'in_file')
        featpreproc.connect(plot_motion, 'out_file', outputnode,
                            'motion_plots')
        """
        Extract the mean volume of the first functional run
        """
    else:
        featpreproc.connect(img2float, 'out_file', outputnode,
                            'functional_files')
        #TODO: check whether this is really necessary

    if motion_corr:
        meanfunc = pe.Node(interface=fsl.ImageMaths(op_string='-Tmean',
                                                    suffix='_mean'),
                           name='meanfunc')
        featpreproc.connect(motion_correct, ('out_file', pickrun, whichrun),
                            meanfunc, 'in_file')
    else:
        meanfunc = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',
                                                       suffix='_mean'),
                              iterfield=['in_file'],
                              name='meanfunc')
        featpreproc.connect(img2float, 'out_file', meanfunc, 'in_file')
    """
    Strip the skull from the mean functional to generate a mask
    """
    if motion_corr:
        meanfuncmask = pe.Node(interface=fsl.BET(mask=True,
                                                 no_output=True,
                                                 frac=0.3),
                               name='meanfuncmask')
    else:
        meanfuncmask = pe.MapNode(interface=fsl.BET(mask=True,
                                                    no_output=True,
                                                    frac=0.3),
                                  iterfield=['in_file'],
                                  name='meanfuncmask')

    featpreproc.connect(meanfunc, 'out_file', meanfuncmask, 'in_file')
    """
    Mask the functional runs with the extracted mask
    """
    if motion_corr:
        maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet',
                                                       op_string='-mas'),
                              iterfield=['in_file'],
                              name='maskfunc')
        featpreproc.connect(motion_correct, 'out_file', maskfunc, 'in_file')
    else:
        maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet',
                                                       op_string='-mas'),
                              iterfield=['in_file', 'in_file2'],
                              name='maskfunc')
        featpreproc.connect(img2float, 'out_file', maskfunc, 'in_file')

    featpreproc.connect(meanfuncmask, 'mask_file', maskfunc, 'in_file2')
    """
    Determine the 2nd and 98th percentile intensities of each functional run
    """

    getthresh = pe.MapNode(interface=fsl.ImageStats(op_string='-p 2 -p 98'),
                           iterfield=['in_file'],
                           name='getthreshold')
    featpreproc.connect(maskfunc, 'out_file', getthresh, 'in_file')
    """
    Threshold the first run of the functional data at 10% of the 98th percentile
    """

    threshold = pe.MapNode(interface=fsl.ImageMaths(out_data_type='char',
                                                    suffix='_thresh'),
                           iterfield=['in_file', 'op_string'],
                           name='threshold')
    featpreproc.connect(maskfunc, 'out_file', threshold, 'in_file')
    """
    Define a function to get 10% of the intensity
    """

    featpreproc.connect(getthresh, ('out_stat', getthreshop), threshold,
                        'op_string')
    """
    Determine the median value of the functional runs using the mask
    """

    medianval = pe.MapNode(interface=fsl.ImageStats(op_string='-k %s -p 50'),
                           iterfield=['in_file', 'mask_file'],
                           name='medianval')

    if motion_corr:
        featpreproc.connect(motion_correct, 'out_file', medianval, 'in_file')
    else:
        featpreproc.connect(img2float, 'out_file', medianval, 'in_file')

    featpreproc.connect(threshold, 'out_file', medianval, 'mask_file')
    """
    Dilate the mask
    """

    dilatemask = pe.MapNode(interface=fsl.ImageMaths(suffix='_dil',
                                                     op_string='-dilF'),
                            iterfield=['in_file'],
                            name='dilatemask')
    featpreproc.connect(threshold, 'out_file', dilatemask, 'in_file')
    featpreproc.connect(dilatemask, 'out_file', outputnode, 'mask')
    """
    Mask the motion corrected functional runs with the dilated mask
    """

    maskfunc2 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                           iterfield=['in_file', 'in_file2'],
                           name='maskfunc2')

    if motion_corr:
        featpreproc.connect(motion_correct, 'out_file', maskfunc2, 'in_file')
    else:
        featpreproc.connect(img2float, 'out_file', maskfunc2, 'in_file')
    featpreproc.connect(dilatemask, 'out_file', maskfunc2, '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 = create_susan_smooth()

    featpreproc.connect(inputnode, 'fwhm', smooth, 'inputnode.fwhm')
    featpreproc.connect(maskfunc2, 'out_file', smooth, 'inputnode.in_files')
    featpreproc.connect(dilatemask, 'out_file', smooth, 'inputnode.mask_file')
    """
    Mask the smoothed data with the dilated mask
    """

    maskfunc3 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                           iterfield=['in_file', 'in_file2'],
                           name='maskfunc3')
    featpreproc.connect(smooth, 'outputnode.smoothed_files', maskfunc3,
                        'in_file')

    featpreproc.connect(dilatemask, 'out_file', maskfunc3, 'in_file2')

    concatnode = pe.Node(interface=util.Merge(2), name='concat')
    featpreproc.connect(maskfunc2, ('out_file', tolist), concatnode, 'in1')
    featpreproc.connect(maskfunc3, ('out_file', tolist), concatnode, 'in2')
    """
    The following nodes select smooth or unsmoothed data depending on the
    fwhm. This is because SUSAN defaults to smoothing the data with about the
    voxel size of the input data if the fwhm parameter is less than 1/3 of the
    voxel size.
    """
    selectnode = pe.Node(interface=util.Select(), name='select')

    featpreproc.connect(concatnode, 'out', selectnode, 'inlist')

    featpreproc.connect(inputnode, ('fwhm', chooseindex), selectnode, 'index')
    featpreproc.connect(selectnode, 'out', outputnode, 'smoothed_files')
    """
    Scale the median value of the run is set to 10000
    """

    meanscale = pe.MapNode(interface=fsl.ImageMaths(suffix='_gms'),
                           iterfield=['in_file', 'op_string'],
                           name='meanscale')
    featpreproc.connect(selectnode, 'out', meanscale, 'in_file')
    """
    Define a function to get the scaling factor for intensity normalization
    """

    featpreproc.connect(medianval, ('out_stat', getmeanscale), meanscale,
                        'op_string')
    """
    Generate a mean functional image from the first run
    """

    meanfunc3 = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',
                                                    suffix='_mean'),
                           iterfield=['in_file'],
                           name='meanfunc3')

    if motion_corr:
        featpreproc.connect(meanscale, ('out_file', pickrun, whichrun),
                            meanfunc3, 'in_file')
    else:
        featpreproc.connect(meanscale, 'out_file', meanfunc3, 'in_file')
    featpreproc.connect(meanfunc3, 'out_file', outputnode, 'mean')
    """
    Perform temporal highpass filtering on the data
    """

    if highpass:
        highpass = pe.MapNode(interface=fsl.ImageMaths(suffix='_tempfilt'),
                              iterfield=['in_file'],
                              name='highpass')
        featpreproc.connect(inputnode, ('highpass', highpass_operand),
                            highpass, 'op_string')
        featpreproc.connect(meanscale, 'out_file', highpass, 'in_file')

        if version < 507:
            featpreproc.connect(highpass, 'out_file', outputnode,
                                'highpassed_files')
        else:
            """
            Add back the mean removed by the highpass filter operation as of FSL 5.0.7
            """
            meanfunc4 = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',
                                                            suffix='_mean'),
                                   iterfield=['in_file'],
                                   name='meanfunc4')

            featpreproc.connect(meanscale, 'out_file', meanfunc4, 'in_file')
            addmean = pe.MapNode(interface=fsl.BinaryMaths(operation='add'),
                                 iterfield=['in_file', 'operand_file'],
                                 name='addmean')
            featpreproc.connect(highpass, 'out_file', addmean, 'in_file')
            featpreproc.connect(meanfunc4, 'out_file', addmean, 'operand_file')
            featpreproc.connect(addmean, 'out_file', outputnode,
                                'highpassed_files')

    return featpreproc
Beispiel #18
0
def create_parallelfeat_preproc(name='featpreproc', highpass=True):
    """Preprocess each run with FSL independently of the others

    Parameters
    ----------

    ::

      name : name of workflow (default: featpreproc)
      highpass : boolean (default: True)

    Inputs::

        inputspec.func : functional runs (filename or list of filenames)
        inputspec.fwhm : fwhm for smoothing with SUSAN
        inputspec.highpass : HWHM in TRs (if created with highpass=True)

    Outputs::

        outputspec.reference : volume to which runs are realigned
        outputspec.motion_parameters : motion correction parameters
        outputspec.realigned_files : motion corrected files
        outputspec.motion_plots : plots of motion correction parameters
        outputspec.mask : mask file used to mask the brain
        outputspec.smoothed_files : smoothed functional data
        outputspec.highpassed_files : highpassed functional data (if highpass=True)
        outputspec.mean : mean file

    Example
    -------

    >>> preproc = create_parallelfeat_preproc()
    >>> preproc.inputs.inputspec.func = ['f3.nii', 'f5.nii']
    >>> preproc.inputs.inputspec.fwhm = 5
    >>> preproc.inputs.inputspec.highpass = 128./(2*2.5)
    >>> preproc.base_dir = '/tmp'
    >>> preproc.run() # doctest: +SKIP

    >>> preproc = create_parallelfeat_preproc(highpass=False)
    >>> preproc.inputs.inputspec.func = 'f3.nii'
    >>> preproc.inputs.inputspec.fwhm = 5
    >>> preproc.base_dir = '/tmp'
    >>> preproc.run() # doctest: +SKIP
    """

    featpreproc = pe.Workflow(name=name)

    """
    Set up a node to define all inputs required for the preprocessing workflow

    """

    if highpass:
        inputnode = pe.Node(interface=util.IdentityInterface(fields=['func',
                                                                     'fwhm',
                                                                     'highpass']),
                            name='inputspec')
        outputnode = pe.Node(interface=util.IdentityInterface(fields=['reference',
                                                                  'motion_parameters',
                                                                  'realigned_files',
                                                                  'motion_plots',
                                                                  'mask',
                                                                  'smoothed_files',
                                                                  'highpassed_files',
                                                                  'mean']),
                         name='outputspec')
    else:
        inputnode = pe.Node(interface=util.IdentityInterface(fields=['func',
                                                                     'fwhm']),
                            name='inputspec')
        outputnode = pe.Node(interface=util.IdentityInterface(fields=['reference',
                                                                  'motion_parameters',
                                                                  'realigned_files',
                                                                  'motion_plots',
                                                                  'mask',
                                                                  'smoothed_files',
                                                                  'mean']),
                         name='outputspec')

    """
    Set up a node to define outputs for the preprocessing workflow

    """

    """
    Convert functional images to float representation. Since there can
    be more than one functional run we use a MapNode to convert each
    run.
    """

    img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float',
                                                 op_string = '',
                                                 suffix='_dtype'),
                           iterfield=['in_file'],
                           name='img2float')
    featpreproc.connect(inputnode, 'func', img2float, 'in_file')

    """
    Extract the first volume of the first run as the reference
    """

    extract_ref = pe.MapNode(interface=fsl.ExtractROI(t_size=1),
                             iterfield=['in_file', 't_min'],
                             name = 'extractref')

    featpreproc.connect(img2float, 'out_file', extract_ref, 'in_file')
    featpreproc.connect(img2float, ('out_file', pickmiddle), extract_ref, 't_min')
    featpreproc.connect(extract_ref, 'roi_file', outputnode, 'reference')

    """
    Realign the functional runs to the reference (1st volume of first run)
    """

    motion_correct = pe.MapNode(interface=fsl.MCFLIRT(save_mats = True,
                                                      save_plots = True),
                                name='realign',
                                iterfield = ['in_file', 'ref_file'])
    featpreproc.connect(img2float, 'out_file', motion_correct, 'in_file')
    featpreproc.connect(extract_ref, 'roi_file', motion_correct, 'ref_file')
    featpreproc.connect(motion_correct, 'par_file', outputnode, 'motion_parameters')
    featpreproc.connect(motion_correct, 'out_file', outputnode, 'realigned_files')

    """
    Plot the estimated motion parameters
    """

    plot_motion = pe.MapNode(interface=fsl.PlotMotionParams(in_source='fsl'),
                            name='plot_motion',
                            iterfield=['in_file'])
    plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
    featpreproc.connect(motion_correct, 'par_file', plot_motion, 'in_file')
    featpreproc.connect(plot_motion, 'out_file', outputnode, 'motion_plots')

    """
    Extract the mean volume of the first functional run
    """

    meanfunc = pe.MapNode(interface=fsl.ImageMaths(op_string = '-Tmean',
                                                   suffix='_mean'),
                          iterfield=['in_file'],
                          name='meanfunc')
    featpreproc.connect(motion_correct, 'out_file', meanfunc, 'in_file')

    """
    Strip the skull from the mean functional to generate a mask
    """

    meanfuncmask = pe.MapNode(interface=fsl.BET(mask = True,
                                             no_output=True,
                                             frac = 0.3),
                              iterfield=['in_file'],
                              name = 'meanfuncmask')
    featpreproc.connect(meanfunc, 'out_file', meanfuncmask, 'in_file')

    """
    Mask the functional runs with the extracted mask
    """

    maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet',
                                                   op_string='-mas'),
                          iterfield=['in_file', 'in_file2'],
                          name = 'maskfunc')
    featpreproc.connect(motion_correct, 'out_file', maskfunc, 'in_file')
    featpreproc.connect(meanfuncmask, 'mask_file', maskfunc, 'in_file2')


    """
    Determine the 2nd and 98th percentile intensities of each functional run
    """

    getthresh = pe.MapNode(interface=fsl.ImageStats(op_string='-p 2 -p 98'),
                           iterfield = ['in_file'],
                           name='getthreshold')
    featpreproc.connect(maskfunc, 'out_file', getthresh, 'in_file')


    """
    Threshold the first run of the functional data at 10% of the 98th percentile
    """

    threshold = pe.MapNode(interface=fsl.ImageMaths(out_data_type='char',
                                                 suffix='_thresh'),
                           iterfield=['in_file', 'op_string'],
                           name='threshold')
    featpreproc.connect(maskfunc, 'out_file', threshold, 'in_file')

    """
    Define a function to get 10% of the intensity
    """

    featpreproc.connect(getthresh, ('out_stat', getthreshop), threshold, 'op_string')

    """
    Determine the median value of the functional runs using the mask
    """

    medianval = pe.MapNode(interface=fsl.ImageStats(op_string='-k %s -p 50'),
                           iterfield = ['in_file', 'mask_file'],
                           name='medianval')
    featpreproc.connect(motion_correct, 'out_file', medianval, 'in_file')
    featpreproc.connect(threshold, 'out_file', medianval, 'mask_file')

    """
    Dilate the mask
    """

    dilatemask = pe.MapNode(interface=fsl.ImageMaths(suffix='_dil',
                                                  op_string='-dilF'),
                            iterfield=['in_file'],
                            name='dilatemask')
    featpreproc.connect(threshold, 'out_file', dilatemask, 'in_file')
    featpreproc.connect(dilatemask, 'out_file', outputnode, 'mask')

    """
    Mask the motion corrected functional runs with the dilated mask
    """

    maskfunc2 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                          iterfield=['in_file', 'in_file2'],
                          name='maskfunc2')
    featpreproc.connect(motion_correct, 'out_file', maskfunc2, 'in_file')
    featpreproc.connect(dilatemask, 'out_file', maskfunc2, 'in_file2')

    """
    Smooth each run using SUSAN with the brightness threshold set to 75%
    of the median value for each run and a mask consituting the mean
    functional
    """

    smooth = create_susan_smooth()

    featpreproc.connect(inputnode, 'fwhm', smooth, 'inputnode.fwhm')
    featpreproc.connect(maskfunc2, 'out_file', smooth, 'inputnode.in_files')
    featpreproc.connect(dilatemask, 'out_file', smooth, 'inputnode.mask_file')

    """
    Mask the smoothed data with the dilated mask
    """

    maskfunc3 = pe.MapNode(interface=fsl.ImageMaths(suffix='_mask',
                                                    op_string='-mas'),
                          iterfield=['in_file', 'in_file2'],
                          name='maskfunc3')
    featpreproc.connect(smooth, 'outputnode.smoothed_files', maskfunc3, 'in_file')

    featpreproc.connect(dilatemask, 'out_file', maskfunc3, 'in_file2')


    concatnode = pe.Node(interface=util.Merge(2),
                         name='concat')
    featpreproc.connect(maskfunc2,('out_file', tolist), concatnode, 'in1')
    featpreproc.connect(maskfunc3,('out_file', tolist), concatnode, 'in2')

    """
    The following nodes select smooth or unsmoothed data depending on the
    fwhm. This is because SUSAN defaults to smoothing the data with about the
    voxel size of the input data if the fwhm parameter is less than 1/3 of the
    voxel size.
    """
    selectnode = pe.Node(interface=util.Select(),name='select')

    featpreproc.connect(concatnode, 'out', selectnode, 'inlist')

    featpreproc.connect(inputnode, ('fwhm', chooseindex), selectnode, 'index')
    featpreproc.connect(selectnode, 'out', outputnode, 'smoothed_files')


    """
    Scale the median value of the run is set to 10000
    """

    meanscale = pe.MapNode(interface=fsl.ImageMaths(suffix='_gms'),
                          iterfield=['in_file','op_string'],
                          name='meanscale')
    featpreproc.connect(selectnode, 'out', meanscale, 'in_file')

    """
    Define a function to get the scaling factor for intensity normalization
    """

    featpreproc.connect(medianval, ('out_stat', getmeanscale), meanscale, 'op_string')

    """
    Perform temporal highpass filtering on the data
    """

    if highpass:
        highpass = pe.MapNode(interface=fsl.ImageMaths(suffix='_tempfilt'),
                              iterfield=['in_file'],
                              name='highpass')
        featpreproc.connect(inputnode, ('highpass', highpass_operand), highpass, 'op_string')
        featpreproc.connect(meanscale, 'out_file', highpass, 'in_file')
        featpreproc.connect(highpass, 'out_file', outputnode, 'highpassed_files')

    """
    Generate a mean functional image from the first run
    """

    meanfunc3 = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean',
                                                    suffix='_mean'),
                           iterfield=['in_file'],
                          name='meanfunc3')
    if highpass:
        featpreproc.connect(highpass, 'out_file', meanfunc3, 'in_file')
    else:
        featpreproc.connect(meanscale, 'out_file', meanfunc3, 'in_file')

    featpreproc.connect(meanfunc3, 'out_file', outputnode, 'mean')


    return featpreproc
Beispiel #19
0
#Wraps command **flirt**
NodeHash_22c888c0 = pe.MapNode(interface = fsl.FLIRT(), name = 'NodeName_22c888c0', iterfield = ['in_file', 'in_matrix_file', 'reference', 'wm_seg'])
NodeHash_22c888c0.inputs.cost = 'bbr'
NodeHash_22c888c0.inputs.dof = 6
NodeHash_22c888c0.inputs.no_resample = True

#Wraps command **mcflirt**
NodeHash_32896ec0 = pe.MapNode(interface = fsl.MCFLIRT(), name = 'NodeName_32896ec0', iterfield = ['in_file', 'ref_file'])
NodeHash_32896ec0.inputs.interpolation = 'spline'
NodeHash_32896ec0.inputs.save_mats = True
NodeHash_32896ec0.inputs.save_plots = True
NodeHash_32896ec0.inputs.save_rms = True

#Wraps command **fsl_tsplot**
NodeHash_2a03f5c0 = pe.MapNode(interface = fsl.PlotMotionParams(), name = 'NodeName_2a03f5c0', iterfield = ['in_file'])
NodeHash_2a03f5c0.inputs.args = '-a x,y,z -w 640 -h 144'
NodeHash_2a03f5c0.inputs.in_source = 'fsl'
NodeHash_2a03f5c0.iterables = [('plot_type', ['rotations', 'translations'])]

#Wraps command **fslmaths**
NodeHash_22a97680 = pe.MapNode(interface = fsl.MeanImage(), name = 'NodeName_22a97680', iterfield = ['in_file'])
NodeHash_22a97680.inputs.dimension = 'T'

#Wraps command **bet**
NodeHash_55ea000 = pe.MapNode(interface = fsl.BET(), name = 'NodeName_55ea000', iterfield = ['in_file'])
NodeHash_55ea000.inputs.frac = 0.3
NodeHash_55ea000.inputs.mask = True
NodeHash_55ea000.inputs.no_output = True

#Wraps command **fslmaths**
Beispiel #20
0
preproc.connect(inputnode, ('func', getmiddlevolume), extract_ref, 't_min')
"""
Realign the functional runs to the middle volume of the first run
"""

motion_correct = pe.MapNode(interface=fsl.MCFLIRT(save_mats=True,
                                                  save_plots=True),
                            name='realign',
                            iterfield=['in_file'])
preproc.connect(img2float, 'out_file', motion_correct, 'in_file')
preproc.connect(extract_ref, 'roi_file', motion_correct, 'ref_file')
"""
Plot the estimated motion parameters
"""

plot_motion = pe.MapNode(interface=fsl.PlotMotionParams(in_source='fsl'),
                         name='plot_motion',
                         iterfield=['in_file'])
plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
preproc.connect(motion_correct, 'par_file', plot_motion, 'in_file')
"""
Extract the mean volume of the first functional run
"""

meanfunc = pe.Node(interface=fsl.ImageMaths(op_string='-Tmean',
                                            suffix='_mean'),
                   name='meanfunc')
preproc.connect(motion_correct, ('out_file', pickfirst), meanfunc, 'in_file')
"""
Strip the skull from the mean functional to generate a mask
"""
Beispiel #21
0
def create_motion_correction_workflow(analysis_info, name='moco'):
    """uses sub-workflows to perform different registration steps.
    Requires fsl and freesurfer tools
    Parameters
    ----------
    name : string
        name of workflow
    
    Example
    -------
    >>> motion_correction_workflow = create_motion_correction_workflow('motion_correction_workflow')
    >>> motion_correction_workflow.inputs.inputspec.output_directory = '/data/project/raw/BIDS/sj_1/'
    >>> motion_correction_workflow.inputs.inputspec.in_files = ['sub-001.nii.gz','sub-002.nii.gz']
    >>> motion_correction_workflow.inputs.inputspec.which_file_is_EPI_space = 'middle'
 
    Inputs::
          inputspec.output_directory : directory in which to sink the result files
          inputspec.in_files : list of functional files
          inputspec.which_file_is_EPI_space : determines which file is the 'standard EPI space'
    Outputs::
           outputspec.EPI_space_file : standard EPI space file, one timepoint
           outputspec.motion_corrected_files : motion corrected files
           outputspec.motion_correction_plots : motion correction plots
           outputspec.motion_correction_parameters : motion correction parameters
    """
    import os
    import os.path as op
    import nipype.pipeline as pe
    import nipype.interfaces.fsl as fsl
    import nipype.interfaces.utility as util
    import nipype.interfaces.io as nio
    from nipype.interfaces.utility import Function, IdentityInterface
    import nipype.interfaces.utility as niu

    ########################################################################################
    # nodes
    ########################################################################################

    input_node = pe.Node(IdentityInterface(fields=[
        'in_files', 'inplane_T2_files', 'T2_files_reg_matrices',
        'output_directory', 'which_file_is_EPI_space', 'sub_id', 'tr'
    ]),
                         name='inputspec')
    output_node = pe.Node(IdentityInterface(fields=([
        'motion_corrected_files', 'EPI_space_file', 'T2_space_file',
        'motion_correction_plots', 'motion_correction_parameters',
        'extended_motion_correction_parameters',
        'new_motion_correction_parameters'
    ])),
                          name='outputspec')

    EPI_file_selector_node = pe.Node(Function(
        input_names=['which_file', 'in_files'],
        output_names='raw_EPI_space_file',
        function=EPI_file_selector),
                                     name='EPI_file_selector_node')

    # motion_correct_EPI_space = pe.Node(interface=fsl.MCFLIRT(
    #                 save_mats = True,
    #                 stats_imgs = True,
    #                 save_plots = True,
    #                 save_rms = True,
    #                 cost = 'normmi',
    #                 interpolation = 'sinc',
    #                 dof = 6,
    #                 # ref_vol = 0
    #                 ), name='realign_space')

    # mean_bold = pe.Node(interface=fsl.maths.MeanImage(dimension='T'), name='mean_space')

    # new approach, which should aid in the joint motion correction of
    # multiple sessions together, by pre-registering each run.
    # the strategy would be to, for each run, take the first TR
    # and FLIRT-align (6dof) it to the EPI_space file.
    # then we can use this as an --infile argument to mcflirt.

    select_target_T2_node = pe.Node(Function(
        input_names=['T2_file_list', 'target_session'],
        output_names=['which_T2'],
        function=select_target_T2),
                                    name='select_target_T2_node')
    select_target_T2_node.inputs.target_session = analysis_info[
        'target_session']

    # select_target_epi_node = pe.Node(Function(input_names=['epi_file_list', 'T2_file_list', 'target_session', 'which_file'], output_names=['target_epi'],
    #                                 function=select_target_epi), name='select_target_epi_node')
    # select_target_epi_node.inputs.target_session = analysis_info['target_session']

    select_T2_for_epi_node = pe.MapNode(Function(
        input_names=['epi_file', 'T2_file_list'],
        output_names=['which_T2_file'],
        function=select_T2_for_epi),
                                        name='select_T2_for_epi_node',
                                        iterfield=['epi_file'])

    select_T2_mat_for_epi_node = pe.MapNode(Function(
        input_names=['epi_file', 'T2_file_list'],
        output_names=['which_T2_file'],
        function=select_T2_for_epi),
                                            name='select_T2_mat_for_epi_node',
                                            iterfield=['epi_file'])

    bet_T2_node = pe.MapNode(interface=fsl.BET(
        frac=analysis_info['T2_bet_f_value'],
        vertical_gradient=analysis_info['T2_bet_g_value'],
        functional=False,
        mask=True),
                             name='bet_T2',
                             iterfield=['in_file'])

    bet_epi_node = pe.MapNode(interface=fsl.BET(
        frac=analysis_info['T2_bet_f_value'],
        vertical_gradient=analysis_info['T2_bet_g_value'],
        functional=True,
        mask=True),
                              name='bet_epi',
                              iterfield=['in_file'])

    motion_correct_all = pe.MapNode(interface=fsl.MCFLIRT(save_mats=True,
                                                          save_plots=True,
                                                          cost='normmi',
                                                          interpolation='sinc',
                                                          stats_imgs=True,
                                                          dof=6),
                                    name='realign_all',
                                    iterfield=['in_file', 'ref_file'])

    plot_motion = pe.MapNode(interface=fsl.PlotMotionParams(in_source='fsl'),
                             name='plot_motion',
                             iterfield=['in_file'])

    extend_motion_pars = pe.MapNode(Function(
        input_names=['moco_par_file', 'tr'],
        output_names=['new_out_file', 'ext_out_file'],
        function=_extend_motion_parameters),
                                    name='extend_motion_pars',
                                    iterfield=['moco_par_file'])

    # registration node is set up for rigid-body within-modality reg
    # reg_flirt_N = pe.MapNode(fsl.FLIRT(cost_func='normcorr', output_type = 'NIFTI_GZ',# dof = 6, schedule =  op.abspath(op.join(os.environ['FSLDIR'], 'etc', 'flirtsch', 'sch2D_6dof')),
    #                                     interp = 'sinc', dof = 6),
    #                     name = 'reg_flirt_N', iterfield = ['in_file'])

    regapply_moco_node = pe.MapNode(interface=fsl.ApplyXfm(interp='spline'),
                                    name='regapply_moco_node',
                                    iterfield=['in_file', 'in_matrix_file'])

    resample_epis = pe.MapNode(fsl.maths.MathsCommand(args=' -subsamp2offc '),
                               name='resample_epis',
                               iterfield=['in_file'])
    resample_target_T2 = pe.Node(
        fsl.maths.MathsCommand(args=' -subsamp2offc '),
        name='resample_target_T2')

    rename = pe.Node(niu.Rename(format_string='session_EPI_space',
                                keep_ext=True),
                     name='namer')

    rename_T2 = pe.Node(niu.Rename(format_string='session_T2_space',
                                   keep_ext=True),
                        name='namer_T2')

    ########################################################################################
    # workflow
    ########################################################################################

    motion_correction_workflow = pe.Workflow(name=name)

    motion_correction_workflow.connect(input_node, 'in_files', bet_epi_node,
                                       'in_file')
    motion_correction_workflow.connect(input_node, 'inplane_T2_files',
                                       bet_T2_node, 'in_file')

    # select example func data, and example T2 space
    # motion_correction_workflow.connect(input_node, 'which_file_is_EPI_space', select_target_epi_node, 'which_file')
    # motion_correction_workflow.connect(bet_epi_node, 'out_file', select_target_epi_node, 'epi_file_list')
    # motion_correction_workflow.connect(bet_T2_node, 'out_file', select_target_epi_node, 'T2_file_list')
    motion_correction_workflow.connect(bet_T2_node, 'out_file',
                                       select_target_T2_node, 'T2_file_list')

    # motion correct and average the standard EPI file
    # motion_correction_workflow.connect(select_target_epi_node, 'target_epi', motion_correct_EPI_space, 'in_file')
    # motion_correction_workflow.connect(motion_correct_EPI_space, 'out_file', mean_bold, 'in_file')

    # output node, for later saving
    # motion_correction_workflow.connect(mean_bold, 'out_file', output_node, 'EPI_space_file')
    motion_correction_workflow.connect(select_target_T2_node, 'which_T2',
                                       output_node, 'T2_space_file')

    # find the relevant T2 files for each of the epi files
    motion_correction_workflow.connect(bet_epi_node, 'out_file',
                                       select_T2_for_epi_node, 'epi_file')
    motion_correction_workflow.connect(bet_T2_node, 'out_file',
                                       select_T2_for_epi_node, 'T2_file_list')

    # find the relevant T2 registration file for each of the epi files
    motion_correction_workflow.connect(bet_epi_node, 'out_file',
                                       select_T2_mat_for_epi_node, 'epi_file')
    motion_correction_workflow.connect(input_node, 'T2_files_reg_matrices',
                                       select_T2_mat_for_epi_node,
                                       'T2_file_list')

    # motion correction across runs
    # motion_correction_workflow.connect(prereg_flirt_N, 'out_matrix_file', motion_correct_all, 'init')
    motion_correction_workflow.connect(bet_epi_node, 'out_file',
                                       motion_correct_all, 'in_file')
    motion_correction_workflow.connect(select_T2_for_epi_node, 'which_T2_file',
                                       motion_correct_all, 'ref_file')
    # motion_correction_workflow.connect(mean_bold, 'out_file', motion_correct_all, 'ref_file')

    # the registration
    # motion_correction_workflow.connect(select_T2_for_epi_node, 'which_T2_file', reg_flirt_N, 'in_file')
    # motion_correction_workflow.connect(select_target_T2_node, 'which_T2', reg_flirt_N, 'reference')

    # output of motion correction of all files
    motion_correction_workflow.connect(motion_correct_all, 'par_file',
                                       output_node,
                                       'motion_correction_parameters')
    motion_correction_workflow.connect(motion_correct_all, 'out_file',
                                       regapply_moco_node, 'in_file')

    # registration has already been done by hand. This registration matrix is in the datasource, and applied here.
    motion_correction_workflow.connect(select_T2_mat_for_epi_node,
                                       'which_T2_file', regapply_moco_node,
                                       'in_matrix_file')
    motion_correction_workflow.connect(select_target_T2_node, 'which_T2',
                                       regapply_moco_node, 'reference')

    motion_correction_workflow.connect(regapply_moco_node, 'out_file',
                                       resample_epis, 'in_file')
    motion_correction_workflow.connect(resample_epis, 'out_file', output_node,
                                       'motion_corrected_files')

    motion_correction_workflow.connect(motion_correct_all, 'par_file',
                                       extend_motion_pars, 'moco_par_file')
    motion_correction_workflow.connect(input_node, 'tr', extend_motion_pars,
                                       'tr')
    motion_correction_workflow.connect(
        extend_motion_pars, 'ext_out_file', output_node,
        'extended_motion_correction_parameters')
    motion_correction_workflow.connect(extend_motion_pars, 'new_out_file',
                                       output_node,
                                       'new_motion_correction_parameters')

    motion_correction_workflow.connect(rename, 'out_file', output_node,
                                       'EPI_space_file')

    ########################################################################################
    # Plot the estimated motion parameters
    ########################################################################################

    plot_motion.iterables = ('plot_type', ['rotations', 'translations'])
    motion_correction_workflow.connect(motion_correct_all, 'par_file',
                                       plot_motion, 'in_file')
    motion_correction_workflow.connect(plot_motion, 'out_file', output_node,
                                       'motion_correction_plots')

    ########################################################################################
    # outputs via datasink
    ########################################################################################
    datasink = pe.Node(nio.DataSink(), name='sinker')
    datasink.inputs.parameterization = False

    # first link the workflow's output_directory into the datasink.
    motion_correction_workflow.connect(input_node, 'output_directory',
                                       datasink, 'base_directory')
    motion_correction_workflow.connect(input_node, 'sub_id', datasink,
                                       'container')

    motion_correction_workflow.connect(select_target_T2_node, 'which_T2',
                                       resample_target_T2, 'in_file')
    motion_correction_workflow.connect(resample_target_T2, 'out_file', rename,
                                       'in_file')
    motion_correction_workflow.connect(rename, 'out_file', datasink, 'reg')

    motion_correction_workflow.connect(select_target_T2_node, 'which_T2',
                                       rename_T2, 'in_file')
    motion_correction_workflow.connect(rename_T2, 'out_file', datasink,
                                       'reg.@T2')

    # motion_correction_workflow.connect(regapply_moco_node, 'out_file', datasink, 'mcf.hr')
    motion_correction_workflow.connect(resample_epis, 'out_file', datasink,
                                       'mcf')
    motion_correction_workflow.connect(motion_correct_all, 'par_file',
                                       datasink, 'mcf.motion_pars')
    motion_correction_workflow.connect(plot_motion, 'out_file', datasink,
                                       'mcf.motion_plots')
    motion_correction_workflow.connect(extend_motion_pars, 'ext_out_file',
                                       datasink, 'mcf.ext_motion_pars')
    motion_correction_workflow.connect(extend_motion_pars, 'new_out_file',
                                       datasink, 'mcf.new_motion_pars')

    motion_correction_workflow.connect(bet_T2_node, 'out_file', datasink,
                                       'mcf.T2s')
    # motion_correction_workflow.connect(motion_correct_all, 'out_file', datasink, 'mcf.hr_per_session')
    # motion_correction_workflow.connect(reg_flirt_N, 'out_file', datasink, 'mcf.T2_per_session')

    return motion_correction_workflow