def test_coregister_list_outputs(): filelist, outdir, cwd = create_files_in_directory() coreg = spm.Coregister(source=filelist[0]) yield assert_true, coreg._list_outputs( )['coregistered_source'][0].startswith('r') coreg = spm.Coregister(source=filelist[0], apply_to_files=filelist[1]) yield assert_true, coreg._list_outputs( )['coregistered_files'][0].startswith('r') clean_directory(outdir, cwd)
def epi_normalize(name='epi_normalize'): inputnode = pe.Node( utility.IdentityInterface( fields=['fmri_mean','t1','t1_to_mni','t1_mask']), name='inputspec') outputnode = pe.Node( utility.IdentityInterface( fields=['epi2t1_warp','coregistered_fmri_mean','epi2mni_warp', 't1_to_epi_warp','epi_mask']), name='outputspec') n_spm_coregister = pe.Node( spm.Coregister(jobtype='estimate'), name='spm_coregister') # n_epi2mni = pe.Node( # spm.preprocess.ApplyDeformations( # reference_volume='/coconut/applis/src/spm8_x64/toolbox/Seg/TPM.nii'), # name='epi2mni') n_flirt_epi2t1 = pe.Node( fsl.FLIRT(out_matrix_file='flirt_epi2t1.mat', out_file='%s_flirt', cost='normmi', # as in fcon1000 preproc, why?? searchr_x=[-10,10],searchr_y=[-10,10],searchr_z=[-10,10], dof=6), name='flirt_epi2t1') n_t1_to_epi = pe.Node( fsl.ConvertXFM(invert_xfm=True), name='t1_to_epi') n_mask_to_epi = pe.Node( fsl.FLIRT(interp='nearestneighbour', out_file='%s_epi', apply_xfm=True,), name='mask_to_epi') w=pe.Workflow(name=name) w.connect([ # (inputnode,n_spm_coregister,[('fmri_mean','source'), # ('t1','target')]), (inputnode,n_flirt_epi2t1,[('t1','reference')]), # (n_spm_coregister,n_epi2mni,[('coregistered_source','in_files')]), # (inputnode,n_epi2mni,[('t1_to_mni','deformation_field')]), (inputnode,n_flirt_epi2t1,[('fmri_mean','in_file')]), (n_flirt_epi2t1,outputnode,[('out_matrix_file','epi2t1_warp')]), (n_flirt_epi2t1,n_t1_to_epi,[('out_matrix_file','in_file')]), (n_t1_to_epi,outputnode,[('out_file','t1_to_epi_warp')]), (inputnode,n_mask_to_epi,[('fmri_mean','reference'), ('t1_mask','in_file')]), (n_t1_to_epi, n_mask_to_epi,[('out_file','in_matrix_file')]), (n_mask_to_epi, outputnode, [('out_file','epi_mask')]) # (n_spm_coregister,outputnode,[('coregistered_source', # 'coregistered_fmri_mean')]), ]) return w
def evaluate_coregister_wf(name='evaluate_coregister'): w = pe.Workflow(name=name) n_epi_grey_to_t1 = pe.Node(spm.Coregister(jobtype='write'), name='warp') w.add_nodes([n_epi_grey_to_t1]) return w
def __init__(self, target='path', source='path', **options): import nipype.interfaces.spm as spm coreg = spm.Coregister() coreg.inputs.target = target coreg.inputs.source = source for ef in options: setattr(coreg.inputs, ef, options[ef]) self.res = coreg.run()
def test_coregister(): yield assert_equal, spm.Coregister._jobtype, 'spatial' yield assert_equal, spm.Coregister._jobname, 'coreg' yield assert_equal, spm.Coregister().inputs.jobtype, 'estwrite' input_map = dict(target=dict(field='ref', mandatory=True, copyfile=False), source=dict(field='source', copyfile=True), apply_to_files=dict(field='other', copyfile=True), cost_function=dict(field='eoptions.cost_fun'), fwhm=dict(field='eoptions.fwhm'), separation=dict(field='eoptions.sep'), tolerance=dict(field='eoptions.tol'), write_interp=dict(field='roptions.interp'), write_wrap=dict(field='roptions.wrap'), write_mask=dict(field='roptions.mask')) coreg = spm.Coregister() for key, metadata in input_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(coreg.inputs.traits()[key], metakey), value
def create_visualise_thresholded_overlay(pipeline_name, name): #, contrasts): inputnode = pe.Node(interface=util.IdentityInterface(fields=[ 'background', "overlays", "ggmm_overlays", "contrasts", "task_name" ]), name="inputnode") reslice_overlay = pe.Node(interface=spm.Coregister(), name="reslice_overlay") reslice_overlay.inputs.jobtype = "write" reslice_overlay.inputs.write_interp = 0 reslice_ggmm_overlay = reslice_overlay.clone(name="reslice_ggmm_overlay") plot = pe.MapNode(interface=neuroutils.Overlay(), name="plot", iterfield=['overlay', 'title']) make_titles_fdr = pe.Node(interface=util.Function( input_names=['task', 'contrasts', 'prefix'], output_names=['titles'], function=_make_titles), name="make_titles_fdr") make_titles_fdr.inputs.prefix = "Topo FDR " plot_ggmm = plot.clone("plot_ggmm") make_titles_ggmm = pe.Node(interface=util.Function( input_names=['task', 'contrasts', 'prefix'], output_names=['titles'], function=_make_titles), name="make_titles_ggmm") make_titles_ggmm.inputs.prefix = "Topo GGMM " #plot = pe.MapNode(interface=neuroutils.Overlay(), name="plot", iterfield=['overlay']) visualise_overlay = pe.Workflow(name="visualise" + name) visualise_overlay.connect([ (inputnode, reslice_overlay, [("background", "target"), ("overlays", "source")]), (inputnode, reslice_ggmm_overlay, [("background", "target"), ("ggmm_overlays", "source")]), (reslice_overlay, plot, [("coregistered_source", "overlay")]), (inputnode, plot, [("background", "background")]), (inputnode, make_titles_fdr, [('task_name', 'task'), ('contrasts', 'contrasts')]), (make_titles_fdr, plot, [('titles', 'title')]), (reslice_ggmm_overlay, plot_ggmm, [("coregistered_source", "overlay") ]), (inputnode, plot_ggmm, [("background", "background")]), (inputnode, make_titles_ggmm, [('task_name', 'task'), ('contrasts', 'contrasts')]), (make_titles_ggmm, plot_ggmm, [('titles', 'title')]), ]) return visualise_overlay
def __init__(self, experiment_dir, output_dir, working_dir, func_source, struct_source, datasink): self.experiment_dir = experiment_dir self.output_dir = output_dir self.working_dir = working_dir # specify input and output nodes self.func_source = func_source self.struct_source = struct_source self.datasink = datasink # specify workflow instance self.workflow = pe.Workflow(name='workflow') # specify nodes self.realign = pe.Node(interface=spm.Realign(), name='realign') self.coregister = pe.Node(interface=spm.Coregister(), name="coregister") self.coregister.inputs.jobtype = 'estimate' self.segment = pe.Node(interface=spm.Segment(), name="segment") self.normalize_func = pe.Node(interface=spm.Normalize(), name="normalize_func") self.normalize_func.inputs.jobtype = "write" self.normalize_struc = pe.Node(interface=spm.Normalize(), name="normalize_struc") self.normalize_struc.inputs.jobtype = "write" self.smooth = pe.Node(interface=spm.Smooth(), name="smooth") # connect the nodes to complete the workflow self.workflow.connect([ (self.func_source, self.realign, [('outfiles', 'in_files')]), (self.struct_source, self.coregister, [('outfiles', 'source')]), (self.realign, self.coregister, [('mean_image', 'target')]), (self.coregister, self.segment, [('coregistered_source', 'data')]), (self.segment, self.normalize_func, [('transformation_mat', 'parameter_file')]), (self.realign, self.normalize_func, [('realigned_files', 'apply_to_files')]), (self.normalize_func, self.smooth, [('normalized_files', 'in_files')]), #(self.realign, self.datasink, [('realigned_files', 'realign')]), #(self.realign, self.datasink, [('mean_image', 'mean')]), (self.normalize_func, self.datasink, [('normalized_files', 'norm')] ), (self.smooth, self.datasink, [('smoothed_files', 'smooth')]) ])
def process_subject(func_fname, anat_fname): # Drop dummy volumes img = nib.load(func_fname) dropped_img = nib.Nifti1Image(img.get_data()[..., n_dummies:], img.affine, img.header) fixed_fname = prefix_path('f', degz(func_fname)) nib.save(dropped_img, fixed_fname) # Ungz anatomical if anat_fname.endswith('.gz'): anat_img = nib.load(anat_fname) anat_fname = degz(anat_fname) nib.save(anat_img, anat_fname) # Slice time correction num_slices = img.shape[2] time_for_one_slice = TR / num_slices TA = TR - time_for_one_slice st = spm.SliceTiming() st.inputs.in_files = fixed_fname st.inputs.num_slices = num_slices st.inputs.time_repetition = TR st.inputs.time_acquisition = TA st.inputs.slice_order = order_func(num_slices) st.inputs.ref_slice = ref_slice st.run() fixed_stimed = prefix_path('a', fixed_fname) # Realign realign = spm.Realign() realign.inputs.in_files = fixed_stimed # Do not write resliced files, do write mean image realign.inputs.write_which = write_which realign.run() # Coregistration coreg = spm.Coregister() # Coregister structural to mean image from realignment coreg.inputs.target = prefix_path('mean', fixed_stimed) coreg.inputs.source = anat_fname coreg.run() # Normalization / resampling with normalization + realign params seg_norm = spm.Normalize12() seg_norm.inputs.image_to_align = anat_fname seg_norm.inputs.apply_to_files = fixed_stimed seg_norm.inputs.write_bounding_box = bounding_box seg_norm.inputs.write_voxel_sizes = voxel_sizes seg_norm.run()
def simple_coregister(target, moving, other=None): """ uses the basic spm Coregister functionality to move the moving image to target, and applies to others is any""" startdir = os.getcwd() pth, _ = os.path.split(moving) os.chdir(pth) corg = spm.Coregister(matlab_cmd='matlab-spm8') corg.inputs.target = target corg.inputs.source = moving corg.inputs.ignore_exception = True if other is not None: corg.inputs.apply_to_files = other corg_out = corg.run() os.chdir(startdir) return corg_out
def coregistration_4D(source_file, ref, out_file=None, spm_path=None): ''' Coregistration with spm + fsl for 4D files. Why? Nor SPM, nor fsl are able to do this by default :param source_file: path to input 4D file :param ref: reference file to co-register the source-file to :param out_file: output file :param spm_path: path to spm :return: path to coregistered file ''' if spm_path is not None: mlab.MatlabCommand.set_default_paths(spm_path) if spm.SPMCommand().version is None: raise Exception('SPM path not set correctly:', spm_path, spm.SPMCommand().version) main_dir, source_file_name = os.path.split(source_file) if out_file is None: out_file = os.path.join(main_dir, 'r' + source_file_name) split_folder = os.path.join(main_dir, '4D_split') if not os.path.exists(os.path.join(main_dir, '4D_split')): os.mkdir(split_folder) split = Split(in_file=source_file, dimension='t') split.inputs.in_file = source_file split.inputs.dimension = 't' split.inputs.out_base_name = os.path.join(split_folder, '4D_vol_') split.inputs.output_type = 'NIFTI' split = split.run() split_files = split.outputs.out_files index_file = split_files.pop(0) coreg = spm.Coregister() coreg.inputs.target = ref coreg.inputs.source = index_file coreg.inputs.apply_to_files = split_files coreg = coreg.run() merger = Merge() merger.inputs.in_files = coreg.outputs.coregistered_files merger.inputs.dimension = 't' merger.inputs.output_type = 'NIFTI_GZ' merger.inputs.merged_file = out_file merger = merger.run() shutil.rmtree(split_folder) return merger.outputs.merged_file
def coregister_to_T1(slice_time_dir, T1_dir): # Function coregisters all EPIs in sequence to ac-pc aligned T1 # Get the name of the ac-pc aligned t1 os.chdir(T1_dir) for files in os.listdir(T1_dir): T1name = files # Go to the dir with the slice time corrected EPI's and iter over # filenames to coregister each to the ac-pc aligned T1. os.chdir(slice_time_dir) for files in os.listdir(slice_time_dir): if files.startswith("ar"): fname = files coreg = spm.Coregister() coreg.inputs.target = slice_time_dir + '/' + fname coreg.inputs.source = T1_dir + '/' + T1name print "<:::Coregistering EPI %s to AC-PC aligned T1:::>" % (fname) coreg.run()
def spm_coregister(src_img=traits.Undefined, tgt_img=traits.Undefined, cost_function='mi'): """Use spm_coreg for estimating cross-modality rigid body alignment. The write_interp option is set to 0 by default. More info: http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=39 Parameters ---------- src_img: str Path to the coregistration source image tgt_img: str Path to the coregistration target image cost_function: ('mi' or 'nmi' or 'ecc' or 'ncc') cost function, one of: 'mi' - Mutual Information, 'nmi' - Normalised Mutual Information, 'ecc' - Entropy Correlation Coefficient, 'ncc' - Normalised Cross Correlation For more info: http://www.mit.edu/~satra/nipype-nightly/interfaces/generated/nipype.interfaces.spm.preprocess.html#coregister Returns ------- coreg: nipype.interfaces.smp.Coregister spm.Coregister interface object """ coreg = spm.Coregister() coreg.inputs.source = src_img coreg.inputs.target = tgt_img coreg.inputs.cost_function = cost_function coreg.inputs.jobtype = 'estwrite' #coreg.run() return coreg
def create_visualise_masked_overlay(pipeline_name, name): #, contrasts): inputnode = pe.Node(interface=util.IdentityInterface( fields=['background', "mask", "overlays", "contrasts", "task_name"]), name="inputnode") reslice_mask = pe.Node(interface=spm.Coregister(), name="reslice_mask") reslice_mask.inputs.jobtype = "write" reslice_mask.inputs.write_interp = 0 reslice_overlay = reslice_mask.clone(name="reslice_overlay") plot = pe.MapNode(interface=neuroutils.Overlay(), name="plot", iterfield=['overlay', 'title']) plot.inputs.bbox = True #plot.inputs.title = [(pipeline_name + ": " + contrast[0]) for contrast in contrasts] plot.inputs.nrows = 12 make_titles = pe.Node(interface=util.Function( input_names=['task', 'contrasts'], output_names=['titles'], function=_make_titles), name="make_titles") visualise_overlay = pe.Workflow(name="visualise" + name) visualise_overlay.connect([ (inputnode, reslice_overlay, [("background", "target"), ("overlays", "source")]), (inputnode, reslice_mask, [("background", "target"), ("mask", "source")]), (inputnode, make_titles, [('task_name', 'task'), ('contrasts', 'contrasts')]), (make_titles, plot, [('titles', 'title')]), (reslice_overlay, plot, [("coregistered_source", "overlay")]), (inputnode, plot, [("background", "background")]), (reslice_mask, plot, [("coregistered_source", "mask")]), ]) return visualise_overlay
def analysis_steps(self): self.analysis = type('', (), {})() # Get files subj_list = [ subj.split('_')[:-1] for subj in next(os.walk(self.proj_dir))[1] ] # TODO limit the subj_list to those without sw processed files. # for parallelization by subject, use idnetityInterface self.analysis.infosource = Node( IdentityInterface(fields=['subj_id', 'task']), name="infosource") self.analysis.infosource.iterables = [('subject_id', subj_list), ('task', self.task_names)] templates = { 'anat': '{subj_id}/t1/{subj_id}_t1*.nii', 'func': '{subj_id}/{task}*/{subj_id}_{task}*.nii' } self.analysis.sf = Node(SelectFiles(templates), name='selectfiles') self.analysis.sf.inputs.base_directory = self.proj_dir # Realign self.analysis.realign = Node(spm.Realign(register_to_mean=True, fwhm=self.opts.fwhm), name='realign') # Coregister self.analysis.coreg = Node(spm.Coregister(), name='coregistration') # Normalize self.analysis.norm12 = Node(spm.Normalize12( bias_regularization=1e-05, affine_regularization_type='mni'), name='normalize') #Smooth self.analysis.smooth = Node(spm.Smooth(), name='smooth') #smooth.inputs.in_files = 'functional.nii' self.analysis.smooth.inputs.fwhm = self.opts.smooth_fwhm
def test_coregister(): yield assert_equal, spm.Coregister._jobtype, 'spatial' yield assert_equal, spm.Coregister._jobname, 'coreg' yield assert_equal, spm.Coregister().inputs.jobtype, 'estwrite'
def test_coregister_list_outputs(create_files_in_directory): filelist, outdir, cwd = create_files_in_directory coreg = spm.Coregister(source=filelist[0]) assert coreg._list_outputs()['coregistered_source'][0].startswith('r') coreg = spm.Coregister(source=filelist[0], apply_to_files=filelist[1]) assert coreg._list_outputs()['coregistered_files'][0].startswith('r')
def test_coregister(): assert spm.Coregister._jobtype == 'spatial' assert spm.Coregister._jobname == 'coreg' assert spm.Coregister().inputs.jobtype == 'estwrite'
def build_core_nodes(self): """Build and connect an output node to the pipeline.""" import nipype.interfaces.spm as spm import nipype.interfaces.spm.utils as spmutils from nipype.interfaces.petpvc import PETPVC import nipype.interfaces.utility as nutil import nipype.pipeline.engine as npe from clinica.utils.filemanip import unzip_nii from clinica.utils.spm import spm_standalone_is_available, use_spm_standalone import clinica.pipelines.pet_volume.pet_volume_utils as utils if spm_standalone_is_available(): use_spm_standalone() # Initialize pipeline # =================== init_node = npe.Node(interface=nutil.Function( input_names=['pet_nii'], output_names=['pet_nii'], function=utils.init_input_node), name='init_pipeline') # Unzipping # ========= unzip_pet_image = npe.Node(nutil.Function(input_names=['in_file'], output_names=['out_file'], function=unzip_nii), name='unzip_pet_image') unzip_t1_image_native = npe.Node(nutil.Function( input_names=['in_file'], output_names=['out_file'], function=unzip_nii), name='unzip_t1_image_native') unzip_flow_fields = npe.Node(nutil.Function(input_names=['in_file'], output_names=['out_file'], function=unzip_nii), name='unzip_flow_fields') unzip_dartel_template = npe.Node(nutil.Function( input_names=['in_file'], output_names=['out_file'], function=unzip_nii), name='unzip_dartel_template') unzip_reference_mask = npe.Node(nutil.Function( input_names=['in_file'], output_names=['out_file'], function=unzip_nii), name='unzip_reference_mask') unzip_mask_tissues = npe.MapNode(nutil.Function( input_names=['in_file'], output_names=['out_file'], function=unzip_nii), name='unzip_mask_tissues', iterfield=['in_file']) # Coregister PET into T1 native space # =================================== coreg_pet_t1 = npe.Node(spm.Coregister(), name='coreg_pet_t1') # Spatially normalize PET into MNI # ================================ dartel_mni_reg = npe.Node(spm.DARTELNorm2MNI(), name='dartel_mni_reg') dartel_mni_reg.inputs.modulate = False dartel_mni_reg.inputs.fwhm = 0 # Reslice reference region mask into PET # ====================================== reslice = npe.Node(spmutils.Reslice(), name='reslice') # Normalize PET values according to reference region # ================================================== norm_to_ref = npe.Node(nutil.Function( input_names=['pet_image', 'region_mask'], output_names=['suvr_pet_path'], function=utils.normalize_to_reference), name='norm_to_ref') # Create binary mask from segmented tissues # ========================================= binary_mask = npe.Node(nutil.Function( input_names=['tissues', 'threshold'], output_names=['out_mask'], function=utils.create_binary_mask), name='binary_mask') binary_mask.inputs.threshold = self.parameters['mask_threshold'] # Mask PET image # ============== apply_mask = npe.Node(nutil.Function( input_names=['image', 'binary_mask'], output_names=['masked_image_path'], function=utils.apply_binary_mask), name='apply_mask') # Smoothing # ========= if self.parameters['smooth'] is not None and len( self.parameters['smooth']) > 0: smoothing_node = npe.MapNode(spm.Smooth(), name='smoothing_node', iterfield=['fwhm', 'out_prefix']) smoothing_node.inputs.fwhm = [[x, x, x] for x in self.parameters['smooth']] smoothing_node.inputs.out_prefix = [ 'fwhm-' + str(x) + 'mm_' for x in self.parameters['smooth'] ] self.connect([(apply_mask, smoothing_node, [('masked_image_path', 'in_files')]), (smoothing_node, self.output_node, [('smoothed_files', 'pet_suvr_masked_smoothed')])]) else: self.output_node.inputs.pet_suvr_masked_smoothed = [[]] # Atlas Statistics # ================ atlas_stats_node = npe.MapNode(nutil.Function( input_names=['in_image', 'in_atlas_list'], output_names=['atlas_statistics'], function=utils.atlas_statistics), name='atlas_stats_node', iterfield=['in_image']) atlas_stats_node.inputs.in_atlas_list = self.parameters['atlases'] # Connection # ========== self.connect([ (self.input_node, init_node, [('pet_image', 'pet_nii')]), (init_node, unzip_pet_image, [('pet_nii', 'in_file')]), (self.input_node, unzip_t1_image_native, [('t1_image_native', 'in_file')]), (self.input_node, unzip_flow_fields, [('flow_fields', 'in_file')]), (self.input_node, unzip_dartel_template, [('dartel_template', 'in_file')]), (self.input_node, unzip_reference_mask, [('reference_mask', 'in_file')]), (self.input_node, unzip_mask_tissues, [('mask_tissues', 'in_file') ]), (unzip_pet_image, coreg_pet_t1, [('out_file', 'source')]), (unzip_t1_image_native, coreg_pet_t1, [('out_file', 'target')]), (unzip_flow_fields, dartel_mni_reg, [('out_file', 'flowfield_files')]), (unzip_dartel_template, dartel_mni_reg, [('out_file', 'template_file')]), (unzip_reference_mask, reslice, [('out_file', 'in_file')]), (unzip_mask_tissues, binary_mask, [('out_file', 'tissues')]), (coreg_pet_t1, dartel_mni_reg, [('coregistered_source', 'apply_to_files')]), (dartel_mni_reg, reslice, [('normalized_files', 'space_defining') ]), (dartel_mni_reg, norm_to_ref, [('normalized_files', 'pet_image')]), (reslice, norm_to_ref, [('out_file', 'region_mask')]), (norm_to_ref, apply_mask, [('suvr_pet_path', 'image')]), (binary_mask, apply_mask, [('out_mask', 'binary_mask')]), (norm_to_ref, atlas_stats_node, [('suvr_pet_path', 'in_image')]), (coreg_pet_t1, self.output_node, [('coregistered_source', 'pet_t1_native')]), (dartel_mni_reg, self.output_node, [('normalized_files', 'pet_mni') ]), (norm_to_ref, self.output_node, [('suvr_pet_path', 'pet_suvr')]), (binary_mask, self.output_node, [('out_mask', 'binary_mask')]), (apply_mask, self.output_node, [('masked_image_path', 'pet_suvr_masked')]), (atlas_stats_node, self.output_node, [('atlas_statistics', 'atlas_statistics')]) ]) # PVC # ========== if self.parameters['apply_pvc']: # Unzipping # ========= unzip_pvc_mask_tissues = npe.MapNode(nutil.Function( input_names=['in_file'], output_names=['out_file'], function=unzip_nii), name='unzip_pvc_mask_tissues', iterfield=['in_file']) # Creating Mask to use in PVC # =========================== pvc_mask = npe.Node(nutil.Function(input_names=['tissues'], output_names=['out_mask'], function=utils.create_pvc_mask), name='pvc_mask') # PET PVC # ======= petpvc = npe.Node(PETPVC(), name='pvc') petpvc.inputs.pvc = 'RBV' petpvc.inputs.out_file = 'pvc.nii' # Spatially normalize PET into MNI # ================================ dartel_mni_reg_pvc = npe.Node(spm.DARTELNorm2MNI(), name='dartel_mni_reg_pvc') dartel_mni_reg_pvc.inputs.modulate = False dartel_mni_reg_pvc.inputs.fwhm = 0 # Reslice reference region mask into PET # ====================================== reslice_pvc = npe.Node(spmutils.Reslice(), name='reslice_pvc') # Normalize PET values according to reference region # ================================================== norm_to_ref_pvc = npe.Node(nutil.Function( input_names=['pet_image', 'region_mask'], output_names=['suvr_pet_path'], function=utils.normalize_to_reference), name='norm_to_ref_pvc') # Mask PET image # ============== apply_mask_pvc = npe.Node(nutil.Function( input_names=['image', 'binary_mask'], output_names=['masked_image_path'], function=utils.apply_binary_mask), name='apply_mask_pvc') # Smoothing # ========= if self.parameters['smooth'] is not None and len( self.parameters['smooth']) > 0: smoothing_pvc = npe.MapNode(spm.Smooth(), name='smoothing_pvc', iterfield=['fwhm', 'out_prefix']) smoothing_pvc.inputs.fwhm = [[x, x, x] for x in self.parameters['smooth'] ] smoothing_pvc.inputs.out_prefix = [ 'fwhm-' + str(x) + 'mm_' for x in self.parameters['smooth'] ] self.connect([(apply_mask_pvc, smoothing_pvc, [('masked_image_path', 'in_files')]), (smoothing_pvc, self.output_node, [('smoothed_files', 'pet_pvc_suvr_masked_smoothed')])]) else: self.output_node.inputs.pet_pvc_suvr_masked_smoothed = [[]] # Atlas Statistics # ================ atlas_stats_pvc = npe.MapNode(nutil.Function( input_names=['in_image', 'in_atlas_list'], output_names=['atlas_statistics'], function=utils.atlas_statistics), name='atlas_stats_pvc', iterfield=['in_image']) atlas_stats_pvc.inputs.in_atlas_list = self.parameters['atlases'] # Connection # ========== self.connect([ (self.input_node, unzip_pvc_mask_tissues, [('pvc_mask_tissues', 'in_file')]), (unzip_pvc_mask_tissues, pvc_mask, [('out_file', 'tissues')]), (unzip_flow_fields, dartel_mni_reg_pvc, [('out_file', 'flowfield_files')]), (unzip_dartel_template, dartel_mni_reg_pvc, [('out_file', 'template_file')]), (unzip_reference_mask, reslice_pvc, [('out_file', 'in_file')]), (coreg_pet_t1, petpvc, [('coregistered_source', 'in_file'), (('coregistered_source', utils.pet_pvc_name, 'RBV'), 'out_file')]), (pvc_mask, petpvc, [('out_mask', 'mask_file')]), (self.input_node, petpvc, [(('psf', utils.get_from_list, 0), 'fwhm_x'), (('psf', utils.get_from_list, 1), 'fwhm_y'), (('psf', utils.get_from_list, 2), 'fwhm_z')]), (petpvc, dartel_mni_reg_pvc, [('out_file', 'apply_to_files')]), (dartel_mni_reg_pvc, reslice_pvc, [('normalized_files', 'space_defining')]), (dartel_mni_reg_pvc, norm_to_ref_pvc, [('normalized_files', 'pet_image')]), (reslice_pvc, norm_to_ref_pvc, [('out_file', 'region_mask')]), (norm_to_ref_pvc, apply_mask_pvc, [('suvr_pet_path', 'image') ]), (binary_mask, apply_mask_pvc, [('out_mask', 'binary_mask')]), (norm_to_ref_pvc, atlas_stats_pvc, [('suvr_pet_path', 'in_image')]), (petpvc, self.output_node, [('out_file', 'pet_pvc')]), (dartel_mni_reg_pvc, self.output_node, [('normalized_files', 'pet_pvc_mni')]), (norm_to_ref_pvc, self.output_node, [('suvr_pet_path', 'pet_pvc_suvr')]), (apply_mask_pvc, self.output_node, [('masked_image_path', 'pet_pvc_suvr_masked')]), (atlas_stats_pvc, self.output_node, [('atlas_statistics', 'pvc_atlas_statistics')]) ]) else: self.output_node.inputs.pet_pvc = [[]] self.output_node.inputs.pet_pvc_mni = [[]] self.output_node.inputs.pet_pvc_suvr = [[]] self.output_node.inputs.pet_pvc_suvr_masked = [[]] self.output_node.inputs.pvc_atlas_statistics = [[]] self.output_node.inputs.pet_pvc_suvr_masked_smoothed = [[]]
def create_spm_preproc_func_pipeline(data_dir=None, subject_id=None, task_list=None): ############################### ## Set up Nodes ############################### ds = Node(nio.DataGrabber(infields=['subject_id', 'task_id'], outfields=['func', 'struc']), name='datasource') ds.inputs.base_directory = os.path.abspath(data_dir + '/' + subject_id) ds.inputs.template = '*' ds.inputs.sort_filelist = True ds.inputs.template_args = {'func': [['task_id']], 'struc': []} ds.inputs.field_template = { 'func': 'Functional/Raw/%s/func.nii', 'struc': 'Structural/SPGR/spgr.nii' } ds.inputs.subject_id = subject_id ds.inputs.task_id = task_list ds.iterables = ('task_id', task_list) # ds.run().outputs #show datafiles # #Setup Data Sinker for writing output files # datasink = Node(nio.DataSink(), name='sinker') # datasink.inputs.base_directory = '/path/to/output' # workflow.connect(realigner, 'realignment_parameters', datasink, 'motion.@par') # datasink.inputs.substitutions = [('_variable', 'variable'),('file_subject_', '')] #Get Timing Acquisition for slice timing tr = 2 ta = Node(interface=util.Function(input_names=['tr', 'n_slices'], output_names=['ta'], function=get_ta), name="ta") ta.inputs.tr = tr #Slice Timing: sequential ascending slice_timing = Node(interface=spm.SliceTiming(), name="slice_timing") slice_timing.inputs.time_repetition = tr slice_timing.inputs.ref_slice = 1 #Realignment - 6 parameters - realign to first image of very first series. realign = Node(interface=spm.Realign(), name="realign") realign.inputs.register_to_mean = True #Plot Realignment plot_realign = Node(interface=PlotRealignmentParameters(), name="plot_realign") #Artifact Detection art = Node(interface=ra.ArtifactDetect(), name="art") art.inputs.use_differences = [True, False] art.inputs.use_norm = True art.inputs.norm_threshold = 1 art.inputs.zintensity_threshold = 3 art.inputs.mask_type = 'file' art.inputs.parameter_source = 'SPM' #Coregister - 12 parameters, cost function = 'nmi', fwhm 7, interpolate, don't mask #anatomical to functional mean across all available data. coregister = Node(interface=spm.Coregister(), name="coregister") coregister.inputs.jobtype = 'estimate' # Segment structural, gray/white/csf,mni, segment = Node(interface=spm.Segment(), name="segment") segment.inputs.save_bias_corrected = True #Normalize - structural to MNI - then apply this to the coregistered functionals normalize = Node(interface=spm.Normalize(), name="normalize") normalize.inputs.template = os.path.abspath(t1_template_file) #Plot normalization Check plot_normalization_check = Node(interface=Plot_Coregistration_Montage(), name="plot_normalization_check") plot_normalization_check.inputs.canonical_img = canonical_file #Create Mask compute_mask = Node(interface=ComputeMask(), name="compute_mask") #remove lower 5% of histogram of mean image compute_mask.inputs.m = .05 #Smooth #implicit masking (.im) = 0, dtype = 0 smooth = Node(interface=spm.Smooth(), name="smooth") fwhmlist = [0, 5, 8] smooth.iterables = ('fwhm', fwhmlist) #Create Covariate matrix make_covariates = Node(interface=Create_Covariates(), name="make_covariates") ############################### ## Create Pipeline ############################### Preprocessed = Workflow(name="Preprocessed") Preprocessed.base_dir = os.path.abspath(data_dir + '/' + subject_id + '/Functional') Preprocessed.connect([ (ds, ta, [(('func', get_n_slices), "n_slices")]), (ta, slice_timing, [("ta", "time_acquisition")]), (ds, slice_timing, [ ('func', 'in_files'), (('func', get_n_slices), "num_slices"), (('func', get_slice_order), "slice_order"), ]), (slice_timing, realign, [('timecorrected_files', 'in_files')]), (realign, compute_mask, [('mean_image', 'mean_volume')]), (realign, coregister, [('mean_image', 'target')]), (ds, coregister, [('struc', 'source')]), (coregister, segment, [('coregistered_source', 'data')]), (segment, normalize, [ ('transformation_mat', 'parameter_file'), ('bias_corrected_image', 'source'), ]), (realign, normalize, [('realigned_files', 'apply_to_files'), (('realigned_files', get_vox_dims), 'write_voxel_sizes')]), (normalize, smooth, [('normalized_files', 'in_files')]), (compute_mask, art, [('brain_mask', 'mask_file')]), (realign, art, [('realignment_parameters', 'realignment_parameters')]), (realign, art, [('realigned_files', 'realigned_files')]), (realign, plot_realign, [('realignment_parameters', 'realignment_parameters')]), (normalize, plot_normalization_check, [('normalized_files', 'wra_img') ]), (realign, make_covariates, [('realignment_parameters', 'realignment_parameters')]), (art, make_covariates, [('outlier_files', 'spike_id')]), ]) return Preprocessed
def __init__(self, func_source, struct_source, datasink): # specify input and output nodes self.func_source = func_source self.struct_source = struct_source self.datasink = datasink # specify nodes # structual process self.bet_struct = pe.Node(interface=fsl.BET(), name='non_brain_removal_BET_struct') self.bet_struct.inputs.output_type = "NIFTI" # functional process self.slice_timer = pe.Node(interface=fsl.SliceTimer(), name='time_slice_correction') self.mcflirt = pe.Node(interface=fsl.MCFLIRT(), name='motion_correction') self.mcflirt.inputs.output_type = "NIFTI" self.mcflirt.inputs.mean_vol = True self.fslsplit = pe.Node(interface=fsl.Split(), name='fslsplit') self.fslsplit.inputs.dimension = 't' self.fslsplit.inputs.output_type = "NIFTI" self.fslmerge = pe.Node(interface=fsl.Merge(), name='fslmerge') self.fslmerge.inputs.dimension = 't' self.fslmerge.inputs.output_type = "NIFTI" self.bet_mean = pe.Node(interface=fsl.BET(), name='non_brain_removal_BET_mean') self.bet_mean.inputs.output_type = "NIFTI" # helper function(s) def bet_each(in_files): ''' @param in_files: list of image files @return out_files: list of image files after applied fsl.BET on it ''' from nipype.interfaces import fsl import nipype.pipeline.engine as pe out_files = list() step_no = 0 for file_ in in_files: bet = pe.Node(interface=fsl.BET(), name='BET_for_step_{}'.format(step_no)) bet.inputs.in_file = file_ bet.inputs.out_file = file_[:len(file_) - 4] + '_bet.nii' bet.inputs.output_type = "NIFTI" bet.run() out_files.append(bet.inputs.out_file) step_no += 1 return out_files # bet_func return a list of NIFITI files self.bet_func = pe.Node(interface=Function(input_names=['in_files'], output_names=['out_files'], function=bet_each), name='non_brain_removal_BET_func') self.coregister = pe.Node(interface=spm.Coregister(), name="coregister") self.coregister.inputs.jobtype = 'estimate' self.segment = pe.Node(interface=spm.Segment(), name="segment") self.segment.inputs.affine_regularization = 'mni' self.normalize_func = pe.Node(interface=spm.Normalize(), name="normalize_func") self.normalize_func.inputs.jobtype = "write" # self.fourier = pe.Node(interface=afni.Fourier(), name='temporal_filtering') # self.fourier.inputs.highpass = 0.01 # self.fourier.inputs.lowpass = 0.1 self.smooth = pe.Node(interface=spm.Smooth(), name="smooth") self.smooth.inputs.fwhm = [8, 8, 8] # specify workflow instance self.workflow = pe.Workflow(name='preprocessing_workflow') # connect nodes self.workflow.connect([ (self.struct_source, self.bet_struct, [('outfiles', 'in_file')]), (self.func_source, self.slice_timer, [('outfiles', 'in_file')]), (self.slice_timer, self.mcflirt, [('slice_time_corrected_file', 'in_file')]), (self.mcflirt, self.bet_mean, [('mean_img', 'in_file')]), (self.mcflirt, self.fslsplit, [('out_file', 'in_file')]), (self.fslsplit, self.bet_func, [('out_files', 'in_files')]), (self.bet_func, self.fslmerge, [('out_files', 'in_files') ]), # intersect (self.bet_struct, self.coregister, [('out_file', 'source')]), (self.bet_mean, self.coregister, [('out_file', 'target')]), (self.coregister, self.segment, [('coregistered_source', 'data')]), (self.segment, self.normalize_func, [('transformation_mat', 'parameter_file')]), (self.fslmerge, self.normalize_func, [('merged_file', 'apply_to_files')]), (self.normalize_func, self.smooth, [('normalized_files', 'in_files')]), (self.coregister, self.datasink, [('coregistered_source', 'registered_file')]), (self.normalize_func, self.datasink, [('normalized_files', 'before_smooth')]), (self.smooth, self.datasink, [('smoothed_files', 'final_out')]) ])
def build_core_nodes(self): """Build and connect an output node to the pipeline.""" import nipype.interfaces.spm as spm import nipype.interfaces.spm.utils as spmutils import nipype.interfaces.utility as nutil import nipype.pipeline.engine as npe from nipype.interfaces.petpvc import PETPVC from clinica.utils.filemanip import unzip_nii from clinica.utils.spm import spm_standalone_is_available, use_spm_standalone from .pet_volume_utils import ( apply_binary_mask, atlas_statistics, create_binary_mask, create_pvc_mask, get_from_list, init_input_node, normalize_to_reference, pet_pvc_name, ) if spm_standalone_is_available(): use_spm_standalone() # Initialize pipeline # =================== init_node = npe.Node( interface=nutil.Function( input_names=["pet_nii"], output_names=["pet_nii"], function=init_input_node, ), name="init_pipeline", ) # Unzipping # ========= unzip_pet_image = npe.Node( nutil.Function(input_names=["in_file"], output_names=["out_file"], function=unzip_nii), name="unzip_pet_image", ) unzip_t1_image_native = npe.Node( nutil.Function(input_names=["in_file"], output_names=["out_file"], function=unzip_nii), name="unzip_t1_image_native", ) unzip_flow_fields = npe.Node( nutil.Function(input_names=["in_file"], output_names=["out_file"], function=unzip_nii), name="unzip_flow_fields", ) unzip_dartel_template = npe.Node( nutil.Function(input_names=["in_file"], output_names=["out_file"], function=unzip_nii), name="unzip_dartel_template", ) unzip_reference_mask = npe.Node( nutil.Function(input_names=["in_file"], output_names=["out_file"], function=unzip_nii), name="unzip_reference_mask", ) unzip_mask_tissues = npe.MapNode( nutil.Function(input_names=["in_file"], output_names=["out_file"], function=unzip_nii), name="unzip_mask_tissues", iterfield=["in_file"], ) # Coregister PET into T1 native space # =================================== coreg_pet_t1 = npe.Node(spm.Coregister(), name="coreg_pet_t1") # Spatially normalize PET into MNI # ================================ dartel_mni_reg = npe.Node(spm.DARTELNorm2MNI(), name="dartel_mni_reg") dartel_mni_reg.inputs.modulate = False dartel_mni_reg.inputs.fwhm = 0 # Reslice reference region mask into PET # ====================================== reslice = npe.Node(spmutils.Reslice(), name="reslice") # Normalize PET values according to reference region # ================================================== norm_to_ref = npe.Node( nutil.Function( input_names=["pet_image", "region_mask"], output_names=["suvr_pet_path"], function=normalize_to_reference, ), name="norm_to_ref", ) # Create binary mask from segmented tissues # ========================================= binary_mask = npe.Node( nutil.Function( input_names=["tissues", "threshold"], output_names=["out_mask"], function=create_binary_mask, ), name="binary_mask", ) binary_mask.inputs.threshold = self.parameters["mask_threshold"] # Mask PET image # ============== apply_mask = npe.Node( nutil.Function( input_names=["image", "binary_mask"], output_names=["masked_image_path"], function=apply_binary_mask, ), name="apply_mask", ) # Smoothing # ========= if self.parameters["smooth"] is not None and len( self.parameters["smooth"]) > 0: smoothing_node = npe.MapNode(spm.Smooth(), name="smoothing_node", iterfield=["fwhm", "out_prefix"]) smoothing_node.inputs.fwhm = [[x, x, x] for x in self.parameters["smooth"]] smoothing_node.inputs.out_prefix = [ "fwhm-" + str(x) + "mm_" for x in self.parameters["smooth"] ] # fmt: off self.connect([ (apply_mask, smoothing_node, [("masked_image_path", "in_files") ]), (smoothing_node, self.output_node, [("smoothed_files", "pet_suvr_masked_smoothed")]), ]) # fmt: on else: self.output_node.inputs.pet_suvr_masked_smoothed = [[]] # Atlas Statistics # ================ atlas_stats_node = npe.MapNode( nutil.Function( input_names=["in_image", "in_atlas_list"], output_names=["atlas_statistics"], function=atlas_statistics, ), name="atlas_stats_node", iterfield=["in_image"], ) atlas_stats_node.inputs.in_atlas_list = self.parameters["atlases"] # Connection # ========== # fmt: off self.connect([ (self.input_node, init_node, [("pet_image", "pet_nii")]), (init_node, unzip_pet_image, [("pet_nii", "in_file")]), (self.input_node, unzip_t1_image_native, [("t1_image_native", "in_file")]), (self.input_node, unzip_flow_fields, [("flow_fields", "in_file")]), (self.input_node, unzip_dartel_template, [("dartel_template", "in_file")]), (self.input_node, unzip_reference_mask, [("reference_mask", "in_file")]), (self.input_node, unzip_mask_tissues, [("mask_tissues", "in_file") ]), (unzip_pet_image, coreg_pet_t1, [("out_file", "source")]), (unzip_t1_image_native, coreg_pet_t1, [("out_file", "target")]), (unzip_flow_fields, dartel_mni_reg, [("out_file", "flowfield_files")]), (unzip_dartel_template, dartel_mni_reg, [("out_file", "template_file")]), (unzip_reference_mask, reslice, [("out_file", "in_file")]), (unzip_mask_tissues, binary_mask, [("out_file", "tissues")]), (coreg_pet_t1, dartel_mni_reg, [("coregistered_source", "apply_to_files")]), (dartel_mni_reg, reslice, [("normalized_files", "space_defining") ]), (dartel_mni_reg, norm_to_ref, [("normalized_files", "pet_image")]), (reslice, norm_to_ref, [("out_file", "region_mask")]), (norm_to_ref, apply_mask, [("suvr_pet_path", "image")]), (binary_mask, apply_mask, [("out_mask", "binary_mask")]), (norm_to_ref, atlas_stats_node, [("suvr_pet_path", "in_image")]), (coreg_pet_t1, self.output_node, [("coregistered_source", "pet_t1_native")]), (dartel_mni_reg, self.output_node, [("normalized_files", "pet_mni") ]), (norm_to_ref, self.output_node, [("suvr_pet_path", "pet_suvr")]), (binary_mask, self.output_node, [("out_mask", "binary_mask")]), (apply_mask, self.output_node, [("masked_image_path", "pet_suvr_masked")]), (atlas_stats_node, self.output_node, [("atlas_statistics", "atlas_statistics")]), ]) # fmt: on # PVC # ========== if self.parameters["apply_pvc"]: # Unzipping # ========= unzip_pvc_mask_tissues = npe.MapNode( nutil.Function( input_names=["in_file"], output_names=["out_file"], function=unzip_nii, ), name="unzip_pvc_mask_tissues", iterfield=["in_file"], ) # Creating Mask to use in PVC # =========================== pvc_mask = npe.Node( nutil.Function( input_names=["tissues"], output_names=["out_mask"], function=create_pvc_mask, ), name="pvc_mask", ) # PET PVC # ======= petpvc = npe.Node(PETPVC(), name="pvc") petpvc.inputs.pvc = "RBV" petpvc.inputs.out_file = "pvc.nii" # Spatially normalize PET into MNI # ================================ dartel_mni_reg_pvc = npe.Node(spm.DARTELNorm2MNI(), name="dartel_mni_reg_pvc") dartel_mni_reg_pvc.inputs.modulate = False dartel_mni_reg_pvc.inputs.fwhm = 0 # Reslice reference region mask into PET # ====================================== reslice_pvc = npe.Node(spmutils.Reslice(), name="reslice_pvc") # Normalize PET values according to reference region # ================================================== norm_to_ref_pvc = npe.Node( nutil.Function( input_names=["pet_image", "region_mask"], output_names=["suvr_pet_path"], function=normalize_to_reference, ), name="norm_to_ref_pvc", ) # Mask PET image # ============== apply_mask_pvc = npe.Node( nutil.Function( input_names=["image", "binary_mask"], output_names=["masked_image_path"], function=apply_binary_mask, ), name="apply_mask_pvc", ) # Smoothing # ========= if (self.parameters["smooth"] is not None and len(self.parameters["smooth"]) > 0): smoothing_pvc = npe.MapNode(spm.Smooth(), name="smoothing_pvc", iterfield=["fwhm", "out_prefix"]) smoothing_pvc.inputs.fwhm = [[x, x, x] for x in self.parameters["smooth"] ] smoothing_pvc.inputs.out_prefix = [ "fwhm-" + str(x) + "mm_" for x in self.parameters["smooth"] ] # fmt: off self.connect([ (apply_mask_pvc, smoothing_pvc, [("masked_image_path", "in_files")]), (smoothing_pvc, self.output_node, [("smoothed_files", "pet_pvc_suvr_masked_smoothed")]), ]) # fmt: on else: self.output_node.inputs.pet_pvc_suvr_masked_smoothed = [[]] # Atlas Statistics # ================ atlas_stats_pvc = npe.MapNode( nutil.Function( input_names=["in_image", "in_atlas_list"], output_names=["atlas_statistics"], function=atlas_statistics, ), name="atlas_stats_pvc", iterfield=["in_image"], ) atlas_stats_pvc.inputs.in_atlas_list = self.parameters["atlases"] # Connection # ========== # fmt: off self.connect([ (self.input_node, unzip_pvc_mask_tissues, [("pvc_mask_tissues", "in_file")]), (unzip_pvc_mask_tissues, pvc_mask, [("out_file", "tissues")]), (unzip_flow_fields, dartel_mni_reg_pvc, [("out_file", "flowfield_files")]), (unzip_dartel_template, dartel_mni_reg_pvc, [("out_file", "template_file")]), (unzip_reference_mask, reslice_pvc, [("out_file", "in_file")]), (coreg_pet_t1, petpvc, [("coregistered_source", "in_file"), (("coregistered_source", pet_pvc_name, "RBV"), "out_file")]), (pvc_mask, petpvc, [("out_mask", "mask_file")]), (self.input_node, petpvc, [(("psf", get_from_list, 0), "fwhm_x"), (("psf", get_from_list, 1), "fwhm_y"), (("psf", get_from_list, 2), "fwhm_z")]), (petpvc, dartel_mni_reg_pvc, [("out_file", "apply_to_files")]), (dartel_mni_reg_pvc, reslice_pvc, [("normalized_files", "space_defining")]), (dartel_mni_reg_pvc, norm_to_ref_pvc, [("normalized_files", "pet_image")]), (reslice_pvc, norm_to_ref_pvc, [("out_file", "region_mask")]), (norm_to_ref_pvc, apply_mask_pvc, [("suvr_pet_path", "image") ]), (binary_mask, apply_mask_pvc, [("out_mask", "binary_mask")]), (norm_to_ref_pvc, atlas_stats_pvc, [("suvr_pet_path", "in_image")]), (petpvc, self.output_node, [("out_file", "pet_pvc")]), (dartel_mni_reg_pvc, self.output_node, [("normalized_files", "pet_pvc_mni")]), (norm_to_ref_pvc, self.output_node, [("suvr_pet_path", "pet_pvc_suvr")]), (apply_mask_pvc, self.output_node, [("masked_image_path", "pet_pvc_suvr_masked")]), (atlas_stats_pvc, self.output_node, [("atlas_statistics", "pvc_atlas_statistics")]), ]) # fmt: on else: self.output_node.inputs.pet_pvc = [[]] self.output_node.inputs.pet_pvc_mni = [[]] self.output_node.inputs.pet_pvc_suvr = [[]] self.output_node.inputs.pet_pvc_suvr_masked = [[]] self.output_node.inputs.pvc_atlas_statistics = [[]] self.output_node.inputs.pet_pvc_suvr_masked_smoothed = [[]]
#Outputs: detrended_file, mean_file, stddev_file, tsnr_file smooth = Node(spm.Smooth(), name='smooth') smooth.inputs.fwhm = fwhm ####Anatomical preprocessing#### #dcmstack - Convert dicoms to nii (with embeded metadata) anat_stack = Node(dcmstack.DcmStack(), name='anatstack') anat_stack.inputs.embed_meta = True anat_stack.inputs.out_format = 'anat' anat_stack.inputs.out_ext = '.nii' #Outputs: out_file #Coregisters FLAIR & mask to T1 (NOTE: settings taken from Clinical Toolbox) flaircoreg = Node(spm.Coregister(), name='coreg2anat') flaircoreg.inputs.cost_function = 'nmi' flaircoreg.inputs.separation = [4, 2] flaircoreg.inputs.tolerance = [ 0.02, 0.02, 0.02, 0.001, 0.001, 0.001, 0.01, 0.01, 0.01, 0.001, 0.001, 0.001 ] flaircoreg.inputs.fwhm = [7, 7] flaircoreg.inputs.write_interp = 1 flaircoreg.inputs.write_wrap = [0, 0, 0] flaircoreg.inputs.write_mask = False #Coregisters T1, FLAIR + mask to EPI (NOTE: settings taken from Clinical Toolbox) coreg = MapNode(spm.Coregister(), iterfield='apply_to_files', name='coreg2epi') coreg.inputs.cost_function = 'nmi' coreg.inputs.separation = [4, 2]
import nipype.interfaces.spm as spm # Start at the slice-time corrected image base_fname = 'afds114_sub009_t2r1.nii' structural_fname = 'ds114_sub009_highres.nii' # Realign realign = spm.Realign() realign.inputs.in_files = base_fname # Do not write resliced files, do write mean image realign.inputs.write_which = [0, 1] realign.run() # Coregistration coreg = spm.Coregister() # Coregister structural to mean image from realignment coreg.inputs.target = 'mean' + base_fname coreg.inputs.source = structural_fname coreg.run() # Normalization / resampling with normalization + realign params seg_norm = spm.Normalize12() seg_norm.inputs.image_to_align = structural_fname seg_norm.inputs.apply_to_files = base_fname seg_norm.run() # Smoothing smooth = spm.Smooth() smooth.inputs.in_files = 'w' + base_fname smooth.inputs.fwhm = [8, 8, 8]
def __init__(self, subject, func_source, struct_source, datasink, TR, num_slices, dim=2): self.subject = subject # specify input and output nodes self.func_source = func_source self.struct_source = struct_source self.datasink = datasink self.TR = TR self.num_slices = num_slices # specify nodes # structual process self.bet_struct = pe.Node(interface=fsl.BET(), name='non_brain_removal_BET_struct') self.bet_struct.inputs.output_type = "NIFTI" self.bet_struct.inputs.frac = 0.3 self.coregister_struct = pe.Node(interface=spm.Coregister(), name="coregister_struct_to_mni") self.coregister_struct.inputs.target = '/mnt/Program/python/dev/images/MNI152_T1_2mm_brain.nii' if dim == 1: self.coregister_struct.inputs.target = '/mnt/Program/python/dev/images/MNI152_T1_1mm_brain.nii' self.coregister_struct.inputs.write_interp = 7 self.coregister_struct.inputs.separation = [1.0, 1.0] self.coregister_struct.inputs.jobtype = 'estwrite' self.segment_struct = pe.Node(interface=spm.Segment(), name="segment_struct") # self.segment_struct.inputs.affine_regularization = 'mni' self.segment_struct.inputs.csf_output_type = [True, True, True] self.segment_struct.inputs.gm_output_type = [True, True, True] self.segment_struct.inputs.wm_output_type = [True, True, True] self.normalize_struct = pe.Node(interface=spm.Normalize(), name='normalize_struct') self.normalize_struct.inputs.jobtype = 'write' self.normalize_struct.inputs.write_bounding_box = [[-90, -126, -72], [90, 90, 108] ] # 91, 109, 91 if dim == 1: self.normalize_struct.inputs.write_bounding_box = [[ -91, -126, -72 ], [90, 91, 109]] # 182, 218, 182 self.normalize_struct.inputs.write_voxel_sizes = [1, 1, 1] self.normalize_gm = pe.Node(interface=spm.Normalize(), name='normalize_gm') self.normalize_gm.inputs.jobtype = 'write' self.normalize_gm.inputs.write_bounding_box = [[-90, -126, -72], [90, 90, 108]] # 91, 109, 91 if dim == 1: self.normalize_gm.inputs.write_bounding_box = [[-91, -126, -72], [90, 91, 109] ] # 182, 218, 182 self.normalize_gm.inputs.write_voxel_sizes = [1, 1, 1] self.normalize_wm = pe.Node(interface=spm.Normalize(), name='normalize_wm') self.normalize_wm.inputs.jobtype = 'write' self.normalize_wm.inputs.write_bounding_box = [[-90, -126, -72], [90, 90, 108]] # 91, 109, 91 if dim == 1: self.normalize_wm.inputs.write_bounding_box = [[-91, -126, -72], [90, 91, 109] ] # 182, 218, 182 self.normalize_wm.inputs.write_voxel_sizes = [1, 1, 1] self.normalize_csf = pe.Node(interface=spm.Normalize(), name='normalize_csf') self.normalize_csf.inputs.jobtype = 'write' self.normalize_csf.inputs.write_bounding_box = [[-90, -126, -72], [90, 90, 108]] # 91, 109, 91 if dim == 1: self.normalize_csf.inputs.write_bounding_box = [[-91, -126, -72], [90, 91, 109] ] # 182, 218, 182 self.normalize_csf.inputs.write_voxel_sizes = [1, 1, 1] ################################################################################################### # functional process self.fslsplit = pe.Node(interface=fsl.Split(), name='fslsplit') self.fslsplit.inputs.dimension = 't' self.fslsplit.inputs.output_type = "NIFTI" self.fslmerge = pe.Node(interface=fsl.Merge(), name='fslmerge') self.fslmerge.inputs.dimension = 't' self.fslmerge.inputs.output_type = "NIFTI" # helper function(s) def bet_each(in_files, subject_name): ''' @param in_files: list of image files @return out_files: list of image files after applied fsl.BET on it ''' from nipype.interfaces import fsl import nipype.pipeline.engine as pe out_files = list() step_no = 0 for file_ in in_files: bet = pe.Node(interface=fsl.BET(), name='BET_for_step_{}_{}'.format( step_no, subject_name)) bet.inputs.in_file = file_ bet.inputs.out_file = file_[:len(file_) - 4] + '_bet.nii' bet.inputs.output_type = "NIFTI" bet.inputs.frac = 0.5 bet.run() out_files.append(bet.inputs.out_file) step_no += 1 return out_files # bet_func return a list of NIFITI files self.bet_func = pe.Node(interface=Function( input_names=['in_files', 'subject_name'], output_names=['out_files'], function=bet_each), name='non_brain_removal_BET_func') self.bet_func.inputs.subject_name = self.subject self.realign = pe.Node(interface=spm.Realign(), name='realign_motion_correction') self.realign.inputs.register_to_mean = True self.coregister_func = pe.Node(interface=spm.Coregister(), name="coregister_func_to_mni") self.coregister_func.inputs.target = '/mnt/Program/python/dev/images/MNI152_T1_2mm_brain.nii' self.coregister_func.inputs.write_interp = 7 self.coregister_func.inputs.separation = [1.0, 1.0] self.coregister_func.inputs.jobtype = 'estwrite' self.segment = pe.Node(interface=spm.Segment(), name="segment") self.normalize_func = pe.Node(interface=spm.Normalize(), name="normalize_func") self.normalize_func.inputs.jobtype = 'write' self.normalize_func.inputs.write_bounding_box = [[-90, -126, -72], [90, 90, 108]] # 91, 109, 91 self.smooth = pe.Node(interface=spm.Smooth(), name="smooth") self.smooth.inputs.fwhm = [8, 8, 8] # backup node(s) self.slice_timing = pe.Node(interface=spm.SliceTiming(), name='time_slice_correction') self.slice_timing.inputs.time_repetition = self.TR self.slice_timing.inputs.num_slices = self.num_slices self.slice_timing.inputs.time_acquisition = self.TR - (self.TR / self.num_slices) self.slice_timing.inputs.slice_order = list( range(self.num_slices, 0, -1)) self.slice_timing.inputs.ref_slice = 1 self.direct_normalize = pe.Node(interface=spm.Normalize12(), name='direct_normalize') self.direct_normalize.inputs.image_to_align = 'images/MNI152_T1_2mm_brain.nii' self.direct_normalize.inputs.affine_regularization_type = 'size' # specify workflow instance self.workflow = pe.Workflow(name='preprocess_workflow') # connect nodes self.workflow.connect([ (self.struct_source, self.bet_struct, [('outfiles', 'in_file')]), (self.bet_struct, self.coregister_struct, [('out_file', 'source') ]), (self.coregister_struct, self.segment_struct, [('coregistered_source', 'data')]), (self.segment_struct, self.normalize_struct, [('transformation_mat', 'parameter_file')]), (self.coregister_struct, self.normalize_struct, [('coregistered_source', 'apply_to_files')]), (self.segment_struct, self.normalize_gm, [('transformation_mat', 'parameter_file')]), (self.segment_struct, self.normalize_gm, [('native_gm_image', 'apply_to_files')]), (self.segment_struct, self.normalize_wm, [('transformation_mat', 'parameter_file')]), (self.segment_struct, self.normalize_wm, [('native_wm_image', 'apply_to_files')]), (self.segment_struct, self.normalize_csf, [('transformation_mat', 'parameter_file')]), (self.segment_struct, self.normalize_csf, [('native_csf_image', 'apply_to_files')]), (self.func_source, self.fslsplit, [('outfiles', 'in_file')]), (self.fslsplit, self.bet_func, [('out_files', 'in_files')]), (self.bet_func, self.fslmerge, [('out_files', 'in_files')]), (self.fslmerge, self.realign, [('merged_file', 'in_files')]), (self.realign, self.datasink, [('realignment_parameters', 'realignment_parameters')]), (self.realign, self.coregister_func, [('mean_image', 'source')]), (self.realign, self.coregister_func, [('realigned_files', 'apply_to_files')]), (self.coregister_func, self.segment, [('coregistered_source', 'data')]), (self.segment, self.normalize_func, [('transformation_mat', 'parameter_file')]), (self.coregister_func, self.normalize_func, [('coregistered_files', 'apply_to_files')]), (self.normalize_func, self.smooth, [('normalized_files', 'in_files')]), # end (self.normalize_func, self.datasink, [('normalized_files', 'before_smooth')]), (self.smooth, self.datasink, [('smoothed_files', 'final_out')]), (self.normalize_struct, self.datasink, [('normalized_files', 'standardized_struct_file')]), # (self.segment_struct, self.datasink, [('native_csf_image', 'csf'), ('native_gm_image', 'grey_matter'), ('native_wm_image', 'white_matter')]) (self.normalize_gm, self.datasink, [('normalized_files', 'grey_matter')]), (self.normalize_wm, self.datasink, [('normalized_files', 'white_matter')]), (self.normalize_csf, self.datasink, [('normalized_files', 'csf')]), ]) # backup workflow(s) self.workflow_only_fmri = pe.Workflow(name='preprocess_workflow') # connect nodes self.workflow_only_fmri.connect([ (self.func_source, self.fslsplit, [('outfiles', 'in_file')]), (self.fslsplit, self.bet_func, [('out_files', 'in_files')]), (self.bet_func, self.fslmerge, [('out_files', 'in_files')]), (self.fslmerge, self.realign, [('merged_file', 'in_files')]), (self.realign, self.direct_normalize, [('realigned_files', 'apply_to_files')]), (self.direct_normalize, self.smooth, [('normalized_files', 'in_files')]), # end (self.direct_normalize, self.datasink, [('normalized_files', 'before_smooth')]), (self.smooth, self.datasink, [('smoothed_files', 'final_out')]) ])
# fMRI pre-processing # # skip dummy scans extract = Node( fsl.ExtractROI( in_file=imagefMRI, # input image t_min=4, # first 4 volumes are deleted t_size=-1, output_type='NIFTI'), # forces output to be .nii name="extract") # motion correction aka realignment realign = Node(spm.Realign(), name="realign") # coregistration, fMRI to T1w coreg = Node(spm.Coregister(cost_function='nmi'), name="coreg") # estimating affine transform for co-registration coregEst = Node(spm.CalcCoregAffine(), name="coregEst") # warping fMRI by applying the warping estimated for T1 normalizefMRI = Node(spm.Normalize12(jobtype='write', write_bounding_box=[[-90, -120, -70], [90, 90, 105]], write_voxel_sizes=voxfMRI), name="normalizefMRI") # gunzip node, FSL brain mask gunzip_mask = Node(Gunzip(in_file=fmask), name="gunzip_mask") # Reslice the FSL template to match fMRI
def create_preproc_func_pipeline( ): #ref_slice, n_skip=4, n_slices=30, tr=2.5, sparse=False): # if sparse: # real_tr = tr/2 # else: # real_tr = tr inputnode = pe.Node(interface=util.IdentityInterface( fields=['func', "struct", "TR", "sparse"]), name="inputnode") skip = pe.Node(interface=fsl.ExtractROI(), name="skip") skip.inputs.t_min = 4 #TODO skip.inputs.t_size = 100000 realign = pe.Node(interface=spm.Realign(), name="realign") realign.inputs.register_to_mean = True tr_convert = pe.Node(interface=util.Function(input_names=['tr', 'sparse'], output_names=['tr'], function=get_tr), name="tr_converter") ta = pe.Node(interface=util.Function(input_names=['real_tr', 'n_slices'], output_names=['ta'], function=get_ta), name="ta") slice_timing = pe.Node(interface=spm.SliceTiming(), name="slice_timing") #slice_timing.inputs.num_slices = n_slices #slice_timing.inputs.time_repetition = real_tr #slice_timing.inputs.time_acquisition = real_tr - real_tr/float(n_slices) #slice_timing.inputs.slice_order = range(1,n_slices+1,2) + range(2,n_slices+1,2) #slice_timing.inputs.ref_slice = ref_slice coregister = pe.Node(interface=spm.Coregister(), name="coregister") coregister.inputs.jobtype = "estimate" smooth = pe.Node(interface=spm.Smooth(), name="smooth") smooth.iterables = ('fwhm', [[8, 8, 8], [0, 0, 0]]) art = pe.Node(interface=ra.ArtifactDetect(), name="art") art.inputs.use_differences = [True, False] art.inputs.use_norm = True art.inputs.norm_threshold = 1 art.inputs.zintensity_threshold = 3 art.inputs.mask_type = 'file' art.inputs.parameter_source = 'SPM' compute_mask = pe.Node(interface=ComputeMask(), name="compute_mask") plot_realign = pe.Node(interface=neuroutils.PlotRealignemntParameters(), name="plot_realign") preproc_func = pe.Workflow(name="preproc_func") preproc_func.connect([ (inputnode, skip, [("func", "in_file")]), (inputnode, coregister, [("struct", "target")]), (realign, coregister, [('mean_image', 'source'), ('realigned_files', 'apply_to_files')]), (coregister, compute_mask, [('coregistered_source', 'mean_volume')]), (skip, slice_timing, [("roi_file", "in_files"), (('roi_file', get_n_slices), "num_slices"), (('roi_file', get_slice_order), "slice_order"), (('roi_file', get_ref_slice), "ref_slice")]), (inputnode, tr_convert, [("sparse", "sparse"), ("TR", "tr")]), (tr_convert, slice_timing, [("tr", "time_repetition")]), (tr_convert, ta, [("tr", "real_tr")]), (skip, ta, [(('roi_file', get_n_slices), "n_slices")]), (ta, slice_timing, [("ta", "time_acquisition")]), (slice_timing, realign, [("timecorrected_files", "in_files")]), (coregister, smooth, [("coregistered_files", "in_files")]), (compute_mask, art, [('brain_mask', 'mask_file')]), (realign, art, [('realignment_parameters', 'realignment_parameters')]), (realign, art, [('realigned_files', 'realigned_files')]), (realign, plot_realign, [('realignment_parameters', 'realignment_parameters')]) ]) return preproc_func
art.inputs.use_norm = True art.inputs.norm_threshold = 1 art.inputs.zintensity_threshold = 3 art.inputs.mask_type = 'file' art.inputs.parameter_source = 'SPM' """Skull strip structural images using :class:`nipype.interfaces.fsl.BET`. """ skullstrip = pe.Node(fsl.BET(), name="skullstrip") skullstrip.inputs.mask = True """Use :class:`nipype.interfaces.spm.Coregister` to perform a rigid body registration of the functional data to the structural data. """ coregister = pe.Node(spm.Coregister(), name="coregister") coregister.inputs.jobtype = 'estimate' """Normalize and smooth functional data using DARTEL template """ normalize_and_smooth_func = pe.Node(spm.DARTELNorm2MNI(modulate=True), name='normalize_and_smooth_func') fwhmlist = [4] normalize_and_smooth_func.iterables = ('fwhm', fwhmlist) """Normalize structural data using DARTEL template """ normalize_struct = pe.Node(spm.DARTELNorm2MNI(modulate=True), name='normalize_struct') normalize_struct.inputs.fwhm = 2
def build_core_nodes(self): """Build and connect the core nodes of the pipelines. """ import fmri_preprocessing_workflows as utils import nipype.interfaces.utility as nutil import nipype.interfaces.spm as spm import nipype.pipeline.engine as npe from clinica.utils.filemanip import zip_nii, unzip_nii # Zipping # ======= unzip_node = npe.MapNode(name='Unzipping', iterfield=['in_file'], interface=nutil.Function( input_names=['in_file'], output_names=['out_file'], function=unzip_nii)) unzip_T1w = unzip_node.clone('UnzippingT1w') unzip_phasediff = unzip_node.clone('UnzippingPhasediff') unzip_bold = unzip_node.clone('UnzippingBold') unzip_magnitude1 = unzip_node.clone('UnzippingMagnitude1') # FieldMap calculation # ==================== if self.parameters['unwarping']: fm_node = npe.MapNode(name="FieldMapCalculation", iterfield=[ 'phase', 'magnitude', 'epi', 'et', 'blipdir', 'tert' ], interface=spm.FieldMap()) # Slice timing correction # ======================= st_node = npe.MapNode(name="SliceTimingCorrection", iterfield=[ 'in_files', 'time_repetition', 'slice_order', 'num_slices', 'ref_slice', 'time_acquisition' ], interface=spm.SliceTiming()) # Motion correction and unwarping # =============================== if self.parameters['unwarping']: mc_node = npe.MapNode(name="MotionCorrectionUnwarping", iterfield=["scans", "pmscan"], interface=spm.RealignUnwarp()) mc_node.inputs.register_to_mean = True mc_node.inputs.reslice_mask = False else: mc_node = npe.MapNode(name="MotionCorrection", iterfield=["in_files"], interface=spm.Realign()) mc_node.inputs.register_to_mean = True # Brain extraction # ================ import os.path as path from nipype.interfaces.freesurfer import MRIConvert if self.parameters['freesurfer_brain_mask']: brain_masks = [ path.join(self.caps_directory, 'subjects', self.subjects[i], self.sessions[i], 't1/freesurfer_cross_sectional', self.subjects[i] + '_' + self.sessions[i], 'mri/brain.mgz') for i in range(len(self.subjects)) ] conv_brain_masks = [ str(self.subjects[i] + '_' + self.sessions[i] + '.nii') for i in range(len(self.subjects)) ] bet_node = npe.MapNode(interface=MRIConvert(), iterfield=["in_file", "out_file"], name="BrainConversion") bet_node.inputs.in_file = brain_masks bet_node.inputs.out_file = conv_brain_masks bet_node.inputs.out_type = 'nii' else: bet_node = utils.BrainExtractionWorkflow(name="BrainExtraction") # Registration # ============ reg_node = npe.MapNode( interface=spm.Coregister(), iterfield=["apply_to_files", "source", "target"], name="Registration") # Normalization # ============= norm_node = npe.MapNode(interface=spm.Normalize12(), iterfield=['image_to_align', 'apply_to_files'], name='Normalization') # Smoothing # ========= smooth_node = npe.MapNode(interface=spm.Smooth(), iterfield=['in_files'], name='Smoothing') smooth_node.inputs.fwhm = self.parameters['full_width_at_half_maximum'] # Zipping # ======= zip_node = npe.MapNode(name='Zipping', iterfield=['in_file'], interface=nutil.Function( input_names=['in_file'], output_names=['out_file'], function=zip_nii)) zip_bet_node = zip_node.clone('ZippingBET') zip_mc_node = zip_node.clone('ZippingMC') zip_reg_node = zip_node.clone('ZippingRegistration') zip_norm_node = zip_node.clone('ZippingNormalization') zip_smooth_node = zip_node.clone('ZippingSmoothing') # Connections # =========== if self.parameters['freesurfer_brain_mask']: self.connect([ # Brain extraction (bet_node, reg_node, [('out_file', 'target')]), (bet_node, zip_bet_node, [('out_file', 'in_file')]), ]) else: self.connect([ # Brain extraction (unzip_T1w, bet_node, [('out_file', 'Segmentation.data')]), (unzip_T1w, bet_node, [('out_file', 'ApplyMask.in_file')]), (bet_node, reg_node, [('ApplyMask.out_file', 'target')]), (bet_node, zip_bet_node, [('Fill.out_file', 'in_file')]), ]) if self.parameters['unwarping']: self.connect([ # FieldMap calculation (self.input_node, fm_node, [('et', 'et')]), (self.input_node, fm_node, [('blipdir', 'blipdir')]), (self.input_node, fm_node, [('tert', 'tert')]), (self.input_node, unzip_phasediff, [('phasediff', 'in_file')]), (self.input_node, unzip_magnitude1, [('magnitude1', 'in_file') ]), (unzip_magnitude1, fm_node, [('out_file', 'magnitude')]), (unzip_phasediff, fm_node, [('out_file', 'phase')]), (unzip_bold, fm_node, [('out_file', 'epi')]), # Motion correction and unwarping (st_node, mc_node, [('timecorrected_files', 'scans')]), (fm_node, mc_node, [('vdm', 'pmscan')]), (mc_node, reg_node, [('realigned_unwarped_files', 'apply_to_files')]), (mc_node, zip_mc_node, [('realigned_unwarped_files', 'in_file') ]), ]) else: self.connect([ # Motion correction and unwarping (st_node, mc_node, [('timecorrected_files', 'in_files')]), (mc_node, reg_node, [('realigned_files', 'apply_to_files')]), (mc_node, zip_mc_node, [('realigned_files', 'in_file')]), ]) self.connect([ # Unzipping (self.input_node, unzip_T1w, [('T1w', 'in_file')]), (self.input_node, unzip_bold, [('bold', 'in_file')]), # Slice timing correction (unzip_bold, st_node, [('out_file', 'in_files')]), (self.input_node, st_node, [('time_repetition', 'time_repetition') ]), (self.input_node, st_node, [('num_slices', 'num_slices')]), (self.input_node, st_node, [('slice_order', 'slice_order')]), (self.input_node, st_node, [('ref_slice', 'ref_slice')]), (self.input_node, st_node, [('time_acquisition', 'time_acquisition')]), # Registration (mc_node, reg_node, [('mean_image', 'source')]), # Normalization (unzip_T1w, norm_node, [('out_file', 'image_to_align')]), (reg_node, norm_node, [('coregistered_files', 'apply_to_files')]), # Smoothing (norm_node, smooth_node, [('normalized_files', 'in_files')]), # Zipping (reg_node, zip_reg_node, [('coregistered_files', 'in_file')]), (norm_node, zip_norm_node, [('normalized_files', 'in_file')]), (smooth_node, zip_smooth_node, [('smoothed_files', 'in_file')]), # Returning output (zip_bet_node, self.output_node, [('out_file', 't1_brain_mask')]), (mc_node, self.output_node, [('realignment_parameters', 'mc_params')]), (zip_mc_node, self.output_node, [('out_file', 'native_fmri')]), (zip_reg_node, self.output_node, [('out_file', 't1_fmri')]), (zip_norm_node, self.output_node, [('out_file', 'mni_fmri')]), (zip_smooth_node, self.output_node, [('out_file', 'mni_smoothed_fmri')]), ])
""" preproc = pe.Workflow(name='preproc') """Use :class:`nipype.interfaces.spm.Realign` for motion correction and register all images to the mean image. """ realign = pe.Node(interface=spm.Realign(), name="realign") slice_timing = pe.Node(interface=spm.SliceTiming(), name="slice_timing") """Use :class:`nipype.interfaces.spm.Coregister` to perform a rigid body registration of the functional data to the structural data. """ coregister = pe.Node(interface=spm.Coregister(), name="coregister") coregister.inputs.jobtype = 'estimate' segment = pe.Node(interface=spm.Segment(), name="segment") segment.inputs.save_bias_corrected = True """Uncomment the following line for faster execution """ # segment.inputs.gaussians_per_class = [1, 1, 1, 4] """Warp functional and structural data to SPM's T1 template using :class:`nipype.interfaces.spm.Normalize`. The tutorial data set includes the template image, T1.nii. """ normalize_func = pe.Node(interface=spm.Normalize(), name="normalize_func") normalize_func.inputs.jobtype = "write"
def Couple_Preproc_Pipeline(base_dir=None, output_dir=None, subject_id=None, spm_path=None): """ Create a preprocessing workflow for the Couples Conflict Study using nipype Args: base_dir: path to data folder where raw subject folder is located output_dir: path to where key output files should be saved subject_id: subject_id (str) spm_path: path to spm folder Returns: workflow: a nipype workflow that can be run """ from nipype.interfaces.dcm2nii import Dcm2nii from nipype.interfaces.fsl import Merge, TOPUP, ApplyTOPUP import nipype.interfaces.io as nio import nipype.interfaces.utility as util from nipype.interfaces.utility import Merge as Merge_List from nipype.pipeline.engine import Node, Workflow from nipype.interfaces.fsl.maths import UnaryMaths from nipype.interfaces.nipy.preprocess import Trim from nipype.algorithms.rapidart import ArtifactDetect from nipype.interfaces import spm from nipype.interfaces.spm import Normalize12 from nipype.algorithms.misc import Gunzip from nipype.interfaces.nipy.preprocess import ComputeMask import nipype.interfaces.matlab as mlab from nltools.utils import get_resource_path, get_vox_dims, get_n_volumes from nltools.interfaces import Plot_Coregistration_Montage, PlotRealignmentParameters, Create_Covariates import os import glob ######################################## ## Setup Paths and Nodes ######################################## # Specify Paths canonical_file = os.path.join(spm_path, 'canonical', 'single_subj_T1.nii') template_file = os.path.join(spm_path, 'tpm', 'TPM.nii') # Set the way matlab should be called mlab.MatlabCommand.set_default_matlab_cmd("matlab -nodesktop -nosplash") mlab.MatlabCommand.set_default_paths(spm_path) # Get File Names for different types of scans. Parse into separate processing streams datasource = Node(interface=nio.DataGrabber( infields=['subject_id'], outfields=['struct', 'ap', 'pa']), name='datasource') datasource.inputs.base_directory = base_dir datasource.inputs.template = '*' datasource.inputs.field_template = { 'struct': '%s/Study*/t1w_32ch_mpr_08mm*', 'ap': '%s/Study*/distortion_corr_32ch_ap*', 'pa': '%s/Study*/distortion_corr_32ch_pa*' } datasource.inputs.template_args = { 'struct': [['subject_id']], 'ap': [['subject_id']], 'pa': [['subject_id']] } datasource.inputs.subject_id = subject_id datasource.inputs.sort_filelist = True # iterate over functional scans to define paths scan_file_list = glob.glob( os.path.join(base_dir, subject_id, 'Study*', '*')) func_list = [s for s in scan_file_list if "romcon_ap_32ch_mb8" in s] func_list = [s for s in func_list if "SBRef" not in s] # Exclude sbref for now. func_source = Node(interface=util.IdentityInterface(fields=['scan']), name="func_source") func_source.iterables = ('scan', func_list) # Create Separate Converter Nodes for each different type of file. (dist corr scans need to be done before functional) ap_dcm2nii = Node(interface=Dcm2nii(), name='ap_dcm2nii') ap_dcm2nii.inputs.gzip_output = True ap_dcm2nii.inputs.output_dir = '.' ap_dcm2nii.inputs.date_in_filename = False pa_dcm2nii = Node(interface=Dcm2nii(), name='pa_dcm2nii') pa_dcm2nii.inputs.gzip_output = True pa_dcm2nii.inputs.output_dir = '.' pa_dcm2nii.inputs.date_in_filename = False f_dcm2nii = Node(interface=Dcm2nii(), name='f_dcm2nii') f_dcm2nii.inputs.gzip_output = True f_dcm2nii.inputs.output_dir = '.' f_dcm2nii.inputs.date_in_filename = False s_dcm2nii = Node(interface=Dcm2nii(), name='s_dcm2nii') s_dcm2nii.inputs.gzip_output = True s_dcm2nii.inputs.output_dir = '.' s_dcm2nii.inputs.date_in_filename = False ######################################## ## Setup Nodes for distortion correction ######################################## # merge output files into list merge_to_file_list = Node(interface=Merge_List(2), infields=['in1', 'in2'], name='merge_to_file_list') # fsl merge AP + PA files (depends on direction) merger = Node(interface=Merge(dimension='t'), name='merger') merger.inputs.output_type = 'NIFTI_GZ' # use topup to create distortion correction map topup = Node(interface=TOPUP(), name='topup') topup.inputs.encoding_file = os.path.join(get_resource_path(), 'epi_params_APPA_MB8.txt') topup.inputs.output_type = "NIFTI_GZ" topup.inputs.config = 'b02b0.cnf' # apply topup to all functional images apply_topup = Node(interface=ApplyTOPUP(), name='apply_topup') apply_topup.inputs.in_index = [1] apply_topup.inputs.encoding_file = os.path.join(get_resource_path(), 'epi_params_APPA_MB8.txt') apply_topup.inputs.output_type = "NIFTI_GZ" apply_topup.inputs.method = 'jac' apply_topup.inputs.interp = 'spline' # Clear out Zeros from spline interpolation using absolute value. abs_maths = Node(interface=UnaryMaths(), name='abs_maths') abs_maths.inputs.operation = 'abs' ######################################## ## Preprocessing ######################################## # Trim - remove first 10 TRs n_vols = 10 trim = Node(interface=Trim(), name='trim') trim.inputs.begin_index = n_vols #Realignment - 6 parameters - realign to first image of very first series. realign = Node(interface=spm.Realign(), name="realign") realign.inputs.register_to_mean = True #Coregister - 12 parameters coregister = Node(interface=spm.Coregister(), name="coregister") coregister.inputs.jobtype = 'estwrite' #Plot Realignment plot_realign = Node(interface=PlotRealignmentParameters(), name="plot_realign") #Artifact Detection art = Node(interface=ArtifactDetect(), name="art") art.inputs.use_differences = [True, False] art.inputs.use_norm = True art.inputs.norm_threshold = 1 art.inputs.zintensity_threshold = 3 art.inputs.mask_type = 'file' art.inputs.parameter_source = 'SPM' # Gunzip - unzip the functional and structural images gunzip_struc = Node(Gunzip(), name="gunzip_struc") gunzip_func = Node(Gunzip(), name="gunzip_func") # Normalize - normalizes functional and structural images to the MNI template normalize = Node(interface=Normalize12(jobtype='estwrite', tpm=template_file), name="normalize") #Plot normalization Check plot_normalization_check = Node(interface=Plot_Coregistration_Montage(), name="plot_normalization_check") plot_normalization_check.inputs.canonical_img = canonical_file #Create Mask compute_mask = Node(interface=ComputeMask(), name="compute_mask") #remove lower 5% of histogram of mean image compute_mask.inputs.m = .05 #Smooth #implicit masking (.im) = 0, dtype = 0 smooth = Node(interface=spm.Smooth(), name="smooth") smooth.inputs.fwhm = 6 #Create Covariate matrix make_cov = Node(interface=Create_Covariates(), name="make_cov") # Create a datasink to clean up output files datasink = Node(interface=nio.DataSink(), name='datasink') datasink.inputs.base_directory = output_dir datasink.inputs.container = subject_id ######################################## # Create Workflow ######################################## workflow = Workflow(name='Preprocessed') workflow.base_dir = os.path.join(base_dir, subject_id) workflow.connect([ (datasource, ap_dcm2nii, [('ap', 'source_dir')]), (datasource, pa_dcm2nii, [('pa', 'source_dir')]), (datasource, s_dcm2nii, [('struct', 'source_dir')]), (func_source, f_dcm2nii, [('scan', 'source_dir')]), (ap_dcm2nii, merge_to_file_list, [('converted_files', 'in1')]), (pa_dcm2nii, merge_to_file_list, [('converted_files', 'in2')]), (merge_to_file_list, merger, [('out', 'in_files')]), (merger, topup, [('merged_file', 'in_file')]), (topup, apply_topup, [('out_fieldcoef', 'in_topup_fieldcoef'), ('out_movpar', 'in_topup_movpar')]), (f_dcm2nii, trim, [('converted_files', 'in_file')]), (trim, apply_topup, [('out_file', 'in_files')]), (apply_topup, abs_maths, [('out_corrected', 'in_file')]), (abs_maths, gunzip_func, [('out_file', 'in_file')]), (gunzip_func, realign, [('out_file', 'in_files')]), (s_dcm2nii, gunzip_struc, [('converted_files', 'in_file')]), (gunzip_struc, coregister, [('out_file', 'source')]), (coregister, normalize, [('coregistered_source', 'image_to_align')]), (realign, coregister, [('mean_image', 'target'), ('realigned_files', 'apply_to_files')]), (realign, normalize, [(('mean_image', get_vox_dims), 'write_voxel_sizes')]), (coregister, normalize, [('coregistered_files', 'apply_to_files')]), (normalize, smooth, [('normalized_files', 'in_files')]), (realign, compute_mask, [('mean_image', 'mean_volume')]), (compute_mask, art, [('brain_mask', 'mask_file')]), (realign, art, [('realignment_parameters', 'realignment_parameters'), ('realigned_files', 'realigned_files')]), (realign, plot_realign, [('realignment_parameters', 'realignment_parameters')]), (normalize, plot_normalization_check, [('normalized_files', 'wra_img') ]), (realign, make_cov, [('realignment_parameters', 'realignment_parameters')]), (art, make_cov, [('outlier_files', 'spike_id')]), (normalize, datasink, [('normalized_files', 'structural.@normalize')]), (coregister, datasink, [('coregistered_source', 'structural.@struct') ]), (topup, datasink, [('out_fieldcoef', 'distortion.@fieldcoef')]), (topup, datasink, [('out_movpar', 'distortion.@movpar')]), (smooth, datasink, [('smoothed_files', 'functional.@smooth')]), (plot_realign, datasink, [('plot', 'functional.@plot_realign')]), (plot_normalization_check, datasink, [('plot', 'functional.@plot_normalization')]), (make_cov, datasink, [('covariates', 'functional.@covariates')]) ]) return workflow