def create_preproc_func_pipeline():#ref_slice, n_skip=4, n_slices=30, tr=2.5, sparse=False): # if sparse: # real_tr = tr/2 # else: # real_tr = tr inputnode = pe.Node(interface=util.IdentityInterface(fields=['func', "struct", "TR", "sparse"]), name="inputnode") pre_ica = pe.Node(interface=fsl.MELODIC(), name="pre_ica") pre_ica.inputs.no_mask = True pre_ica.inputs.out_all = True pre_ica.inputs.report = True skip = pe.Node(interface=fsl.ExtractROI(), name="skip") skip.inputs.t_min = 4 #TODO skip.inputs.t_size = 100000 realign = pe.Node(interface=spm.Realign(), name="realign") realign.inputs.register_to_mean = True tr_convert = pe.Node(interface=util.Function(input_names=['tr', 'sparse'], output_names=['tr'], function=get_tr), name="tr_converter") ta = pe.Node(interface=util.Function(input_names=['real_tr', 'n_slices'], output_names=['ta'], function=get_ta), name="ta") slice_timing = pe.Node(interface=spm.SliceTiming(), name="slice_timing") #slice_timing.inputs.num_slices = n_slices #slice_timing.inputs.time_repetition = real_tr #slice_timing.inputs.time_acquisition = real_tr - real_tr/float(n_slices) #slice_timing.inputs.slice_order = range(1,n_slices+1,2) + range(2,n_slices+1,2) #slice_timing.inputs.ref_slice = ref_slice coregister = pe.Node(interface=spm.Coregister(), name="coregister") coregister.inputs.jobtype= "estimate" smooth = pe.Node(interface=spm.Smooth(), name="smooth") smooth.inputs.fwhm = [8, 8, 8] susan_smooth = create_susan_smooth(name="susan_smooth") susan_smooth.inputs.inputnode.fwhm = 8 art = pe.Node(interface=ra.ArtifactDetect(), name="art") art.inputs.use_differences = [True,False] art.inputs.use_norm = True art.inputs.norm_threshold = 1 art.inputs.zintensity_threshold = 3 art.inputs.mask_type = 'file' art.inputs.parameter_source = 'SPM' compute_mask = pe.Node(interface=ComputeMask(), name="compute_mask") post_ica = pe.Node(interface=fsl.MELODIC(), name="post_ica") post_ica.inputs.out_all = True post_ica.inputs.report = True preproc_func = pe.Workflow(name="preproc_func") preproc_func.connect([ (inputnode,skip, [("func", "in_file")]), # (inputnode, pre_ica, [("func", "in_files"), # ("TR", "tr_sec")]), (coregister, compute_mask, [('coregistered_source','mean_volume')]), (skip, slice_timing, [("roi_file", "in_files"), (('roi_file', get_n_slices), "num_slices"), (('roi_file', get_slice_order), "slice_order"), (('roi_file', get_ref_slice), "ref_slice") ]), (inputnode, tr_convert, [("sparse", "sparse"), ("TR", "tr")]), (tr_convert, slice_timing, [("tr", "time_repetition")]), (tr_convert, ta, [("tr", "real_tr")]), (skip, ta, [(('roi_file', get_n_slices), "n_slices")]), (ta, slice_timing, [("ta", "time_acquisition")]), (slice_timing, realign, [("timecorrected_files", "in_files")]), # (skip, realign, [("roi_file", "in_files")]), (inputnode, coregister, [("struct", "target")]), (realign, coregister,[('mean_image', 'source'), ('realigned_files','apply_to_files')]), (coregister, susan_smooth, [("coregistered_files","inputnode.in_files")]), (compute_mask, susan_smooth,[('brain_mask','inputnode.mask_file')]), # (susan_smooth, post_ica, [("outputnode.smoothed_files", "in_files")]), # (inputnode, post_ica, [("TR", "tr_sec")]), # (compute_mask,post_ica,[('brain_mask','mask')]), # (coregister, smooth, [("coregistered_files","in_files")]), (compute_mask,art,[('brain_mask','mask_file')]), (realign,art,[('realignment_parameters','realignment_parameters')]), (realign,art,[('realigned_files','realigned_files')]), ]) outputnode = pe.Node(interface=util.IdentityInterface(fields=['preproced_files', 'realignment_parameters', 'outlier_files', 'mask_file']), name="outputnode") preproc_func.connect(realign, 'realignment_parameters', outputnode, 'realignment_parameters') preproc_func.connect(susan_smooth, 'outputnode.smoothed_files', outputnode, 'preproced_files') preproc_func.connect(art, 'outlier_files', outputnode, 'outlier_files') preproc_func.connect(compute_mask, 'brain_mask', outputnode, 'mask_file') return preproc_func
def create_func_preproc_workflow(name='functional_preprocessing', func_preproc_name="func_preproc"): ##### # Setup workflow ##### preproc = pe.Workflow(name=name) ##### # Setup input node ##### input_fields = [ "func", # list of functional images to run "func_mask", # list of functional images to run "fwhm", # fwhm "highpass", # highpass filtering "lowpass", # lowpass filtering ] inputnode = pe.Node(interface=util.IdentityInterface(fields=input_fields), name="inputspec") ##### # Setup output node ##### # Outputs output_fields = [ func_preproc_name, # final output (also has been intensity normalized) ] outputnode = pe.Node(util.IdentityInterface(fields=output_fields), name="outputspec") ##### # Setup renaming ##### renamer = OutputConnector(preproc, outputnode) # allows easy renaming of output file names ##### # Main Commands #### """ Prepare Input """ # Convert functional images to float representation img2float = pe.MapNode(fsl.ChangeDataType(output_datatype="float"), iterfield=["in_file"], name="00_img2float") preproc.connect(inputnode, 'func', img2float, 'in_file') """ Smoothing """ # Anisitropic-like? smoothing with your friend susan smooth = create_susan_smooth(name="01_susan_smooth") preproc.connect(inputnode, 'fwhm', smooth, 'inputnode.fwhm') preproc.connect(img2float, 'out_file', smooth, 'inputnode.in_files') preproc.connect(inputnode, 'func_mask', smooth, 'inputnode.mask_file') # Mask smoothed data with dilated mask funcbrain = pe.MapNode(fsl.ApplyMask(), iterfield=["in_file", "mask_file"], name="02_funcbrain") preproc.connect(smooth, 'outputnode.smoothed_files', funcbrain, 'in_file') preproc.connect(inputnode, 'func_mask', funcbrain, 'mask_file') # Determine if want to take output from smoothed or non-smoothed data forward # This would be the case if the fwhm is less than 1/3 of the voxel size ## gather 2 types of functional images concatnode = pe.Node(interface=util.Merge(2), name='02_concat') preproc.connect(img2float, ('out_file', tolist), concatnode, 'in1') preproc.connect(funcbrain, ('out_file', tolist), concatnode, 'in2') ## select one selectnode = pe.Node(interface=util.Select(),name='02_select') preproc.connect(concatnode, 'out', selectnode, 'inlist') preproc.connect(inputnode, ('fwhm', chooseindex), selectnode, 'index') """ Filter """ filt = pe.MapNode(fsl.TemporalFilter(), iterfield=["in_file"], name="03_filter") preproc.connect(inputnode, 'highpass', filt, 'highpass_sigma') preproc.connect(inputnode, 'lowpass', filt, 'lowpass_sigma') preproc.connect(selectnode, 'out', filt, 'in_file') """ Intensity Normalization """ # Determine the median value of the functional runs using the mask medianval = pe.MapNode(fsl.ImageStats(op_string="-k %s -p 50"), iterfield = ["in_file", "mask_file"], name="04_medianval") preproc.connect(filt, 'out_file', medianval, 'in_file') preproc.connect(inputnode, 'func_mask', medianval, 'mask_file') # Scale mean value of run to 10000 meanscale = pe.MapNode(interface=fsl.ImageMaths(suffix='_gms'), iterfield=['in_file', 'op_string'], name='04_meanscale') preproc.connect(filt, 'out_file', meanscale, 'in_file') ## function to get scaling factor preproc.connect(medianval, ('out_stat', getmeanscale), meanscale, 'op_string') """ Get Final Functional Data and Mean """ ## functional 4D renamer.connect(meanscale, 'out_file', func_preproc_name) return preproc
def create_resting_workflow(name="resting_state"): """Return a preprocessing workflow. Input spec node takes these three inputs: - Timeseries (image files) - FWHM of smoothing kernel for (in mms) - FNIRT warp coefficient image - Freesurfer Subject ID Output node returns these files: - Smoothed timeseries (fully preprocessed and smoothed timeseries in native space) - Unsmoothed timeseries (identical steps except no smoothing in the volume) - Example func (target volume for MCFLIRT realignment) - Mean func (unsmoothed mean functional) - Funcational mask (binary dilated brainmask in functional space) - Realignment parameters (text files from MCFLIRT) - Outlier Files (outlier text files from ART) - Plotted estimated rotations from MCFLIRT - Plotted estimated translastion from MCFLIRT - Plotted estimated relative and absolute displacement from MCFLIRT - Plotted global mean intensity value - Sliced png of the example func (MCFLIRT target) - Sliced png of the unsmoothed mean functional volume - Tkregister-style affine matrix - FSL-style affine matrix - Sliced png summarizing the functional to anatomical transform - Optimization cost file quantitatively summarizing the transformation """ resting = pe.Workflow(name=name) # Define the inputs for the preprocessing workflow inputnode = pe.Node(util.IdentityInterface(fields=["timeseries", "subject_id", "warpfield", "smooth_fwhm"]), name="inputspec") # Remove the first two frames to account for T1 stabalization trimmer = pe.MapNode(fsl.ExtractROI(t_min=6), iterfield=["in_file"], name="trimmer") # Convert functional images to float representation img2float = pe.MapNode(fsl.ChangeDataType(output_datatype="float"), iterfield=["in_file"], name="img2float") # Perform slice-timing correction slicetime = pe.MapNode(fsl.SliceTimer(interleaved=True, time_repetition=6), iterfield=["in_file"], name="slicetime") # Motion correct realign = create_realignment_workflow() skullstrip = create_skullstrip_workflow() art = create_art_workflow(make_movie=False) func2anat = create_bbregister_workflow() confounds = create_confound_removal_workflow() susan = create_susan_smooth() normalize = create_normalize_workflow() tosurf = create_surface_projection_workflow() rename = pe.MapNode(util.Rename(format_string="timeseries", keep_ext=True), iterfield=["in_file"], name="rename") resting.connect([ (inputnode, trimmer, [("timeseries", "in_file"), (("timeseries", get_trimmed_length), "t_size")]), (trimmer, img2float, [("roi_file", "in_file")]), (img2float, slicetime, [("out_file", "in_file")]), (slicetime, realign, [("slice_time_corrected_file", "inputs.timeseries")]), (realign, skullstrip, [("outputs.timeseries", "inputs.timeseries")]), (realign, art, [("outputs.realign_parameters", "inputs.realignment_parameters")]), (img2float, art, [("out_file", "inputs.raw_timeseries")]), (skullstrip, art, [("outputs.timeseries", "inputs.realigned_timeseries"), ("outputs.mask_file", "inputs.mask_file")]), (skullstrip, func2anat, [("outputs.mean_func", "inputs.source_file")]), (inputnode, func2anat, [("subject_id", "inputs.subject_id")]), (inputnode, confounds, [("subject_id", "inputs.subject_id")]), (skullstrip, confounds, [("outputs.timeseries", "inputs.timeseries")]), (realign, confounds, [("outputs.realign_parameters", "inputs.motion_parameters")]), (func2anat, confounds, [("outputs.tkreg_mat", "inputs.reg_file")]), (confounds, susan, [("outputs.timeseries", "inputnode.in_files")]), (skullstrip, susan, [("outputs.mask_file", "inputnode.mask_file")]), (inputnode, susan, [("smooth_fwhm", "inputnode.fwhm")]), (susan, rename, [("outputnode.smoothed_files", "in_file")]), (susan, normalize, [("outputnode.smoothed_files", "inputs.timeseries")]), (inputnode, normalize, [("warpfield", "inputs.warpfield")]), (func2anat, normalize, [("outputs.flirt_mat", "inputs.flirt_affine")]), (confounds, tosurf, [("outputs.timeseries", "inputs.timeseries")]), (func2anat, tosurf, [("outputs.tkreg_mat", "inputs.tkreg_affine")]), (inputnode, tosurf, [("subject_id", "inputs.subject_id"), ("smooth_fwhm", "inputs.smooth_fwhm")]), ]) # Define the outputs of the top-level workflow output_fields = ["volume_timeseries", "surface_timeseries", "native_timeseries", "example_func", "mean_func", "functional_mask", "realign_parameters", "mean_func_slices", "intensity_plot", "outlier_volumes", "realign_report", "flirt_affine", "tkreg_affine", "coreg_report", "confound_sources"] outputnode = pe.Node(util.IdentityInterface(fields=output_fields), name="outputspec") resting.connect([ (realign, outputnode, [("outputs.realign_report", "realign_report"), ("outputs.realign_parameters", "realign_parameters"), ("outputs.example_func", "example_func")]), (skullstrip, outputnode, [("outputs.mean_func", "mean_func"), ("outputs.mask_file", "functional_mask"), ("outputs.report_png", "mean_func_slices")]), (art, outputnode, [("outputs.intensity_plot", "intensity_plot"), ("outputs.outlier_volumes", "outlier_volumes")]), (func2anat, outputnode, [("outputs.tkreg_mat", "tkreg_affine"), ("outputs.flirt_mat", "flirt_affine"), ("outputs.report", "coreg_report")]), (confounds, outputnode, [("outputs.confound_sources", "confound_sources")]), (tosurf, outputnode, [("outputs.timeseries", "surface_timeseries")]), (normalize, outputnode, [("outputs.timeseries", "volume_timeseries")]), (rename, outputnode, [("out_file", "native_timeseries")]), ]) return resting, inputnode, outputnode
def create_resting_workflow(name="resting_state"): """Return a preprocessing workflow. Input spec node takes these three inputs: - Timeseries (image files) - FWHM of smoothing kernel for (in mms) - FNIRT warp coefficient image - Freesurfer Subject ID Output node returns these files: - Smoothed timeseries (fully preprocessed and smoothed timeseries in native space) - Unsmoothed timeseries (identical steps except no smoothing in the volume) - Example func (target volume for MCFLIRT realignment) - Mean func (unsmoothed mean functional) - Funcational mask (binary dilated brainmask in functional space) - Realignment parameters (text files from MCFLIRT) - Outlier Files (outlier text files from ART) - Plotted estimated rotations from MCFLIRT - Plotted estimated translastion from MCFLIRT - Plotted estimated relative and absolute displacement from MCFLIRT - Plotted global mean intensity value - Sliced png of the example func (MCFLIRT target) - Sliced png of the unsmoothed mean functional volume - Tkregister-style affine matrix - FSL-style affine matrix - Sliced png summarizing the functional to anatomical transform - Optimization cost file quantitatively summarizing the transformation """ resting = pe.Workflow(name=name) # Define the inputs for the preprocessing workflow inputnode = pe.Node(util.IdentityInterface( fields=["timeseries", "subject_id", "warpfield", "smooth_fwhm"]), name="inputspec") # Remove the first two frames to account for T1 stabalization trimmer = pe.MapNode(fsl.ExtractROI(t_min=6), iterfield=["in_file"], name="trimmer") # Convert functional images to float representation img2float = pe.MapNode(fsl.ChangeDataType(output_datatype="float"), iterfield=["in_file"], name="img2float") # Perform slice-timing correction slicetime = pe.MapNode(fsl.SliceTimer(interleaved=True, time_repetition=6), iterfield=["in_file"], name="slicetime") # Motion correct realign = create_realignment_workflow() skullstrip = create_skullstrip_workflow() art = create_art_workflow(make_movie=False) func2anat = create_bbregister_workflow() confounds = create_confound_removal_workflow() susan = create_susan_smooth() normalize = create_normalize_workflow() tosurf = create_surface_projection_workflow() rename = pe.MapNode(util.Rename(format_string="timeseries", keep_ext=True), iterfield=["in_file"], name="rename") resting.connect([ (inputnode, trimmer, [("timeseries", "in_file"), (("timeseries", get_trimmed_length), "t_size")]), (trimmer, img2float, [("roi_file", "in_file")]), (img2float, slicetime, [("out_file", "in_file")]), (slicetime, realign, [("slice_time_corrected_file", "inputs.timeseries")]), (realign, skullstrip, [("outputs.timeseries", "inputs.timeseries")]), (realign, art, [("outputs.realign_parameters", "inputs.realignment_parameters")]), (img2float, art, [("out_file", "inputs.raw_timeseries")]), (skullstrip, art, [("outputs.timeseries", "inputs.realigned_timeseries"), ("outputs.mask_file", "inputs.mask_file")]), (skullstrip, func2anat, [("outputs.mean_func", "inputs.source_file")]), (inputnode, func2anat, [("subject_id", "inputs.subject_id")]), (inputnode, confounds, [("subject_id", "inputs.subject_id")]), (skullstrip, confounds, [("outputs.timeseries", "inputs.timeseries")]), (realign, confounds, [("outputs.realign_parameters", "inputs.motion_parameters")]), (func2anat, confounds, [("outputs.tkreg_mat", "inputs.reg_file")]), (confounds, susan, [("outputs.timeseries", "inputnode.in_files")]), (skullstrip, susan, [("outputs.mask_file", "inputnode.mask_file")]), (inputnode, susan, [("smooth_fwhm", "inputnode.fwhm")]), (susan, rename, [("outputnode.smoothed_files", "in_file")]), (susan, normalize, [("outputnode.smoothed_files", "inputs.timeseries") ]), (inputnode, normalize, [("warpfield", "inputs.warpfield")]), (func2anat, normalize, [("outputs.flirt_mat", "inputs.flirt_affine")]), (confounds, tosurf, [("outputs.timeseries", "inputs.timeseries")]), (func2anat, tosurf, [("outputs.tkreg_mat", "inputs.tkreg_affine")]), (inputnode, tosurf, [("subject_id", "inputs.subject_id"), ("smooth_fwhm", "inputs.smooth_fwhm")]), ]) # Define the outputs of the top-level workflow output_fields = [ "volume_timeseries", "surface_timeseries", "native_timeseries", "example_func", "mean_func", "functional_mask", "realign_parameters", "mean_func_slices", "intensity_plot", "outlier_volumes", "realign_report", "flirt_affine", "tkreg_affine", "coreg_report", "confound_sources" ] outputnode = pe.Node(util.IdentityInterface(fields=output_fields), name="outputspec") resting.connect([ (realign, outputnode, [("outputs.realign_report", "realign_report"), ("outputs.realign_parameters", "realign_parameters"), ("outputs.example_func", "example_func")]), (skullstrip, outputnode, [("outputs.mean_func", "mean_func"), ("outputs.mask_file", "functional_mask"), ("outputs.report_png", "mean_func_slices")]), (art, outputnode, [("outputs.intensity_plot", "intensity_plot"), ("outputs.outlier_volumes", "outlier_volumes")]), (func2anat, outputnode, [("outputs.tkreg_mat", "tkreg_affine"), ("outputs.flirt_mat", "flirt_affine"), ("outputs.report", "coreg_report")]), (confounds, outputnode, [("outputs.confound_sources", "confound_sources")]), (tosurf, outputnode, [("outputs.timeseries", "surface_timeseries")]), (normalize, outputnode, [("outputs.timeseries", "volume_timeseries")]), (rename, outputnode, [("out_file", "native_timeseries")]), ]) return resting, inputnode, outputnode
'anisotropic_voxel', 'isotropic_surface'])] realign = pe.Node(interface=spm.Realign(), name="realign") realign.inputs.register_to_mean = True isotropic_voxel_smooth = pe.Node(interface=spm.Smooth(), name="isotropic_voxel_smooth") preprocessing.connect(realign, "realigned_files", isotropic_voxel_smooth, "in_files") preprocessing.connect(iter_fwhm, "fwhm", isotropic_voxel_smooth, "fwhm") compute_mask = pe.Node(interface=nipy.ComputeMask(), name="compute_mask") preprocessing.connect(realign, "mean_image", compute_mask, "mean_volume") anisotropic_voxel_smooth = fsl_wf.create_susan_smooth(name="anisotropic_voxel_smooth", separate_masks=False) anisotropic_voxel_smooth.inputs.smooth.output_type = 'NIFTI' preprocessing.connect(realign, "realigned_files", anisotropic_voxel_smooth, "inputnode.in_files") preprocessing.connect(iter_fwhm, "fwhm", anisotropic_voxel_smooth, "inputnode.fwhm") preprocessing.connect(compute_mask, "brain_mask", anisotropic_voxel_smooth, 'inputnode.mask_file') recon_all = pe.Node(interface=fs.ReconAll(), name = "recon_all") surfregister = pe.Node(interface=fs.BBRegister(),name='surfregister') surfregister.inputs.init = 'fsl' surfregister.inputs.contrast_type = 't2'
def create_func_preproc_workflow(name='functional_preprocessing', whichvol='middle', timeshift=False, tpattern=None, delete_vols=0, func_preproc_name="func_preproc"): ##### # Setup workflow ##### preproc = pe.Workflow(name=name) ##### # Setup input node ##### input_fields = [ "func", # list of functional images to run "fwhm", # fwhm "highpass", # highpass filtering "lowpass", # lowpass filtering "motion_nstages" ] inputnode = pe.Node(interface=util.IdentityInterface(fields=input_fields), name="inputspec") ##### # Setup output node ##### # Outputs output_fields = [ "func_mc_ref", # reference for motion correction "motion", # motion parameters "motion_rot", # plot of rotation "motion_trans", # plot of translations "motion_disp", # plot of abs/rel displacement "motion_max", # textfile with max abs/rel displacement "func_mc", # 4D motion corrected and skull stripped data "func_afnimask", # mask from 3dAutomask "example_func", # useful for registration later (simply a mean image) "func_mask", # mask that is less contrained # "func_mc_sm", # smoothed data # "func_mc_sm_ft", # time filtered data func_preproc_name, # final output (also has been intensity normalized) "func_mean", # mean of final output "example_func_all", "func_mask_all", "motion_all", "motion_01", "motion_02", "motion_03", "motion_04", "motion_05", "motion_06", "pics_func_mean_head1", "pics_func_mean_head2", "pics_func_mean_brain1", "pics_func_mean_brain2", "global_intensity", "norm", "outlier_vols", "pics_outlier_vols", "pics_global_plot" ] outputnode = pe.Node(util.IdentityInterface(fields=output_fields), name="outputspec") ##### # Setup renaming ##### renamer = OutputConnector(preproc, outputnode) # allows easy renaming of output file names ##### # Main Commands #### """ Prepare Input """ # Convert functional images to float representation img2float = pe.MapNode(fsl.ChangeDataType(output_datatype="float"), iterfield=["in_file"], name="00_img2float") preproc.connect(inputnode, 'func', img2float, 'in_file') nextnode = img2float nextout = 'out_file' # Remove the first X frames to account for T2 stabalization if delete_vols > 0: trimmer = pe.MapNode(fsl.ExtractROI(t_min=delete_vols), iterfield=["in_file"], name="00_trimmer") preproc.connect(img2float, 'out_file', trimmer, 'in_file') preproc.connect(img2float, ('out_file', get_trimmed_length, delete_vols), trimmer, 't_size') nextnode = trimmer nextout = 'roi_file' """ Time Shift Slices """ if timeshift: tshift = pe.MapNode(afni.ThreedTshift(tzero=0), iterfield=["in_file"], name="01_tshift") if tpattern is not None: tshift.inputs.tpattern = tpattern preproc.connect(nextnode, nextout, tshift, 'in_file') nextnode = tshift nextout = 'out_file' """ Deoblique and Reorient to FSL Friendly Space """ #deoblique = pe.MapNode(interface=afni.ThreedWarp(deoblique=True), # iterfield=["in_file"], name='01_deoblique') #preproc.connect(nextnode, nextout, deoblique, "in_file") deoblique = pe.MapNode(interface=afni.Threedrefit(deoblique=True), iterfield=["in_file"], name='01_deoblique') preproc.connect(nextnode, nextout, deoblique, "in_file") # TODO: # get orientation using following command: # orient=$( 3dinfo /Users/Shared/fsl/data/standard/MNI152_T1_2mm.nii.gz | grep orient | sed -e s/.*orient// -e s/\]// ) # so add additional input of reference orientation! (maybe this can be a general option?) reorient = pe.MapNode(interface=afni.Threedresample(orientation='RPI'), iterfield=["in_file"], name='01_reorient') preproc.connect(deoblique, "out_file", reorient, "in_file") """ Motion Correction """ # Get the middle volume of each run for motion correction if whichvol != 'mean': extract_ref = pe.Node(fsl.ExtractROI(t_size=1), iterfield=["in_file", "t_min"], name = "02_extractref") preproc.connect(reorient, ('out_file', pickfirst), extract_ref, 'in_file') preproc.connect(reorient, ('out_file', pickvol, 0, whichvol), extract_ref, 't_min') renamer.connect(extract_ref, 'roi_file', 'func_mc_ref') # Realign the functional runs to the reference (some volume from the 1st run) motion_correct = pe.MapNode(interface=fsl.MCFLIRT(save_mats = True, save_plots = True, save_rms = True, interpolation = 'sinc'), name='02_realign', iterfield = ['in_file']) preproc.connect(reorient, 'out_file', motion_correct, 'in_file') preproc.connect(inputnode, 'motion_nstages', motion_correct, 'stages') if whichvol != 'mean': preproc.connect(extract_ref, 'roi_file', motion_correct, 'ref_file') else: motion_correct.inputs.mean_vol = True renamer.connect(motion_correct, ('mean_img', pickfirst), 'func_mc_ref') renamer.connect(motion_correct, 'par_file', 'motion') # Combine motion parameters from different runs combinemotion = pe.Node(util.Function(input_names=["in_files"], output_names=["out_file"], function=combine_motion_params), name="combinemotion") preproc.connect(motion_correct, 'par_file', combinemotion, 'in_files') renamer.connect(combinemotion, 'out_file', 'motion_all') # Split motion up splitmotion = pe.Node(util.Function(input_names=["in_file", "out_prefix"], output_names=["out_files"], function=split_motion_params), name="splitmotion") preproc.connect(combinemotion, "out_file", splitmotion, "in_file") preproc.connect(splitmotion, ("out_files", pick_list_elem, 0), outputnode, 'motion_01') preproc.connect(splitmotion, ("out_files", pick_list_elem, 1), outputnode, 'motion_02') preproc.connect(splitmotion, ("out_files", pick_list_elem, 2), outputnode, 'motion_03') preproc.connect(splitmotion, ("out_files", pick_list_elem, 3), outputnode, 'motion_04') preproc.connect(splitmotion, ("out_files", pick_list_elem, 4), outputnode, 'motion_05') preproc.connect(splitmotion, ("out_files", pick_list_elem, 5), outputnode, 'motion_06') # Plot rotation parameters from MCFLIRT plotrot = pe.MapNode(fsl.PlotMotionParams(in_source="fsl", plot_type="rotations"), name="02_plotrotation", iterfield=["in_file"]) preproc.connect(motion_correct, 'par_file', plotrot, 'in_file') renamer.connect(plotrot, 'out_file', 'motion_rot') # Plot translation parameters from MCFLIRT plottrans = pe.MapNode(fsl.PlotMotionParams(in_source="fsl", plot_type="translations"), name="02_plottranslation", iterfield=["in_file"]) preproc.connect(motion_correct, 'par_file', plottrans, 'in_file') renamer.connect(plottrans, 'out_file', 'motion_trans') # Plot displacement parameters from MCFLIRT plotdisp = pe.MapNode(fsl.PlotMotionParams(in_source="fsl", plot_type="displacement"), name="02_plotdisplacement", iterfield=["in_file"]) preproc.connect(motion_correct, 'rms_files', plotdisp, 'in_file') renamer.connect(plotdisp, 'out_file', 'motion_disp') # Plot maximum displacement parameters (abs/rel) from MCFLIRT maxmotion = pe.MapNode(util.Function(input_names=["rms_files"], output_names=["out_file"], function=max_motion_func), iterfield=["rms_files"], name="02_maxmotion") preproc.connect(motion_correct, 'rms_files', maxmotion, 'rms_files') renamer.connect(maxmotion, 'out_file', 'motion_max') """ Skull Strip """ # Get a mean image of the realigned timeseries meanfunc1 = pe.MapNode(fsl.MeanImage(), iterfield=["in_file"], name="03_meanfunc1") preproc.connect(motion_correct, 'out_file', meanfunc1, 'in_file') # Get slices slicer_head1 = pe.MapNode(interface=misc.Slicer(width=5, height=4, slice_name="axial"), iterfield = ["in_file"], name = 'slicer_head1') slicer_head2 = pe.MapNode(interface=misc.Slicer(width=5, height=4, slice_name="sagittal"), iterfield = ["in_file"], name = 'slicer_head2') preproc.connect([ (meanfunc1, slicer_head1, [('out_file', 'in_file')]), (meanfunc1, slicer_head2, [('out_file', 'in_file')]) ]) renamer.connect(slicer_head1, "out_file", "pics_func_mean_head1") renamer.connect(slicer_head2, "out_file", "pics_func_mean_head2") # Skullstrip the mean functional image meanmask1 = pe.MapNode(afni.ThreedAutomask(dilate = 1), iterfield = ["in_file"], name = "03_meanmask1") preproc.connect(meanfunc1, 'out_file', meanmask1, 'in_file') renamer.connect(meanmask1, 'out_file', 'func_afnimask') # Apply to mean meanfunc2 = pe.MapNode(fsl.ApplyMask(), iterfield=["in_file", "mask_file"], name = "03_meanfunc2") preproc.connect(meanfunc1, 'out_file', meanfunc2, 'in_file') preproc.connect(meanmask1, 'out_file', meanfunc2, 'mask_file') renamer.connect(meanfunc2, 'out_file', 'example_func') # Get slices slicer_brain1 = pe.MapNode(interface=misc.Slicer(width=5, height=4, slice_name="axial"), iterfield = ["in_file"], name = 'slicer_brain1') slicer_brain2 = pe.MapNode(interface=misc.Slicer(width=5, height=4, slice_name="sagittal"), iterfield = ["in_file"], name = 'slicer_brain2') preproc.connect([ (meanfunc2, slicer_brain1, [('out_file', 'in_file')]), (meanfunc2, slicer_brain2, [('out_file', 'in_file')]) ]) renamer.connect(slicer_brain1, "out_file", "pics_func_mean_brain1") renamer.connect(slicer_brain2, "out_file", "pics_func_mean_brain2") # Combine different means and get their mean mergenode = pe.Node(fsl.Merge(dimension="t"), name="03b_merge") preproc.connect(meanfunc2, 'out_file', mergenode, 'in_files') meanfunc = pe.Node(fsl.MeanImage(), name="03b_meanfunc") preproc.connect(mergenode, 'merged_file', meanfunc, 'in_file') renamer.connect(meanfunc, 'out_file', 'example_func_all', format_string="example_func") # Apply to 4D functional funcbrain1 = pe.MapNode(fsl.ApplyMask(), iterfield=["in_file", "mask_file"], name = "03_funcbrain1") preproc.connect(motion_correct, 'out_file', funcbrain1, 'in_file') preproc.connect(meanmask1, 'out_file', funcbrain1, 'mask_file') #renamer.connect(funcbrain1, 'out_file', 'func_mc') """ Dilated Brain Mask """ # Determine the 2nd and 98th percentile intensities of each run getthresh = pe.MapNode(fsl.ImageStats(op_string="-p 2 -p 98"), iterfield = ["in_file"], name="04_getthreshold") preproc.connect(funcbrain1, 'out_file', getthresh, 'in_file') # Threshold the functional data at 10% of the 98th percentile threshold = pe.MapNode(fsl.ImageMaths(out_data_type="char", suffix="_thresh"), iterfield = ["in_file", "op_string"], name="04_threshold") preproc.connect(funcbrain1, 'out_file', threshold, "in_file") preproc.connect(getthresh, ("out_stat", get_thresh_op), threshold, "op_string") # Determine the median value of the functional runs using the mask medianval = pe.MapNode(fsl.ImageStats(op_string="-k %s -p 50"), iterfield = ["in_file", "mask_file"], name="04_medianval") preproc.connect(motion_correct, 'out_file', medianval, 'in_file') preproc.connect(threshold, 'out_file', medianval, 'mask_file') # Dilate the mask dilatemask = pe.MapNode(fsl.DilateImage(operation="max"), iterfield=["in_file"], name="04_dilatemask") preproc.connect(threshold, 'out_file', dilatemask, 'in_file') renamer.connect(dilatemask, 'out_file', 'func_mask') # Combine masks mergenode = pe.Node(fsl.Merge(dimension="t"), name="04b_merge") preproc.connect(dilatemask, 'out_file', mergenode, 'in_files') maskfunc = pe.Node(fsl.ImageMaths(op_string="-Tmin", suffix="_mask"), name="04b_maskfunc") preproc.connect(mergenode, 'merged_file', maskfunc, 'in_file') renamer.connect(maskfunc, 'out_file', 'func_mask_all', format_string="func_mask") # Mask the runs again with this new mask funcbrain2 = pe.MapNode(fsl.ApplyMask(), iterfield=["in_file", "mask_file"], name="04_funcbrain2") preproc.connect(motion_correct, 'out_file', funcbrain2, 'in_file') preproc.connect(dilatemask, 'out_file', funcbrain2, 'mask_file') renamer.connect(funcbrain2, 'out_file', 'func_mc') # Get a new mean image from each functional run meanfunc3 = pe.MapNode(fsl.MeanImage(), iterfield=["in_file"], name="04_meanfunc3") preproc.connect(funcbrain2, 'out_file', meanfunc3, 'in_file') """ Detect Any Artifacts """ art = pe.MapNode(ra.ArtifactDetect(use_differences = [True, False], use_norm = True, zintensity_threshold = 4, norm_threshold = 1, parameter_source = "FSL", mask_type = "file"), iterfield=["realignment_parameters","realigned_files","mask_file"], name="05_art") preproc.connect(motion_correct, "par_file", art, "realignment_parameters") preproc.connect(funcbrain2, "out_file", art, "realigned_files") preproc.connect(dilatemask, "out_file", art, "mask_file") renamer.connect(art, 'intensity_files', 'global_intensity') renamer.connect(art, 'norm_files', 'norm') renamer.connect(art, 'outlier_files', 'outlier_vols') renamer.connect(art, 'plot_files', 'pics_outlier_vols') plotmean = pe.MapNode(fsl.PlotTimeSeries(title="Global Mean Intensity"), iterfield=["in_file"], name="05_plotmean") preproc.connect(art, 'intensity_files', plotmean, 'in_file') renamer.connect(plotmean, 'out_file', 'pics_global_plot') """ Smoothing """ # Anisitropic-like? smoothing with your friend susan smooth = create_susan_smooth(name="06_susan_smooth") preproc.connect(inputnode, 'fwhm', smooth, 'inputnode.fwhm') preproc.connect(funcbrain2, 'out_file', smooth, 'inputnode.in_files') preproc.connect(dilatemask, 'out_file', smooth, 'inputnode.mask_file') # Mask smoothed data with dilated mask funcbrain3 = pe.MapNode(fsl.ApplyMask(), iterfield=["in_file", "mask_file"], name="06_funcbrain3") preproc.connect(smooth, 'outputnode.smoothed_files', funcbrain3, 'in_file') preproc.connect(dilatemask, 'out_file', funcbrain3, 'mask_file') # Determine if want to take output from smoothed or non-smoothed data forward # This would be the case if the fwhm is less than 1/3 of the voxel size ## gather 2 types of functional images concatnode = pe.Node(interface=util.Merge(2), name='06_concat') preproc.connect(funcbrain2, ('out_file', tolist), concatnode, 'in1') preproc.connect(funcbrain3, ('out_file', tolist), concatnode, 'in2') ## select one selectnode = pe.Node(interface=util.Select(),name='06_select') preproc.connect(concatnode, 'out', selectnode, 'inlist') preproc.connect(inputnode, ('fwhm', chooseindex), selectnode, 'index') #rename_smooth = renamer.connect(selectnode, 'out', 'func_mc_sm', # format_string="func_mc_sm%(fwhm)s", # fwhm=None) #preproc.connect(inputnode, ('fwhm', fwhm_used), rename_smooth, 'fwhm') """ Filter """ filt = pe.MapNode(fsl.TemporalFilter(), iterfield=["in_file"], name="07_filter") preproc.connect(inputnode, 'highpass', filt, 'highpass_sigma') preproc.connect(inputnode, 'lowpass', filt, 'lowpass_sigma') preproc.connect(selectnode, 'out', filt, 'in_file') ## set renamed output #rename_filt = renamer.connect(filt, 'out_file', 'func_mc_sm_ft', # format_string="func_mc_sm%(fwhm)s_hp%(hp)s_lp%(lp)s", # fwhm=None, hp=None, lp=None) #preproc.connect(inputnode, ('fwhm', fwhm_used), rename_filt, 'fwhm') #preproc.connect(inputnode, ('highpass', filter_used), rename_filt, 'hp') #preproc.connect(inputnode, ('lowpass', filter_used), rename_filt, 'lp') """ Intensity Normalization """ # Scale mean value of run to 10000 meanscale = pe.MapNode(interface=fsl.ImageMaths(suffix='_gms'), iterfield=['in_file', 'op_string'], name='08_meanscale') preproc.connect(filt, 'out_file', meanscale, 'in_file') ## function to get scaling factor preproc.connect(medianval, ('out_stat', getmeanscale), meanscale, 'op_string') """ Get Final Functional Data and Mean """ ## functional 4D renamer.connect(meanscale, 'out_file', func_preproc_name) ## mean meanfunc4 = pe.MapNode(fsl.MeanImage(), iterfield=["in_file"], name="08_meanfunc4") preproc.connect(meanscale, 'out_file', meanfunc4, 'in_file') renamer.connect(meanfunc4, 'out_file', 'func_mean') """ Combine all ? (maybe make another workflow) """ # Use the -t Merge option to # Use fslmaths -Tmin -bin to get proper mask # Get mean image across entire run # Combine all the motion together return preproc