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
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) realign = Node(nipy.SpaceTimeRealigner(), name="spacetime_realign") realign.inputs.slice_times = slice_times realign.inputs.tr = TR realign.inputs.slice_info = 2 realign.inputs.in_file = files realign.plugin_args = {'sbatch_args': '-c%d' % 4} # 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') """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' art.inputs.save_plot = False #dbg temporary while matplotlib is not available """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([(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(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.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, '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.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] + 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) 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] + 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', ''), ] 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, 'qa.motion') wf.connect(art, 'norm_files', datasink, 'qa.art.@norm') wf.connect(art, 'intensity_files', datasink, 'qa.art.@intensity') wf.connect(art, 'outlier_files', datasink, 'qa.art.@outlier_files') wf.connect(registration, 'outputspec.segmentation_files', datasink, 'mask_files') wf.connect(registration, 'outputspec.anat2target', datasink, 'qa.ants') wf.connect(mask, 'mask_file', datasink, 'mask_files.@brainmask') wf.connect(mask_target, 'out_file', datasink, 'mask_files.target') wf.connect(filter1, 'out_f', datasink, 'qa.compmaps.@mc_F') wf.connect(filter1, 'out_pf', datasink, 'qa.compmaps.@mc_pF') wf.connect(filter2, 'out_f', datasink, 'qa.compmaps') wf.connect(filter2, 'out_pf', datasink, 'qa.compmaps.@p') wf.connect(registration, 'outputspec.min_cost_file', datasink, 'qa.mincost') wf.connect(tsnr, 'tsnr_file', datasink, 'qa.tsnr.@map') wf.connect([(get_roi_tsnr, datasink, [('avgwf_txt_file', 'qa.tsnr'), ('summary_file', 'qa.tsnr.@summary')])]) wf.connect(bandpass, 'out_files', datasink, 'timeseries.@bandpassed') wf.connect(smooth, 'out_file', datasink, 'timeseries.@smoothed') wf.connect(createfilter1, 'out_files', datasink, 'regress.@regressors') wf.connect(createfilter2, 'out_files', datasink, 'regress.@compcorr') wf.connect(maskts, 'out_file', datasink, 'timeseries.target') wf.connect(sampleaparc, 'summary_file', datasink, 'parcellations.aparc') wf.connect(sampleaparc, 'avgwf_txt_file', datasink, 'parcellations.aparc.@avgwf') wf.connect(ts2txt, 'out_file', datasink, '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, 'parcellations.grayo.@surface') return wf
def create_timeseries_model_workflow(name="model", exp_info=None): # Default experiment parameters for generating graph inamge, testing, etc. if exp_info is None: exp_info = default_experiment_parameters() # Define constant inputs inputs = ["design_file", "realign_file", "artifact_file", "timeseries"] # Possibly add the regressor file to the inputs if exp_info["regressor_file"] is not None: inputs.append("regressor_file") # Define the workflow inputs inputnode = Node(IdentityInterface(inputs), "inputs") # Set up the experimental design modelsetup = MapNode(Function(["exp_info", "design_file", "realign_file", "artifact_file", "regressor_file", "run"], ["design_matrix_file", "contrast_file", "design_matrix_pkl", "report"], setup_model, imports), ["realign_file", "artifact_file", "run"], "modelsetup") modelsetup.inputs.exp_info = exp_info if exp_info["regressor_file"] is None: modelsetup.inputs.regressor_file = None # Use film_gls to estimate the timeseries model modelestimate = MapNode(fsl.FILMGLS(smooth_autocorr=True, mask_size=5, threshold=1000), ["design_file", "in_file"], "modelestimate") # Run the contrast estimation routine contrastestimate = MapNode(fsl.ContrastMgr(), ["tcon_file", "dof_file", "corrections", "param_estimates", "sigmasquareds"], "contrastestimate") calcrsquared = MapNode(Function(["design_matrix_pkl", "timeseries", "pe_files"], ["r2_files", "ss_files"], compute_rsquareds, imports), ["design_matrix_pkl", "timeseries", "pe_files"], "calcrsquared") calcrsquared.plugin_args = dict(qsub_args="-l h_vmem=8G") # Save the experiment info for this run dumpjson = MapNode(Function(["exp_info", "timeseries"], ["json_file"], dump_exp_info, imports), "timeseries", "dumpjson") dumpjson.inputs.exp_info = exp_info # Report on the results of the model modelreport = MapNode(Function(["timeseries", "sigmasquareds_file", "zstat_files", "r2_files"], ["report"], report_model, imports), ["timeseries", "sigmasquareds_file", "zstat_files", "r2_files"], "modelreport") # Define the workflow outputs outputnode = Node(IdentityInterface(["results", "copes", "varcopes", "zstats", "r2_files", "ss_files", "report", "design_mat", "contrast_mat", "design_pkl", "design_report", "json_file"]), "outputs") # Define the workflow and connect the nodes model = Workflow(name=name) model.connect([ (inputnode, modelsetup, [("design_file", "design_file"), ("realign_file", "realign_file"), ("artifact_file", "artifact_file"), (("timeseries", run_indices), "run")]), (inputnode, modelestimate, [("timeseries", "in_file")]), (inputnode, dumpjson, [("timeseries", "timeseries")]), (modelsetup, modelestimate, [("design_matrix_file", "design_file")]), (modelestimate, contrastestimate, [("dof_file", "dof_file"), ("corrections", "corrections"), ("param_estimates", "param_estimates"), ("sigmasquareds", "sigmasquareds")]), (modelsetup, contrastestimate, [("contrast_file", "tcon_file")]), (modelsetup, calcrsquared, [("design_matrix_pkl", "design_matrix_pkl")]), (inputnode, calcrsquared, [("timeseries", "timeseries")]), (modelestimate, calcrsquared, [("param_estimates", "pe_files")]), (inputnode, modelreport, [("timeseries", "timeseries")]), (modelestimate, modelreport, [("sigmasquareds", "sigmasquareds_file")]), (contrastestimate, modelreport, [("zstats", "zstat_files")]), (calcrsquared, modelreport, [("r2_files", "r2_files")]), (modelsetup, outputnode, [("design_matrix_file", "design_mat"), ("contrast_file", "contrast_mat"), ("design_matrix_pkl", "design_pkl"), ("report", "design_report")]), (dumpjson, outputnode, [("json_file", "json_file")]), (modelestimate, outputnode, [("results_dir", "results")]), (contrastestimate, outputnode, [("copes", "copes"), ("varcopes", "varcopes"), ("zstats", "zstats")]), (calcrsquared, outputnode, [("r2_files", "r2_files"), ("ss_files", "ss_files")]), (modelreport, outputnode, [("report", "report")]), ]) if exp_info["regressor_file"] is not None: model.connect([ (inputnode, modelsetup, [("regressor_file", "regressor_file")]) ]) return model, inputnode, outputnode
def create_timeseries_model_workflow(name="model", exp_info=None): # Default experiment parameters for generating graph image, testing, etc. if exp_info is None: exp_info = lyman.default_experiment_parameters() # Define constant inputs inputs = ["realign_file", "nuisance_file", "artifact_file", "timeseries"] # Possibly add the design and regressor files to the inputs if exp_info["design_name"] is not None: inputs.append("design_file") if exp_info["regressor_file"] is not None: inputs.append("regressor_file") # Define the workflow inputs inputnode = Node(IdentityInterface(inputs), "inputs") # Set up the experimental design modelsetup = MapNode( ModelSetup(exp_info=exp_info), ["timeseries", "realign_file", "nuisance_file", "artifact_file"], "modelsetup") # For some nodes, make it possible to request extra memory mem_request = {"qsub_args": "-l h_vmem=%dG" % exp_info["memory_request"]} # Use film_gls to estimate the timeseries model modelestimate = MapNode( fsl.FILMGLS(smooth_autocorr=True, mask_size=5, threshold=100), ["design_file", "in_file", "tcon_file"], "modelestimate") modelestimate.plugin_args = mem_request # Compute summary statistics about the model fit modelsummary = MapNode(ModelSummary(), ["design_matrix_pkl", "timeseries", "pe_files"], "modelsummary") modelsummary.plugin_args = mem_request # Save the experiment info for this run # Save the experiment info for this run saveparams = MapNode(SaveParameters(exp_info=exp_info), "in_file", "saveparams") # Report on the results of the model # Note: see below for a conditional iterfield modelreport = MapNode( ModelReport(), ["timeseries", "sigmasquareds_file", "tsnr_file", "r2_files"], "modelreport") # Define the workflow outputs outputnode = Node( IdentityInterface([ "results", "copes", "varcopes", "zstats", "r2_files", "ss_files", "tsnr_file", "report", "design_mat", "contrast_mat", "design_pkl", "design_report", "json_file" ]), "outputs") # Define the workflow and connect the nodes model = Workflow(name=name) model.connect([ (inputnode, modelsetup, [("realign_file", "realign_file"), ("nuisance_file", "nuisance_file"), ("artifact_file", "artifact_file"), ("timeseries", "timeseries")]), (inputnode, modelestimate, [("timeseries", "in_file")]), (inputnode, saveparams, [("timeseries", "in_file")]), (modelsetup, modelestimate, [("design_matrix_file", "design_file"), ("contrast_file", "tcon_file")]), (modelsetup, modelsummary, [("design_matrix_pkl", "design_matrix_pkl") ]), (inputnode, modelsummary, [("timeseries", "timeseries")]), (modelestimate, modelsummary, [("param_estimates", "pe_files")]), (inputnode, modelreport, [("timeseries", "timeseries")]), (modelestimate, modelreport, [("sigmasquareds", "sigmasquareds_file") ]), (modelsummary, modelreport, [("r2_files", "r2_files"), ("tsnr_file", "tsnr_file")]), (modelsetup, outputnode, [("design_matrix_file", "design_mat"), ("contrast_file", "contrast_mat"), ("design_matrix_pkl", "design_pkl"), ("report", "design_report")]), (saveparams, outputnode, [("json_file", "json_file")]), (modelestimate, outputnode, [("results_dir", "results"), ("copes", "copes"), ("varcopes", "varcopes"), ("zstats", "zstats")]), (modelsummary, outputnode, [("r2_files", "r2_files"), ("ss_files", "ss_files"), ("tsnr_file", "tsnr_file")]), (modelreport, outputnode, [("out_files", "report")]), ]) if exp_info["design_name"] is not None: model.connect(inputnode, "design_file", modelsetup, "design_file") if exp_info["regressor_file"] is not None: model.connect(inputnode, "regressor_file", modelsetup, "regressor_file") if exp_info["contrasts"]: model.connect(modelestimate, "zstats", modelreport, "zstat_files") modelreport.iterfield.append("zstat_files") return model, inputnode, outputnode
def create_timeseries_model_workflow(name="model", exp_info=None): # Default experiment parameters for generating graph image, testing, etc. if exp_info is None: exp_info = lyman.default_experiment_parameters() # Define constant inputs inputs = ["realign_file", "artifact_file", "timeseries"] # Possibly add the design and regressor files to the inputs if exp_info["design_name"] is not None: inputs.append("design_file") if exp_info["regressor_file"] is not None: inputs.append("regressor_file") # Define the workflow inputs inputnode = Node(IdentityInterface(inputs), "inputs") # Set up the experimental design modelsetup = MapNode(ModelSetup(exp_info=exp_info), ["timeseries", "realign_file", "artifact_file"], "modelsetup") # For some nodes, make it possible to request extra memory mem_request = {"qsub_args": "-l h_vmem=%dG" % exp_info["memory_request"]} # Use film_gls to estimate the timeseries model modelestimate = MapNode(fsl.FILMGLS(smooth_autocorr=True, mask_size=5, threshold=100), ["design_file", "in_file"], "modelestimate") modelestimate.plugin_args = mem_request # Run the contrast estimation routine contrastestimate = MapNode(fsl.ContrastMgr(), ["tcon_file", "dof_file", "corrections", "param_estimates", "sigmasquareds"], "contrastestimate") contrastestimate.plugin_args = mem_request # Compute summary statistics about the model fit modelsummary = MapNode(ModelSummary(), ["design_matrix_pkl", "timeseries", "pe_files"], "modelsummary") modelsummary.plugin_args = mem_request # Save the experiment info for this run # Save the experiment info for this run saveparams = MapNode(SaveParameters(exp_info=exp_info), "in_file", "saveparams") # Report on the results of the model # Note: see below for a conditional iterfield modelreport = MapNode(ModelReport(), ["timeseries", "sigmasquareds_file", "tsnr_file", "r2_files"], "modelreport") # Define the workflow outputs outputnode = Node(IdentityInterface(["results", "copes", "varcopes", "zstats", "r2_files", "ss_files", "tsnr_file", "report", "design_mat", "contrast_mat", "design_pkl", "design_report", "json_file"]), "outputs") # Define the workflow and connect the nodes model = Workflow(name=name) model.connect([ (inputnode, modelsetup, [("realign_file", "realign_file"), ("artifact_file", "artifact_file"), ("timeseries", "timeseries")]), (inputnode, modelestimate, [("timeseries", "in_file")]), (inputnode, saveparams, [("timeseries", "in_file")]), (modelsetup, modelestimate, [("design_matrix_file", "design_file")]), (modelestimate, contrastestimate, [("dof_file", "dof_file"), ("corrections", "corrections"), ("param_estimates", "param_estimates"), ("sigmasquareds", "sigmasquareds")]), (modelsetup, contrastestimate, [("contrast_file", "tcon_file")]), (modelsetup, modelsummary, [("design_matrix_pkl", "design_matrix_pkl")]), (inputnode, modelsummary, [("timeseries", "timeseries")]), (modelestimate, modelsummary, [("param_estimates", "pe_files")]), (inputnode, modelreport, [("timeseries", "timeseries")]), (modelestimate, modelreport, [("sigmasquareds", "sigmasquareds_file")]), (modelsummary, modelreport, [("r2_files", "r2_files"), ("tsnr_file", "tsnr_file")]), (modelsetup, outputnode, [("design_matrix_file", "design_mat"), ("contrast_file", "contrast_mat"), ("design_matrix_pkl", "design_pkl"), ("report", "design_report")]), (saveparams, outputnode, [("json_file", "json_file")]), (modelestimate, outputnode, [("results_dir", "results")]), (contrastestimate, outputnode, [("copes", "copes"), ("varcopes", "varcopes"), ("zstats", "zstats")]), (modelsummary, outputnode, [("r2_files", "r2_files"), ("ss_files", "ss_files"), ("tsnr_file", "tsnr_file")]), (modelreport, outputnode, [("out_files", "report")]), ]) if exp_info["design_name"] is not None: model.connect(inputnode, "design_file", modelsetup, "design_file") if exp_info["regressor_file"] is not None: model.connect(inputnode, "regressor_file", modelsetup, "regressor_file") if exp_info["contrasts"]: model.connect(contrastestimate, "zstats", modelreport, "zstat_files") modelreport.iterfield.append("zstat_files") return model, inputnode, outputnode