def workflow_ieeg(parameters): node_read = Node(function_ieeg_read, name='read') node_read.inputs.active_conditions = parameters['ieeg']['read']['active_conditions'] node_read.inputs.baseline_conditions = parameters['ieeg']['read']['baseline_conditions'] node_read.inputs.minimalduration = parameters['ieeg']['read']['minimalduration'] node_preprocess = MapNode(function_ieeg_preprocess, name='preprocess', iterfield=['ieeg', ]) node_preprocess.inputs.duration = parameters['ieeg']['preprocess']['duration'] node_preprocess.inputs.reref = parameters['ieeg']['preprocess']['reref'] node_preprocess.inputs.offset = parameters['ieeg']['preprocess']['offset'] node_frequency = MapNode(function_ieeg_powerspectrum, name='powerspectrum', iterfield=['ieeg', ]) node_frequency.inputs.method = parameters['ieeg']['powerspectrum']['method'] node_frequency.inputs.taper = parameters['ieeg']['powerspectrum']['taper'] node_frequency.inputs.halfbandwidth = parameters['ieeg']['powerspectrum']['halfbandwidth'] node_frequency.inputs.duration = parameters['ieeg']['powerspectrum']['duration'] node_compare = Node(function_ieeg_compare, name='ecog_compare') node_compare.iterables = ( 'frequency', parameters['ieeg']['ecog_compare']['frequency_bands'], ) node_compare.inputs.baseline = parameters['ieeg']['ecog_compare']['baseline'] node_compare.inputs.method = parameters['ieeg']['ecog_compare']['method'] node_compare.inputs.measure = parameters['ieeg']['ecog_compare']['measure'] node_compare_allfreq = Node(function_ieeg_compare_allfreq, name='ecog_compare_allfreq') w = Workflow('ieeg') w.connect(node_read, 'ieeg', node_preprocess, 'ieeg') w.connect(node_preprocess, 'ieeg', node_frequency, 'ieeg') w.connect(node_frequency, 'ieeg', node_compare, 'in_files') w.connect(node_frequency, 'ieeg', node_compare_allfreq, 'in_files') return w
def bids_node(parameters): bids = Node(BIDS, name='bids') bids.inputs.bids_dir = parameters['paths']['input'] subjects = [ sub.stem[4:] for sub in parameters['paths']['input'].glob('sub-*') ] bids.iterables = ('subject', subjects) return bids
def create_surface_projection_workflow(name="surfproj", exp_info=None): """Project the group mask and thresholded zstat file onto the surface.""" if exp_info is None: exp_info = lyman.default_experiment_parameters() inputnode = Node(IdentityInterface(["zstat_file", "mask_file"]), "inputs") # Sample the zstat image to the surface hemisource = Node(IdentityInterface(["mni_hemi"]), "hemisource") hemisource.iterables = ("mni_hemi", ["lh", "rh"]) zstatproj = Node(freesurfer.SampleToSurface( sampling_method=exp_info["sampling_method"], sampling_range=exp_info["sampling_range"], sampling_units=exp_info["sampling_units"], smooth_surf=exp_info["surf_smooth"], subject_id="fsaverage", mni152reg=True, target_subject="fsaverage"), "zstatproj") # Sample the mask to the surface maskproj = Node(freesurfer.SampleToSurface( sampling_range=exp_info["sampling_range"], sampling_units=exp_info["sampling_units"], subject_id="fsaverage", mni152reg=True, target_subject="fsaverage"), "maskproj") if exp_info["sampling_method"] == "point": maskproj.inputs.sampling_method = "point" else: maskproj.inputs.sampling_method = "max" outputnode = Node(IdentityInterface(["surf_zstat", "surf_mask"]), "outputs") # Define and connect the workflow proj = Workflow(name) proj.connect([ (inputnode, zstatproj, [("zstat_file", "source_file")]), (inputnode, maskproj, [("mask_file", "source_file")]), (hemisource, zstatproj, [("mni_hemi", "hemi")]), (hemisource, maskproj, [("mni_hemi", "hemi")]), (zstatproj, outputnode, [("out_file", "surf_zstat")]), (maskproj, outputnode, [("out_file", "surf_mask")]), ]) return proj
def define_workflow(subject_list, run_list, experiment_dir, output_dir): """run the smooth workflow given subject and runs""" # ExtractROI - skip dummy scans extract = Node(ExtractROI(t_min=4, t_size=-1, output_type='NIFTI'), name="extract") # Smooth - image smoothing smooth = Node(Smooth(fwhm=[8, 8, 8]), name="smooth") # Mask - applying mask to smoothed # mask_func = Node(ApplyMask(output_type='NIFTI'), # name="mask_func") # Infosource - a function free node to iterate over the list of subject names infosource = Node(IdentityInterface(fields=['subject_id', 'run_num']), name="infosource") infosource.iterables = [('subject_id', subject_list), ('run_num', run_list)] # SelectFiles - to grab the data (alternativ to DataGrabber) func_file = opj( 'sub-{subject_id}', 'func', 'sub-{subject_id}_task-tsl_run-{run_num}_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz' ) templates = {'func': func_file} selectfiles = Node(SelectFiles(templates, base_directory=data_dir), name="selectfiles") # Datasink - creates output folder for important outputs datasink = Node(DataSink(base_directory=experiment_dir, container=output_dir), name="datasink") ## Use the following DataSink output substitutions substitutions = [('_subject_id_', 'sub-'), ('ssub', 'sub'), ('_space-MNI152NLin2009cAsym_desc-preproc_', '_fwhm-8_'), ('_fwhm_', ''), ('_roi', '')] substitutions += [('_run_num_%s' % r, '') for r in run_list] datasink.inputs.substitutions = substitutions # Create a preprocessing workflow preproc = Workflow(name='preproc') preproc.base_dir = opj(experiment_dir, working_dir) # Connect all components of the preprocessing workflow (spm smooth) preproc.connect([(infosource, selectfiles, [('subject_id', 'subject_id'), ('run_num', 'run_num')]), (selectfiles, extract, [('func', 'in_file')]), (extract, smooth, [('roi_file', 'in_files')]), (smooth, datasink, [('smoothed_files', 'preproc.@smooth') ])]) return preproc
def create_surface_projection_workflow(name="surfproj", exp_info=None): """Project the group mask and thresholded zstat file onto the surface.""" if exp_info is None: exp_info = lyman.default_experiment_parameters() inputnode = Node(IdentityInterface(["zstat_file", "mask_file"]), "inputs") # Sample the zstat image to the surface hemisource = Node(IdentityInterface(["mni_hemi"]), "hemisource") hemisource.iterables = ("mni_hemi", ["lh", "rh"]) zstatproj = Node( freesurfer.SampleToSurface(sampling_method=exp_info["sampling_method"], sampling_range=exp_info["sampling_range"], sampling_units=exp_info["sampling_units"], smooth_surf=exp_info["surf_smooth"], subject_id="fsaverage", mni152reg=True, target_subject="fsaverage"), "zstatproj") # Sample the mask to the surface maskproj = Node( freesurfer.SampleToSurface(sampling_range=exp_info["sampling_range"], sampling_units=exp_info["sampling_units"], subject_id="fsaverage", mni152reg=True, target_subject="fsaverage"), "maskproj") if exp_info["sampling_method"] == "point": maskproj.inputs.sampling_method = "point" else: maskproj.inputs.sampling_method = "max" outputnode = Node(IdentityInterface(["surf_zstat", "surf_mask"]), "outputs") # Define and connect the workflow proj = Workflow(name) proj.connect([ (inputnode, zstatproj, [("zstat_file", "source_file")]), (inputnode, maskproj, [("mask_file", "source_file")]), (hemisource, zstatproj, [("mni_hemi", "hemi")]), (hemisource, maskproj, [("mni_hemi", "hemi")]), (zstatproj, outputnode, [("out_file", "surf_zstat")]), (maskproj, outputnode, [("out_file", "surf_mask")]), ]) return proj
def runNipypeBet(controller, subject_list, anatomical_id, proj_directory): infosource = Node(IdentityInterface(fields=['subject_id']), name="infosource") infosource.iterables = [('subject_id', subject_list)] #anat_file = opj('{subject_id}','{subject_id}_{anatomical_id}.nii') seperator = '' concat_words = ('{subject_id}_', anatomical_id, '.nii.gz') anat_file_name = seperator.join(concat_words) if controller.b_radiological_convention.get() == True: anat_file = opj('{subject_id}', anat_file_name) else: anat_file = opj('{subject_id}', 'Intermediate_Files', 'Original_Files', anat_file_name) templates = {'anat': anat_file} selectfiles = Node(SelectFiles(templates, base_directory=proj_directory), name="selectfiles") skullstrip = Node(BET(robust=True, frac=0.5, vertical_gradient=0, output_type='NIFTI_GZ'), name="skullstrip") # Datasink - creates output folder for important outputs datasink = Node(DataSink(base_directory=proj_directory), name="datasink") wf_sub = Workflow(name="wf_sub") wf_sub.base_dir = proj_directory wf_sub.connect(infosource, "subject_id", selectfiles, "subject_id") wf_sub.connect(selectfiles, "anat", skullstrip, "in_file") wf_sub.connect(skullstrip, "out_file", datasink, "bet.@out_file") substitutions = [('%s_brain' % (anatomical_id), 'brain')] # Feed the substitution strings to the DataSink node datasink.inputs.substitutions = substitutions # Run the workflow again with the substitutions in place wf_sub.run(plugin='MultiProc') return 'brain'
def get_bids_surf_data_node(path_bids): layout = BIDSLayout(path_bids) subjects = layout.get_subjects() sessions = layout.get_sessions() print("Found {} subjects and {} sessions in the dataset".format( len(subjects), len(sessions))) bids_data_grabber = Node(Function( function=get_bids_surf_data, input_names=["path_bids", "subject", "session", "output_dir"], output_names=[ "lh_surf", "rh_surf", "confounds", "outputDir", "prefix" ]), name="SurfaceDataGrabber") bids_data_grabber.inputs.path_bids = path_bids bids_data_grabber.inputs.output_dir = opj(path_bids, "derivatives", "connectivityWorkflowSurface") bids_data_grabber.iterables = [("subject", subjects), ("session", sessions)] return bids_data_grabber
def GetBidsDataGrabberNode(pathBids): layout = BIDSLayout(pathBids) subjects = layout.get_subjects() sessions = layout.get_sessions() print("Found {} subjects and {} sessions in the dataset".format( len(subjects), len(sessions))) #Initialize the dataGrabber node BIDSDataGrabber = Node(Function( function=get_BidsData, input_names=["pathBids", "subject", "session", "outputDir"], output_names=[ "aparcaseg", "preproc", "confounds", "outputDir", "prefix" ]), name="FunctionalDataGrabber") #Specify path to dataset BIDSDataGrabber.inputs.pathBids = pathBids BIDSDataGrabber.inputs.outputDir = opj(pathBids, "derivatives", "connectivityWorkflow") #Specify subjects and sessions to iterate over them #Stored in iterables for multiprocessing purpose BIDSDataGrabber.iterables = [("subject", subjects), ("session", sessions)] #Return the node return BIDSDataGrabber
import nipype.pipeline.engine as pe from nipype import Node, JoinNode, Workflow from nipype.interfaces.utility import IdentityInterface from nipype.interfaces import (ants, dcm2nii, fsl) #make workflow object wf = Workflow(name='preprocess') #infospec is a node that makes a subject identity. identity matrix is what Subject.py was trying to acomplish inputspec = Node(IdentityInterface(fields=['image']), name='inputspec') #these look like the images that will be processed in this node. Subject.seq might work here inputspec.iterables = [('image', ['img1.nii', 'img2.nii', 'img3.nii'])] #not sure what this is, applys img2flt (?) need to ask Ryan img2flt = Node(fsl.ImageMaths(out_data_type='float'), name='img2flt') #connects the first node with the second node wf.connect(inputspec, 'image', img2flt, 'in_file') #3rd node average = JoinNode(ants.AverageImages(), joinsource='inputspec', joinfield='images', name='average') #add new node to wf wf.connect(img2flt, 'out_file', average, 'images') #new node realign = Node(fsl.FLIRT(), name='realign') #add to wf after img2flt & after average wf.connect(img2flt, 'out_file', realign, 'in_file') wf.connect(average, 'output_average_image', realign, 'reference') strip = Node(fsl.BET(), name='strip') wf.connect(realign, 'out_file', strip, 'in_file')
def prepare_flair_intNorm(flair_prep_dir, out_dir, wd_dir, crash_dir, subjects_sessions, flair_acq, n_cpu=-1): out_dir.mkdir(exist_ok=True, parents=True) export_version(out_dir) wf = Workflow(name="prepare_flair_intNorm") wf.base_dir = wd_dir wf.config.remove_unnecessary_outputs = False wf.config["execution"]["crashdump_dir"] = crash_dir wf.config["monitoring"]["enabled"] = "true" subjects, sessions = list(zip(*subjects_sessions)) infosource = Node(niu.IdentityInterface(fields=["subject", "session", "flair_acq"]), name="infosource") infosource.iterables = [("subject", subjects), ("session", sessions), ] infosource.synchronize = True def subject_info_fnc(flair_prep_dir, subject, session, flair_acq): from pathlib import Path sub_ses = f"sub-{subject}_ses-{session}" flair_files = list(Path(flair_prep_dir).glob( f"sub-{subject}/ses-{session}/anat/{sub_ses}_acq-{flair_acq}_*_FLAIR_biascorr.nii.gz")) assert len(flair_files) == 1, f"Expected one file, but found {flair_files}" flair_file = flair_files[0] brain_masks = list(Path(flair_prep_dir).glob( f"sub-{subject}/ses-{session}/anat/{sub_ses}_space-flair{flair_acq}_desc-brainmask.nii.gz")) assert len(brain_masks) > 0, f"Expected one file, but found {brain_masks}" brain_mask = brain_masks[0] out_list = [flair_file, brain_mask] return [str(o) for o in out_list] # as Path is not taken everywhere grabber = Node(niu.Function(input_names=["flair_prep_dir", "subject", "session", "flair_acq"], output_names=["flair_file", "brain_mask"], function=subject_info_fnc), name="grabber" ) grabber.inputs.flair_prep_dir = flair_prep_dir grabber.inputs.flair_acq = flair_acq wf.connect([(infosource, grabber, [("subject", "subject"), ("session", "session"), ] ) ] ) # adapted from https://gist.github.com/lebedov/94f1caf8a792d80cd91e7b99c1a0c1d7 # Intensity normalization - subtract minimum, then divide by difference of maximum and minimum: img_range = Node(interface=fsl.ImageStats(op_string='-k %s -R'), name='img_range') wf.connect(grabber, "flair_file", img_range, "in_file") wf.connect(grabber, "brain_mask", img_range, "mask_file") def func(in_stat): min_val, max_val = in_stat return '-sub %s -div %s' % (min_val, (max_val - min_val)) stat_to_op_string = Node(interface=niu.Function(input_names=['in_stat'], output_names=['op_string'], function=func), name='stat_to_op_string', iterfield=['in_stat']) wf.connect(img_range, "out_stat", stat_to_op_string, "in_stat") flair_normalized = Node(interface=fsl.ImageMaths(), name='flair_normalized') wf.connect(stat_to_op_string, "op_string", flair_normalized, "op_string") wf.connect(grabber, "flair_file", flair_normalized, "in_file") base_directory = str(out_dir.parent) out_path_base = str(out_dir.name) ds_flair_biascorr_intNorm = Node(DerivativesDataSink(base_directory=base_directory, out_path_base=out_path_base), name="ds_flair_biascorr_intNorm") ds_flair_biascorr_intNorm.inputs.suffix = "FLAIR_biascorrIntNorm" wf.connect(flair_normalized, "out_file", ds_flair_biascorr_intNorm, "in_file") wf.connect(grabber, "flair_file", ds_flair_biascorr_intNorm, "source_file") wf.run(plugin='MultiProc', plugin_args={'n_procs': n_cpu})
def create_workflow(files, target_file, subject_id, TR, slice_times, norm_threshold=1, num_components=5, vol_fwhm=None, surf_fwhm=None, lowpass_freq=-1, highpass_freq=-1, subjects_dir=None, sink_directory=os.getcwd(), target_subject=['fsaverage3', 'fsaverage4'], name='resting'): wf = Workflow(name=name) # Rename files in case they are named identically name_unique = MapNode(Rename(format_string='rest_%(run)02d'), iterfield=['in_file', 'run'], name='rename') name_unique.inputs.keep_ext = True name_unique.inputs.run = list(range(1, len(files) + 1)) name_unique.inputs.in_file = files realign = Node(interface=spm.Realign(), name="realign") realign.inputs.jobtype = 'estwrite' num_slices = len(slice_times) slice_timing = Node(interface=spm.SliceTiming(), name="slice_timing") slice_timing.inputs.num_slices = num_slices slice_timing.inputs.time_repetition = TR slice_timing.inputs.time_acquisition = TR - TR / float(num_slices) slice_timing.inputs.slice_order = (np.argsort(slice_times) + 1).tolist() slice_timing.inputs.ref_slice = int(num_slices / 2) # Comute TSNR on realigned data regressing polynomials upto order 2 tsnr = MapNode(TSNR(regress_poly=2), iterfield=['in_file'], name='tsnr') wf.connect(slice_timing, 'timecorrected_files', tsnr, 'in_file') # Compute the median image across runs calc_median = Node(Function(input_names=['in_files'], output_names=['median_file'], function=median, imports=imports), name='median') wf.connect(tsnr, 'detrended_file', calc_median, 'in_files') """Segment and Register """ registration = create_reg_workflow(name='registration') wf.connect(calc_median, 'median_file', registration, 'inputspec.mean_image') registration.inputs.inputspec.subject_id = subject_id registration.inputs.inputspec.subjects_dir = subjects_dir registration.inputs.inputspec.target_image = target_file """Use :class:`nipype.algorithms.rapidart` to determine which of the images in the functional series are outliers based on deviations in intensity or movement. """ art = Node(interface=ArtifactDetect(), name="art") art.inputs.use_differences = [True, True] art.inputs.use_norm = True art.inputs.norm_threshold = norm_threshold art.inputs.zintensity_threshold = 9 art.inputs.mask_type = 'spm_global' art.inputs.parameter_source = 'SPM' """Here we are connecting all the nodes together. Notice that we add the merge node only if you choose to use 4D. Also `get_vox_dims` function is passed along the input volume of normalise to set the optimal voxel sizes. """ wf.connect([ (name_unique, realign, [('out_file', 'in_files')]), (realign, slice_timing, [('realigned_files', 'in_files')]), (slice_timing, art, [('timecorrected_files', 'realigned_files')]), (realign, art, [('realignment_parameters', 'realignment_parameters')]), ]) def selectindex(files, idx): import numpy as np from nipype.utils.filemanip import filename_to_list, list_to_filename return list_to_filename( np.array(filename_to_list(files))[idx].tolist()) mask = Node(fsl.BET(), name='getmask') mask.inputs.mask = True wf.connect(calc_median, 'median_file', mask, 'in_file') # get segmentation in normalized functional space def merge_files(in1, in2): out_files = filename_to_list(in1) out_files.extend(filename_to_list(in2)) return out_files # filter some noise # Compute motion regressors motreg = Node(Function( input_names=['motion_params', 'order', 'derivatives'], output_names=['out_files'], function=motion_regressors, imports=imports), name='getmotionregress') wf.connect(realign, 'realignment_parameters', motreg, 'motion_params') # Create a filter to remove motion and art confounds createfilter1 = Node(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 = 2 wf.connect(motreg, 'out_files', createfilter1, 'motion_params') wf.connect(art, 'norm_files', createfilter1, 'comp_norm') wf.connect(art, 'outlier_files', createfilter1, 'outliers') filter1 = MapNode(fsl.GLM(out_f_name='F_mcart.nii', out_pf_name='pF_mcart.nii', demean=True), iterfield=['in_file', 'design', 'out_res_name'], name='filtermotion') wf.connect(slice_timing, 'timecorrected_files', filter1, 'in_file') wf.connect(slice_timing, ('timecorrected_files', rename, '_filtermotart'), filter1, 'out_res_name') wf.connect(createfilter1, 'out_files', filter1, 'design') createfilter2 = MapNode(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(filter1, 'out_res', createfilter2, 'realigned_file') wf.connect(registration, ('outputspec.segmentation_files', selectindex, [0, 2]), createfilter2, 'mask_file') filter2 = MapNode(fsl.GLM(out_f_name='F.nii', out_pf_name='pF.nii', demean=True), iterfield=['in_file', 'design', 'out_res_name'], name='filter_noise_nosmooth') wf.connect(filter1, 'out_res', filter2, 'in_file') wf.connect(filter1, ('out_res', rename, '_cleaned'), filter2, 'out_res_name') wf.connect(createfilter2, 'out_files', filter2, 'design') wf.connect(mask, 'mask_file', filter2, 'mask') bandpass = Node(Function( input_names=['files', 'lowpass_freq', 'highpass_freq', 'fs'], output_names=['out_files'], function=bandpass_filter, imports=imports), name='bandpass_unsmooth') bandpass.inputs.fs = 1. / TR bandpass.inputs.highpass_freq = highpass_freq bandpass.inputs.lowpass_freq = lowpass_freq wf.connect(filter2, 'out_res', bandpass, 'files') """Smooth the functional data using :class:`nipype.interfaces.spm.Smooth`. """ smooth = Node(interface=spm.Smooth(), name="smooth") smooth.inputs.fwhm = vol_fwhm wf.connect(bandpass, 'out_files', smooth, 'in_files') collector = Node(Merge(2), name='collect_streams') wf.connect(smooth, 'smoothed_files', collector, 'in1') wf.connect(bandpass, 'out_files', collector, 'in2') """ Transform the remaining images. First to anatomical and then to target """ warpall = MapNode(ants.ApplyTransforms(), iterfield=['input_image'], name='warpall') warpall.inputs.input_image_type = 3 warpall.inputs.interpolation = 'Linear' warpall.inputs.invert_transform_flags = [False, False] warpall.inputs.terminal_output = 'file' warpall.inputs.reference_image = target_file warpall.inputs.args = '--float' warpall.inputs.num_threads = 1 # transform to target wf.connect(collector, 'out', warpall, 'input_image') wf.connect(registration, 'outputspec.transforms', warpall, 'transforms') mask_target = Node(fsl.ImageMaths(op_string='-bin'), name='target_mask') wf.connect(registration, 'outputspec.anat2target', mask_target, 'in_file') maskts = MapNode(fsl.ApplyMask(), iterfield=['in_file'], name='ts_masker') wf.connect(warpall, 'output_image', maskts, 'in_file') wf.connect(mask_target, 'out_file', maskts, 'mask_file') # map to surface # extract aparc+aseg ROIs # extract subcortical ROIs # extract target space ROIs # combine subcortical and cortical rois into a single cifti file ####### # Convert aparc to subject functional space # Sample the average time series in aparc ROIs sampleaparc = MapNode( freesurfer.SegStats(default_color_table=True), iterfield=['in_file', 'summary_file', 'avgwf_txt_file'], name='aparc_ts') sampleaparc.inputs.segment_id = ([8] + list(range(10, 14)) + [17, 18, 26, 47] + list(range(49, 55)) + [58] + list(range(1001, 1036)) + list(range(2001, 2036))) wf.connect(registration, 'outputspec.aparc', sampleaparc, 'segmentation_file') wf.connect(collector, 'out', sampleaparc, 'in_file') def get_names(files, suffix): """Generate appropriate names for output files """ from nipype.utils.filemanip import (split_filename, filename_to_list, list_to_filename) out_names = [] for filename in files: _, name, _ = split_filename(filename) out_names.append(name + suffix) return list_to_filename(out_names) wf.connect(collector, ('out', get_names, '_avgwf.txt'), sampleaparc, 'avgwf_txt_file') wf.connect(collector, ('out', get_names, '_summary.stats'), sampleaparc, 'summary_file') # Sample the time series onto the surface of the target surface. Performs # sampling into left and right hemisphere target = Node(IdentityInterface(fields=['target_subject']), name='target') target.iterables = ('target_subject', filename_to_list(target_subject)) samplerlh = MapNode(freesurfer.SampleToSurface(), iterfield=['source_file'], name='sampler_lh') samplerlh.inputs.sampling_method = "average" samplerlh.inputs.sampling_range = (0.1, 0.9, 0.1) samplerlh.inputs.sampling_units = "frac" samplerlh.inputs.interp_method = "trilinear" samplerlh.inputs.smooth_surf = surf_fwhm # samplerlh.inputs.cortex_mask = True samplerlh.inputs.out_type = 'niigz' samplerlh.inputs.subjects_dir = subjects_dir samplerrh = samplerlh.clone('sampler_rh') samplerlh.inputs.hemi = 'lh' wf.connect(collector, 'out', samplerlh, 'source_file') wf.connect(registration, 'outputspec.out_reg_file', samplerlh, 'reg_file') wf.connect(target, 'target_subject', samplerlh, 'target_subject') samplerrh.set_input('hemi', 'rh') wf.connect(collector, 'out', samplerrh, 'source_file') wf.connect(registration, 'outputspec.out_reg_file', samplerrh, 'reg_file') wf.connect(target, 'target_subject', samplerrh, 'target_subject') # Combine left and right hemisphere to text file combiner = MapNode(Function(input_names=['left', 'right'], output_names=['out_file'], function=combine_hemi, imports=imports), iterfield=['left', 'right'], name="combiner") wf.connect(samplerlh, 'out_file', combiner, 'left') wf.connect(samplerrh, 'out_file', combiner, 'right') # Sample the time series file for each subcortical roi ts2txt = MapNode(Function( input_names=['timeseries_file', 'label_file', 'indices'], output_names=['out_file'], function=extract_subrois, imports=imports), iterfield=['timeseries_file'], name='getsubcortts') ts2txt.inputs.indices = [8] + list(range(10, 14)) + [17, 18, 26, 47] +\ list(range(49, 55)) + [58] ts2txt.inputs.label_file = \ os.path.abspath(('OASIS-TRT-20_jointfusion_DKT31_CMA_labels_in_MNI152_' '2mm_v2.nii.gz')) wf.connect(maskts, 'out_file', ts2txt, 'timeseries_file') ###### substitutions = [('_target_subject_', ''), ('_filtermotart_cleaned_bp_trans_masked', ''), ('_filtermotart_cleaned_bp', '')] regex_subs = [ ('_ts_masker.*/sar', '/smooth/'), ('_ts_masker.*/ar', '/unsmooth/'), ('_combiner.*/sar', '/smooth/'), ('_combiner.*/ar', '/unsmooth/'), ('_aparc_ts.*/sar', '/smooth/'), ('_aparc_ts.*/ar', '/unsmooth/'), ('_getsubcortts.*/sar', '/smooth/'), ('_getsubcortts.*/ar', '/unsmooth/'), ('series/sar', 'series/smooth/'), ('series/ar', 'series/unsmooth/'), ('_inverse_transform./', ''), ] # Save the relevant data into an output directory datasink = Node(interface=DataSink(), name="datasink") datasink.inputs.base_directory = sink_directory datasink.inputs.container = subject_id datasink.inputs.substitutions = substitutions datasink.inputs.regexp_substitutions = regex_subs # (r'(/_.*(\d+/))', r'/run\2') wf.connect(realign, 'realignment_parameters', datasink, 'resting.qa.motion') wf.connect(art, 'norm_files', datasink, 'resting.qa.art.@norm') wf.connect(art, 'intensity_files', datasink, 'resting.qa.art.@intensity') wf.connect(art, 'outlier_files', datasink, 'resting.qa.art.@outlier_files') wf.connect(registration, 'outputspec.segmentation_files', datasink, 'resting.mask_files') wf.connect(registration, 'outputspec.anat2target', datasink, 'resting.qa.ants') wf.connect(mask, 'mask_file', datasink, 'resting.mask_files.@brainmask') wf.connect(mask_target, 'out_file', datasink, 'resting.mask_files.target') wf.connect(filter1, 'out_f', datasink, 'resting.qa.compmaps.@mc_F') wf.connect(filter1, 'out_pf', datasink, 'resting.qa.compmaps.@mc_pF') wf.connect(filter2, 'out_f', datasink, 'resting.qa.compmaps') wf.connect(filter2, 'out_pf', datasink, 'resting.qa.compmaps.@p') wf.connect(bandpass, 'out_files', datasink, 'resting.timeseries.@bandpassed') wf.connect(smooth, 'smoothed_files', datasink, 'resting.timeseries.@smoothed') wf.connect(createfilter1, 'out_files', datasink, 'resting.regress.@regressors') wf.connect(createfilter2, 'out_files', datasink, 'resting.regress.@compcorr') wf.connect(maskts, 'out_file', datasink, 'resting.timeseries.target') wf.connect(sampleaparc, 'summary_file', datasink, 'resting.parcellations.aparc') wf.connect(sampleaparc, 'avgwf_txt_file', datasink, 'resting.parcellations.aparc.@avgwf') wf.connect(ts2txt, 'out_file', datasink, 'resting.parcellations.grayo.@subcortical') datasink2 = Node(interface=DataSink(), name="datasink2") datasink2.inputs.base_directory = sink_directory datasink2.inputs.container = subject_id datasink2.inputs.substitutions = substitutions datasink2.inputs.regexp_substitutions = regex_subs # (r'(/_.*(\d+/))', r'/run\2') wf.connect(combiner, 'out_file', datasink2, 'resting.parcellations.grayo.@surface') return wf
def group_onesample_openfmri(dataset_dir,model_id=None,task_id=None,l1output_dir=None,out_dir=None, no_reversal=False): wk = Workflow(name='one_sample') wk.base_dir = os.path.abspath(work_dir) info = Node(util.IdentityInterface(fields=['model_id','task_id','dataset_dir']), name='infosource') info.inputs.model_id=model_id info.inputs.task_id=task_id info.inputs.dataset_dir=dataset_dir num_copes=contrasts_num(model_id,task_id,dataset_dir) dg = Node(DataGrabber(infields=['model_id','task_id','cope_id'], outfields=['copes', 'varcopes']),name='grabber') dg.inputs.template = os.path.join(l1output_dir,'model%03d/task%03d/*/%scopes/mni/%scope%02d.nii.gz') dg.inputs.template_args['copes'] = [['model_id','task_id','', '', 'cope_id']] dg.inputs.template_args['varcopes'] = [['model_id','task_id','var', 'var', 'cope_id']] dg.iterables=('cope_id',num_copes) dg.inputs.sort_filelist = True wk.connect(info,'model_id',dg,'model_id') wk.connect(info,'task_id',dg,'task_id') model = Node(L2Model(), name='l2model') wk.connect(dg, ('copes', get_len), model, 'num_copes') mergecopes = Node(Merge(dimension='t'), name='merge_copes') wk.connect(dg, 'copes', mergecopes, 'in_files') mergevarcopes = Node(Merge(dimension='t'), name='merge_varcopes') wk.connect(dg, 'varcopes', mergevarcopes, 'in_files') mask_file = fsl.Info.standard_image('MNI152_T1_2mm_brain_mask.nii.gz') flame = Node(FLAMEO(), name='flameo') flame.inputs.mask_file = mask_file flame.inputs.run_mode = 'flame1' wk.connect(model, 'design_mat', flame, 'design_file') wk.connect(model, 'design_con', flame, 't_con_file') wk.connect(mergecopes, 'merged_file', flame, 'cope_file') wk.connect(mergevarcopes, 'merged_file', flame, 'var_cope_file') wk.connect(model, 'design_grp', flame, 'cov_split_file') smoothest = Node(SmoothEstimate(), name='smooth_estimate') wk.connect(flame, 'zstats', smoothest, 'zstat_file') smoothest.inputs.mask_file = mask_file cluster = Node(Cluster(), name='cluster') wk.connect(smoothest,'dlh', cluster, 'dlh') wk.connect(smoothest, 'volume', cluster, 'volume') cluster.inputs.connectivity = 26 cluster.inputs.threshold=2.3 cluster.inputs.pthreshold = 0.05 cluster.inputs.out_threshold_file = True cluster.inputs.out_index_file = True cluster.inputs.out_localmax_txt_file = True wk.connect(flame, 'zstats', cluster, 'in_file') ztopval = Node(ImageMaths(op_string='-ztop', suffix='_pval'), name='z2pval') wk.connect(flame, 'zstats', ztopval,'in_file') sinker = Node(DataSink(), name='sinker') sinker.inputs.base_directory = os.path.abspath(out_dir) sinker.inputs.substitutions = [('_cope_id', 'contrast'), ('_maths__', '_reversed_')] wk.connect(flame, 'zstats', sinker, 'stats') wk.connect(cluster, 'threshold_file', sinker, 'stats.@thr') wk.connect(cluster, 'index_file', sinker, 'stats.@index') wk.connect(cluster, 'localmax_txt_file', sinker, 'stats.@localmax') if no_reversal == False: zstats_reverse = Node( BinaryMaths() , name='zstats_reverse') zstats_reverse.inputs.operation = 'mul' zstats_reverse.inputs.operand_value= -1 wk.connect(flame, 'zstats', zstats_reverse, 'in_file') cluster2=cluster.clone(name='cluster2') wk.connect(smoothest,'dlh',cluster2,'dlh') wk.connect(smoothest,'volume',cluster2,'volume') wk.connect(zstats_reverse,'out_file',cluster2,'in_file') ztopval2 = ztopval.clone(name='ztopval2') wk.connect(zstats_reverse,'out_file',ztopval2,'in_file') wk.connect(zstats_reverse,'out_file',sinker,'stats.@neg') wk.connect(cluster2,'threshold_file',sinker,'stats.@neg_thr') wk.connect(cluster2,'index_file',sinker,'stats.@neg_index') wk.connect(cluster2,'localmax_txt_file',sinker,'stats.@neg_localmax') return wk
def create_surface_ols_workflow(name="surface_group", subject_list=None, exp_info=None): """Workflow to project ffx copes onto surface and run ols.""" if subject_list is None: subject_list = [] if exp_info is None: exp_info = lyman.default_experiment_parameters() inputnode = Node( IdentityInterface(["l1_contrast", "copes", "reg_file", "subject_id"]), "inputnode") hemisource = Node(IdentityInterface(["hemi"]), "hemisource") hemisource.iterables = ("hemi", ["lh", "rh"]) # Sample the volume-encoded native data onto the fsaverage surface # manifold with projection + spherical transform surfsample = MapNode( fs.SampleToSurface(sampling_method=exp_info["sampling_method"], sampling_range=exp_info["sampling_range"], sampling_units=exp_info["sampling_units"], smooth_surf=exp_info["surf_smooth"], target_subject="fsaverage"), ["subject_id", "reg_file", "source_file"], "surfsample") # Remove subjects with completely empty images removeempty = Node(RemoveEmpty(), "removeempty") # Concatenate the subject files into a 4D image mergecope = Node(fs.Concatenate(), "mergecope") # Run the one-sample OLS model glmfit = Node( fs.GLMFit(one_sample=True, surf=True, cortex=True, glm_dir="_glm_results", subject_id="fsaverage"), "glmfit") # Use the cached Monte-Carlo simulations for correction cluster = Node( Function(["y_file", "glm_dir", "sign", "cluster_zthresh", "p_thresh"], ["glm_dir", "thresholded_file"], glm_corrections, imports), "cluster") cluster.inputs.cluster_zthresh = exp_info["cluster_zthresh"] cluster.inputs.p_thresh = exp_info["grf_pthresh"] cluster.inputs.sign = exp_info["surf_corr_sign"] # Return the outputs outputnode = Node(IdentityInterface(["glm_dir", "sig_file"]), "outputnode") # Define and connect the workflow group = Workflow(name) group.connect([ (inputnode, surfsample, [("copes", "source_file"), ("reg_file", "reg_file"), ("subject_id", "subject_id")]), (hemisource, surfsample, [("hemi", "hemi")]), (surfsample, removeempty, [("out_file", "in_files")]), (removeempty, mergecope, [("out_files", "in_files")]), (mergecope, glmfit, [("concatenated_file", "in_file")]), (hemisource, glmfit, [("hemi", "hemi")]), (mergecope, cluster, [("concatenated_file", "y_file")]), (glmfit, cluster, [("glm_dir", "glm_dir")]), (glmfit, outputnode, [("glm_dir", "glm_dir")]), (cluster, outputnode, [("thresholded_file", "sig_file")]), ]) return group, inputnode, outputnode
def batch_paramatric_GLM(nii_root_dir, sub_num_list, total_session_num, all_sub_dataframe, params_name, contrast_list, cache_folder, result_folder, parallel_cores): from nipype import Node, Workflow, Function from nipype.interfaces.spm import Level1Design, EstimateModel, EstimateContrast from nipype.algorithms.modelgen import SpecifySPMModel from nipype.interfaces.utility import IdentityInterface from nipype import DataSink # Define the helper functions def nii_selector(root_dir, sub_num, session_num, all_sub_dataframe, data_type="Smooth_8mm"): import os import glob session_list = ["session" + str(i) for i in range(1, session_num + 1)] sub_name = "sub" + str(sub_num) # print(file_path) nii_list = [] for s in session_list: file_path = os.path.join(root_dir, sub_name, data_type, s) nii_list.append(glob.glob(file_path + "/*.nii")) single_sub_data = all_sub_dataframe[all_sub_dataframe.Subject_num == sub_num] return (nii_list, single_sub_data, sub_name) def condition_generator(single_sub_data, params_name, duration=2): from nipype.interfaces.base import Bunch run_num = set(single_sub_data.run) subject_info = [] for i in run_num: tmp_table = single_sub_data[single_sub_data.run == i] tmp_onset = tmp_table.onset.values.tolist() pmod_names = [] pmod_params = [] pmod_poly = [] for param in params_name: pmod_params.append(tmp_table[param].values.tolist()) pmod_names.append(param) pmod_poly.append(1) tmp_Bunch = Bunch(conditions=["trial_onset_run" + str(i)], onsets=[tmp_onset], durations=[[duration]], pmod=[ Bunch(name=pmod_names, poly=pmod_poly, param=pmod_params) ]) subject_info.append(tmp_Bunch) return subject_info # Define each Nodes in the workflow NiiSelector = Node(Function( input_names=[ "root_dir", "sub_num", "session_num", "all_sub_dataframe", "data_type" ], output_names=["nii_list", "single_sub_data", "sub_name"], function=nii_selector), name="NiiSelector") ConditionGenerator = Node(Function( input_names=["single_sub_data", "params_name", "duration"], output_names=["subject_info"], function=condition_generator), name="ConditionGenerator") glm_input = Node(IdentityInterface( fields=['nii_list', 'single_sub_data', 'params_name', 'contrast_list'], mandatory_inputs=True), name="glm_input") # SpecifyModel - Generates SPM-specific Model modelspec = Node(SpecifySPMModel(concatenate_runs=False, input_units='scans', output_units='scans', time_repetition=2, high_pass_filter_cutoff=128), name="modelspec") # Level1Design - Generates an SPM design matrix level1design = Node(Level1Design(bases={'hrf': { 'derivs': [0, 0] }}, timing_units='scans', interscan_interval=2), name="level1design") level1estimate = Node(EstimateModel(estimation_method={'Classical': 1}), name="level1estimate") level1conest = Node(EstimateContrast(), name="level1conest") OutputNode = Node(DataSink(), name="OutputNode") # Define the attributes of those nodes NiiSelector.inputs.root_dir = nii_root_dir NiiSelector.iterables = ("sub_num", sub_num_list) NiiSelector.inputs.session_num = total_session_num NiiSelector.inputs.data_type = "Smooth_8mm" NiiSelector.inputs.all_sub_dataframe = all_sub_dataframe glm_input.inputs.params_name = params_name glm_input.inputs.contrast_list = contrast_list OutputNode.inputs.base_directory = result_folder # Define the workflows single_sub_GLM_wf = Workflow(name='single_sub_GLM_wf') single_sub_GLM_wf.connect([ (glm_input, ConditionGenerator, [('single_sub_data', 'single_sub_data'), ('params_name', 'params_name')]), (glm_input, modelspec, [('nii_list', 'functional_runs')]), (glm_input, level1conest, [('contrast_list', 'contrasts')]), (ConditionGenerator, modelspec, [('subject_info', 'subject_info')]), (modelspec, level1design, [('session_info', 'session_info')]), (level1design, level1estimate, [('spm_mat_file', 'spm_mat_file')]), (level1estimate, level1conest, [('spm_mat_file', 'spm_mat_file'), ('beta_images', 'beta_images'), ('residual_image', 'residual_image')]) ]) batch_GLM_wf = Workflow(name="batch_GLM_wf", base_dir=cache_folder) batch_GLM_wf.connect([(NiiSelector, single_sub_GLM_wf, [ ('nii_list', 'glm_input.nii_list'), ('single_sub_data', 'glm_input.single_sub_data') ]), (NiiSelector, OutputNode, [('sub_name', 'container')]), (single_sub_GLM_wf, OutputNode, [('level1conest.spm_mat_file', '1stLevel.@spm_mat'), ('level1conest.spmT_images', '1stLevel.@T'), ('level1conest.con_images', '1stLevel.@con'), ('level1conest.spmF_images', '1stLevel.@F'), ('level1conest.ess_images', '1stLevel.@ess')])]) # Excute the workflow batch_GLM_wf.run(plugin='MultiProc', plugin_args={'n_procs': parallel_cores})
# Make sure that there is a place to put the output, b/c nipype won't create the structure for you and the code will error out. if not os.path.isdir(os.path.join(output_dir, workflow_name)): os.mkdir(os.path.join(output_dir, workflow_name)) else: print(os.path.join(output_dir, workflow_name)) infosource = Node( util.IdentityInterface(fields=['subj_id', 'task', 'timept', 't1']), name='infosource') subjs = get_subject_list(data_dir, 'exo') print(subjs[-1:]) tasks = ["fp_run1", "fp_run2"] # TODO turn into paradigm object field timepts = scan_dict[ 'fmri'] # access the embedded dictionary, rather than iterate over every t1 and fmri scan combo t1_timepts = scan_dict['t1'] infosource.iterables = [("subj_id", subjs[-20:]), ("task", tasks), ('timept', timepts), ('t1', t1_timepts)] # Tip 15: iterables run full combinations. Be sneaky with using a dictionary of limited iterables, if you are only trying to select combinations. For example, having the T1 be iterable with timepoints [1,1,3,3] and the fmri scans be iterable with [1,2,3,4] will create 16 results, instead of the intended 2 combinations (wher 1 went with 1, t1=1 went with fmri=2, t1=3 went with fmri=3,etc.) # Create the templates for the scan locations # The values from the template dictionary are added onto the end of the base_directory, when the templates key is invoked by the Workflow coneection templates = { 'struct': '{subj_id}*{t1}*/t1/{subj_id}*t1*.nii', 'func': '{subj_id}*_{timept}_*/{task}/{subj_id}*_????????.nii' } # Setup the options for the SelectFiles command. SelectFiles seems to be a bit more straightforward than DataGrabber and still invokes glob... sf = Node( SelectFiles( templates, base_directory=op.abspath(data_dir), raise_on_empty=
def create_workflow(files, subject_id, n_vol=0, despike=True, TR=None, slice_times=None, slice_thickness=None, fieldmap_images=[], norm_threshold=1, num_components=6, vol_fwhm=None, surf_fwhm=None, lowpass_freq=-1, highpass_freq=-1, sink_directory=os.getcwd(), FM_TEdiff=2.46, FM_sigma=2, FM_echo_spacing=.7, target_subject=['fsaverage3', 'fsaverage4'], name='resting'): wf = Workflow(name=name) # Skip starting volumes remove_vol = MapNode(fsl.ExtractROI(t_min=n_vol, t_size=-1), iterfield=['in_file'], name="remove_volumes") remove_vol.inputs.in_file = files # Run AFNI's despike. This is always run, however, whether this is fed to # realign depends on the input configuration despiker = MapNode(afni.Despike(outputtype='NIFTI_GZ'), iterfield=['in_file'], name='despike') #despiker.plugin_args = {'qsub_args': '-l nodes=1:ppn='} wf.connect(remove_vol, 'roi_file', despiker, 'in_file') # Run Nipy joint slice timing and realignment algorithm realign = Node(nipy.SpaceTimeRealigner(), name='realign') realign.inputs.tr = TR realign.inputs.slice_times = slice_times realign.inputs.slice_info = 2 if despike: wf.connect(despiker, 'out_file', realign, 'in_file') else: wf.connect(remove_vol, 'roi_file', realign, 'in_file') # Comute TSNR on realigned data regressing polynomials upto order 2 tsnr = MapNode(TSNR(regress_poly=2), iterfield=['in_file'], name='tsnr') wf.connect(realign, 'out_file', tsnr, 'in_file') # Compute the median image across runs calc_median = Node(Function(input_names=['in_files'], output_names=['median_file'], function=median, imports=imports), name='median') wf.connect(tsnr, 'detrended_file', calc_median, 'in_files') # Coregister the median to the surface register = Node(freesurfer.BBRegister(), name='bbregister') register.inputs.subject_id = subject_id register.inputs.init = 'fsl' register.inputs.contrast_type = 't2' register.inputs.out_fsl_file = True register.inputs.epi_mask = True # Compute fieldmaps and unwarp using them if fieldmap_images: fieldmap = Node(interface=EPIDeWarp(), name='fieldmap_unwarp') fieldmap.inputs.tediff = FM_TEdiff fieldmap.inputs.esp = FM_echo_spacing fieldmap.inputs.sigma = FM_sigma fieldmap.inputs.mag_file = fieldmap_images[0] fieldmap.inputs.dph_file = fieldmap_images[1] wf.connect(calc_median, 'median_file', fieldmap, 'exf_file') dewarper = MapNode(interface=fsl.FUGUE(), iterfield=['in_file'], name='dewarper') wf.connect(tsnr, 'detrended_file', dewarper, 'in_file') wf.connect(fieldmap, 'exf_mask', dewarper, 'mask_file') wf.connect(fieldmap, 'vsm_file', dewarper, 'shift_in_file') wf.connect(fieldmap, 'exfdw', register, 'source_file') else: wf.connect(calc_median, 'median_file', register, 'source_file') # Get the subject's freesurfer source directory fssource = Node(FreeSurferSource(), name='fssource') fssource.inputs.subject_id = subject_id fssource.inputs.subjects_dir = os.environ['SUBJECTS_DIR'] # Extract wm+csf, brain masks by eroding freesurfer lables and then # transform the masks into the space of the median wmcsf = Node(freesurfer.Binarize(), name='wmcsfmask') mask = wmcsf.clone('anatmask') wmcsftransform = Node(freesurfer.ApplyVolTransform(inverse=True, interp='nearest'), name='wmcsftransform') wmcsftransform.inputs.subjects_dir = os.environ['SUBJECTS_DIR'] wmcsf.inputs.wm_ven_csf = True wmcsf.inputs.match = [4, 5, 14, 15, 24, 31, 43, 44, 63] wmcsf.inputs.binary_file = 'wmcsf.nii.gz' wmcsf.inputs.erode = int(np.ceil(slice_thickness)) wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), wmcsf, 'in_file') if fieldmap_images: wf.connect(fieldmap, 'exf_mask', wmcsftransform, 'source_file') else: wf.connect(calc_median, 'median_file', wmcsftransform, 'source_file') wf.connect(register, 'out_reg_file', wmcsftransform, 'reg_file') wf.connect(wmcsf, 'binary_file', wmcsftransform, 'target_file') mask.inputs.binary_file = 'mask.nii.gz' mask.inputs.dilate = int(np.ceil(slice_thickness)) + 1 mask.inputs.erode = int(np.ceil(slice_thickness)) mask.inputs.min = 0.5 wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), mask, 'in_file') masktransform = wmcsftransform.clone("masktransform") if fieldmap_images: wf.connect(fieldmap, 'exf_mask', masktransform, 'source_file') else: wf.connect(calc_median, 'median_file', masktransform, 'source_file') wf.connect(register, 'out_reg_file', masktransform, 'reg_file') wf.connect(mask, 'binary_file', masktransform, 'target_file') # Compute Art outliers art = Node(interface=ArtifactDetect(use_differences=[True, False], use_norm=True, norm_threshold=norm_threshold, zintensity_threshold=3, parameter_source='NiPy', bound_by_brainmask=True, save_plot=False, mask_type='file'), name="art") if fieldmap_images: wf.connect(dewarper, 'unwarped_file', art, 'realigned_files') else: wf.connect(tsnr, 'detrended_file', art, 'realigned_files') wf.connect(realign, 'par_file', art, 'realignment_parameters') wf.connect(masktransform, 'transformed_file', art, 'mask_file') # Compute motion regressors motreg = Node(Function(input_names=['motion_params', 'order', 'derivatives'], output_names=['out_files'], function=motion_regressors, imports=imports), name='getmotionregress') wf.connect(realign, 'par_file', motreg, 'motion_params') # Create a filter to remove motion and art confounds createfilter1 = Node(Function(input_names=['motion_params', 'comp_norm', 'outliers'], output_names=['out_files'], function=build_filter1, imports=imports), name='makemotionbasedfilter') wf.connect(motreg, 'out_files', createfilter1, 'motion_params') wf.connect(art, 'norm_files', createfilter1, 'comp_norm') wf.connect(art, 'outlier_files', createfilter1, 'outliers') # Filter the motion and art confounds filter1 = MapNode(fsl.GLM(out_res_name='timeseries.nii.gz', demean=True), iterfield=['in_file', 'design'], name='filtermotion') if fieldmap_images: wf.connect(dewarper, 'unwarped_file', filter1, 'in_file') else: wf.connect(tsnr, 'detrended_file', filter1, 'in_file') wf.connect(createfilter1, 'out_files', filter1, 'design') wf.connect(masktransform, 'transformed_file', filter1, 'mask') # Create a filter to remove noise components based on white matter and CSF createfilter2 = MapNode(Function(input_names=['realigned_file', 'mask_file', 'num_components'], output_names=['out_files'], function=extract_noise_components, imports=imports), iterfield=['realigned_file'], name='makecompcorrfilter') createfilter2.inputs.num_components = num_components wf.connect(filter1, 'out_res', createfilter2, 'realigned_file') wf.connect(masktransform, 'transformed_file', createfilter2, 'mask_file') # Filter noise components filter2 = MapNode(fsl.GLM(out_res_name='timeseries_cleaned.nii.gz', demean=True), iterfield=['in_file', 'design'], name='filtercompcorr') wf.connect(filter1, 'out_res', filter2, 'in_file') wf.connect(createfilter2, 'out_files', filter2, 'design') wf.connect(masktransform, 'transformed_file', filter2, 'mask') # Smoothing using surface and volume smoothing smooth = MapNode(freesurfer.Smooth(), iterfield=['in_file'], name='smooth') smooth.inputs.proj_frac_avg = (0.1, 0.9, 0.1) if surf_fwhm is None: surf_fwhm = 5 * slice_thickness smooth.inputs.surface_fwhm = surf_fwhm if vol_fwhm is None: vol_fwhm = 2 * slice_thickness smooth.inputs.vol_fwhm = vol_fwhm wf.connect(filter2, 'out_res', smooth, 'in_file') wf.connect(register, 'out_reg_file', smooth, 'reg_file') # Bandpass filter the data bandpass = MapNode(fsl.TemporalFilter(), iterfield=['in_file'], name='bandpassfilter') if highpass_freq < 0: bandpass.inputs.highpass_sigma = -1 else: bandpass.inputs.highpass_sigma = 1. / (2 * TR * highpass_freq) if lowpass_freq < 0: bandpass.inputs.lowpass_sigma = -1 else: bandpass.inputs.lowpass_sigma = 1. / (2 * TR * lowpass_freq) wf.connect(smooth, 'smoothed_file', bandpass, 'in_file') # Convert aparc to subject functional space aparctransform = wmcsftransform.clone("aparctransform") if fieldmap_images: wf.connect(fieldmap, 'exf_mask', aparctransform, 'source_file') else: wf.connect(calc_median, 'median_file', aparctransform, 'source_file') wf.connect(register, 'out_reg_file', aparctransform, 'reg_file') wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), aparctransform, 'target_file') # Sample the average time series in aparc ROIs sampleaparc = MapNode(freesurfer.SegStats(avgwf_txt_file=True, default_color_table=True), iterfield=['in_file'], name='aparc_ts') sampleaparc.inputs.segment_id = ([8] + range(10, 14) + [17, 18, 26, 47] + range(49, 55) + [58] + range(1001, 1036) + range(2001, 2036)) wf.connect(aparctransform, 'transformed_file', sampleaparc, 'segmentation_file') wf.connect(bandpass, 'out_file', sampleaparc, 'in_file') # Sample the time series onto the surface of the target surface. Performs # sampling into left and right hemisphere target = Node(IdentityInterface(fields=['target_subject']), name='target') target.iterables = ('target_subject', filename_to_list(target_subject)) samplerlh = MapNode(freesurfer.SampleToSurface(), iterfield=['source_file'], name='sampler_lh') samplerlh.inputs.sampling_method = "average" samplerlh.inputs.sampling_range = (0.1, 0.9, 0.1) samplerlh.inputs.sampling_units = "frac" samplerlh.inputs.interp_method = "trilinear" #samplerlh.inputs.cortex_mask = True samplerlh.inputs.out_type = 'niigz' samplerlh.inputs.subjects_dir = os.environ['SUBJECTS_DIR'] samplerrh = samplerlh.clone('sampler_rh') samplerlh.inputs.hemi = 'lh' wf.connect(bandpass, 'out_file', samplerlh, 'source_file') wf.connect(register, 'out_reg_file', samplerlh, 'reg_file') wf.connect(target, 'target_subject', samplerlh, 'target_subject') samplerrh.set_input('hemi', 'rh') wf.connect(bandpass, 'out_file', samplerrh, 'source_file') wf.connect(register, 'out_reg_file', samplerrh, 'reg_file') wf.connect(target, 'target_subject', samplerrh, 'target_subject') # Combine left and right hemisphere to text file combiner = MapNode(Function(input_names=['left', 'right'], output_names=['out_file'], function=combine_hemi, imports=imports), iterfield=['left', 'right'], name="combiner") wf.connect(samplerlh, 'out_file', combiner, 'left') wf.connect(samplerrh, 'out_file', combiner, 'right') # Compute registration between the subject's structural and MNI template # This is currently set to perform a very quick registration. However, the # registration can be made significantly more accurate for cortical # structures by increasing the number of iterations # All parameters are set using the example from: # https://github.com/stnava/ANTs/blob/master/Scripts/newAntsExample.sh reg = Node(ants.Registration(), name='antsRegister') reg.inputs.output_transform_prefix = "output_" reg.inputs.transforms = ['Translation', 'Rigid', 'Affine', 'SyN'] reg.inputs.transform_parameters = [(0.1,), (0.1,), (0.1,), (0.2, 3.0, 0.0)] # reg.inputs.number_of_iterations = ([[10000, 111110, 11110]]*3 + # [[100, 50, 30]]) reg.inputs.number_of_iterations = [[100, 100, 100]] * 3 + [[100, 20, 10]] reg.inputs.dimension = 3 reg.inputs.write_composite_transform = True reg.inputs.collapse_output_transforms = False reg.inputs.metric = ['Mattes'] * 3 + [['Mattes', 'CC']] reg.inputs.metric_weight = [1] * 3 + [[0.5, 0.5]] reg.inputs.radius_or_number_of_bins = [32] * 3 + [[32, 4]] reg.inputs.sampling_strategy = ['Regular'] * 3 + [[None, None]] reg.inputs.sampling_percentage = [0.3] * 3 + [[None, None]] reg.inputs.convergence_threshold = [1.e-8] * 3 + [-0.01] reg.inputs.convergence_window_size = [20] * 3 + [5] reg.inputs.smoothing_sigmas = [[4, 2, 1]] * 3 + [[1, 0.5, 0]] reg.inputs.sigma_units = ['vox'] * 4 reg.inputs.shrink_factors = [[6, 4, 2]] + [[3, 2, 1]]*2 + [[4, 2, 1]] reg.inputs.use_estimate_learning_rate_once = [True] * 4 reg.inputs.use_histogram_matching = [False] * 3 + [True] reg.inputs.output_warped_image = 'output_warped_image.nii.gz' reg.inputs.fixed_image = \ os.path.abspath('OASIS-30_Atropos_template_in_MNI152_2mm.nii.gz') reg.inputs.num_threads = 4 reg.plugin_args = {'qsub_args': '-l nodes=1:ppn=4'} # Convert T1.mgz to nifti for using with ANTS convert = Node(freesurfer.MRIConvert(out_type='niigz'), name='convert2nii') wf.connect(fssource, 'T1', convert, 'in_file') # Mask the T1.mgz file with the brain mask computed earlier maskT1 = Node(fsl.BinaryMaths(operation='mul'), name='maskT1') wf.connect(mask, 'binary_file', maskT1, 'operand_file') wf.connect(convert, 'out_file', maskT1, 'in_file') wf.connect(maskT1, 'out_file', reg, 'moving_image') # Convert the BBRegister transformation to ANTS ITK format convert2itk = MapNode(C3dAffineTool(), iterfield=['transform_file', 'source_file'], name='convert2itk') convert2itk.inputs.fsl2ras = True convert2itk.inputs.itk_transform = True wf.connect(register, 'out_fsl_file', convert2itk, 'transform_file') if fieldmap_images: wf.connect(fieldmap, 'exf_mask', convert2itk, 'source_file') else: wf.connect(calc_median, 'median_file', convert2itk, 'source_file') wf.connect(convert, 'out_file', convert2itk, 'reference_file') # Concatenate the affine and ants transforms into a list pickfirst = lambda x: x[0] merge = MapNode(Merge(2), iterfield=['in2'], name='mergexfm') wf.connect(convert2itk, 'itk_transform', merge, 'in2') wf.connect(reg, ('composite_transform', pickfirst), merge, 'in1') # Apply the combined transform to the time series file sample2mni = MapNode(ants.ApplyTransforms(), iterfield=['input_image', 'transforms'], name='sample2mni') sample2mni.inputs.input_image_type = 3 sample2mni.inputs.interpolation = 'BSpline' sample2mni.inputs.invert_transform_flags = [False, False] sample2mni.inputs.reference_image = \ os.path.abspath('OASIS-30_Atropos_template_in_MNI152_2mm.nii.gz') sample2mni.inputs.terminal_output = 'file' wf.connect(bandpass, 'out_file', sample2mni, 'input_image') wf.connect(merge, 'out', sample2mni, 'transforms') # Sample the time series file for each subcortical roi ts2txt = MapNode(Function(input_names=['timeseries_file', 'label_file', 'indices'], output_names=['out_file'], function=extract_subrois, imports=imports), iterfield=['timeseries_file'], name='getsubcortts') ts2txt.inputs.indices = [8] + range(10, 14) + [17, 18, 26, 47] +\ range(49, 55) + [58] ts2txt.inputs.label_file = \ os.path.abspath(('OASIS-TRT-20_jointfusion_DKT31_CMA_labels_in_MNI152_' '2mm.nii.gz')) wf.connect(sample2mni, 'output_image', ts2txt, 'timeseries_file') # Save the relevant data into an output directory datasink = Node(interface=DataSink(), name="datasink") datasink.inputs.base_directory = sink_directory datasink.inputs.container = subject_id datasink.inputs.substitutions = [('_target_subject_', '')] datasink.inputs.regexp_substitutions = (r'(/_.*(\d+/))', r'/run\2') wf.connect(despiker, 'out_file', datasink, 'resting.qa.despike') wf.connect(realign, 'par_file', datasink, 'resting.qa.motion') wf.connect(tsnr, 'tsnr_file', datasink, 'resting.qa.tsnr') wf.connect(tsnr, 'mean_file', datasink, 'resting.qa.tsnr.@mean') wf.connect(tsnr, 'stddev_file', datasink, 'resting.qa.@tsnr_stddev') if fieldmap_images: wf.connect(fieldmap, 'exf_mask', datasink, 'resting.reference') else: wf.connect(calc_median, 'median_file', datasink, 'resting.reference') wf.connect(art, 'norm_files', datasink, 'resting.qa.art.@norm') wf.connect(art, 'intensity_files', datasink, 'resting.qa.art.@intensity') wf.connect(art, 'outlier_files', datasink, 'resting.qa.art.@outlier_files') wf.connect(mask, 'binary_file', datasink, 'resting.mask') wf.connect(masktransform, 'transformed_file', datasink, 'resting.mask.@transformed_file') wf.connect(register, 'out_reg_file', datasink, 'resting.registration.bbreg') wf.connect(reg, ('composite_transform', pickfirst), datasink, 'resting.registration.ants') wf.connect(register, 'min_cost_file', datasink, 'resting.qa.bbreg.@mincost') wf.connect(smooth, 'smoothed_file', datasink, 'resting.timeseries.fullpass') wf.connect(bandpass, 'out_file', datasink, 'resting.timeseries.bandpassed') wf.connect(sample2mni, 'output_image', datasink, 'resting.timeseries.mni') wf.connect(createfilter1, 'out_files', datasink, 'resting.regress.@regressors') wf.connect(createfilter2, 'out_files', datasink, 'resting.regress.@compcorr') wf.connect(sampleaparc, 'summary_file', datasink, 'resting.parcellations.aparc') wf.connect(sampleaparc, 'avgwf_txt_file', datasink, 'resting.parcellations.aparc.@avgwf') wf.connect(ts2txt, 'out_file', datasink, 'resting.parcellations.grayo.@subcortical') datasink2 = Node(interface=DataSink(), name="datasink2") datasink2.inputs.base_directory = sink_directory datasink2.inputs.container = subject_id datasink2.inputs.substitutions = [('_target_subject_', '')] datasink2.inputs.regexp_substitutions = (r'(/_.*(\d+/))', r'/run\2') wf.connect(combiner, 'out_file', datasink2, 'resting.parcellations.grayo.@surface') return wf
from nipype import Node, Function, Workflow, IdentityInterface from nipype.interfaces.freesurfer import ReconAll from nipype.interfaces.io import DataGrabber #curr_dir_age = 'cmind_age00_raw' #data_dir = '/home/data/madlab/data/mri/cmind/raw_data' #sids = os.listdir('%s/%s' % (data_dir, curr_dir_age)) #sids = sids [:-1] #REMOVES THE .tar file sids = ['783125', '783126', '783127', '783128', '783129', '783131', '783132', '783133'] info = dict(T1=[['subject_id']]) infosource = Node(IdentityInterface(fields=['subject_id']), name='infosource') infosource.iterables = ('subject_id', sids) # Create a datasource node to get the T1 file datasource = Node(DataGrabber(infields=['subject_id'],outfields=info.keys()),name = 'datasource') datasource.inputs.template = '%s/%s' datasource.inputs.base_directory = os.path.abspath('/home/data/madlab/data/mri/seqtrd/') datasource.inputs.field_template = dict(T1='%s/anatomy/T1_*.nii.gz') datasource.inputs.template_args = info datasource.inputs.sort_filelist = True reconall_node = Node(ReconAll(), name='reconall_node') reconall_node.inputs.openmp = 2 reconall_node.inputs.subjects_dir = os.environ['SUBJECTS_DIR'] reconall_node.inputs.terminal_output = 'allatonce' reconall_node.plugin_args={'bsub_args': ('-q PQ_madlab -n 2'), 'overwrite': True}
def create_surfdist_workflow(subjects_dir, subject_list, sources, target, hemi, atlas, labs, name): sd = Workflow(name=name) # Run a separate tree for each template, hemisphere and source structure infosource = Node(IdentityInterface(fields=['template','hemi','source']), name="infosource") infosource.iterables = [('template', target),('hemi', hemi),('source',sources)] # Get template files fsst = Node(FreeSurferSource(),name='FS_Source_template') fsst.inputs.subjects_dir = subjects_dir sd.connect(infosource,'template',fsst,'subject_id') sd.connect(infosource,'hemi',fsst,'hemi') # Generate folder name for output genfoldname = Node(Function(input_names=['hemi','source','target'], output_names=['cname'], function=genfname), name='genfoldname') sd.connect(infosource,'hemi',genfoldname,'hemi') sd.connect(infosource,'source',genfoldname,'source') sd.connect(infosource,'template',genfoldname,'target') # Get subjects fss = Node(FreeSurferSource(),name='FS_Source') fss.iterables = ('subject_id', subject_list) fss.inputs.subjects_dir = subjects_dir fss.inputs.subject_id = subject_list sd.connect(infosource,'hemi',fss,'hemi') # Trim labels tlab = Node(Function(input_names=['itemz','phrase'], output_names=['item'], function=trimming), name='tlab') tlab.inputs.phrase = labs sd.connect(fss,'label',tlab,'itemz') # Trim annotations tannot = Node(Function(input_names=['itemz','phrase'], output_names=['item'], function=trimming), name='tannot') tannot.inputs.phrase = atlas sd.connect(fss,'annot',tannot,'itemz') # Calculate distances for each hemi sdist = Node(Function(input_names=['surface','labels','annot','reg','origin','target'], output_names=['distances'], function=calc_surfdist), name='sdist') sd.connect(infosource,'source',sdist,'origin') sd.connect(fss,'pial',sdist,'surface') sd.connect(tlab,'item',sdist,'labels') sd.connect(tannot,'item',sdist,'annot') sd.connect(fss,'sphere_reg',sdist,'reg') sd.connect(fsst,'sphere_reg',sdist,'target') # Gather data for each hemi from all subjects bucket = JoinNode(Function(input_names=['files','hemi','source','target'],output_names=['group_dist'], function=stack_files), joinsource = fss, joinfield = 'files', name='bucket') sd.connect(infosource,'source',bucket,'source') sd.connect(infosource,'template',bucket,'target') sd.connect(infosource,'hemi',bucket,'hemi') sd.connect(sdist,'distances',bucket,'files') # Sink the data datasink = Node(DataSink(), name='sinker') datasink.inputs.parameterization = False datasink.inputs.base_directory = os.path.abspath(args.sink) sd.connect(genfoldname,'cname',datasink,'container') sd.connect(bucket,'group_dist',datasink,'group_distances') return sd
sampling_strategy=['Regular', 'Regular', 'None'], shrink_factors=[[8, 4, 2, 1]] * 3, smoothing_sigmas=[[3, 2, 1, 0]] * 3, transform_parameters=[(0.1,), (0.1,), (0.1, 3.0, 0.0)], use_histogram_matching=True, write_composite_transform=True), name='antsreg') ### # Input & Output Stream # Infosource - a function free node to iterate over the list of subject names infosource = Node(IdentityInterface(fields=['subject_id']), name="infosource") infosource.iterables = [('subject_id', subject_list)] # SelectFiles - to grab the data (alternative to DataGrabber) anat_file = opj('sub-{subject_id}', 'ses-test', 'anat', 'sub-{subject_id}_ses-test_T1w.nii.gz') templates = {'anat': anat_file} selectfiles = Node(SelectFiles(templates, base_directory='/data/ds000114'), name="selectfiles") # Datasink - creates output folder for important outputs datasink = Node(DataSink(base_directory=experiment_dir, container=output_dir), name="datasink") # Use the following DataSink output substitutions
os.path.join(baseDir, 'sub-{subject_id}', 'func', ('sub-{subject_id}' + '_task-flanker' + '_run-{run_id}' + '_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz')), 'mask': os.path.join(baseDir, 'sub-{subject_id}', 'func', ('sub-{subject_id}' + '_task-flanker' + '_run-{run_id}' + '_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz')), 'events': os.path.join(dataDir, 'sub-{subject_id}', 'func', ('sub-{subject_id}' + '_task-flanker' + '_run-{run_id}' + '_events.tsv')) } # Create SelectFiles node sf = Node(SelectFiles(templates, sort_filelist=True), name='sf') sf.iterables = [('subject_id', subject_list), ('run_id', run_list)] ########### # # FMRI PREPROCESSING NODES # ########### # smoothing with SUSAN susan = Node( fsl.SUSAN(brightness_threshold=2000.0, fwhm=6.0), # smoothing filter width (6mm, isotropic) name='susan') # masking the fMRI with a brain mask applymask = Node(fsl.ApplyMask(), name='applymask')
args = parser.parse_args() try: nruns = int(args.nruns) except: raise Exception("number of runs should be an integer") if not os.path.isdir(args.save_name): os.makedirs(args.save_name) cwd = os.getcwd() wf = Workflow(name="sing") wf.base_dir = cwd Iternode = Node(IdentityInterface(fields=["run_idx"]), name="Iternode") Iternode.iterables = ("run_idx", np.arange(nruns) + 1) def write_varbvs(base_dir, data_path, save_name, col_idx, cnames): import os f_name = "bf-feature_idx-{}.csv".format(col_idx) shfile = "\n".join([ "#!/bin/bash", ("R_DEFAULT_PACKAGES= Rscript " "{script} {data_path} {save_name} {col_idx} {cnames}") ]) file_name = os.path.join(base_dir, "gtoi_template.r") r_file = shfile.format(script=file_name, data_path=data_path, save_name=save_name, col_idx=col_idx,
spm.Threshold( contrast_index=1, use_topo_fdr=True, # use_fwe_correction=True, # here we can use fwe or fdr, default is true # extent_threshold=10, # height_threshold= 0.05, # default is 0.05 extent_fdr_p_threshold=0.05, height_threshold_type='p-value', # default is p-value ), name="level2thresh") #Infosource - a function free node to iterate over the list of subject names infosource = Node(util.IdentityInterface(fields=['contrast_id', 'subject_id']), name="infosource") infosource.iterables = [('contrast_id', contrast_list)] infosource.inputs.subject_id = subject_list # SelectFiles - to grab the data (alternative to DataGrabber) templates = { 'cons': os.path.join( '/home/rj299/scratch60/mdm_analysis/output/imaging/Sink_resp_mon_sv/1stLevel/_subject_id_{subject_id}/', '{contrast_id}.nii') } selectfiles = MapNode(SelectFiles( templates, base_directory='/home/rj299/scratch60/mdm_analysis/work/', sort_filelist=True), name="selectfiles",
def group_multregress_openfmri(dataset_dir, model_id=None, task_id=None, l1output_dir=None, out_dir=None, no_reversal=False, plugin=None, plugin_args=None, flamemodel='flame1', nonparametric=False, use_spm=False): meta_workflow = Workflow(name='mult_regress') meta_workflow.base_dir = work_dir for task in task_id: task_name = get_taskname(dataset_dir, task) cope_ids = l1_contrasts_num(model_id, task_name, dataset_dir) regressors_needed, contrasts, groups, subj_list = get_sub_vars(dataset_dir, task_name, model_id) for idx, contrast in enumerate(contrasts): wk = Workflow(name='model_%03d_task_%03d_contrast_%s' % (model_id, task, contrast[0][0])) info = Node(util.IdentityInterface(fields=['model_id', 'task_id', 'dataset_dir', 'subj_list']), name='infosource') info.inputs.model_id = model_id info.inputs.task_id = task info.inputs.dataset_dir = dataset_dir dg = Node(DataGrabber(infields=['model_id', 'task_id', 'cope_id'], outfields=['copes', 'varcopes']), name='grabber') dg.inputs.template = os.path.join(l1output_dir, 'model%03d/task%03d/%s/%scopes/%smni/%scope%02d.nii%s') if use_spm: dg.inputs.template_args['copes'] = [['model_id', 'task_id', subj_list, '', 'spm/', '', 'cope_id', '']] dg.inputs.template_args['varcopes'] = [['model_id', 'task_id', subj_list, 'var', 'spm/', 'var', 'cope_id', '.gz']] else: dg.inputs.template_args['copes'] = [['model_id', 'task_id', subj_list, '', '', '', 'cope_id', '.gz']] dg.inputs.template_args['varcopes'] = [['model_id', 'task_id', subj_list, 'var', '', 'var', 'cope_id', '.gz']] dg.iterables=('cope_id', cope_ids) dg.inputs.sort_filelist = False wk.connect(info, 'model_id', dg, 'model_id') wk.connect(info, 'task_id', dg, 'task_id') model = Node(MultipleRegressDesign(), name='l2model') model.inputs.groups = groups model.inputs.contrasts = contrasts[idx] model.inputs.regressors = regressors_needed[idx] mergecopes = Node(Merge(dimension='t'), name='merge_copes') wk.connect(dg, 'copes', mergecopes, 'in_files') if flamemodel != 'ols': mergevarcopes = Node(Merge(dimension='t'), name='merge_varcopes') wk.connect(dg, 'varcopes', mergevarcopes, 'in_files') mask_file = fsl.Info.standard_image('MNI152_T1_2mm_brain_mask.nii.gz') flame = Node(FLAMEO(), name='flameo') flame.inputs.mask_file = mask_file flame.inputs.run_mode = flamemodel #flame.inputs.infer_outliers = True wk.connect(model, 'design_mat', flame, 'design_file') wk.connect(model, 'design_con', flame, 't_con_file') wk.connect(mergecopes, 'merged_file', flame, 'cope_file') if flamemodel != 'ols': wk.connect(mergevarcopes, 'merged_file', flame, 'var_cope_file') wk.connect(model, 'design_grp', flame, 'cov_split_file') if nonparametric: palm = Node(Function(input_names=['cope_file', 'design_file', 'contrast_file', 'group_file', 'mask_file', 'cluster_threshold'], output_names=['palm_outputs'], function=run_palm), name='palm') palm.inputs.cluster_threshold = 3.09 palm.inputs.mask_file = mask_file palm.plugin_args = {'sbatch_args': '-p om_all_nodes -N1 -c2 --mem=10G', 'overwrite': True} wk.connect(model, 'design_mat', palm, 'design_file') wk.connect(model, 'design_con', palm, 'contrast_file') wk.connect(mergecopes, 'merged_file', palm, 'cope_file') wk.connect(model, 'design_grp', palm, 'group_file') smoothest = Node(SmoothEstimate(), name='smooth_estimate') wk.connect(flame, 'zstats', smoothest, 'zstat_file') smoothest.inputs.mask_file = mask_file cluster = Node(Cluster(), name='cluster') wk.connect(smoothest,'dlh', cluster, 'dlh') wk.connect(smoothest, 'volume', cluster, 'volume') cluster.inputs.connectivity = 26 cluster.inputs.threshold = 2.3 cluster.inputs.pthreshold = 0.05 cluster.inputs.out_threshold_file = True cluster.inputs.out_index_file = True cluster.inputs.out_localmax_txt_file = True wk.connect(flame, 'zstats', cluster, 'in_file') ztopval = Node(ImageMaths(op_string='-ztop', suffix='_pval'), name='z2pval') wk.connect(flame, 'zstats', ztopval,'in_file') sinker = Node(DataSink(), name='sinker') sinker.inputs.base_directory = os.path.join(out_dir, 'task%03d' % task, contrast[0][0]) sinker.inputs.substitutions = [('_cope_id', 'contrast'), ('_maths_', '_reversed_')] wk.connect(flame, 'zstats', sinker, 'stats') wk.connect(cluster, 'threshold_file', sinker, 'stats.@thr') wk.connect(cluster, 'index_file', sinker, 'stats.@index') wk.connect(cluster, 'localmax_txt_file', sinker, 'stats.@localmax') if nonparametric: wk.connect(palm, 'palm_outputs', sinker, 'stats.palm') if not no_reversal: zstats_reverse = Node( BinaryMaths() , name='zstats_reverse') zstats_reverse.inputs.operation = 'mul' zstats_reverse.inputs.operand_value = -1 wk.connect(flame, 'zstats', zstats_reverse, 'in_file') cluster2=cluster.clone(name='cluster2') wk.connect(smoothest, 'dlh', cluster2, 'dlh') wk.connect(smoothest, 'volume', cluster2, 'volume') wk.connect(zstats_reverse, 'out_file', cluster2, 'in_file') ztopval2 = ztopval.clone(name='ztopval2') wk.connect(zstats_reverse, 'out_file', ztopval2, 'in_file') wk.connect(zstats_reverse, 'out_file', sinker, 'stats.@neg') wk.connect(cluster2, 'threshold_file', sinker, 'stats.@neg_thr') wk.connect(cluster2, 'index_file',sinker, 'stats.@neg_index') wk.connect(cluster2, 'localmax_txt_file', sinker, 'stats.@neg_localmax') meta_workflow.add_nodes([wk]) return meta_workflow
def create_surface_ols_workflow(name="surface_group", subject_list=None, exp_info=None): """Workflow to project ffx copes onto surface and run ols.""" if subject_list is None: subject_list = [] if exp_info is None: exp_info = lyman.default_experiment_parameters() inputnode = Node(IdentityInterface(["l1_contrast", "copes", "reg_file", "subject_id"]), "inputnode") hemisource = Node(IdentityInterface(["hemi"]), "hemisource") hemisource.iterables = ("hemi", ["lh", "rh"]) # Sample the volume-encoded native data onto the fsaverage surface # manifold with projection + spherical transform surfsample = MapNode(fs.SampleToSurface( sampling_method=exp_info["sampling_method"], sampling_range=exp_info["sampling_range"], sampling_units=exp_info["sampling_units"], smooth_surf=exp_info["surf_smooth"], target_subject="fsaverage"), ["subject_id", "reg_file", "source_file"], "surfsample") # Remove subjects with completely empty images removeempty = Node(RemoveEmpty(), "removeempty") # Concatenate the subject files into a 4D image mergecope = Node(fs.Concatenate(), "mergecope") # Run the one-sample OLS model glmfit = Node(fs.GLMFit(one_sample=True, surf=True, cortex=True, glm_dir="_glm_results", subject_id="fsaverage"), "glmfit") # Use the cached Monte-Carlo simulations for correction cluster = Node(Function(["y_file", "glm_dir", "sign", "cluster_zthresh", "p_thresh"], ["glm_dir", "thresholded_file"], glm_corrections, imports), "cluster") cluster.inputs.cluster_zthresh = exp_info["cluster_zthresh"] cluster.inputs.p_thresh = exp_info["grf_pthresh"] cluster.inputs.sign = exp_info["surf_corr_sign"] # Return the outputs outputnode = Node(IdentityInterface(["glm_dir", "sig_file"]), "outputnode") # Define and connect the workflow group = Workflow(name) group.connect([ (inputnode, surfsample, [("copes", "source_file"), ("reg_file", "reg_file"), ("subject_id", "subject_id")]), (hemisource, surfsample, [("hemi", "hemi")]), (surfsample, removeempty, [("out_file", "in_files")]), (removeempty, mergecope, [("out_files", "in_files")]), (mergecope, glmfit, [("concatenated_file", "in_file")]), (hemisource, glmfit, [("hemi", "hemi")]), (mergecope, cluster, [("concatenated_file", "y_file")]), (glmfit, cluster, [("glm_dir", "glm_dir")]), (glmfit, outputnode, [("glm_dir", "glm_dir")]), (cluster, outputnode, [("thresholded_file", "sig_file")]), ]) return group, inputnode, outputnode
# setup workflow nodes # Create SelectFiles node templates = {'eeg_raw': 'sub-{subject_id}.bdf'} selectfiles = Node(SelectFiles(templates, base_directory=source_data_path), name='selectfiles') # Create DataSink node datasink = Node(DataSink(base_directory=data_dir, container=bids_root), name="datasink") # Infosource - a function free node to iterate over the list of subject names infosource = Node(IdentityInterface(fields=['subject_id', 'run_id']), name="infosource") infosource.iterables = [('subject_id', subject_list), ('run_id', run_list)] # Create split run node split_single_file = Node(Function( input_names=['source_data_file', 'source_data_path', 'rb_trig'], output_names=['run_files', 'run_ids'], function=split_runs), name='split_single_file') split_single_file.inputs.source_data_path = source_data_path split_single_file.inputs.rb_trig = run_break_trigger # Create raw_to_bids node raw_to_bids = MapNode(Function(input_names=[ 'source_data_run_file', 'bids_root', 'run_id', 'subject_id', 'task_name', 'event_id' ],
import numpy as np from nipype import Function from nipype import Node from nipype import Workflow from nipype import IdentityInterface ds = "/storage/gablab001/data/genus/fs_cog/pred_diag/data_sets" data_sets = [os.path.join(ds, x) for x in os.listdir(ds) if ".csv" in x] response_var = os.path.join(ds, "response.txt") wf = Workflow(name="classify_disease") wf.base_dir = "/om/scratch/Sat/ysa" Iternode = Node(IdentityInterface(fields=['data', 'classifier']), name="Iternode") Iternode.iterables = [('data', data_sets), ('classifier', ['et', 'lg'])] def run(data, classifier, response): import numpy as np import pandas as pd from custom import Mods from custom import utils y = np.genfromtxt(response) X = pd.read_csv(data) data_mod = data.split('/')[-1].replace('.csv', '') if classifier == 'et': od = '/storage/gablab001/data/genus/fs_cog/pred_diag/extra_trees/results/' on = classifier + '_{}.pkl'.format(data_mod)
from bids.grabbids import BIDSLayout layout = BIDSLayout(data_dir) checkGet = layout.get(type="bold", extensions="nii.gz") checkGet[0].subject layout.get(type="bold", task="3", session="1", extensions="nii.gz")[0].filename # Specify the subject directories subject_list = ['1063', '1072', '1206', '1244'] #,'1273' ,'1291', '1305', '1340', '1345', '1346'] # Map field names to individual subject runs. task_list = ['3', '4', '5', '6'] infosource = Node(util.IdentityInterface(fields=['subject_id'], ), name="infosource") infosource.iterables = [('subject_id', subject_list)] ## SelectFiles - to grab the data (alternativ to DataGrabber) #templates = {'func': '/media/Data/FromHPC/output/fmriprep/sub-{subject_id}/ses-1/func/sub-{subject_id}_ses-1_task-*_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz'} #selectfiles = Node(SelectFiles(templates, # base_directory=data_dir), # name="selectfiles") # info = dict(func=[['subject_id', ['3', '4', '5', '6']]], ) # SelectFiles - to grab the data (alternativ to DataGrabber) templates = { 'func': '/media/Data/FromHPC/output/fmriprep/sub-%s/ses-1/func/sub-*_ses-1_task-%s_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz' } #selectfiles = Node(SelectFiles(templates, # base_directory=data_dir),
# Smoothing widths to apply fwhm = [2, 3, 4] # main workflow # Reorient reorient = Node(fsl.Reorient2Std(output_type='NIFTI_GZ', ignore_exception=True), name='reorient') # Bias Field Correction N4_BFC = Node(ants.N4BiasFieldCorrection(dimension=3), name='N4_BFC') # Smooth - image smoothing smooth = Node(Smooth(), name="smooth") smooth.iterables = ("fwhm", fwhm) # coregistration Workflow def coreg_workflow(): # BET - Skull-stripping bet_anat = Node(fsl.BET(frac=0.2, robust=True, vertical_gradient=0.7, output_type='NIFTI_GZ'), name="bet_anat") # FAST - tissue Segmentation segmentation = Node(fsl.FAST(no_bias=True, probability_maps=True,
name="mr_convertaparc_aseg",iterfield='in_file') mr_convertbrainmask=Node(MRIConvert(out_type=u'niigz'), name="mr_convertbrainmask") mr_convertbrain=Node(MRIConvert(out_type=u'niigz'), name="mr_convertbrain") mr_convertwmparc=Node(MRIConvert(out_type=u'niigz'), name="mr_convertwmparc") mr_convertwm=Node(MRIConvert(out_type=u'niigz'), name="mr_convertwm") ############################### #specify input output ############################### # Infosource - a function free node to iterate over the list of subject names infosource = Node(IdentityInterface(fields=['subject_id']), name="infosource") infosource.iterables = [('subject_id', subject_list)] t1_file = opj('sub_{subject_id}','t1_mprage.nii.gz') templates = {'t1': t1_file} selectfiles = Node(SelectFiles(templates, base_directory='/home/luiscp/Documents/Data/ADRC_90Plus'), name="selectfiles") datasink = Node(DataSink(base_directory=experiment_dir, container=output_dir), name="datasink") substitutions = [('_subject_id_', 'sub_'), ('_out',''), ('_mr_convertaparc_aseg0/',''),
data_grabber_node = Node(DataGrabber(base_directory=args['directory'], sort_filelist=True, raise_on_empty=False, infields=template_arguments.keys(), outfields=[tmp for tmp in temps_dict]), name='data_grabber') data_grabber_node.inputs.template = '*' data_grabber_node.inputs.raise_on_empty = True data_grabber_node.inputs.drop_blank_outputs = True data_grabber_node.inputs.field_template = temps_dict data_grabber_node.inputs.template_args = temp_args_dict data_grabber_node.iterables = [ (key, [thing.rstrip('\n') for thing in open(template_arguments[key], 'r')]) for key in template_arguments.keys() ] template = abspath(args['template']) bias_correction_node = Node(N4BiasFieldCorrection(), name='bias_correction') generate_transforms_node = Node(legacy.GenWarpFields(reference_image=template), name='generate_transforms') merge_transforms_node = Node(Merge(2), iterfield='in2', name='merge_transforms') if args['derivatives'] is not None: merge_input_files_node = Node(Merge(len(derivatives_names)), name='merge_input_files')
'_task-' + task_name + '_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz')), 'mask': os.path.join(baseDir, 'sub-{subject_id}', 'ses-{subsession_id}', 'func', ('sub-{subject_id}' + '_ses-{subsession_id}' + '_task-' + task_name + '_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz')) } # Create SelectFiles node sf = Node(SelectFiles(templates, sort_filelist=True), name='sf') sf.iterables = [('subject_id', subject_list), ('subsession_id', session_list)] ########### # # FMRI PREPROCESSING NODES # ########### # skip dummy scans extract = Node(fsl.ExtractROI(t_min=nDelfMRI, # first volumes to be deleted t_size=-1), name="extract") # smoothing with SUSAN
def group_multregress_openfmri(dataset_dir, model_id=None, task_id=None, l1output_dir=None, out_dir=None, no_reversal=False, plugin=None, plugin_args=None, flamemodel='flame1', nonparametric=False, use_spm=False): meta_workflow = Workflow(name='mult_regress') meta_workflow.base_dir = work_dir for task in task_id: task_name = get_taskname(dataset_dir, task) cope_ids = l1_contrasts_num(model_id, task_name, dataset_dir) regressors_needed, contrasts, groups, subj_list = get_sub_vars( dataset_dir, task_name, model_id) for idx, contrast in enumerate(contrasts): wk = Workflow(name='model_%03d_task_%03d_contrast_%s' % (model_id, task, contrast[0][0])) info = Node(util.IdentityInterface( fields=['model_id', 'task_id', 'dataset_dir', 'subj_list']), name='infosource') info.inputs.model_id = model_id info.inputs.task_id = task info.inputs.dataset_dir = dataset_dir dg = Node(DataGrabber(infields=['model_id', 'task_id', 'cope_id'], outfields=['copes', 'varcopes']), name='grabber') dg.inputs.template = os.path.join( l1output_dir, 'model%03d/task%03d/%s/%scopes/%smni/%scope%02d.nii%s') if use_spm: dg.inputs.template_args['copes'] = [[ 'model_id', 'task_id', subj_list, '', 'spm/', '', 'cope_id', '' ]] dg.inputs.template_args['varcopes'] = [[ 'model_id', 'task_id', subj_list, 'var', 'spm/', 'var', 'cope_id', '.gz' ]] else: dg.inputs.template_args['copes'] = [[ 'model_id', 'task_id', subj_list, '', '', '', 'cope_id', '.gz' ]] dg.inputs.template_args['varcopes'] = [[ 'model_id', 'task_id', subj_list, 'var', '', 'var', 'cope_id', '.gz' ]] dg.iterables = ('cope_id', cope_ids) dg.inputs.sort_filelist = False wk.connect(info, 'model_id', dg, 'model_id') wk.connect(info, 'task_id', dg, 'task_id') model = Node(MultipleRegressDesign(), name='l2model') model.inputs.groups = groups model.inputs.contrasts = contrasts[idx] model.inputs.regressors = regressors_needed[idx] mergecopes = Node(Merge(dimension='t'), name='merge_copes') wk.connect(dg, 'copes', mergecopes, 'in_files') if flamemodel != 'ols': mergevarcopes = Node(Merge(dimension='t'), name='merge_varcopes') wk.connect(dg, 'varcopes', mergevarcopes, 'in_files') mask_file = fsl.Info.standard_image( 'MNI152_T1_2mm_brain_mask.nii.gz') flame = Node(FLAMEO(), name='flameo') flame.inputs.mask_file = mask_file flame.inputs.run_mode = flamemodel #flame.inputs.infer_outliers = True wk.connect(model, 'design_mat', flame, 'design_file') wk.connect(model, 'design_con', flame, 't_con_file') wk.connect(mergecopes, 'merged_file', flame, 'cope_file') if flamemodel != 'ols': wk.connect(mergevarcopes, 'merged_file', flame, 'var_cope_file') wk.connect(model, 'design_grp', flame, 'cov_split_file') if nonparametric: palm = Node(Function(input_names=[ 'cope_file', 'design_file', 'contrast_file', 'group_file', 'mask_file', 'cluster_threshold' ], output_names=['palm_outputs'], function=run_palm), name='palm') palm.inputs.cluster_threshold = 3.09 palm.inputs.mask_file = mask_file palm.plugin_args = { 'sbatch_args': '-p om_all_nodes -N1 -c2 --mem=10G', 'overwrite': True } wk.connect(model, 'design_mat', palm, 'design_file') wk.connect(model, 'design_con', palm, 'contrast_file') wk.connect(mergecopes, 'merged_file', palm, 'cope_file') wk.connect(model, 'design_grp', palm, 'group_file') smoothest = Node(SmoothEstimate(), name='smooth_estimate') wk.connect(flame, 'zstats', smoothest, 'zstat_file') smoothest.inputs.mask_file = mask_file cluster = Node(Cluster(), name='cluster') wk.connect(smoothest, 'dlh', cluster, 'dlh') wk.connect(smoothest, 'volume', cluster, 'volume') cluster.inputs.connectivity = 26 cluster.inputs.threshold = 2.3 cluster.inputs.pthreshold = 0.05 cluster.inputs.out_threshold_file = True cluster.inputs.out_index_file = True cluster.inputs.out_localmax_txt_file = True wk.connect(flame, 'zstats', cluster, 'in_file') ztopval = Node(ImageMaths(op_string='-ztop', suffix='_pval'), name='z2pval') wk.connect(flame, 'zstats', ztopval, 'in_file') sinker = Node(DataSink(), name='sinker') sinker.inputs.base_directory = os.path.join( out_dir, 'task%03d' % task, contrast[0][0]) sinker.inputs.substitutions = [('_cope_id', 'contrast'), ('_maths_', '_reversed_')] wk.connect(flame, 'zstats', sinker, 'stats') wk.connect(cluster, 'threshold_file', sinker, 'stats.@thr') wk.connect(cluster, 'index_file', sinker, 'stats.@index') wk.connect(cluster, 'localmax_txt_file', sinker, 'stats.@localmax') if nonparametric: wk.connect(palm, 'palm_outputs', sinker, 'stats.palm') if not no_reversal: zstats_reverse = Node(BinaryMaths(), name='zstats_reverse') zstats_reverse.inputs.operation = 'mul' zstats_reverse.inputs.operand_value = -1 wk.connect(flame, 'zstats', zstats_reverse, 'in_file') cluster2 = cluster.clone(name='cluster2') wk.connect(smoothest, 'dlh', cluster2, 'dlh') wk.connect(smoothest, 'volume', cluster2, 'volume') wk.connect(zstats_reverse, 'out_file', cluster2, 'in_file') ztopval2 = ztopval.clone(name='ztopval2') wk.connect(zstats_reverse, 'out_file', ztopval2, 'in_file') wk.connect(zstats_reverse, 'out_file', sinker, 'stats.@neg') wk.connect(cluster2, 'threshold_file', sinker, 'stats.@neg_thr') wk.connect(cluster2, 'index_file', sinker, 'stats.@neg_index') wk.connect(cluster2, 'localmax_txt_file', sinker, 'stats.@neg_localmax') meta_workflow.add_nodes([wk]) return meta_workflow
from glob import glob from nipype import Node, Function, Workflow, IdentityInterface from nipype.interfaces.freesurfer import ReconAll from nipype.interfaces.io import DataGrabber # CURRENT PROJECT DATA DIRECTORY data_dir = '/home/data/madlab/data/mri/emuR01' # CURRENT PROJECT SUBJECT IDS sids = ['4000', '4001'] info = dict(T1=[['subject_id']]) infosource = Node(IdentityInterface(fields=['subject_id']), name='infosource') infosource.iterables = ('subject_id', sids) # Create a datasource node to get the T1 file datasource = Node(DataGrabber(infields=['subject_id'], outfields=info.keys()), name='datasource') datasource.inputs.template = '%s/%s' datasource.inputs.base_directory = os.path.abspath(data_dir) datasource.inputs.field_template = dict(T1='%s/s1/anatomy/T1_002.nii.gz') datasource.inputs.template_args = info datasource.inputs.sort_filelist = True reconall_node = Node(ReconAll(), name='reconall_node') reconall_node.inputs.openmp = 2 reconall_node.inputs.args = '-hippocampal-subfields-T1' reconall_node.inputs.subjects_dir = '/home/data/madlab/surfaces/emuR01' reconall_node.plugin_args = {
def create_main_pipeline(subject_list=SUBJECTS): RADIUS = 5 # selection sphere radius (mm) # create node that contains meta-variables about data inputnode = Node( IdentityInterface(fields=[ "subject_id", "center", "modality", "acquisition", "correction" ]), name="inputnode", ) inputnode.inputs.center = CENTER inputnode.inputs.modality = MODALITY inputnode.inputs.acquisition = ACQUISITION inputnode.inputs.correction = CORRECTION inputnode.iterables = [("subject_id", subject_list)] # templates = { "diffusion_volume": "DTI/{center}/{subject_id}/{modality}/{acquisition}/{" "correction}/corrected_dwi_{subject_id}.nii.gz", "bvals": "DTI/{center}/{subject_id}/{modality}/{acquisition}/raw_bvals_{subject_id}.txt", "bvecs": "DTI/{center}/{subject_id}/{modality}/{acquisition}/{correction}/corrected_bvecs_{subject_id}.txt", "t1_volume": "analysis_{subject_id}/anat/{" "subject_id}_ses-01_T1w_denoised_debiased_in-MNI152.nii.gz", "func_contrast_volume": "analysis_{subject_id}/spm_realign/results_8WM_9CSF_0mvt/In-MNI152_{subject_id}_res-8WM_9CSF_0mvt_human_vs_all_t.nii.gz", } datagrabber = pe.Node(SelectFiles(templates), name="datagrabber") datagrabber.inputs.base_directory = PRIMAVOICE study_pipeline = create_study_pipeline(radius=RADIUS) main_pipeline = pe.Workflow(name="main_pipeline") main_pipeline.connect([( inputnode, datagrabber, [ ("subject_id", "subject_id"), ("center", "center"), ("modality", "modality"), ("acquisition", "acquisition"), ("correction", "correction"), ], )]) main_pipeline.connect([( datagrabber, study_pipeline, [ ("diffusion_volume", "inputnode.diffusion_volume"), ("bvals", "inputnode.bvals"), ("bvecs", "inputnode.bvecs"), ("t1_volume", "inputnode.t1_volume"), ("func_contrast_volume", "inputnode.func_contrast_volume"), ], )]) return main_pipeline
# subject_list_done_norm = [sub[-4:] for sub in subject_list_done_norm] # subject_list_done_norm.sort() # full_subject_list = os.listdir("/data/wellbeing_bids") # full_subject_list.remove('dataset_description.json') # full_subject_list = [sub[-4:] for sub in full_subject_list] # full_subject_list.sort() # subject_list = list(set(subject_list_done_reg)^set(subject_list_done_norm)) # Set up Nodes for Normalization # Infosource - a function free node to iterate over the list of subject names infosource = Node( IdentityInterface(fields=['subject_id', 'task_name', 'fwhm_id']), name="infosource") infosource.iterables = [('subject_id', subject_list), ('task_name', task_list), ('fwhm_id', fwhm)] # SelectFiles - to grab the data (alternativ to DataGrabber) templates = { 'bold': opj('/data/wellbeing_analysis/datasink/preproc', 'sub-{subject_id}', 'task-{task_name}', 'fwhm-{fwhm_id}_sasub-{subject_id}_task-{task_name}_bold.nii'), 'anat': opj('/data/wellbeing_analysis/datasink/preproc', 'sub-{subject_id}', 'task-{task_name}', 'sub-{subject_id}_T1w_brain.nii.gz'), 'transform': opj('/data/wellbeing_analysis/datasink/antsreg', 'sub-{subject_id}', 'transformComposite.h5') }
fbvec = os.path.abspath( glob(os.path.join(data_dir, 'bvecs', 'camino_120_RAS_flipped-xy.bvecs'))[0]) print("bvec file = %s" % fbvec) fbval = os.path.abspath( glob(os.path.join(data_dir, 'bvecs', 'camino_120_RAS.bvals'))[0]) print("bval file = %s" % fbval) all_streamlines = os.path.join(work_dir, 'exvivo/_region_label_8/tracker', 'Reg_S64550_csd_streamline.trk') fa_file = os.path.join(work_dir, 'exvivo/_region_label_8/tracker', 'Reg_S64550_tensor_fa.nii.gz') # iterate through the labels iden = Node(IdentityInterface(fields=['label']), name="identity") iden.iterables = [("label", atlas_labels)] # extract the seed ROI from an atlas file def extract_region(atlas_file, label): from nipype.interfaces.base import CommandLine from nipype.pipeline.engine import Node import os from glob import glob node = Node(CommandLine('fslmaths %s -thr %s -uthr %s region_%s.nii.gz' % (atlas_file, label, label, label)), name='extract_roi') cwd = os.getcwd() print("cwd = ", cwd) node.base_dir = cwd node.config = {'execution': {'keep_unnecessary_outputs': 'true'}}
def finish_the_job(fmriprep_dir, subjects, pipeline, work_dir=None): """Run common preprocessing steps after fMRIprep. Parameters ========== fmriprep_dir : str the root directory of the fMRIprep data subjects : list the subjects to preprocess pipeline : dict the preprocessing pipeline (ordered!); possible options are: "spatial_smoothing": numeric (FWHM Gaussian kernel in millimeters) "temporal_filtering": list (high and cutoff values in seconds) "timecourse_normalization": str (method; one of "Zscore" or "PSC") work_dir : str, optional the working directory (default=None) Examples ======== >>> from finish_the_job import finish_the_job >>> finish_the_job(fmriprep_dir="/path/to/fmriprep_dir/" ... subjects=[1,2,3], ... pipeline = {"spatial_smoothing": 5, ... "temporal_filtering": [100, None], "timecourse_normalization": "Zscore"}) """ if type(subjects) not in (list, tuple): subjects = (subjects) ftj = Workflow(name="finish_the_job") if work_dir is not None: ftj.base_dir = work_dir # set working/output directory # Get boldfile template boldfile_template = Node(utility.Function( input_names=["fmriprep_dir", "subject"], output_names=["template"], function=get_boldfile_template), name='locate_bold_files') boldfile_template.inputs.fmriprep_dir = fmriprep_dir boldfile_template.iterables = ("subject", subjects) # Get inputs dg = Node(io.DataGrabber(), name="get_data") dg.inputs.sort_filelist = True ftj.connect(boldfile_template, "template", dg, "template") # Preprocess files preprocessing = create_preprocessing_workflow(pipeline=pipeline) ftj.connect(dg, "outfiles", preprocessing, "inputspec.in_files") # Get output filenames filenames = MapNode(utility.Function( input_names=["bold_filename", "suffix"], output_names=["output_filename"], function=get_output_filename), iterfield=["bold_filename"], name='create_output_filenames') ftj.connect(preprocessing, "outputspec.suffix", filenames, "suffix") ftj.connect(dg, "outfiles", filenames, "bold_filename") # Save preprocessed files ef = MapNode(io.ExportFile(), iterfield=["in_file", "out_file"], name="save_data") ftj.connect(preprocessing, "outputspec.preprocessed_files", ef, "in_file") ftj.connect(filenames, "output_filename", ef, "out_file") # Run workflow if work_dir: ftj.write_graph(graph2use="colored", dotfilename="graph_colored.dot") ftj.run()
def create_workflow(files, subject_id, n_vol=0, despike=True, TR=None, slice_times=None, slice_thickness=None, fieldmap_images=[], norm_threshold=1, num_components=6, vol_fwhm=None, surf_fwhm=None, lowpass_freq=-1, highpass_freq=-1, sink_directory=os.getcwd(), FM_TEdiff=2.46, FM_sigma=2, FM_echo_spacing=.7, target_subject=['fsaverage3', 'fsaverage4'], name='resting'): wf = Workflow(name=name) # Skip starting volumes remove_vol = MapNode(fsl.ExtractROI(t_min=n_vol, t_size=-1), iterfield=['in_file'], name="remove_volumes") remove_vol.inputs.in_file = files # Run AFNI's despike. This is always run, however, whether this is fed to # realign depends on the input configuration despiker = MapNode(afni.Despike(outputtype='NIFTI_GZ'), iterfield=['in_file'], name='despike') #despiker.plugin_args = {'qsub_args': '-l nodes=1:ppn='} wf.connect(remove_vol, 'roi_file', despiker, 'in_file') # Run Nipy joint slice timing and realignment algorithm realign = Node(nipy.SpaceTimeRealigner(), name='realign') realign.inputs.tr = TR realign.inputs.slice_times = slice_times realign.inputs.slice_info = 2 if despike: wf.connect(despiker, 'out_file', realign, 'in_file') else: wf.connect(remove_vol, 'roi_file', realign, 'in_file') # Comute TSNR on realigned data regressing polynomials upto order 2 tsnr = MapNode(TSNR(regress_poly=2), iterfield=['in_file'], name='tsnr') wf.connect(realign, 'out_file', tsnr, 'in_file') # Compute the median image across runs calc_median = Node(Function(input_names=['in_files'], output_names=['median_file'], function=median, imports=imports), name='median') wf.connect(tsnr, 'detrended_file', calc_median, 'in_files') # Coregister the median to the surface register = Node(freesurfer.BBRegister(), name='bbregister') register.inputs.subject_id = subject_id register.inputs.init = 'fsl' register.inputs.contrast_type = 't2' register.inputs.out_fsl_file = True register.inputs.epi_mask = True # Compute fieldmaps and unwarp using them if fieldmap_images: fieldmap = Node(interface=EPIDeWarp(), name='fieldmap_unwarp') fieldmap.inputs.tediff = FM_TEdiff fieldmap.inputs.esp = FM_echo_spacing fieldmap.inputs.sigma = FM_sigma fieldmap.inputs.mag_file = fieldmap_images[0] fieldmap.inputs.dph_file = fieldmap_images[1] wf.connect(calc_median, 'median_file', fieldmap, 'exf_file') dewarper = MapNode(interface=fsl.FUGUE(), iterfield=['in_file'], name='dewarper') wf.connect(tsnr, 'detrended_file', dewarper, 'in_file') wf.connect(fieldmap, 'exf_mask', dewarper, 'mask_file') wf.connect(fieldmap, 'vsm_file', dewarper, 'shift_in_file') wf.connect(fieldmap, 'exfdw', register, 'source_file') else: wf.connect(calc_median, 'median_file', register, 'source_file') # Get the subject's freesurfer source directory fssource = Node(FreeSurferSource(), name='fssource') fssource.inputs.subject_id = subject_id fssource.inputs.subjects_dir = os.environ['SUBJECTS_DIR'] # Extract wm+csf, brain masks by eroding freesurfer labels and then # transform the masks into the space of the median wmcsf = Node(freesurfer.Binarize(), name='wmcsfmask') mask = wmcsf.clone('anatmask') wmcsftransform = Node(freesurfer.ApplyVolTransform(inverse=True, interp='nearest'), name='wmcsftransform') wmcsftransform.inputs.subjects_dir = os.environ['SUBJECTS_DIR'] wmcsf.inputs.wm_ven_csf = True wmcsf.inputs.match = [4, 5, 14, 15, 24, 31, 43, 44, 63] wmcsf.inputs.binary_file = 'wmcsf.nii.gz' wmcsf.inputs.erode = int(np.ceil(slice_thickness)) wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), wmcsf, 'in_file') if fieldmap_images: wf.connect(fieldmap, 'exf_mask', wmcsftransform, 'source_file') else: wf.connect(calc_median, 'median_file', wmcsftransform, 'source_file') wf.connect(register, 'out_reg_file', wmcsftransform, 'reg_file') wf.connect(wmcsf, 'binary_file', wmcsftransform, 'target_file') mask.inputs.binary_file = 'mask.nii.gz' mask.inputs.dilate = int(np.ceil(slice_thickness)) + 1 mask.inputs.erode = int(np.ceil(slice_thickness)) mask.inputs.min = 0.5 wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), mask, 'in_file') masktransform = wmcsftransform.clone("masktransform") if fieldmap_images: wf.connect(fieldmap, 'exf_mask', masktransform, 'source_file') else: wf.connect(calc_median, 'median_file', masktransform, 'source_file') wf.connect(register, 'out_reg_file', masktransform, 'reg_file') wf.connect(mask, 'binary_file', masktransform, 'target_file') # Compute Art outliers art = Node(interface=ArtifactDetect(use_differences=[True, False], use_norm=True, norm_threshold=norm_threshold, zintensity_threshold=3, parameter_source='NiPy', bound_by_brainmask=True, save_plot=False, mask_type='file'), name="art") if fieldmap_images: wf.connect(dewarper, 'unwarped_file', art, 'realigned_files') else: wf.connect(tsnr, 'detrended_file', art, 'realigned_files') wf.connect(realign, 'par_file', art, 'realignment_parameters') wf.connect(masktransform, 'transformed_file', art, 'mask_file') # Compute motion regressors motreg = Node(Function( input_names=['motion_params', 'order', 'derivatives'], output_names=['out_files'], function=motion_regressors, imports=imports), name='getmotionregress') wf.connect(realign, 'par_file', motreg, 'motion_params') # Create a filter to remove motion and art confounds createfilter1 = Node(Function( input_names=['motion_params', 'comp_norm', 'outliers'], output_names=['out_files'], function=build_filter1, imports=imports), name='makemotionbasedfilter') wf.connect(motreg, 'out_files', createfilter1, 'motion_params') wf.connect(art, 'norm_files', createfilter1, 'comp_norm') wf.connect(art, 'outlier_files', createfilter1, 'outliers') # Filter the motion and art confounds filter1 = MapNode(fsl.GLM(out_res_name='timeseries.nii.gz', demean=True), iterfield=['in_file', 'design'], name='filtermotion') if fieldmap_images: wf.connect(dewarper, 'unwarped_file', filter1, 'in_file') else: wf.connect(tsnr, 'detrended_file', filter1, 'in_file') wf.connect(createfilter1, 'out_files', filter1, 'design') wf.connect(masktransform, 'transformed_file', filter1, 'mask') # Create a filter to remove noise components based on white matter and CSF createfilter2 = MapNode(Function( input_names=['realigned_file', 'mask_file', 'num_components'], output_names=['out_files'], function=extract_noise_components, imports=imports), iterfield=['realigned_file'], name='makecompcorrfilter') createfilter2.inputs.num_components = num_components wf.connect(filter1, 'out_res', createfilter2, 'realigned_file') wf.connect(masktransform, 'transformed_file', createfilter2, 'mask_file') # Filter noise components filter2 = MapNode(fsl.GLM(out_res_name='timeseries_cleaned.nii.gz', demean=True), iterfield=['in_file', 'design'], name='filtercompcorr') wf.connect(filter1, 'out_res', filter2, 'in_file') wf.connect(createfilter2, 'out_files', filter2, 'design') wf.connect(masktransform, 'transformed_file', filter2, 'mask') # Smoothing using surface and volume smoothing smooth = MapNode(freesurfer.Smooth(), iterfield=['in_file'], name='smooth') smooth.inputs.proj_frac_avg = (0.1, 0.9, 0.1) if surf_fwhm is None: surf_fwhm = 5 * slice_thickness smooth.inputs.surface_fwhm = surf_fwhm if vol_fwhm is None: vol_fwhm = 2 * slice_thickness smooth.inputs.vol_fwhm = vol_fwhm wf.connect(filter2, 'out_res', smooth, 'in_file') wf.connect(register, 'out_reg_file', smooth, 'reg_file') # Bandpass filter the data bandpass = MapNode(fsl.TemporalFilter(), iterfield=['in_file'], name='bandpassfilter') if highpass_freq < 0: bandpass.inputs.highpass_sigma = -1 else: bandpass.inputs.highpass_sigma = 1. / (2 * TR * highpass_freq) if lowpass_freq < 0: bandpass.inputs.lowpass_sigma = -1 else: bandpass.inputs.lowpass_sigma = 1. / (2 * TR * lowpass_freq) wf.connect(smooth, 'smoothed_file', bandpass, 'in_file') # Convert aparc to subject functional space aparctransform = wmcsftransform.clone("aparctransform") if fieldmap_images: wf.connect(fieldmap, 'exf_mask', aparctransform, 'source_file') else: wf.connect(calc_median, 'median_file', aparctransform, 'source_file') wf.connect(register, 'out_reg_file', aparctransform, 'reg_file') wf.connect(fssource, ('aparc_aseg', get_aparc_aseg), aparctransform, 'target_file') # Sample the average time series in aparc ROIs sampleaparc = MapNode(freesurfer.SegStats(avgwf_txt_file=True, default_color_table=True), iterfield=['in_file'], name='aparc_ts') sampleaparc.inputs.segment_id = ([8] + range(10, 14) + [17, 18, 26, 47] + range(49, 55) + [58] + range(1001, 1036) + range(2001, 2036)) wf.connect(aparctransform, 'transformed_file', sampleaparc, 'segmentation_file') wf.connect(bandpass, 'out_file', sampleaparc, 'in_file') # Sample the time series onto the surface of the target surface. Performs # sampling into left and right hemisphere target = Node(IdentityInterface(fields=['target_subject']), name='target') target.iterables = ('target_subject', filename_to_list(target_subject)) samplerlh = MapNode(freesurfer.SampleToSurface(), iterfield=['source_file'], name='sampler_lh') samplerlh.inputs.sampling_method = "average" samplerlh.inputs.sampling_range = (0.1, 0.9, 0.1) samplerlh.inputs.sampling_units = "frac" samplerlh.inputs.interp_method = "trilinear" #samplerlh.inputs.cortex_mask = True samplerlh.inputs.out_type = 'niigz' samplerlh.inputs.subjects_dir = os.environ['SUBJECTS_DIR'] samplerrh = samplerlh.clone('sampler_rh') samplerlh.inputs.hemi = 'lh' wf.connect(bandpass, 'out_file', samplerlh, 'source_file') wf.connect(register, 'out_reg_file', samplerlh, 'reg_file') wf.connect(target, 'target_subject', samplerlh, 'target_subject') samplerrh.set_input('hemi', 'rh') wf.connect(bandpass, 'out_file', samplerrh, 'source_file') wf.connect(register, 'out_reg_file', samplerrh, 'reg_file') wf.connect(target, 'target_subject', samplerrh, 'target_subject') # Combine left and right hemisphere to text file combiner = MapNode(Function(input_names=['left', 'right'], output_names=['out_file'], function=combine_hemi, imports=imports), iterfield=['left', 'right'], name="combiner") wf.connect(samplerlh, 'out_file', combiner, 'left') wf.connect(samplerrh, 'out_file', combiner, 'right') # Compute registration between the subject's structural and MNI template # This is currently set to perform a very quick registration. However, the # registration can be made significantly more accurate for cortical # structures by increasing the number of iterations # All parameters are set using the example from: # https://github.com/stnava/ANTs/blob/master/Scripts/newAntsExample.sh reg = Node(ants.Registration(), name='antsRegister') reg.inputs.output_transform_prefix = "output_" reg.inputs.transforms = ['Translation', 'Rigid', 'Affine', 'SyN'] reg.inputs.transform_parameters = [(0.1, ), (0.1, ), (0.1, ), (0.2, 3.0, 0.0)] # reg.inputs.number_of_iterations = ([[10000, 111110, 11110]]*3 + # [[100, 50, 30]]) reg.inputs.number_of_iterations = [[100, 100, 100]] * 3 + [[100, 20, 10]] reg.inputs.dimension = 3 reg.inputs.write_composite_transform = True reg.inputs.collapse_output_transforms = False reg.inputs.metric = ['Mattes'] * 3 + [['Mattes', 'CC']] reg.inputs.metric_weight = [1] * 3 + [[0.5, 0.5]] reg.inputs.radius_or_number_of_bins = [32] * 3 + [[32, 4]] reg.inputs.sampling_strategy = ['Regular'] * 3 + [[None, None]] reg.inputs.sampling_percentage = [0.3] * 3 + [[None, None]] reg.inputs.convergence_threshold = [1.e-8] * 3 + [-0.01] reg.inputs.convergence_window_size = [20] * 3 + [5] reg.inputs.smoothing_sigmas = [[4, 2, 1]] * 3 + [[1, 0.5, 0]] reg.inputs.sigma_units = ['vox'] * 4 reg.inputs.shrink_factors = [[6, 4, 2]] + [[3, 2, 1]] * 2 + [[4, 2, 1]] reg.inputs.use_estimate_learning_rate_once = [True] * 4 reg.inputs.use_histogram_matching = [False] * 3 + [True] reg.inputs.output_warped_image = 'output_warped_image.nii.gz' reg.inputs.fixed_image = \ os.path.abspath('OASIS-30_Atropos_template_in_MNI152_2mm.nii.gz') reg.inputs.num_threads = 4 reg.plugin_args = {'qsub_args': '-l nodes=1:ppn=4'} # Convert T1.mgz to nifti for using with ANTS convert = Node(freesurfer.MRIConvert(out_type='niigz'), name='convert2nii') wf.connect(fssource, 'T1', convert, 'in_file') # Mask the T1.mgz file with the brain mask computed earlier maskT1 = Node(fsl.BinaryMaths(operation='mul'), name='maskT1') wf.connect(mask, 'binary_file', maskT1, 'operand_file') wf.connect(convert, 'out_file', maskT1, 'in_file') wf.connect(maskT1, 'out_file', reg, 'moving_image') # Convert the BBRegister transformation to ANTS ITK format convert2itk = MapNode(C3dAffineTool(), iterfield=['transform_file', 'source_file'], name='convert2itk') convert2itk.inputs.fsl2ras = True convert2itk.inputs.itk_transform = True wf.connect(register, 'out_fsl_file', convert2itk, 'transform_file') if fieldmap_images: wf.connect(fieldmap, 'exf_mask', convert2itk, 'source_file') else: wf.connect(calc_median, 'median_file', convert2itk, 'source_file') wf.connect(convert, 'out_file', convert2itk, 'reference_file') # Concatenate the affine and ants transforms into a list pickfirst = lambda x: x[0] merge = MapNode(Merge(2), iterfield=['in2'], name='mergexfm') wf.connect(convert2itk, 'itk_transform', merge, 'in2') wf.connect(reg, ('composite_transform', pickfirst), merge, 'in1') # Apply the combined transform to the time series file sample2mni = MapNode(ants.ApplyTransforms(), iterfield=['input_image', 'transforms'], name='sample2mni') sample2mni.inputs.input_image_type = 3 sample2mni.inputs.interpolation = 'BSpline' sample2mni.inputs.invert_transform_flags = [False, False] sample2mni.inputs.reference_image = \ os.path.abspath('OASIS-30_Atropos_template_in_MNI152_2mm.nii.gz') sample2mni.inputs.terminal_output = 'file' wf.connect(bandpass, 'out_file', sample2mni, 'input_image') wf.connect(merge, 'out', sample2mni, 'transforms') # Sample the time series file for each subcortical roi ts2txt = MapNode(Function( input_names=['timeseries_file', 'label_file', 'indices'], output_names=['out_file'], function=extract_subrois, imports=imports), iterfield=['timeseries_file'], name='getsubcortts') ts2txt.inputs.indices = [8] + range(10, 14) + [17, 18, 26, 47] +\ range(49, 55) + [58] ts2txt.inputs.label_file = \ os.path.abspath(('OASIS-TRT-20_jointfusion_DKT31_CMA_labels_in_MNI152_' '2mm.nii.gz')) wf.connect(sample2mni, 'output_image', ts2txt, 'timeseries_file') # Save the relevant data into an output directory datasink = Node(interface=DataSink(), name="datasink") datasink.inputs.base_directory = sink_directory datasink.inputs.container = subject_id datasink.inputs.substitutions = [('_target_subject_', '')] datasink.inputs.regexp_substitutions = (r'(/_.*(\d+/))', r'/run\2') wf.connect(despiker, 'out_file', datasink, 'resting.qa.despike') wf.connect(realign, 'par_file', datasink, 'resting.qa.motion') wf.connect(tsnr, 'tsnr_file', datasink, 'resting.qa.tsnr') wf.connect(tsnr, 'mean_file', datasink, 'resting.qa.tsnr.@mean') wf.connect(tsnr, 'stddev_file', datasink, 'resting.qa.@tsnr_stddev') if fieldmap_images: wf.connect(fieldmap, 'exf_mask', datasink, 'resting.reference') else: wf.connect(calc_median, 'median_file', datasink, 'resting.reference') wf.connect(art, 'norm_files', datasink, 'resting.qa.art.@norm') wf.connect(art, 'intensity_files', datasink, 'resting.qa.art.@intensity') wf.connect(art, 'outlier_files', datasink, 'resting.qa.art.@outlier_files') wf.connect(mask, 'binary_file', datasink, 'resting.mask') wf.connect(masktransform, 'transformed_file', datasink, 'resting.mask.@transformed_file') wf.connect(register, 'out_reg_file', datasink, 'resting.registration.bbreg') wf.connect(reg, ('composite_transform', pickfirst), datasink, 'resting.registration.ants') wf.connect(register, 'min_cost_file', datasink, 'resting.qa.bbreg.@mincost') wf.connect(smooth, 'smoothed_file', datasink, 'resting.timeseries.fullpass') wf.connect(bandpass, 'out_file', datasink, 'resting.timeseries.bandpassed') wf.connect(sample2mni, 'output_image', datasink, 'resting.timeseries.mni') wf.connect(createfilter1, 'out_files', datasink, 'resting.regress.@regressors') wf.connect(createfilter2, 'out_files', datasink, 'resting.regress.@compcorr') wf.connect(sampleaparc, 'summary_file', datasink, 'resting.parcellations.aparc') wf.connect(sampleaparc, 'avgwf_txt_file', datasink, 'resting.parcellations.aparc.@avgwf') wf.connect(ts2txt, 'out_file', datasink, 'resting.parcellations.grayo.@subcortical') datasink2 = Node(interface=DataSink(), name="datasink2") datasink2.inputs.base_directory = sink_directory datasink2.inputs.container = subject_id datasink2.inputs.substitutions = [('_target_subject_', '')] datasink2.inputs.regexp_substitutions = (r'(/_.*(\d+/))', r'/run\2') wf.connect(combiner, 'out_file', datasink2, 'resting.parcellations.grayo.@surface') return wf
def create_workflow(files, target_file, subject_id, TR, slice_times, norm_threshold=1, num_components=5, vol_fwhm=None, surf_fwhm=None, lowpass_freq=-1, highpass_freq=-1, subjects_dir=None, sink_directory=os.getcwd(), target_subject=['fsaverage3', 'fsaverage4'], name='resting'): wf = Workflow(name=name) # Rename files in case they are named identically name_unique = MapNode(Rename(format_string='rest_%(run)02d'), iterfield=['in_file', 'run'], name='rename') name_unique.inputs.keep_ext = True name_unique.inputs.run = list(range(1, len(files) + 1)) name_unique.inputs.in_file = files realign = Node(nipy.SpaceTimeRealigner(), name="spacetime_realign") realign.inputs.slice_times = slice_times realign.inputs.tr = TR realign.inputs.slice_info = 2 realign.plugin_args = {'sbatch_args': '-c%d' % 4} # Compute TSNR on realigned data regressing polynomials up to order 2 tsnr = MapNode(TSNR(regress_poly=2), iterfield=['in_file'], name='tsnr') wf.connect(realign, "out_file", tsnr, "in_file") # Compute the median image across runs calc_median = Node(Function(input_names=['in_files'], output_names=['median_file'], function=median, imports=imports), name='median') wf.connect(tsnr, 'detrended_file', calc_median, 'in_files') """Segment and Register """ registration = create_reg_workflow(name='registration') wf.connect(calc_median, 'median_file', registration, 'inputspec.mean_image') registration.inputs.inputspec.subject_id = subject_id registration.inputs.inputspec.subjects_dir = subjects_dir registration.inputs.inputspec.target_image = target_file """Quantify TSNR in each freesurfer ROI """ get_roi_tsnr = MapNode(fs.SegStats(default_color_table=True), iterfield=['in_file'], name='get_aparc_tsnr') get_roi_tsnr.inputs.avgwf_txt_file = True wf.connect(tsnr, 'tsnr_file', get_roi_tsnr, 'in_file') wf.connect(registration, 'outputspec.aparc', get_roi_tsnr, 'segmentation_file') """Use :class:`nipype.algorithms.rapidart` to determine which of the images in the functional series are outliers based on deviations in intensity or movement. """ art = Node(interface=ArtifactDetect(), name="art") art.inputs.use_differences = [True, True] art.inputs.use_norm = True art.inputs.norm_threshold = norm_threshold art.inputs.zintensity_threshold = 9 art.inputs.mask_type = 'spm_global' art.inputs.parameter_source = 'NiPy' """Here we are connecting all the nodes together. Notice that we add the merge node only if you choose to use 4D. Also `get_vox_dims` function is passed along the input volume of normalise to set the optimal voxel sizes. """ wf.connect([(name_unique, realign, [('out_file', 'in_file')]), (realign, art, [('out_file', 'realigned_files')]), (realign, art, [('par_file', 'realignment_parameters')]), ]) def selectindex(files, idx): import numpy as np from nipype.utils.filemanip import filename_to_list, list_to_filename return list_to_filename(np.array(filename_to_list(files))[idx].tolist()) mask = Node(fsl.BET(), name='getmask') mask.inputs.mask = True wf.connect(calc_median, 'median_file', mask, 'in_file') # get segmentation in normalized functional space def merge_files(in1, in2): out_files = filename_to_list(in1) out_files.extend(filename_to_list(in2)) return out_files # filter some noise # Compute motion regressors motreg = Node(Function(input_names=['motion_params', 'order', 'derivatives'], output_names=['out_files'], function=motion_regressors, imports=imports), name='getmotionregress') wf.connect(realign, 'par_file', motreg, 'motion_params') # Create a filter to remove motion and art confounds createfilter1 = Node(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 = 2 wf.connect(motreg, 'out_files', createfilter1, 'motion_params') wf.connect(art, 'norm_files', createfilter1, 'comp_norm') wf.connect(art, 'outlier_files', createfilter1, 'outliers') filter1 = MapNode(fsl.GLM(out_f_name='F_mcart.nii.gz', out_pf_name='pF_mcart.nii.gz', demean=True), iterfield=['in_file', 'design', 'out_res_name'], name='filtermotion') wf.connect(realign, 'out_file', filter1, 'in_file') wf.connect(realign, ('out_file', rename, '_filtermotart'), filter1, 'out_res_name') wf.connect(createfilter1, 'out_files', filter1, 'design') createfilter2 = MapNode(ACompCor(), iterfield=['realigned_file', 'extra_regressors'], name='makecompcorrfilter') createfilter2.inputs.components_file = 'noise_components.txt' createfilter2.inputs.num_components = num_components wf.connect(createfilter1, 'out_files', createfilter2, 'extra_regressors') wf.connect(filter1, 'out_res', createfilter2, 'realigned_file') wf.connect(registration, ('outputspec.segmentation_files', selectindex, [0, 2]), createfilter2, 'mask_file') filter2 = MapNode(fsl.GLM(out_f_name='F.nii.gz', out_pf_name='pF.nii.gz', demean=True), iterfield=['in_file', 'design', 'out_res_name'], name='filter_noise_nosmooth') wf.connect(filter1, 'out_res', filter2, 'in_file') wf.connect(filter1, ('out_res', rename, '_cleaned'), filter2, 'out_res_name') wf.connect(createfilter2, 'components_file', filter2, 'design') wf.connect(mask, 'mask_file', filter2, 'mask') bandpass = Node(Function(input_names=['files', 'lowpass_freq', 'highpass_freq', 'fs'], output_names=['out_files'], function=bandpass_filter, imports=imports), name='bandpass_unsmooth') bandpass.inputs.fs = 1. / TR bandpass.inputs.highpass_freq = highpass_freq bandpass.inputs.lowpass_freq = lowpass_freq wf.connect(filter2, 'out_res', bandpass, 'files') """Smooth the functional data using :class:`nipype.interfaces.fsl.IsotropicSmooth`. """ smooth = MapNode(interface=fsl.IsotropicSmooth(), name="smooth", iterfield=["in_file"]) smooth.inputs.fwhm = vol_fwhm wf.connect(bandpass, 'out_files', smooth, 'in_file') collector = Node(Merge(2), name='collect_streams') wf.connect(smooth, 'out_file', collector, 'in1') wf.connect(bandpass, 'out_files', collector, 'in2') """ Transform the remaining images. First to anatomical and then to target """ warpall = MapNode(ants.ApplyTransforms(), iterfield=['input_image'], name='warpall') warpall.inputs.input_image_type = 3 warpall.inputs.interpolation = 'Linear' warpall.inputs.invert_transform_flags = [False, False] warpall.inputs.terminal_output = 'file' warpall.inputs.reference_image = target_file warpall.inputs.args = '--float' warpall.inputs.num_threads = 2 warpall.plugin_args = {'sbatch_args': '-c%d' % 2} # transform to target wf.connect(collector, 'out', warpall, 'input_image') wf.connect(registration, 'outputspec.transforms', warpall, 'transforms') mask_target = Node(fsl.ImageMaths(op_string='-bin'), name='target_mask') wf.connect(registration, 'outputspec.anat2target', mask_target, 'in_file') maskts = MapNode(fsl.ApplyMask(), iterfield=['in_file'], name='ts_masker') wf.connect(warpall, 'output_image', maskts, 'in_file') wf.connect(mask_target, 'out_file', maskts, 'mask_file') # map to surface # extract aparc+aseg ROIs # extract subcortical ROIs # extract target space ROIs # combine subcortical and cortical rois into a single cifti file ####### # Convert aparc to subject functional space # Sample the average time series in aparc ROIs sampleaparc = MapNode(freesurfer.SegStats(default_color_table=True), iterfield=['in_file', 'summary_file', 'avgwf_txt_file'], name='aparc_ts') sampleaparc.inputs.segment_id = ([8] + list(range(10, 14)) + [17, 18, 26, 47] + list(range(49, 55)) + [58] + list(range(1001, 1036)) + list(range(2001, 2036))) wf.connect(registration, 'outputspec.aparc', sampleaparc, 'segmentation_file') wf.connect(collector, 'out', sampleaparc, 'in_file') def get_names(files, suffix): """Generate appropriate names for output files """ from nipype.utils.filemanip import (split_filename, filename_to_list, list_to_filename) import os out_names = [] for filename in files: path, name, _ = split_filename(filename) out_names.append(os.path.join(path, name + suffix)) return list_to_filename(out_names) wf.connect(collector, ('out', get_names, '_avgwf.txt'), sampleaparc, 'avgwf_txt_file') wf.connect(collector, ('out', get_names, '_summary.stats'), sampleaparc, 'summary_file') # Sample the time series onto the surface of the target surface. Performs # sampling into left and right hemisphere target = Node(IdentityInterface(fields=['target_subject']), name='target') target.iterables = ('target_subject', filename_to_list(target_subject)) samplerlh = MapNode(freesurfer.SampleToSurface(), iterfield=['source_file'], name='sampler_lh') samplerlh.inputs.sampling_method = "average" samplerlh.inputs.sampling_range = (0.1, 0.9, 0.1) samplerlh.inputs.sampling_units = "frac" samplerlh.inputs.interp_method = "trilinear" samplerlh.inputs.smooth_surf = surf_fwhm # samplerlh.inputs.cortex_mask = True samplerlh.inputs.out_type = 'niigz' samplerlh.inputs.subjects_dir = subjects_dir samplerrh = samplerlh.clone('sampler_rh') samplerlh.inputs.hemi = 'lh' wf.connect(collector, 'out', samplerlh, 'source_file') wf.connect(registration, 'outputspec.out_reg_file', samplerlh, 'reg_file') wf.connect(target, 'target_subject', samplerlh, 'target_subject') samplerrh.set_input('hemi', 'rh') wf.connect(collector, 'out', samplerrh, 'source_file') wf.connect(registration, 'outputspec.out_reg_file', samplerrh, 'reg_file') wf.connect(target, 'target_subject', samplerrh, 'target_subject') # Combine left and right hemisphere to text file combiner = MapNode(Function(input_names=['left', 'right'], output_names=['out_file'], function=combine_hemi, imports=imports), iterfield=['left', 'right'], name="combiner") wf.connect(samplerlh, 'out_file', combiner, 'left') wf.connect(samplerrh, 'out_file', combiner, 'right') # Sample the time series file for each subcortical roi ts2txt = MapNode(Function(input_names=['timeseries_file', 'label_file', 'indices'], output_names=['out_file'], function=extract_subrois, imports=imports), iterfield=['timeseries_file'], name='getsubcortts') ts2txt.inputs.indices = [8] + list(range(10, 14)) + [17, 18, 26, 47] +\ list(range(49, 55)) + [58] ts2txt.inputs.label_file = \ os.path.abspath(('OASIS-TRT-20_jointfusion_DKT31_CMA_labels_in_MNI152_' '2mm_v2.nii.gz')) wf.connect(maskts, 'out_file', ts2txt, 'timeseries_file') ###### substitutions = [('_target_subject_', ''), ('_filtermotart_cleaned_bp_trans_masked', ''), ('_filtermotart_cleaned_bp', ''), ] substitutions += [("_smooth%d" % i, "") for i in range(11)[::-1]] substitutions += [("_ts_masker%d" % i, "") for i in range(11)[::-1]] substitutions += [("_getsubcortts%d" % i, "") for i in range(11)[::-1]] substitutions += [("_combiner%d" % i, "") for i in range(11)[::-1]] substitutions += [("_filtermotion%d" % i, "") for i in range(11)[::-1]] substitutions += [("_filter_noise_nosmooth%d" % i, "") for i in range(11)[::-1]] substitutions += [("_makecompcorfilter%d" % i, "") for i in range(11)[::-1]] substitutions += [("_get_aparc_tsnr%d/" % i, "run%d_" % (i + 1)) for i in range(11)[::-1]] substitutions += [("T1_out_brain_pve_0_maths_warped", "compcor_csf"), ("T1_out_brain_pve_1_maths_warped", "compcor_gm"), ("T1_out_brain_pve_2_maths_warped", "compcor_wm"), ("output_warped_image_maths", "target_brain_mask"), ("median_brain_mask", "native_brain_mask"), ("corr_", "")] regex_subs = [('_combiner.*/sar', '/smooth/'), ('_combiner.*/ar', '/unsmooth/'), ('_aparc_ts.*/sar', '/smooth/'), ('_aparc_ts.*/ar', '/unsmooth/'), ('_getsubcortts.*/sar', '/smooth/'), ('_getsubcortts.*/ar', '/unsmooth/'), ('series/sar', 'series/smooth/'), ('series/ar', 'series/unsmooth/'), ('_inverse_transform./', ''), ] # Save the relevant data into an output directory datasink = Node(interface=DataSink(), name="datasink") datasink.inputs.base_directory = sink_directory datasink.inputs.container = subject_id datasink.inputs.substitutions = substitutions datasink.inputs.regexp_substitutions = regex_subs # (r'(/_.*(\d+/))', r'/run\2') wf.connect(realign, 'par_file', datasink, 'resting.qa.motion') wf.connect(art, 'norm_files', datasink, 'resting.qa.art.@norm') wf.connect(art, 'intensity_files', datasink, 'resting.qa.art.@intensity') wf.connect(art, 'outlier_files', datasink, 'resting.qa.art.@outlier_files') wf.connect(registration, 'outputspec.segmentation_files', datasink, 'resting.mask_files') wf.connect(registration, 'outputspec.anat2target', datasink, 'resting.qa.ants') wf.connect(mask, 'mask_file', datasink, 'resting.mask_files.@brainmask') wf.connect(mask_target, 'out_file', datasink, 'resting.mask_files.target') wf.connect(filter1, 'out_f', datasink, 'resting.qa.compmaps.@mc_F') wf.connect(filter1, 'out_pf', datasink, 'resting.qa.compmaps.@mc_pF') wf.connect(filter2, 'out_f', datasink, 'resting.qa.compmaps') wf.connect(filter2, 'out_pf', datasink, 'resting.qa.compmaps.@p') wf.connect(registration, 'outputspec.min_cost_file', datasink, 'resting.qa.mincost') wf.connect(tsnr, 'tsnr_file', datasink, 'resting.qa.tsnr.@map') wf.connect([(get_roi_tsnr, datasink, [('avgwf_txt_file', 'resting.qa.tsnr'), ('summary_file', 'resting.qa.tsnr.@summary')])]) wf.connect(bandpass, 'out_files', datasink, 'resting.timeseries.@bandpassed') wf.connect(smooth, 'out_file', datasink, 'resting.timeseries.@smoothed') wf.connect(createfilter1, 'out_files', datasink, 'resting.regress.@regressors') wf.connect(createfilter2, 'components_file', datasink, 'resting.regress.@compcorr') wf.connect(maskts, 'out_file', datasink, 'resting.timeseries.target') wf.connect(sampleaparc, 'summary_file', datasink, 'resting.parcellations.aparc') wf.connect(sampleaparc, 'avgwf_txt_file', datasink, 'resting.parcellations.aparc.@avgwf') wf.connect(ts2txt, 'out_file', datasink, 'resting.parcellations.grayo.@subcortical') datasink2 = Node(interface=DataSink(), name="datasink2") datasink2.inputs.base_directory = sink_directory datasink2.inputs.container = subject_id datasink2.inputs.substitutions = substitutions datasink2.inputs.regexp_substitutions = regex_subs # (r'(/_.*(\d+/))', r'/run\2') wf.connect(combiner, 'out_file', datasink2, 'resting.parcellations.grayo.@surface') return wf
import numpy as np from nipype import Function from nipype import Node from nipype import Workflow from nipype import IdentityInterface ds="/storage/gablab001/data/genus/GIT/genus/fs_cog/pred_diag/data_sets" data_sets = [os.path.join(ds, x) for x in os.listdir(ds) if ".csv" in x] response_var = os.path.join(ds, "response.txt") wf = Workflow(name="classify_disease") wf.base_dir = "/om/scratch/Sat/ysa" Iternode = Node(IdentityInterface(fields=['data', 'classifier']), name="Iternode") Iternode.iterables = [ ('data', data_sets), ('classifier', ['et', 'lg']) ] def run(data, classifier, response): import numpy as np import pandas as pd from custom import Mods from custom import utils y = np.genfromtxt(response) X = pd.read_csv(data) data_mod = data.split('/')[-1].replace('.csv', '') if classifier == 'et': od = '/storage/gablab001/data/genus/GIT/genus/fs_cog/pred_diag/extra_trees/results/' on = classifier + '_{}.pkl'.format(data_mod)