def run(self): experiment_dir = opj(self.paths['input_path'], 'output/') output_dir = 'datasink' working_dir = 'workingdir' subject_list = self.subject_list iso_size = self.parameters['iso_size'] t1_relative_path = self.paths['t1_relative_path'] dwi_relative_path = self.paths['dwi_relative_path'] bvec_relative_path = self.paths['bvec_relative_path'] bval_relative_path = self.paths['bval_relative_path'] # 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 (alternativ to DataGrabber) anat_file = opj('{subject_id}', t1_relative_path) dwi_file = opj('{subject_id}', dwi_relative_path) bvec_file = opj('{subject_id}', bvec_relative_path) bval_file = opj('{subject_id}', bval_relative_path) templates = { 'anat': anat_file, 'dwi': dwi_file, 'bvec': bvec_file, 'bval': bval_file } selectfiles = Node(SelectFiles( templates, base_directory=self.paths['input_path']), name="selectfiles") # Datasink - creates output folder for important outputs datasink = Node(DataSink(base_directory=experiment_dir, container=output_dir), name="datasink") substitutions = [('_subject_id_', 'sub-')] datasink.inputs.substitutions = substitutions preproc = Workflow(name='preproc') preproc.base_dir = opj(experiment_dir, working_dir) # BET - Skullstrip anatomical anf funtional images bet_t1 = Node(BET(frac=0.5, robust=True, mask=True, output_type='NIFTI_GZ'), name="bet_t1") # FSL denoise_t1 = Node(Denoise(), name="denoising_t1") # Dipy reslicing = Node(Reslicing(vox_sz=iso_size), name="reslicing") #Dipy #registration_atlas = Node(RegistrationAtlas(reference=self.paths['reference'], atlas_to_apply=self.paths['image_parcellation_path']), name="registration_atlas") registration_atlas = Node( RegistrationAtlas(reference=self.paths['reference']), name="registration_atlas") registration_atlas.iterables = [ ('atlas_to_apply', self.paths['image_parcellation_path']) ] #registration_t1 = Node(Registration(reference=self.paths['reference']), name="registration_t1") #registration_dwi = Node(Registration(reference='/home/brainlab/Desktop/Rudas/Data/Parcellation/MNI152_T2_2mm.nii.gz'), name="registration_dwi") tractography = Node(Tractography(), name='tractography') # Dipy model_dti = Node(ModelDTI(), name="model_dti") # Dipy denoise_dwi = Node(Denoise(), name="denoising_dwi") # Dipy extract_b0 = Node(ExtractB0(), name="extract_b0") n4bias = Node(N4Bias(out_file='t1_n4bias.nii.gz'), name='n4bias') # SimpeITK eddycorrection = Node(EddyCorrect(ref_num=0), 'eddycorrection') # FSL median_otsu = Node(MedianOtsu(), 'median_otsu') # Dipy ''' normalize_t1 = Node(Normalize12(jobtype='estwrite', tpm=self.paths['template_spm_path'], write_voxel_sizes=[iso_size, iso_size, iso_size], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_t1") normalize_masks = Node(Normalize12(jobtype='estwrite', tpm=self.paths['template_spm_path'], write_voxel_sizes=[iso_size, iso_size, iso_size], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_masks") # FAST - Image Segmentation segmentation = Node(FAST(output_type='NIFTI'), name="segmentation") # FLIRT - pre-alignment of functional images to anatomical images coreg_pre = Node(FLIRT(dof=6, output_type='NIFTI_GZ'), name="linear_warp_estimation") # Threshold - Threshold WM probability image threshold = Node(Threshold(thresh=0.5, args='-bin', output_type='NIFTI_GZ'), name="wm_mask_threshold") gunzip1 = Node(Gunzip(), name="gunzip1") gunzip2 = Node(Gunzip(), name="gunzip2") ''' # Create a coregistration workflow coregwf = Workflow(name='coreg_fmri_to_t1') coregwf.base_dir = opj(experiment_dir, working_dir) # FLIRT - coregistration of functional images to anatomical images with BBR coreg_bbr = Node(FLIRT(dof=6, cost='bbr', schedule=opj(os.getenv('FSLDIR'), 'etc/flirtsch/bbr.sch'), output_type='NIFTI_GZ'), name="nonlinear_warp_estimation") # Apply coregistration warp to functional images applywarp = Node(FLIRT(interp='spline', apply_isoxfm=iso_size, output_type='NIFTI'), name="registration_dwi") applywarp_mean = Node(FLIRT(interp='spline', apply_isoxfm=iso_size, output_type='NIFTI_GZ'), name="registration_mean_b0") # Connect all components of the coregistration workflow ''' coregwf.connect([(denoise_t1, bet_t1, [('out_file', 'in_file')]), (bet_t1, n4bias, [('out_file', 'in_file')]), (n4bias, segmentation, [('out_file', 'in_files')]), (segmentation, threshold, [(('partial_volume_files', get_latest), 'in_file')]), (n4bias, coreg_pre, [('out_file', 'reference')]), (threshold, coreg_bbr, [('out_file', 'wm_seg')]), (coreg_pre, coreg_bbr, [('out_matrix_file', 'in_matrix_file')]), (coreg_bbr, applywarp, [('out_matrix_file', 'in_matrix_file')]), (n4bias, applywarp, [('out_file', 'reference')]), (coreg_bbr, applywarp_mean, [('out_matrix_file', 'in_matrix_file')]), (n4bias, applywarp_mean, [('out_file', 'reference')]), ]) ''' # Connect all components of the preprocessing workflow preproc.connect([ (infosource, selectfiles, [('subject_id', 'subject_id')]), #(selectfiles, coregwf, [('anat', 'denoising_t1.in_file'), # ('anat', 'nonlinear_warp_estimation.reference')]), #(selectfiles, extract_b0, [('dwi', 'dwi_path'), ('bval', 'bval_path'), ('bvec', 'bvec_path')]), #(extract_b0, coregwf, [('out_file', 'linear_warp_estimation.in_file'), # ('out_file', 'nonlinear_warp_estimation.in_file'), # ('out_file', 'registration_mean_b0.in_file')]), #(selectfiles, coregwf, [('dwi', 'registration_dwi.in_file')]), #(coregwf, eddycorrection, [('registration_dwi.out_file', 'in_file')]), #(eddycorrection, denoise_dwi, [('eddy_corrected', 'in_file')]), #(denoise_dwi, median_otsu, [('out_file', 'in_file')]), (selectfiles, denoise_t1, [('anat', 'in_file')]), (denoise_t1, bet_t1, [('out_file', 'in_file')]), (bet_t1, n4bias, [('out_file', 'in_file')]), (selectfiles, eddycorrection, [('dwi', 'in_file')]), (eddycorrection, reslicing, [('eddy_corrected', 'in_file')]), (reslicing, denoise_dwi, [('out_file', 'in_file')]), (denoise_dwi, median_otsu, [('out_file', 'in_file')]), (median_otsu, extract_b0, [(('out_file', get_first), 'in_file')]), (selectfiles, extract_b0, [('bval', 'bval_path'), ('bvec', 'bvec_path')]), (extract_b0, registration_atlas, [('out_file', 'image_to_align')]), (median_otsu, model_dti, [(('out_file', get_first), 'in_file'), (('out_file', get_latest), 'mask_file') ]), (selectfiles, model_dti, [('bval', 'bval_path'), ('bvec', 'bvec_path')]), (median_otsu, tractography, [(('out_file', get_first), 'in_file'), (('out_file', get_latest), 'mask_file')]), (registration_atlas, tractography, [('out_file', 'image_parcellation_path')]), (selectfiles, tractography, [('bval', 'bval_path'), ('bvec', 'bvec_path')]) ]) preproc.run()
data_dir = 'data/ds000171/' # Leverage BIDS to get subject list layout = BIDSLayout(os.path.join(project_dir, data_dir)) subject_list = layout.get_subjects() grab_anat = Node(BIDSDataGrabber(), name='grab_anat') grab_anat.inputs.base_dir = os.path.join(project_dir, data_dir) # Iterate through subjects; [:2] for only 2 subjects to keep memory usage low grab_anat.iterables = ('subject', subject_list[:2]) # Define filetypes to grab, and how ouput will be accesses by other nodes grab_anat.inputs.output_query = { 'T1w': dict(extension=['nii.gz'], suffix='T1w') } def printFile(paths): print("\n\nPrinting " + str(paths) + "\n\n") printfile = Node(Function(function=printFile, input_names=["paths"], output_names=[]), name="printfile") wf = Workflow(name='wf') wf.connect(grab_anat, 'T1w', printfile, 'paths') res = wf.run()
def run(self): matlab_cmd = self.paths['spm_path'] + ' ' + self.paths[ 'mcr_path'] + '/ script' spm.SPMCommand.set_mlab_paths(matlab_cmd=matlab_cmd, use_mcr=True) print(matlab_cmd) print('SPM version: ' + str(spm.SPMCommand().version)) experiment_dir = opj(self.paths['input_path'], 'output/') output_dir = 'datasink' working_dir = 'workingdir' subject_list = self.subject_list # list of subject identifiers fwhm = self.parameters[ 'fwhm'] # Smoothing widths to apply (Gaussian kernel size) tr = self.parameters['tr'] # Repetition time init_volume = self.parameters[ 'init_volume'] # Firts volumen identification which will use in the pipeline iso_size = self.parameters[ 'iso_size'] # Isometric resample of functional images to voxel size (in mm) low_pass = self.parameters['low_pass'] high_pass = self.parameters['high_pass'] t1_relative_path = self.paths['t1_relative_path'] fmri_relative_path = self.paths['fmri_relative_path'] # ExtractROI - skip dummy scans extract = Node(ExtractROI(t_min=init_volume, t_size=-1, output_type='NIFTI'), name="extract") #FSL # MCFLIRT - motion correction mcflirt = Node(MCFLIRT(mean_vol=True, save_plots=True, output_type='NIFTI'), name="motion_correction") #FSL # SliceTimer - correct for slice wise acquisition slicetimer = Node(SliceTimer(index_dir=False, interleaved=True, output_type='NIFTI', time_repetition=tr), name="slice_timing_correction") #FSL # Smooth - image smoothing denoise = Node(Denoise(), name="denoising") #Interfaces with dipy smooth = Node(spm.Smooth(fwhm=fwhm), name="smooth") #SPM n4bias = Node(N4Bias(out_file='t1_n4bias.nii.gz'), name='n4bias') #Interface with SimpleITK descomposition = Node(Descomposition(n_components=20, low_pass=0.1, high_pass=0.01, tr=tr), name='descomposition') #Interface with nilearn # Artifact Detection - determines outliers in functional images art = Node(ArtifactDetect(norm_threshold=2, zintensity_threshold=3, mask_type='spm_global', parameter_source='FSL', use_differences=[True, False], plot_type='svg'), name="artifact_detection") #Rapidart extract_confounds_ws_csf = Node( ExtractConfounds(out_file='ev_without_gs.csv'), name='extract_confounds_ws_csf') #Interfece extract_confounds_gs = Node(ExtractConfounds(out_file='ev_with_gs.csv', delimiter=','), name='extract_confounds_global_signal') signal_extraction = Node(SignalExtraction( time_series_out_file='time_series.csv', correlation_matrix_out_file='correlation_matrix.png', labels_parcellation_path=self.paths['labels_parcellation_path'], mask_mni_path=self.paths['mask_mni_path'], tr=tr, low_pass=low_pass, high_pass=high_pass, plot=False), name='signal_extraction') signal_extraction.iterables = [('image_parcellation_path', self.paths['image_parcellation_path'])] art_remotion = Node( ArtifacRemotion(out_file='fmri_art_removed.nii'), name='artifact_remotion') #This interface requires implementation # BET - Skullstrip anatomical anf funtional images bet_t1 = Node(BET(frac=0.5, robust=True, mask=True, output_type='NIFTI_GZ'), name="bet_t1") #FSL # FAST - Image Segmentation segmentation = Node(FAST(output_type='NIFTI'), name="segmentation") #FSL # Normalize - normalizes functional and structural images to the MNI template normalize_fmri = Node(Normalize12( jobtype='estwrite', tpm=self.paths['template_spm_path'], write_voxel_sizes=[iso_size, iso_size, iso_size], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_fmri") #SPM gunzip = Node(Gunzip(), name="gunzip") normalize_t1 = Node(Normalize12( jobtype='estwrite', tpm=self.paths['template_spm_path'], write_voxel_sizes=[iso_size, iso_size, iso_size], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_t1") normalize_masks = Node(Normalize12( jobtype='estwrite', tpm=self.paths['template_spm_path'], write_voxel_sizes=[iso_size, iso_size, iso_size], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_masks") # Threshold - Threshold WM probability image threshold = Node(Threshold(thresh=0.5, args='-bin', output_type='NIFTI_GZ'), name="wm_mask_threshold") # FLIRT - pre-alignment of functional images to anatomical images coreg_pre = Node(FLIRT(dof=6, output_type='NIFTI_GZ'), name="linear_warp_estimation") # FLIRT - coregistration of functional images to anatomical images with BBR coreg_bbr = Node(FLIRT(dof=6, cost='bbr', schedule=opj(os.getenv('FSLDIR'), 'etc/flirtsch/bbr.sch'), output_type='NIFTI_GZ'), name="nonlinear_warp_estimation") # Apply coregistration warp to functional images applywarp = Node(FLIRT(interp='spline', apply_isoxfm=iso_size, output_type='NIFTI'), name="registration_fmri") # Apply coregistration warp to mean file applywarp_mean = Node(FLIRT(interp='spline', apply_isoxfm=iso_size, output_type='NIFTI_GZ'), name="registration_mean_fmri") # 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 (alternativ to DataGrabber) anat_file = opj('{subject_id}', t1_relative_path) func_file = opj('{subject_id}', fmri_relative_path) #anat_file = opj('{subject_id}/anat/', 'data.nii') #func_file = opj('{subject_id}/func/', 'data.nii') templates = {'anat': anat_file, 'func': func_file} selectfiles = Node(SelectFiles( templates, base_directory=self.paths['input_path']), name="selectfiles") # Datasink - creates output folder for important outputs datasink = Node(DataSink(base_directory=experiment_dir, container=output_dir), name="datasink") # Create a coregistration workflow coregwf = Workflow(name='coreg_fmri_to_t1') coregwf.base_dir = opj(experiment_dir, working_dir) # Create a preprocessing workflow preproc = Workflow(name='preproc') preproc.base_dir = opj(experiment_dir, working_dir) # Connect all components of the coregistration workflow coregwf.connect([ (bet_t1, n4bias, [('out_file', 'in_file')]), (n4bias, segmentation, [('out_file', 'in_files')]), (segmentation, threshold, [(('partial_volume_files', get_latest), 'in_file')]), (n4bias, coreg_pre, [('out_file', 'reference')]), (threshold, coreg_bbr, [('out_file', 'wm_seg')]), (coreg_pre, coreg_bbr, [('out_matrix_file', 'in_matrix_file')]), (coreg_bbr, applywarp, [('out_matrix_file', 'in_matrix_file')]), (n4bias, applywarp, [('out_file', 'reference')]), (coreg_bbr, applywarp_mean, [('out_matrix_file', 'in_matrix_file') ]), (n4bias, applywarp_mean, [('out_file', 'reference')]), ]) ## Use the following DataSink output substitutions substitutions = [('_subject_id_', 'sub-')] # ('_fwhm_', 'fwhm-'), # ('_roi', ''), # ('_mcf', ''), # ('_st', ''), # ('_flirt', ''), # ('.nii_mean_reg', '_mean'), # ('.nii.par', '.par'), # ] # subjFolders = [('fwhm-%s/' % f, 'fwhm-%s_' % f) for f in fwhm] # substitutions.extend(subjFolders) datasink.inputs.substitutions = substitutions # Connect all components of the preprocessing workflow preproc.connect([ (infosource, selectfiles, [('subject_id', 'subject_id')]), (selectfiles, extract, [('func', 'in_file')]), (extract, mcflirt, [('roi_file', 'in_file')]), (mcflirt, slicetimer, [('out_file', 'in_file')]), (selectfiles, denoise, [('anat', 'in_file')]), (denoise, coregwf, [('out_file', 'bet_t1.in_file'), ('out_file', 'nonlinear_warp_estimation.reference')]), (mcflirt, coregwf, [('mean_img', 'linear_warp_estimation.in_file'), ('mean_img', 'nonlinear_warp_estimation.in_file'), ('mean_img', 'registration_mean_fmri.in_file')]), (slicetimer, coregwf, [('slice_time_corrected_file', 'registration_fmri.in_file')]), (coregwf, art, [('registration_fmri.out_file', 'realigned_files') ]), (mcflirt, art, [('par_file', 'realignment_parameters')]), (art, art_remotion, [('outlier_files', 'outlier_files')]), (coregwf, art_remotion, [('registration_fmri.out_file', 'in_file') ]), (coregwf, gunzip, [('n4bias.out_file', 'in_file')]), (selectfiles, normalize_fmri, [('anat', 'image_to_align')]), (art_remotion, normalize_fmri, [('out_file', 'apply_to_files')]), (selectfiles, normalize_t1, [('anat', 'image_to_align')]), (gunzip, normalize_t1, [('out_file', 'apply_to_files')]), (selectfiles, normalize_masks, [('anat', 'image_to_align')]), (coregwf, normalize_masks, [(('segmentation.partial_volume_files', get_wm_csf), 'apply_to_files')]), (normalize_fmri, smooth, [('normalized_files', 'in_files')]), (smooth, extract_confounds_ws_csf, [('smoothed_files', 'in_file') ]), (normalize_masks, extract_confounds_ws_csf, [('normalized_files', 'list_mask')]), (mcflirt, extract_confounds_ws_csf, [('par_file', 'file_concat')]), (art, extract_confounds_ws_csf, [('outlier_files', 'outlier_files') ]), # (smooth, extract_confounds_gs, [('smoothed_files', 'in_file')]), # (normalize_t1, extract_confounds_gs, [(('normalized_files',change_to_list), 'list_mask')]), # (extract_confounds_ws_csf, extract_confounds_gs, [('out_file', 'file_concat')]), (smooth, signal_extraction, [('smoothed_files', 'in_file')]), # (extract_confounds_gs, signal_extraction, [('out_file', 'confounds_file')]), (extract_confounds_ws_csf, signal_extraction, [('out_file', 'confounds_file')]), #(smooth, descomposition, [('smoothed_files', 'in_file')]), #(extract_confounds_ws_csf, descomposition, [('out_file', 'confounds_file')]), # (extract_confounds_gs, datasink, [('out_file', 'preprocessing.@confounds_with_gs')]), (denoise, datasink, [('out_file', 'preprocessing.@t1_denoised')]), (extract_confounds_ws_csf, datasink, [('out_file', 'preprocessing.@confounds_without_gs')]), (smooth, datasink, [('smoothed_files', 'preprocessing.@smoothed') ]), (normalize_fmri, datasink, [('normalized_files', 'preprocessing.@fmri_normalized')]), (normalize_t1, datasink, [('normalized_files', 'preprocessing.@t1_normalized')]), (normalize_masks, datasink, [('normalized_files', 'preprocessing.@masks_normalized')]), (signal_extraction, datasink, [('time_series_out_file', 'preprocessing.@time_serie')]), (signal_extraction, datasink, [('correlation_matrix_out_file', 'preprocessing.@correlation_matrix')]) ]) #(signal_extraction, datasink, # [('fmri_cleaned_out_file', 'preprocessing.@fmri_cleaned_out_file')])]) #, #(descomposition, datasink, [('out_file', 'preprocessing.@descomposition')]), #(descomposition, datasink, [('plot_files', 'preprocessing.@descomposition_plot_files')]) #]) preproc.write_graph(graph2use='colored', format='png', simple_form=True) preproc.run()
modelspec = Node(interface=model.SpecifySPMModel(), name="modelspec") modelspec.inputs.concatenate_runs = False modelspec.inputs.input_units = 'scans' # supposedly it means tr modelspec.inputs.output_units = 'scans' #modelspec.inputs.outlier_files = '/media/Data/R_A_PTSD/preproccess_data/sub-1063_ses-01_task-3_bold_outliers.txt' modelspec.inputs.time_repetition = 1. # make sure its with a dot modelspec.inputs.high_pass_filter_cutoff = 128. level1design = pe.Node(interface=spm.Level1Design(), name="level1design") #, base_dir = '/media/Data/work') level1design.inputs.timing_units = modelspec.inputs.output_units level1design.inputs.interscan_interval = 1. level1design.inputs.bases = {'hrf': {'derivs': [0, 0]}} level1design.inputs.model_serial_correlations = 'AR(1)' # create workflow wfSPM = Workflow(name="l1spm_resp_sv", base_dir=work_dir) wfSPM.connect([ (infosource, selectfiles, [('subject_id', 'subject_id')]), (selectfiles, runinfo, [('events','events_file'),('regressors','regressors_file')]), (selectfiles, extract, [('func','in_file')]), (extract, smooth, [('roi_file','in_files')]), (smooth, runinfo, [('smoothed_files','in_file')]), (smooth, modelspec, [('smoothed_files', 'functional_runs')]), (runinfo, modelspec, [('info', 'subject_info'), ('realign_file', 'realignment_parameters')]), ]) wfSPM.connect([(modelspec, level1design, [("session_info", "session_info")])]) #%% level1estimate = pe.Node(interface=spm.EstimateModel(), name="level1estimate") level1estimate.inputs.estimation_method = {'Classical': 1}
def create_rs_qc(subjectlist): # main workflow for extended qc of diffusion/rsfmri data # fsl output type fsl.FSLCommand.set_default_output_type('NIFTI_GZ') # some hard coded things fd_thres = 0.2 tr = 1.4 # Specify the location of the preprocessed data data_dir = "/data/pt_02030/wd_preprocessing/hcp_prep_workflow/resting/" working_dir = "/data/pt_02030/wd_preprocessing/" #MODIFY freesurfer_dir = "/data/pt_02030/preprocessed/freesurfer/" qc = Workflow(name="qc") qc.base_dir = working_dir + '/' qc.config['execution']['crashdump_dir'] = qc.base_dir + "/crash_files" #first get all data needed identitynode = Node(util.IdentityInterface(fields=['subject']), name='identitynode') identitynode.iterables = ('subject', subjectlist) info = dict(func=[[ 'transform_timeseries/', '_subject_', 'subj', '/merge/rest2anat.nii.gz' ]], dvars=[[ 'transform_timeseries/', '_subject_', 'subj', '/dvars/rest2anat_dvars.tsv' ]], motpars=[[ '/motion_correction/', '_subject_', 'subj', '/mcflirt/rest_realigned.nii.gz.par' ]], brainmask=[[ 'transform_timeseries/', '_subject_', 'subj', '/resample_brain/T1_brain_mask_lowres.nii.gz' ]]) ds_rs = Node(interface=nio.DataGrabber( infields=['subj'], outfields=['func', 'dvars', 'motpars', 'brainmask']), name='ds_rs') ds_rs.inputs.base_directory = data_dir ds_rs.inputs.template = '%s%s%s%s' ds_rs.inputs.template_args = info ds_rs.inputs.sort_filelist = True get_fs = Node(nio.FreeSurferSource(), name="get_fs") get_fs.inputs.subjects_dir = freesurfer_dir get_correct_aseg = Node(util.Function(input_names=['in_list'], output_names=['out_aseg'], function=get_aseg), name="get_correct_aseg") convert = Node(fs.MRIConvert(), name="convert") convert.inputs.out_type = "niigz" downsample = Node(afni.Resample(resample_mode='NN', outputtype='NIFTI_GZ', out_file='aparcaseg_lowres.nii.gz'), name='downsample') calc_fd = Node(util.Function( input_names=['realignment_parameters_file', 'parameter_source'], output_names=['FD_power', 'fn'], function=calc_frame_displacement), name="calc_fd") calc_fd.inputs.parameter_source = 'FSL' outliers = Node(afni.OutlierCount(fraction=True, out_file='outliers.out'), name='outliers', mem_gb=1 * 2.5) bigplot = Node(util.Function(input_names=[ 'func', 'seg', 'tr', 'fd_thres', 'outliers', 'dvars', 'fd', 'subj', 'outfile' ], output_names=['fn', 'dataframe'], function=make_the_plot), name="bigplot") bigplot.inputs.tr = tr bigplot.inputs.fd_thres = fd_thres bigplot.inputs.outfile = "summary_fmriplot.png" fftplot = Node(util.Function(input_names=['fn_pd', 'tr'], output_names=['fn'], function=plot_fft), name="fftplot") fftplot.inputs.tr = tr datasink = Node(name="datasink", interface=nio.DataSink()) datasink.inputs.base_directory = "/data/pt_02030/preprocessed/reports/" datasink.inputs.substitutions = [('_subject_', '')] qc.connect([(identitynode, get_fs, [('subject', 'subject_id')]), (identitynode, ds_rs, [('subject', 'subj')]), (identitynode, bigplot, [('subject', 'subj')]), (get_fs, get_correct_aseg, [('aparc_aseg', 'in_list')]), (get_correct_aseg, convert, [('out_aseg', 'in_file')]), (convert, downsample, [('out_file', 'in_file')]), (ds_rs, downsample, [('func', 'master')]), (downsample, bigplot, [('out_file', 'seg')]), (ds_rs, calc_fd, [('motpars', 'realignment_parameters_file')]), (ds_rs, bigplot, [('func', 'func')]), (ds_rs, bigplot, [('dvars', 'dvars')]), (calc_fd, bigplot, [('FD_power', 'fd')]), (ds_rs, outliers, [('func', 'in_file')]), (ds_rs, outliers, [('brainmask', 'mask')]), (outliers, bigplot, [('out_file', 'outliers')]), (bigplot, datasink, [('fn', 'detailedQA.@bigplot')]), (bigplot, fftplot, [('dataframe', 'fn_pd')]), (bigplot, datasink, [('dataframe', 'detailedQA.metrics.@dataframe')]), (fftplot, datasink, [('fn', 'detailedQA.@fftplot')]), (calc_fd, datasink, [('fn', 'detailedQA.metrics.@fd')])]) qc.run(plugin="MultiProc", plugin_args={"n_procs": 16, "non_daemon": True}) return qc
def create_reg_workflow(name='registration'): """Create a FEAT preprocessing workflow together with freesurfer Parameters ---------- name : name of workflow (default: 'registration') Inputs:: inputspec.source_files : files (filename or list of filenames to register) inputspec.mean_image : reference image to use inputspec.anatomical_image : anatomical image to coregister to inputspec.target_image : registration target Outputs:: outputspec.func2anat_transform : FLIRT transform outputspec.anat2target_transform : FLIRT+FNIRT transform outputspec.transformed_files : transformed files in target space outputspec.transformed_mean : mean image in target space """ register = Workflow(name=name) inputnode = Node(interface=IdentityInterface(fields=[ 'source_files', 'mean_image', 'subject_id', 'subjects_dir', 'target_image' ]), name='inputspec') outputnode = Node(interface=IdentityInterface(fields=[ 'func2anat_transform', 'out_reg_file', 'anat2target_transform', 'transforms', 'transformed_mean', 'segmentation_files', 'anat2target', 'aparc' ]), name='outputspec') # Get the subject's freesurfer source directory fssource = Node(FreeSurferSource(), name='fssource') fssource.run_without_submitting = True register.connect(inputnode, 'subject_id', fssource, 'subject_id') register.connect(inputnode, 'subjects_dir', fssource, 'subjects_dir') convert = Node(freesurfer.MRIConvert(out_type='nii'), name="convert") register.connect(fssource, 'T1', convert, 'in_file') # Coregister the median to the surface bbregister = Node(freesurfer.BBRegister(), name='bbregister') bbregister.inputs.init = 'fsl' bbregister.inputs.contrast_type = 't2' bbregister.inputs.out_fsl_file = True bbregister.inputs.epi_mask = True register.connect(inputnode, 'subject_id', bbregister, 'subject_id') register.connect(inputnode, 'mean_image', bbregister, 'source_file') register.connect(inputnode, 'subjects_dir', bbregister, 'subjects_dir') """ Estimate the tissue classes from the anatomical image. But use spm's segment as FSL appears to be breaking. """ stripper = Node(fsl.BET(), name='stripper') register.connect(convert, 'out_file', stripper, 'in_file') fast = Node(fsl.FAST(), name='fast') register.connect(stripper, 'out_file', fast, 'in_files') """ Binarize the segmentation """ binarize = MapNode(fsl.ImageMaths(op_string='-nan -thr 0.9 -ero -bin'), iterfield=['in_file'], name='binarize') register.connect(fast, 'partial_volume_files', binarize, 'in_file') """ Apply inverse transform to take segmentations to functional space """ applyxfm = MapNode(freesurfer.ApplyVolTransform(inverse=True, interp='nearest'), iterfield=['target_file'], name='inverse_transform') register.connect(inputnode, 'subjects_dir', applyxfm, 'subjects_dir') register.connect(bbregister, 'out_reg_file', applyxfm, 'reg_file') register.connect(binarize, 'out_file', applyxfm, 'target_file') register.connect(inputnode, 'mean_image', applyxfm, 'source_file') """ Apply inverse transform to aparc file """ aparcxfm = Node(freesurfer.ApplyVolTransform(inverse=True, interp='nearest'), name='aparc_inverse_transform') register.connect(inputnode, 'subjects_dir', aparcxfm, 'subjects_dir') register.connect(bbregister, 'out_reg_file', aparcxfm, 'reg_file') register.connect(fssource, ('aparc_aseg', get_aparc_aseg), aparcxfm, 'target_file') register.connect(inputnode, 'mean_image', aparcxfm, 'source_file') """ Convert the BBRegister transformation to ANTS ITK format """ convert2itk = Node(C3dAffineTool(), name='convert2itk') convert2itk.inputs.fsl2ras = True convert2itk.inputs.itk_transform = True register.connect(bbregister, 'out_fsl_file', convert2itk, 'transform_file') register.connect(inputnode, 'mean_image', convert2itk, 'source_file') register.connect(stripper, 'out_file', convert2itk, 'reference_file') """ Compute registration between the subject's structural and MNI template This is currently set to perform a very quick registration. However, the registration can be made significantly more accurate for cortical structures by increasing the number of iterations All parameters are set using the example from: #https://github.com/stnava/ANTs/blob/master/Scripts/newAntsExample.sh """ reg = Node(ants.Registration(), name='antsRegister') reg.inputs.output_transform_prefix = "output_" reg.inputs.transforms = ['Rigid', 'Affine', 'SyN'] reg.inputs.transform_parameters = [(0.1, ), (0.1, ), (0.2, 3.0, 0.0)] reg.inputs.number_of_iterations = [[10000, 11110, 11110]] * 2 + [[ 100, 30, 20 ]] reg.inputs.dimension = 3 reg.inputs.write_composite_transform = True reg.inputs.collapse_output_transforms = True reg.inputs.initial_moving_transform_com = True reg.inputs.metric = ['Mattes'] * 2 + [['Mattes', 'CC']] reg.inputs.metric_weight = [1] * 2 + [[0.5, 0.5]] reg.inputs.radius_or_number_of_bins = [32] * 2 + [[32, 4]] reg.inputs.sampling_strategy = ['Regular'] * 2 + [[None, None]] reg.inputs.sampling_percentage = [0.3] * 2 + [[None, None]] reg.inputs.convergence_threshold = [1.e-8] * 2 + [-0.01] reg.inputs.convergence_window_size = [20] * 2 + [5] reg.inputs.smoothing_sigmas = [[4, 2, 1]] * 2 + [[1, 0.5, 0]] reg.inputs.sigma_units = ['vox'] * 3 reg.inputs.shrink_factors = [[3, 2, 1]] * 2 + [[4, 2, 1]] reg.inputs.use_estimate_learning_rate_once = [True] * 3 reg.inputs.use_histogram_matching = [False] * 2 + [True] reg.inputs.winsorize_lower_quantile = 0.005 reg.inputs.winsorize_upper_quantile = 0.995 reg.inputs.float = True reg.inputs.output_warped_image = 'output_warped_image.nii.gz' reg.inputs.num_threads = 4 reg.plugin_args = {'qsub_args': '-l nodes=1:ppn=4'} register.connect(stripper, 'out_file', reg, 'moving_image') register.connect(inputnode, 'target_image', reg, 'fixed_image') """ Concatenate the affine and ants transforms into a list """ merge = Node(Merge(2), iterfield=['in2'], name='mergexfm') register.connect(convert2itk, 'itk_transform', merge, 'in2') register.connect(reg, 'composite_transform', merge, 'in1') """ Transform the mean image. First to anatomical and then to target """ warpmean = Node(ants.ApplyTransforms(), name='warpmean') warpmean.inputs.input_image_type = 3 warpmean.inputs.interpolation = 'Linear' warpmean.inputs.invert_transform_flags = [False, False] warpmean.inputs.terminal_output = 'file' warpmean.inputs.args = '--float' warpmean.inputs.num_threads = 4 register.connect(inputnode, 'target_image', warpmean, 'reference_image') register.connect(inputnode, 'mean_image', warpmean, 'input_image') register.connect(merge, 'out', warpmean, 'transforms') """ Assign all the output files """ register.connect(reg, 'warped_image', outputnode, 'anat2target') register.connect(warpmean, 'output_image', outputnode, 'transformed_mean') register.connect(applyxfm, 'transformed_file', outputnode, 'segmentation_files') register.connect(aparcxfm, 'transformed_file', outputnode, 'aparc') register.connect(bbregister, 'out_fsl_file', outputnode, 'func2anat_transform') register.connect(bbregister, 'out_reg_file', outputnode, 'out_reg_file') register.connect(reg, 'composite_transform', outputnode, 'anat2target_transform') register.connect(merge, 'out', outputnode, 'transforms') return register
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 = 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] + range(10, 14) + [17, 18, 26, 47] + range(49, 55) + [58] + range(1001, 1036) + 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] + 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_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 define_model_fit_workflow(info, subjects, sessions, qc=True): # --- Workflow parameterization and data input # We just need two levels of iterables here: one subject-level and # one "flat" run-level iterable (i.e. all runs collapsing over # sessions). But we want to be able to specify sessions to process. scan_info = info.scan_info experiment = info.experiment_name model = info.model_name iterables = generate_iterables(scan_info, experiment, subjects, sessions) subject_iterables, run_iterables = iterables subject_source = Node(IdentityInterface(["subject"]), name="subject_source", iterables=("subject", subject_iterables)) run_source = Node(IdentityInterface(["subject", "run"]), name="run_source", itersource=("subject_source", "subject"), iterables=("run", run_iterables)) data_input = Node( ModelFitInput(experiment=experiment, model=model, proc_dir=info.proc_dir), "data_input") # --- Data filtering and model fitting fit_model = Node(ModelFit(data_dir=info.data_dir, info=info.trait_get()), "fit_model") # --- Data output save_info = Node(SaveInfo(info_dict=info.trait_get()), "save_info") data_output = Node( DataSink(base_directory=info.proc_dir, parameterization=False), "data_output") # === Assemble pipeline cache_base = op.join(info.cache_dir, experiment) workflow = Workflow(name="model_fit", base_dir=cache_base) # Connect processing nodes processing_edges = [ (subject_source, run_source, [("subject", "subject")]), (subject_source, data_input, [("subject", "subject")]), (run_source, data_input, [("run", "run_tuple")]), (data_input, fit_model, [("subject", "subject"), ("session", "session"), ("run", "run"), ("seg_file", "seg_file"), ("surf_file", "surf_file"), ("edge_file", "edge_file"), ("mask_file", "mask_file"), ("ts_file", "ts_file"), ("noise_file", "noise_file"), ("mc_file", "mc_file")]), (data_input, data_output, [("output_path", "container")]), (fit_model, data_output, [("mask_file", "@mask"), ("beta_file", "@beta"), ("error_file", "@error"), ("ols_file", "@ols"), ("resid_file", "@resid"), ("model_file", "@model")]), ] workflow.connect(processing_edges) qc_edges = [ (run_source, save_info, [("run", "parameterization")]), (save_info, data_output, [("info_file", "qc.@info_json")]), (fit_model, data_output, [("model_plot", "qc.@model_plot"), ("nuisance_plot", "qc.@nuisance_plot"), ("resid_plot", "qc.@resid_plot"), ("error_plot", "qc.@error_plot")]), ] if qc: workflow.connect(qc_edges) return workflow
def define_model_results_workflow(info, subjects, qc=True): # TODO I am copying a lot from above ... # --- Workflow parameterization and data input # We just need two levels of iterables here: one subject-level and # one "flat" run-level iterable (i.e. all runs collapsing over # sessions). Unlike in the model fit workflow, we always want to process # all sessions. scan_info = info.scan_info experiment = info.experiment_name model = info.model_name iterables = generate_iterables(scan_info, experiment, subjects) subject_iterables, run_iterables = iterables subject_source = Node(IdentityInterface(["subject"]), name="subject_source", iterables=("subject", subject_iterables)) run_source = Node(IdentityInterface(["subject", "run"]), name="run_source", itersource=("subject_source", "subject"), iterables=("run", run_iterables)) data_input = Node( ModelResultsInput(experiment=experiment, model=model, proc_dir=info.proc_dir), "data_input") # --- Run-level contrast estimation estimate_contrasts = Node(EstimateContrasts(info=info.trait_get()), "estimate_contrasts") # --- Subject-level contrast estimation model_results = JoinNode( ModelResults(info=info.trait_get()), name="model_results", joinsource="run_source", joinfield=["contrast_files", "variance_files", "name_files"]) # --- Data output save_info = Node(SaveInfo(info_dict=info.trait_get()), "save_info") run_output = Node( DataSink(base_directory=info.proc_dir, parameterization=False), "run_output") results_path = Node( ModelResultsPath(proc_dir=info.proc_dir, experiment=experiment, model=model), "results_path") subject_output = Node( DataSink(base_directory=info.proc_dir, parameterization=False), "subject_output") # === Assemble pipeline cache_base = op.join(info.cache_dir, experiment) workflow = Workflow(name="model_results", base_dir=cache_base) # Connect processing nodes processing_edges = [ (subject_source, run_source, [("subject", "subject")]), (subject_source, data_input, [("subject", "subject")]), (run_source, data_input, [("run", "run_tuple")]), (data_input, estimate_contrasts, [("mask_file", "mask_file"), ("beta_file", "beta_file"), ("error_file", "error_file"), ("ols_file", "ols_file"), ("model_file", "model_file")]), (subject_source, model_results, [("subject", "subject")]), (data_input, model_results, [("anat_file", "anat_file")]), (estimate_contrasts, model_results, [("contrast_file", "contrast_files"), ("variance_file", "variance_files"), ("name_file", "name_files")]), (run_source, save_info, [("run", "parameterization")]), (save_info, run_output, [("info_file", "qc.@info_json")]), (data_input, run_output, [("output_path", "container")]), (estimate_contrasts, run_output, [("contrast_file", "@contrast"), ("variance_file", "@variance"), ("tstat_file", "@tstat"), ("name_file", "@names")]), (subject_source, results_path, [("subject", "subject")]), (results_path, subject_output, [("output_path", "container")]), (model_results, subject_output, [("result_directories", "@results")]), ] workflow.connect(processing_edges) return workflow
imgZStat = os.path.join(statsDir, 'zstat' + contInd + '.nii.gz') # FINDING CLUSTERS IN THE ANALYSIS RESULTS # cluster node cluster = Node(fsl.Cluster(in_file=imgZStat, threshold=zThresh, out_index_file=True, out_threshold_file=True, out_localmax_txt_file=True), name='cluster') # data sink node datasink = Node(DataSink(base_directory=statsDir), name='datasink') # workflow connecting clustering to the datasink clusterWF = Workflow(name="clusterWF", base_dir=outDir) clusterWF.connect(cluster, 'index_file', datasink, 'index_file') clusterWF.connect(cluster, 'threshold_file', datasink, 'threshold_file') clusterWF.connect(cluster, 'localmax_txt_file', datasink, 'localmax_txt_file') clusterWF.run() # LOADING CLUSTER MAXIMA TABLE fMaxTable = os.path.join(statsDir, 'localmax_txt_file/zstat' + contInd + '_localmax.txt') maxData = pd.read_csv(fMaxTable, sep='\t') # reading the maxima file as a dataframe maxData.dropna(how='all', axis=1, inplace=True) # removing empty columns print(maxData) # CALCULATING CLUSTER SIZES fClusInd = os.path.join(statsDir,
# creating contrasts condition_names = ['GainRisk', 'GainAmb' ,'LossRisk', 'LossAmb'] GainRisk_cond = ['GainRisk','T', condition_names ,[1,0,0,0]] GainAmb_cond = ['GainAmb','T', condition_names ,[0,1,0,0]] LossRisk_cond = ['LossRisk','T', condition_names,[0,0,1,0]] LossAmb_cond = ['LossAmb','T',condition_names,[0,0,0,1]] Risk_vs_Amb = ["Risk vs. Amb",'T', condition_names ,[0.5, -0.5, 0.5, -0.5]] Gain_vs_Loss = ["Gain vs. Loss",'T', condition_names ,[0.5, 0.5, -0.5, -0.5]] #all_motor = ["All motor", 'F', [LossRisk_cond, LossAmb_cond, GainRisk_cond, GainAmb_cond]] contrasts=[GainRisk_cond, GainAmb_cond, LossRisk_cond, LossAmb_cond, Risk_vs_Amb, Gain_vs_Loss] #%% merge all images to one file merge = Node(interface = fsl.Merge(), name = 'merge') merge.inputs.dimension = 't' testWf = Workflow(name="testingMergeFsk", base_dir="/media/Data/work") testWf.connect([ (infosource, datasource, [('subject_id','subject_id')]), (datasource, merge, [('func','in_files')]), ]) testWf.run() #%% os.chdir('/media/Data/work') skip = MapNode(interface = fsl.ExtractROI(), name = "modelROIext", base_dir = '/media/Data/work', iterfield=['in_file']) skip.inputs.t_min = 4 skip.inputs.t_size = -1 skip.inputs.output_type = 'NIFTI_GZ' #skip.inputs.in_file = '/media/Data/FromHPC/output/fmriprep/sub-1063/ses-1/func/sub-1063_ses-1_task-3_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz' #h= skip.run()
# creating datasink to collect outputs datasink = Node(DataSink(base_directory=outDir), name='datasink') ## Use the following DataSink output substitutions substitutions = [('_subject_id_', '/sub-'), ('_run_id_', '/run-')] datasink.inputs.substitutions = substitutions ########### # # SETTING UP THE WORKFLOW NODES # ########### # creating the workflow firstLevel = Workflow(name="Level1", base_dir=outDir) # connecting nodes firstLevel.connect(sf, 'func', susan, 'in_file') firstLevel.connect(sf, 'mask', applymask, 'mask_file') firstLevel.connect(sf, 'events', taskevents, 'fileEvent') firstLevel.connect(susan, 'smoothed_file', applymask, 'in_file') firstLevel.connect(applymask, 'out_file', modelspec, 'functional_runs') firstLevel.connect(taskevents, 'subject_info', modelspec, 'subject_info') firstLevel.connect(modelspec, 'session_info', level1design, 'session_info') firstLevel.connect(taskevents, 'contrast_list', level1design, 'contrasts') firstLevel.connect(level1design, 'fsf_files', modelgen, 'fsf_file') firstLevel.connect(level1design, 'ev_files', modelgen, 'ev_files') firstLevel.connect(level1design, 'fsf_files', feat, 'fsf_file') firstLevel.connect(feat, 'feat_dir', datasink, 'feat_dir') firstLevel.connect(applymask, 'out_file', datasink, 'preproc_out_file')