def save_tmaps(copes_loc, mask_loc, working_dir, permutations, rerun=False): task_dir = path.dirname(copes_loc) contrast_name = path.basename(copes_loc).split('_cope')[0].rstrip( '.nii.gz') contrast_working_dir = path.join(working_dir, path.basename(copes_loc)) tfile_loc = path.join(task_dir, "%s_raw_tfile.nii.gz" % contrast_name) tfile_corrected_loc = path.join( task_dir, "%s_corrected_tfile.nii.gz" % contrast_name) makedirs(contrast_working_dir, exist_ok=True) # perform permutation test to assess significance if not path.exists(tfile_loc) or rerun: mem = Memory(base_dir=contrast_working_dir) randomise = mem.cache(fsl.Randomise) randomise_results = randomise( in_file=copes_loc, mask=mask_loc, one_sample_group_mean=True, tfce=True, # look at paper vox_p_values=True, var_smooth=10, num_perm=permutations) # save results raw_tfile = randomise_results.outputs.tstat_files[0] corrected_tfile = randomise_results.outputs.t_corrected_p_files[0] shutil.move(raw_tfile, tfile_loc) shutil.move(corrected_tfile, tfile_corrected_loc) shutil.rmtree(contrast_working_dir) return tfile_loc, tfile_corrected_loc
def convert_rawdata(base_directory, input_dir, out_prefix): os.environ['UNPACK_MGH_DTI'] = '0' file_list = os.listdir(input_dir) # If RAWDATA folder contains one (and only one) gunzipped nifti file -> copy it first_file = os.path.join(input_dir, file_list[0]) if len(file_list) == 1 and first_file.endswith('nii.gz'): copyfile(first_file, os.path.join(base_directory, 'NIFTI', out_prefix + '.nii.gz'), False, False, 'content') # intelligent copy looking at input's content else: mem = Memory(base_dir=os.path.join(base_directory, 'NIPYPE')) mri_convert = mem.cache(fs.MRIConvert) #mri_convert = mem.cache(fs.MRIConvert) #res = mri_convert(in_file=first_file, out_file=os.path.join(base_directory, 'NIFTI', out_prefix + '.nii.gz')) #mr_convert = mem.cache(mrt.MRConvert) #res = mr_convert(in_dir=str(input_dir), out_filename=os.path.join(base_directory, 'NIFTI', out_prefix + '.nii.gz')) dcm2niix = mem.cache(Dcm2niix) res = dcm2niix(source_dir=str(input_dir), output_dir=os.path.join(base_directory, 'NIFTI'), out_filename=out_prefix) if len(res.outputs.get()) == 0: return False if len(res.outputs.get()) == 0: return False return True
def main(): print('Running subjects:', str(SUBJECTS)) if not os.path.isdir(MEM_DIR): os.mkdir(MEM_DIR) mem = Memory(base_dir=MEM_DIR) layout = BIDSLayout(BIDS_DIR) # func_files[subject_index][run_index] if num_runs > 1: func_files = [[ layout.get(type='bold', task=task, run=i + 1, subject=subj, extensions='nii.gz')[0] for i in range(num_runs) ] for subj in SUBJECTS] else: func_files = [ layout.get(type='bold', task=task, subject=subj, extensions='nii.gz') for subj in SUBJECTS ] events = get_events(func_files) confounds = get_confounds(func_files) info = get_info(events, confounds) specify_model_results = specify_model(layout, func_files, info) level1design_results = lv1_design(mem, layout, func_files, specify_model_results) modelgen_results = feat_model(mem, level1design_results) mask_results = masking(mem, func_files) film_gls(mem, mask_results, modelgen_results)
def anat_preproc(file_to_register, register_to, warp_back, pipeline_dir): # DATA CONFIGURATION. FOLLOWING OPENFMRI STANDARD. save_to = os.path.join(pipeline_dir, file_to_register.split('/')[-1].split('.')[0]) # Run pipeline imperatively with caching (without workflow object) mem = Memory(pipeline_dir) antsreg = mem.cache(Registration) transform = mem.cache(ApplyTransforms) save_list = [] # nodes manual parameter configuration and run reg = antsreg(args='--float', collapse_output_transforms=True, moving_image=file_to_register, fixed_image=register_to, initial_moving_transform_com=True, num_threads=n_proc, output_inverse_warped_image=True, output_warped_image=True, sigma_units=['vox']*3, transforms=['Rigid', 'Affine', 'SyN'], terminal_output='file', winsorize_lower_quantile=0.005, winsorize_upper_quantile=0.995, convergence_threshold=[1e-06], convergence_window_size=[10], metric=['MI', 'MI', 'CC'], metric_weight=[1.0]*3, number_of_iterations=[[1000, 500, 250, 100], [1000, 500, 250, 100], [100, 70, 50, 20]], radius_or_number_of_bins=[32, 32, 4], sampling_percentage=[0.25, 0.25, 1], sampling_strategy=['Regular', 'Regular', 'None'], shrink_factors=[[8, 4, 2, 1]]*3, smoothing_sigmas=[[3, 2, 1, 0]]*3, transform_parameters=[(0.1,), (0.1,), (0.1, 3.0, 0.0)], use_histogram_matching=True, write_composite_transform=True) save_list.append([reg.outputs.composite_transform, save_to]) save_list.append([reg.outputs.warped_image, save_to]) save_list.append([reg.outputs.inverse_composite_transform, save_to]) save_list.append([reg.outputs.inverse_warped_image, save_to]) transformed = transform(args='--float', input_image_type=3, interpolation='NearestNeighbor', invert_transform_flags=[False], num_threads=n_proc, reference_image=file_to_register, terminal_output='file', transforms=reg.outputs.inverse_composite_transform, input_image=warp_back) save_list.append([transformed.outputs.output_image, save_to]) return save_list
def _reorient(unifized_anat_file, unbiased_modality_file, write_dir, modality_name='modality', terminal_output='allatonce', caching=False, verbose=True, environ=None): """ Reorientation of the subject's anatomical image to the modality. Parameters ---------- modality_name : str, optional Name to be used in the transform filename caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. Returns ------- 2-tuple of str : Path to the reoriented anatomical image and to the transform from anat to modality. """ if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) catmatvec = memory.cache(afni.CatMatvec) else: catmatvec = afni.CatMatvec().run registered_anat_oblique_file, mat_file =\ _warp(unifized_anat_file, unbiased_modality_file, write_dir, caching=caching, verbose=verbose, terminal_output=terminal_output, environ=environ) transform_file = fname_presuffix( registered_anat_oblique_file, suffix='_anat_to_{}.aff12.1D'.format(modality_name), use_ext=False) _ = catmatvec(in_file=[(mat_file, 'ONELINE')], oneline=True, out_file=transform_file, environ=environ) # Remove the intermediate outputs if not caching: os.remove(mat_file) return registered_anat_oblique_file, transform_file
def afni_unifize(in_file, write_dir=None, out_file=None, caching=False, terminal_output='allatonce', verbose=True, environ=None, copy_geometry=False, **unifize_kwargs): if write_dir is None: write_dir = os.path.dirname(in_file) if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) copy_geom = memory.cache(fsl.CopyGeom) unifize = memory.cache(afni.Unifize) copy = memory.cache(afni.Copy) unifize.interface().set_default_terminal_output(terminal_output) copy.interface().set_default_terminal_output(terminal_output) else: copy_geom = fsl.CopyGeom(terminal_output=terminal_output).run unifize = afni.Unifize(terminal_output=terminal_output).run copy = afni.Copy(terminal_output=terminal_output).run if out_file is None: out_file = fname_presuffix(in_file, suffix='_unifized', newpath=write_dir) if copy_geometry: unifized_file = fname_presuffix(in_file, suffix='_unifized_rough_geom', newpath=write_dir) else: unifized_file = out_file out_unifize = unifize(in_file=in_file, out_file=unifized_file, environ=environ, quiet=not (verbose), **unifize_kwargs) if copy_geometry: out_copy = copy(in_file=out_unifize.outputs.out_file, out_file=out_file, environ=environ) out_copy_geom = copy_geom(dest_file=out_copy.outputs.out_file, in_file=in_file) return out_file
def dcm2nii(source_names, terminal_output="allatonce", gzip_output=False, anonymize=True, output_dir=None, caching=True, **other_dcm2nii_kwargs): """ Converts DICOM (dcm) images to Nifti. """ # all input files must be DICOM if is_niimg(source_names): return source_names, None for source_name in [source_names] if isinstance( source_names, _basestring) else source_names: if not isdicom(source_name): return source_names, None # not (all) DICOM; nothx to do # sanitize output dir if output_dir is None: output_dir = os.path.dirname(source_names if isinstance( source_names, _basestring) else source_names[0]) if not os.path.exists(output_dir): os.makedirs(output_dir) # prepare node if caching: cache_dir = os.path.join(output_dir, "cache_dir") if not os.path.exists(cache_dir): os.makedirs(cache_dir) dcm2nii_node = Memory(cache_dir).cache(Dcm2nii) else: dcm2nii_node = Dcm2nii.run # run node and collect results dcm2nii_result = dcm2nii_node(source_names=source_names, terminal_output=terminal_output, anonymize=anonymize, gzip_output=gzip_output, output_dir=output_dir, **other_dcm2nii_kwargs) return dcm2nii_result.outputs.converted_files, dcm2nii_result
def ants_n4(in_file, write_dir=None, caching=False, terminal_output='allatonce', environ=None, copy_geometry=True): if write_dir is None: write_dir = os.path.dirname(in_file) if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) bias_correct = memory.cache(ants.N4BiasFieldCorrection) copy = memory.cache(afni.Copy) copy_geom = memory.cache(fsl.CopyGeom) bias_correct.interface().set_default_terminal_output(terminal_output) copy.interface().set_default_terminal_output(terminal_output) else: bias_correct = ants.N4BiasFieldCorrection( terminal_output=terminal_output).run copy = afni.Copy(terminal_output=terminal_output).run copy_geom = fsl.CopyGeom(terminal_output=terminal_output).run unbiased_file = fname_presuffix(in_file, suffix='_n4', newpath=write_dir) if copy_geometry: output_image = fname_presuffix(in_file, suffix='_n4_rough_geom', newpath=write_dir) else: output_image = unbiased_file out_bias_correct = bias_correct( input_image=in_file, shrink_factor=_compute_n4_max_shrink(in_file), output_image=output_image) if copy_geometry: out_copy = copy(in_file=out_bias_correct.outputs.output_image, out_file=unbiased_file, environ=environ) out_copy_geom = copy_geom(dest_file=out_copy.outputs.out_file, in_file=in_file) return unbiased_file
def _warp(to_warp_file, reference_file, write_dir=None, caching=False, terminal_output='allatonce', verbose=True, environ=None): if write_dir is None: write_dir = os.path.dirname(to_warp_file) if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) warp = memory.cache(afni.Warp) else: warp = afni.Warp().run out_warp = warp(in_file=to_warp_file, oblique_parent=reference_file, interp='quintic', gridset=reference_file, out_file=fname_presuffix(to_warp_file, suffix='_warped', newpath=write_dir), verbose=True, save_warp=True, environ=environ) # 3dWarp doesn't put the obliquity in the header, so do it manually warped_oblique_file = fix_obliquity(out_warp.outputs.out_file, reference_file, verbose=verbose, caching=caching, caching_dir=write_dir, environ=environ) return warped_oblique_file, out_warp.outputs.warp_file
def test_caching(): temp_dir = mkdtemp(prefix='test_memory_') old_rerun = config.get('execution', 'stop_on_first_rerun') try: # Prevent rerun to check that evaluation is computed only once config.set('execution', 'stop_on_first_rerun', 'true') mem = Memory(temp_dir) first_nb_run = nb_runs results = mem.cache(SideEffectInterface)(input1=2, input2=1) assert_equal(nb_runs, first_nb_run + 1) assert_equal(results.outputs.output1, [1, 2]) results = mem.cache(SideEffectInterface)(input1=2, input2=1) # Check that the node hasn't been rerun assert_equal(nb_runs, first_nb_run + 1) assert_equal(results.outputs.output1, [1, 2]) results = mem.cache(SideEffectInterface)(input1=1, input2=1) # Check that the node hasn been rerun assert_equal(nb_runs, first_nb_run + 2) assert_equal(results.outputs.output1, [1, 1]) finally: rmtree(temp_dir) config.set('execution', 'stop_on_first_rerun', old_rerun)
def _delete_orientation(in_file, write_dir=None, min_zoom=.1, caching=False, verbose=True): if write_dir is None: write_dir = os.path.dirname(in_file) if verbose: terminal_output = 'stream' else: terminal_output = 'none' if caching: memory = Memory(write_dir) copy = memory.cache(afni.Copy) refit = memory.cache(afni.Refit) center_mass = memory.cache(afni.CenterMass) for step in [copy, refit]: step.interface().set_default_terminal_output(terminal_output) else: copy = afni.Copy(terminal_output=terminal_output).run refit = afni.Refit(terminal_output=terminal_output).run center_mass = afni.CenterMass().run out_copy = copy(in_file=in_file, out_file=fname_presuffix(in_file, newpath=write_dir)) zooms = nibabel.load(in_file).header.get_zooms()[:3] out_refit = refit(in_file=out_copy.outputs.out_file, xyzscale=min_zoom / min(zooms)) out_center_mass = center_mass(in_file=out_refit.outputs.out_file, cm_file=fname_presuffix(in_file, suffix='.txt', use_ext=False, newpath=write_dir), set_cm=(0, 0, 0)) return out_center_mass.outputs.out_file
def _slice_time(func_file, t_r, write_dir, caching=False, terminal_output='allatonce', environ=None): if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) tshift = memory.cache(afni.TShift) tshift.interface().set_default_terminal_output(terminal_output) else: tshift = afni.TShift(terminal_output=terminal_output).run out_tshift = tshift(in_file=func_file, out_file=fname_presuffix(func_file, suffix='_tshifted', newpath=write_dir), tpattern='altplus', tr=str(t_r), environ=environ) return out_tshift.outputs.out_file
def check_input(self, gui=True): print '**** Check Inputs ****' diffusion_available = False t1_available = False t2_available = False valid_inputs = False mem = Memory(base_dir=os.path.join(self.base_directory, 'NIPYPE')) swap_and_reorient = mem.cache(SwapAndReorient) # Check for (and if existing, convert) diffusion data diffusion_model = [] for model in ['DSI', 'DTI', 'HARDI']: input_dir = os.path.join(self.base_directory, 'RAWDATA', model) if len(os.listdir(input_dir)) > 0: if convert_rawdata(self.base_directory, input_dir, model): diffusion_available = True diffusion_model.append(model) # Check for (and if existing, convert) T1 input_dir = os.path.join(self.base_directory, 'RAWDATA', 'T1') if len(os.listdir(input_dir)) > 0: if convert_rawdata(self.base_directory, input_dir, 'T1_orig'): t1_available = True # Check for (and if existing, convert) T2 input_dir = os.path.join(self.base_directory, 'RAWDATA', 'T2') if len(os.listdir(input_dir)) > 0: if convert_rawdata(self.base_directory, input_dir, 'T2_orig'): t2_available = True if diffusion_available: #project.stages['Diffusion'].config.imaging_model_choices = diffusion_model if t2_available: swap_and_reorient( src_file=os.path.join(self.base_directory, 'NIFTI', 'T2_orig.nii.gz'), ref_file=os.path.join(self.base_directory, 'NIFTI', diffusion_model[0] + '.nii.gz'), out_file=os.path.join(self.base_directory, 'NIFTI', 'T2.nii.gz')) if t1_available: swap_and_reorient( src_file=os.path.join(self.base_directory, 'NIFTI', 'T1_orig.nii.gz'), ref_file=os.path.join(self.base_directory, 'NIFTI', diffusion_model[0] + '.nii.gz'), out_file=os.path.join(self.base_directory, 'NIFTI', 'T1.nii.gz')) valid_inputs = True input_message = 'Inputs check finished successfully.\nDiffusion and morphological data available.' else: input_message = 'Error during inputs check.\nMorphological data (T1) not available.' elif t1_available: input_message = 'Error during inputs check. \nDiffusion data not available (DSI/DTI/HARDI).' else: input_message = 'Error during inputs check. No diffusion or morphological data available in folder ' + os.path.join( self.base_directory, 'RAWDATA') + '!' imaging_model = diffusion_model[0] if gui: input_notification = Check_Input_Notification( message=input_message, imaging_model_options=diffusion_model, imaging_model=imaging_model) input_notification.configure_traits() self.global_conf.imaging_model = input_notification.imaging_model diffusion_file = os.path.join( self.base_directory, 'NIFTI', input_notification.imaging_model + '.nii.gz') n_vol = nib.load(diffusion_file).shape[3] if self.stages['Preprocessing'].config.end_vol == 0 or self.stages[ 'Preprocessing'].config.end_vol == self.stages[ 'Preprocessing'].config.max_vol or self.stages[ 'Preprocessing'].config.end_vol >= n_vol - 1: self.stages['Preprocessing'].config.end_vol = n_vol - 1 self.stages['Preprocessing'].config.max_vol = n_vol - 1 self.stages[ 'Registration'].config.imaging_model = input_notification.imaging_model self.stages[ 'Diffusion'].config.imaging_model = input_notification.imaging_model else: print input_message self.global_conf.imaging_model = imaging_model diffusion_file = os.path.join(self.base_directory, 'NIFTI', imaging_model + '.nii.gz') n_vol = nib.load(diffusion_file).shape[3] if self.stages['Preprocessing'].config.end_vol == 0 or self.stages[ 'Preprocessing'].config.end_vol == self.stages[ 'Preprocessing'].config.max_vol or self.stages[ 'Preprocessing'].config.end_vol >= n_vol - 1: self.stages['Preprocessing'].config.end_vol = n_vol - 1 self.stages['Preprocessing'].config.max_vol = n_vol - 1 self.stages['Registration'].config.imaging_model = imaging_model self.stages['Diffusion'].config.imaging_model = imaging_model if t2_available: self.stages['Registration'].config.registration_mode_trait = [ 'Linear (FSL)', 'BBregister (FS)', 'Nonlinear (FSL)' ] self.fill_stages_outputs() return valid_inputs
print nifti_file, anat_image shutil.move(nifti_file, anat_image) else: print nifti_file, fmri_sessions[session_id] shutil.move(nifti_file, fmri_sessions[session_id]) # remove the dicom dirs for x in glob.glob(os.path.join(dicom_dir, '*')): os.remove(x) os.removedirs(dicom_dir) ############################################################## # Preprocessing ############################################################## mem = Memory(base_dir=subject_dir) ############################################################## # Anatomical segmentation (White/Grey matter) seg = mem.cache(spm.Segment) out_seg = seg(data=anat_image, gm_output_type=[True, True, True], wm_output_type=[True, True, True], csf_output_type=[True, True, True]) sn_file = out_seg.outputs.transformation_mat inv_sn_file = out_seg.outputs.inverse_transformation_mat gm_image = out_seg.outputs.normalized_gm_image native_gm_image = out_seg.outputs.native_gm_image
def _func_to_template(func_coreg_filename, template_filename, write_dir, func_to_anat_oned_filename, anat_to_template_oned_filename, anat_to_template_warp_filename, voxel_size=None, caching=False, verbose=True): """ Applies successive transforms to coregistered functional to put it in template space. Parameters ---------- coreg_func_filename : str Path to functional volume, coregistered to a common space with the anatomical volume. template_filename : str Template to register the functional to. func_to_anat_oned_filename : str Path to the affine 1D transform from functional to coregistration space. anat_to_template_oned_filename : str Path to the affine 1D transform from anatomical to template space. anat_to_template_warp_filename : str Path to the warp transform from anatomical to template space. voxel_size : 3-tuple of floats, optional Voxel size of the registered functional, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. """ environ = {} if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if caching: memory = Memory(write_dir) resample = memory.cache(afni.Resample) catmatvec = memory.cache(afni.CatMatvec) allineate = memory.cache(afni.Allineate) warp_apply = memory.cache(afni.NwarpApply) for step in [resample, allineate, warp_apply]: step.interface().set_default_terminal_output(terminal_output) else: resample = afni.Resample(terminal_output=terminal_output).run catmatvec = afni.CatMatvec().run allineate = afni.Allineate(terminal_output=terminal_output).run warp_apply = afni.NwarpApply(terminal_output=terminal_output).run environ['AFNI_DECONFLICT'] = 'OVERWRITE' current_dir = os.getcwd() os.chdir(write_dir) # XXX to remove normalized_filename = fname_presuffix(func_coreg_filename, suffix='_normalized') if voxel_size is None: func_template_filename = template_filename else: out_resample = resample(in_file=template_filename, voxel_size=voxel_size, outputtype='NIFTI_GZ', environ=environ) func_template_filename = out_resample.outputs.out_file if anat_to_template_warp_filename is None: affine_transform_filename = fname_presuffix(func_to_anat_oned_filename, suffix='_to_template') _ = catmatvec(in_file=[(anat_to_template_oned_filename, 'ONELINE'), (func_to_anat_oned_filename, 'ONELINE')], oneline=True, out_file=affine_transform_filename, environ=environ) _ = allineate(in_file=func_coreg_filename, master=func_template_filename, in_matrix=affine_transform_filename, out_file=normalized_filename, environ=environ) else: warp = "'{0} {1} {2}'".format(anat_to_template_warp_filename, anat_to_template_oned_filename, func_to_anat_oned_filename) _ = warp_apply(in_file=func_coreg_filename, master=func_template_filename, warp=warp, out_file=normalized_filename, environ=environ) os.chdir(current_dir) return normalized_filename
def coregister_fmri_session(session_data, t_r, write_dir, brain_volume, use_rats_tool=True, slice_timing=True, prior_rigid_body_registration=False, caching=False, voxel_size_x=.1, voxel_size_y=.1, verbose=True, **environ_kwargs): """ Coregistration of the subject's functional and anatomical images. The functional volume is aligned to the anatomical, first with a rigid body registration and then on a per-slice basis (only a fine correction, this is mostly for correction of EPI distortion). Parameters ---------- session_data : sammba.registration.SessionData Single animal data, giving paths to its functional and anatomical image, as well as it identifier. t_r : float Repetition time for the EPI, in seconds. write_dir : str Directory to save the output and temporary images. brain_volume : int Volume of the brain in mm3 used for brain extraction. Typically 400 for mouse and 1800 for rat. use_rats_tool : bool, optional If True, brain mask is computed using RATS Mathematical Morphology. Otherwise, a histogram-based brain segmentation is used. prior_rigid_body_registration : bool, optional If True, a rigid-body registration of the anat to the func is performed prior to the warp. Useful if the images headers have missing/wrong information. voxel_size_x : float, optional Resampling resolution for the x-axis, in mm. voxel_size_y : float, optional Resampling resolution for the y-axis, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. environ_kwargs : extra arguments keywords Extra arguments keywords, passed to interfaces environ variable. Returns ------- the same sequence with each animal_data updated: the following attributes are added - `output_dir_` : str Path to the output directory. - `coreg_func_` : str Path to paths to the coregistered functional image. - `coreg_anat_` : str Path to paths to the coregistered functional image. - `coreg_transform_` : str Path to the transform from anat to func. Notes ----- If `use_rats_tool` is turned on, RATS tool is used for brain extraction and has to be cited. For more information, see `RATS <http://www.iibi.uiowa.edu/content/rats-overview/>`_ """ func_filename = session_data.func anat_filename = session_data.anat environ = {'AFNI_DECONFLICT': 'OVERWRITE'} for (key, value) in environ_kwargs.items(): environ[key] = value if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if use_rats_tool: if segmentation.interfaces.Info().version() is None: raise ValueError('Can not locate RATS') else: ComputeMask = segmentation.MathMorphoMask else: ComputeMask = segmentation.HistogramMask if ants.base.Info().version is None: raise ValueError('Can not locate ANTS') if caching: memory = Memory(write_dir) tshift = memory.cache(afni.TShift) clip_level = memory.cache(afni.ClipLevel) volreg = memory.cache(afni.Volreg) allineate = memory.cache(afni.Allineate) tstat = memory.cache(afni.TStat) compute_mask = memory.cache(ComputeMask) calc = memory.cache(afni.Calc) allineate = memory.cache(afni.Allineate) allineate2 = memory.cache(afni.Allineate) unifize = memory.cache(afni.Unifize) bias_correct = memory.cache(ants.N4BiasFieldCorrection) catmatvec = memory.cache(afni.CatMatvec) warp = memory.cache(afni.Warp) resample = memory.cache(afni.Resample) slicer = memory.cache(afni.ZCutUp) warp_apply = memory.cache(afni.NwarpApply) qwarp = memory.cache(afni.Qwarp) merge = memory.cache(afni.Zcat) copy_geom = memory.cache(fsl.CopyGeom) overwrite = False for step in [ tshift, volreg, allineate, allineate2, tstat, compute_mask, calc, unifize, resample, slicer, warp_apply, qwarp, merge ]: step.interface().set_default_terminal_output(terminal_output) else: tshift = afni.TShift(terminal_output=terminal_output).run clip_level = afni.ClipLevel().run volreg = afni.Volreg(terminal_output=terminal_output).run allineate = afni.Allineate(terminal_output=terminal_output).run allineate2 = afni.Allineate(terminal_output=terminal_output ).run # TODO: remove after fixed bug tstat = afni.TStat(terminal_output=terminal_output).run compute_mask = ComputeMask().run calc = afni.Calc(terminal_output=terminal_output).run unifize = afni.Unifize(terminal_output=terminal_output).run bias_correct = ants.N4BiasFieldCorrection( terminal_output=terminal_output).run catmatvec = afni.CatMatvec().run warp = afni.Warp().run resample = afni.Resample(terminal_output=terminal_output).run slicer = afni.ZCutUp(terminal_output=terminal_output).run warp_apply = afni.NwarpApply(terminal_output=terminal_output).run qwarp = afni.Qwarp(terminal_output=terminal_output).run merge = afni.Zcat(terminal_output=terminal_output).run copy_geom = fsl.CopyGeom(terminal_output=terminal_output).run overwrite = True session_data._check_inputs() output_dir = os.path.join(os.path.abspath(write_dir), session_data.animal_id) session_data._set_output_dir_(output_dir) current_dir = os.getcwd() os.chdir(output_dir) output_files = [] ####################################### # Correct functional for slice timing # ####################################### if slice_timing: out_tshift = tshift(in_file=func_filename, outputtype='NIFTI_GZ', tpattern='altplus', tr=str(t_r), environ=environ) func_filename = out_tshift.outputs.out_file output_files.append(func_filename) ################################################ # Register functional volumes to the first one # ################################################ # XXX why do you need a thresholded image ? out_clip_level = clip_level(in_file=func_filename) out_calc_threshold = calc(in_file_a=func_filename, expr='ispositive(a-{0}) * a'.format( out_clip_level.outputs.clip_val), outputtype='NIFTI_GZ') thresholded_filename = out_calc_threshold.outputs.out_file out_volreg = volreg( # XXX dfile not saved in_file=thresholded_filename, outputtype='NIFTI_GZ', environ=environ, oned_file=fname_presuffix(thresholded_filename, suffix='Vr.1Dfile.1D', use_ext=False), oned_matrix_save=fname_presuffix(thresholded_filename, suffix='Vr.aff12.1D', use_ext=False)) # Apply the registration to the whole head out_allineate = allineate(in_file=func_filename, master=func_filename, in_matrix=out_volreg.outputs.oned_matrix_save, out_file=fname_presuffix(func_filename, suffix='Av'), environ=environ) # 3dAllineate removes the obliquity. This is not a good way to readd it as # removes motion correction info in the header if it were an AFNI file...as # it happens it's NIfTI which does not store that so irrelevant! out_copy_geom = copy_geom(dest_file=out_allineate.outputs.out_file, in_file=out_volreg.outputs.out_file) allineated_filename = out_copy_geom.outputs.out_file # Create a (hopefully) nice mean image for use in the registration out_tstat = tstat(in_file=allineated_filename, args='-mean', outputtype='NIFTI_GZ', environ=environ) # Update outputs output_files.extend([ thresholded_filename, out_volreg.outputs.oned_matrix_save, out_volreg.outputs.out_file, out_volreg.outputs.md1d_file, allineated_filename, out_tstat.outputs.out_file ]) ########################################### # Corret anat and func for intensity bias # ########################################### # Correct the functional average for intensities bias out_bias_correct = bias_correct(input_image=out_tstat.outputs.out_file) unbiased_func_filename = out_bias_correct.outputs.output_image # Bias correct the antomical image out_unifize = unifize(in_file=anat_filename, outputtype='NIFTI_GZ', environ=environ) unbiased_anat_filename = out_unifize.outputs.out_file # Update outputs output_files.extend([unbiased_func_filename, unbiased_anat_filename]) ############################################# # Rigid-body registration anat -> mean func # ############################################# if prior_rigid_body_registration: # Mask the mean functional volume outside the brain. out_clip_level = clip_level(in_file=unbiased_func_filename) out_compute_mask_func = compute_mask( in_file=unbiased_func_filename, volume_threshold=brain_volume, intensity_threshold=int(out_clip_level.outputs.clip_val)) out_cacl_func = calc(in_file_a=unbiased_func_filename, in_file_b=out_compute_mask_func.outputs.out_file, expr='a*b', outputtype='NIFTI_GZ', environ=environ) # Mask the anatomical volume outside the brain. out_clip_level = clip_level(in_file=unbiased_anat_filename) out_compute_mask_anat = compute_mask( in_file=unbiased_anat_filename, volume_threshold=brain_volume, intensity_threshold=int(out_clip_level.outputs.clip_val)) out_cacl_anat = calc(in_file_a=unbiased_anat_filename, in_file_b=out_compute_mask_anat.outputs.out_file, expr='a*b', outputtype='NIFTI_GZ', environ=environ) # Compute the transformation from functional to anatomical brain # XXX: why in this sense out_allineate = allineate2( in_file=out_cacl_func.outputs.out_file, reference=out_cacl_anat.outputs.out_file, out_matrix=fname_presuffix(out_cacl_func.outputs.out_file, suffix='_shr.aff12.1D', use_ext=False), center_of_mass='', warp_type='shift_rotate', out_file=fname_presuffix(out_cacl_func.outputs.out_file, suffix='_shr'), environ=environ) rigid_transform_file = out_allineate.outputs.out_matrix output_files.extend([ out_compute_mask_func.outputs.out_file, out_cacl_func.outputs.out_file, out_compute_mask_anat.outputs.out_file, out_cacl_anat.outputs.out_file, rigid_transform_file, out_allineate.outputs.out_file ]) # apply the inverse transform to register the anatomical to the func catmatvec_out_file = fname_presuffix(rigid_transform_file, suffix='INV') out_catmatvec = catmatvec(in_file=[(rigid_transform_file, 'I')], oneline=True, out_file=catmatvec_out_file) output_files.append(out_catmatvec.outputs.out_file) out_allineate = allineate(in_file=unbiased_anat_filename, master=unbiased_func_filename, in_matrix=out_catmatvec.outputs.out_file, out_file=fname_presuffix( unbiased_anat_filename, suffix='_shr_in_func_space'), environ=environ) allineated_anat_filename = out_allineate.outputs.out_file output_files.append(allineated_anat_filename) else: allineated_anat_filename = unbiased_anat_filename ############################################ # Nonlinear registration anat -> mean func # ############################################ # 3dWarp doesn't put the obliquity in the header, so do it manually # This step generates one file per slice and per time point, so we are # making sure they are removed at the end out_warp = warp(in_file=allineated_anat_filename, oblique_parent=unbiased_func_filename, interp='quintic', gridset=unbiased_func_filename, outputtype='NIFTI_GZ', verbose=True, environ=environ) registered_anat_filename = out_warp.outputs.out_file registered_anat_oblique_filename = fix_obliquity(registered_anat_filename, unbiased_func_filename, verbose=verbose) # Concatenate all the anat to func tranforms mat_filename = fname_presuffix(registered_anat_filename, suffix='_warp.mat', use_ext=False) # XXX Handle this correctly according to caching if not os.path.isfile(mat_filename): np.savetxt(mat_filename, [out_warp.runtime.stdout], fmt='%s') output_files.append(mat_filename) transform_filename = fname_presuffix(registered_anat_filename, suffix='_anat_to_func.aff12.1D', use_ext=False) if prior_rigid_body_registration: _ = catmatvec(in_file=[(mat_filename, 'ONELINE'), (rigid_transform_file, 'ONELINE')], oneline=True, out_file=transform_filename) else: _ = catmatvec(in_file=[(mat_filename, 'ONELINE')], oneline=True, out_file=transform_filename) ################################################## # Per-slice non-linear registration func -> anat # ################################################## # Slice anatomical image anat_img = nibabel.load(registered_anat_oblique_filename) anat_n_slices = anat_img.header.get_data_shape()[2] sliced_registered_anat_filenames = [] for slice_n in range(anat_n_slices): out_slicer = slicer(in_file=registered_anat_oblique_filename, keep='{0} {0}'.format(slice_n), out_file=fname_presuffix( registered_anat_oblique_filename, suffix='Sl%d' % slice_n), environ=environ) oblique_slice = fix_obliquity(out_slicer.outputs.out_file, registered_anat_oblique_filename, verbose=verbose) sliced_registered_anat_filenames.append(oblique_slice) # Slice mean functional sliced_bias_corrected_filenames = [] img = nibabel.load(func_filename) n_slices = img.header.get_data_shape()[2] for slice_n in range(n_slices): out_slicer = slicer(in_file=unbiased_func_filename, keep='{0} {0}'.format(slice_n), out_file=fname_presuffix(unbiased_func_filename, suffix='Sl%d' % slice_n), environ=environ) oblique_slice = fix_obliquity(out_slicer.outputs.out_file, unbiased_func_filename, verbose=verbose) sliced_bias_corrected_filenames.append(oblique_slice) # Below line is to deal with slices where there is no signal (for example # rostral end of some anatomicals) # The inverse warp frequently fails, Resampling can help it work better # XXX why specifically .1 in voxel_size ? voxel_size_z = anat_img.header.get_zooms()[2] resampled_registered_anat_filenames = [] for sliced_registered_anat_filename in sliced_registered_anat_filenames: out_resample = resample(in_file=sliced_registered_anat_filename, voxel_size=(voxel_size_x, voxel_size_y, voxel_size_z), outputtype='NIFTI_GZ', environ=environ) resampled_registered_anat_filenames.append( out_resample.outputs.out_file) resampled_bias_corrected_filenames = [] for sliced_bias_corrected_filename in sliced_bias_corrected_filenames: out_resample = resample(in_file=sliced_bias_corrected_filename, voxel_size=(voxel_size_x, voxel_size_y, voxel_size_z), outputtype='NIFTI_GZ', environ=environ) resampled_bias_corrected_filenames.append( out_resample.outputs.out_file) # single slice non-linear functional to anatomical registration warped_slices = [] warp_filenames = [] for (resampled_bias_corrected_filename, resampled_registered_anat_filename) in zip( resampled_bias_corrected_filenames, resampled_registered_anat_filenames): warped_slice = fname_presuffix(resampled_bias_corrected_filename, suffix='_qw') out_qwarp = qwarp( in_file=resampled_bias_corrected_filename, base_file=resampled_registered_anat_filename, iwarp=True, # XXX: is this necessary noneg=True, blur=[0], nmi=True, noXdis=True, allineate=True, allineate_opts='-parfix 1 0 -parfix 2 0 -parfix 3 0 ' '-parfix 4 0 -parfix 5 0 -parfix 6 0 ' '-parfix 7 0 -parfix 9 0 ' '-parfix 10 0 -parfix 12 0', out_file=warped_slice, environ=environ) warped_slices.append(out_qwarp.outputs.warped_source) warp_filenames.append(out_qwarp.outputs.source_warp) output_files.append(out_qwarp.outputs.base_warp) # There are files geenrated by the allineate option output_files.extend([ fname_presuffix(out_qwarp.outputs.warped_source, suffix='_Allin'), fname_presuffix(out_qwarp.outputs.warped_source, suffix='_Allin.nii', use_ext=False), fname_presuffix(out_qwarp.outputs.warped_source, suffix='_Allin.aff12.1D', use_ext=False) ]) # Resample the mean volume back to the initial resolution, voxel_size = nibabel.load(unbiased_func_filename).header.get_zooms() resampled_warped_slices = [] for warped_slice in warped_slices: out_resample = resample(in_file=warped_slice, voxel_size=voxel_size, outputtype='NIFTI_GZ', environ=environ) resampled_warped_slices.append(out_resample.outputs.out_file) # fix the obliquity resampled_warped_slices_oblique = [] for (sliced_registered_anat_filename, resampled_warped_slice) in zip(sliced_registered_anat_filenames, resampled_warped_slices): oblique_slice = fix_obliquity(resampled_warped_slice, sliced_registered_anat_filename, verbose=verbose) resampled_warped_slices_oblique.append(oblique_slice) # slice functional sliced_func_filenames = [] for slice_n in range(n_slices): out_slicer = slicer(in_file=allineated_filename, keep='{0} {0}'.format(slice_n), out_file=fname_presuffix(allineated_filename, suffix='Sl%d' % slice_n), environ=environ) oblique_slice = fix_obliquity(out_slicer.outputs.out_file, allineated_filename, verbose=verbose) sliced_func_filenames.append(oblique_slice) # Apply the precomputed warp slice by slice warped_func_slices = [] for (sliced_func_filename, warp_filename) in zip(sliced_func_filenames, warp_filenames): out_warp_apply = warp_apply(in_file=sliced_func_filename, master=sliced_func_filename, warp=warp_filename, out_file=fname_presuffix( sliced_func_filename, suffix='_qw'), environ=environ) warped_func_slices.append(out_warp_apply.outputs.out_file) # Finally, merge all slices ! out_merge_func = merge(in_files=warped_func_slices, outputtype='NIFTI_GZ', environ=environ) # Fix the obliquity merged_oblique = fix_obliquity(out_merge_func.outputs.out_file, allineated_filename, verbose=verbose) # Update the fmri data setattr(session_data, "coreg_func_", merged_oblique) setattr(session_data, "coreg_anat_", registered_anat_oblique_filename) setattr(session_data, "coreg_transform_", transform_filename) os.chdir(current_dir) # Collect the outputs output_files.extend(sliced_registered_anat_filenames + sliced_bias_corrected_filenames + resampled_registered_anat_filenames + resampled_bias_corrected_filenames + warped_slices + warp_filenames + resampled_warped_slices_oblique + sliced_func_filenames + warped_func_slices) if not caching: for out_file in output_files: if os.path.isfile(out_file): os.remove(out_file)
def _realign(func_filename, write_dir, caching=False, terminal_output='allatonce', environ=None): if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) clip_level = memory.cache(afni.ClipLevel) threshold = memory.cache(fsl.Threshold) volreg = memory.cache(afni.Volreg) allineate = memory.cache(afni.Allineate) copy = memory.cache(afni.Copy) copy_geom = memory.cache(fsl.CopyGeom) tstat = memory.cache(afni.TStat) for step in [threshold, volreg, allineate, tstat, copy, copy_geom]: step.interface().set_default_terminal_output(terminal_output) else: clip_level = afni.ClipLevel().run threshold = fsl.Threshold(terminal_output=terminal_output).run volreg = afni.Volreg(terminal_output=terminal_output).run allineate = afni.Allineate(terminal_output=terminal_output).run copy = afni.Copy(terminal_output=terminal_output).run copy_geom = fsl.CopyGeom(terminal_output=terminal_output).run tstat = afni.TStat(terminal_output=terminal_output).run out_clip_level = clip_level(in_file=func_filename) out_threshold = threshold(in_file=func_filename, thresh=out_clip_level.outputs.clip_val, out_file=fname_presuffix(func_filename, suffix='_thresholded', newpath=write_dir)) thresholded_filename = out_threshold.outputs.out_file out_volreg = volreg( # XXX dfile not saved in_file=thresholded_filename, out_file=fname_presuffix(thresholded_filename, suffix='_volreg', newpath=write_dir), environ=environ, oned_file=fname_presuffix(thresholded_filename, suffix='_volreg.1Dfile.1D', use_ext=False, newpath=write_dir), oned_matrix_save=fname_presuffix(thresholded_filename, suffix='_volreg.aff12.1D', use_ext=False, newpath=write_dir)) # Apply the registration to the whole head out_allineate = allineate(in_file=func_filename, master=func_filename, in_matrix=out_volreg.outputs.oned_matrix_save, out_file=fname_presuffix(func_filename, suffix='_volreg', newpath=write_dir), environ=environ) # 3dAllineate removes the obliquity. This is not a good way to readd it as # removes motion correction info in the header if it were an AFNI file...as # it happens it's NIfTI which does not store that so irrelevant! out_copy = copy(in_file=out_allineate.outputs.out_file, out_file=fname_presuffix(out_allineate.outputs.out_file, suffix='_oblique', newpath=write_dir), environ=environ) out_copy_geom = copy_geom(dest_file=out_copy.outputs.out_file, in_file=out_volreg.outputs.out_file) oblique_allineated_filename = out_copy_geom.outputs.out_file # Create a (hopefully) nice mean image for use in the registration out_tstat = tstat(in_file=oblique_allineated_filename, args='-mean', out_file=fname_presuffix(oblique_allineated_filename, suffix='_tstat', newpath=write_dir), environ=environ) # Remove intermediate outputs if not caching: for output_file in [ thresholded_filename, out_volreg.outputs.oned_matrix_save, out_volreg.outputs.out_file, out_volreg.outputs.md1d_file, out_allineate.outputs.out_file ]: os.remove(output_file) return (oblique_allineated_filename, out_tstat.outputs.out_file, out_volreg.outputs.oned_file)
def coregister(unifized_anat_file, unbiased_mean_func_file, write_dir, anat_brain_file=None, func_brain_file=None, slice_timing=True, t_r=None, prior_rigid_body_registration=None, reorient_only=False, voxel_size_x=.1, voxel_size_y=.1, caching=False, verbose=True, **environ_kwargs): """ Coregistration of the subject's functional and anatomical images. The functional volume is aligned to the anatomical, first with a rigid body registration and then on a per-slice basis (only a fine correction, this is mostly for correction of EPI distortion). Parameters ---------- unbiased_mean_func_file : str Path to the slice-time corrected, volume registrated, averaged and bias field corrected functional file prior_rigid_body_registration : bool, optional If True, a rigid-body registration of the anat to the func is performed prior to the warp. Useful if the images headers have missing/wrong information. NOTE: prior_rigid_body_registration is deprecated from 0.1 and will be removed in next release. Use `reorient_only` instead. reorient_only : bool, optional If True, the rigid-body registration of the anat to the func is not performed and only reorientation is done. voxel_size_x : float, optional Resampling resolution for the x-axis, in mm. voxel_size_y : float, optional Resampling resolution for the y-axis, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. environ_kwargs : extra arguments keywords Extra arguments keywords, passed to interfaces environ variable. Returns ------- The following attributes are added - `coreg_func_` : str Path to paths to the coregistered functional image. - `coreg_anat_` : str Path to paths to the coregistered functional image. - `coreg_transform_` : str Path to the transform from anat to func. Notes ----- If `use_rats_tool` is turned on, RATS tool is used for brain extraction and has to be cited. For more information, see `RATS <http://www.iibi.uiowa.edu/content/rats-overview/>`_ """ if prior_rigid_body_registration is not None: warn_str = ("The parameter 'prior_rigid_body_registration' is " "deprecated and will be removed in sammba-mri next " "release. Use parameter 'reorient_only' instead.") warnings.warn(warn_str, VisibleDeprecationWarning, stacklevel=2) reorient_only = not (prior_rigid_body_registration) environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if caching: memory = Memory(write_dir) catmatvec = memory.cache(afni.CatMatvec) else: catmatvec = afni.CatMatvec().run for (key, value) in environ_kwargs.items(): environ[key] = value output_files = [] ############################################# # Rigid-body registration anat -> mean func # ############################################# if reorient_only: allineated_anat_file = unifized_anat_file else: if anat_brain_file is None: raise ValueError("'anat_brain_mask_file' is needed for " "rigid-body registration") if func_brain_file is None: raise ValueError("'func_brain_mask_file' is needed for " "rigid-body registration") allineated_anat_file, rigid_transform_file = \ _rigid_body_register(unifized_anat_file, unbiased_mean_func_file, anat_brain_file, func_brain_file, write_dir=write_dir, caching=caching, terminal_output=terminal_output, environ=environ) output_files.extend([rigid_transform_file, allineated_anat_file]) ############################################ # Nonlinear registration anat -> mean func # ############################################ registered_anat_oblique_file, mat_file =\ _warp(allineated_anat_file, unbiased_mean_func_file, write_dir, caching=caching, verbose=verbose, terminal_output=terminal_output, environ=environ) output_files.append(mat_file) transform_file = fname_presuffix(registered_anat_oblique_file, suffix='_func_to_anat.aff12.1D', use_ext=False) if reorient_only: _ = catmatvec(in_file=[(mat_file, 'ONELINE')], oneline=True, out_file=transform_file, environ=environ) else: _ = catmatvec(in_file=[(rigid_transform_file, 'ONELINE'), (mat_file, 'ONELINE')], oneline=True, out_file=transform_file, environ=environ) ################################################## # Per-slice non-linear registration func -> anat # ################################################## warped_mean_func_file, warp_files, _ =\ _per_slice_qwarp(unbiased_mean_func_file, registered_anat_oblique_file, voxel_size_x, voxel_size_y, write_dir=write_dir, verbose=verbose, caching=caching, terminal_output=terminal_output, environ=environ) # Update the outputs if not caching: for out_file in output_files: os.remove(out_file) return Bunch(coreg_func_=warped_mean_func_file, coreg_anat_=registered_anat_oblique_file, coreg_transform_=transform_file, coreg_warps_=warp_files)
================ Rescaling demo ================ This example compares a volume before and after T1 correction. """ # Load functional ASL image of KIRBY dataset first subject import os from procasl import datasets kirby = datasets.fetch_kirby(subjects=[4]) raw_asl_file = kirby.asl[0] # Create a memory context from nipype.caching import Memory cache_directory = '/tmp' mem = Memory('/tmp') os.chdir(cache_directory) # Rescale from procasl import preprocessing rescale = mem.cache(preprocessing.Rescale) out_rescale = rescale(in_file=raw_asl_file, ss_tr=35.4, t_i_1=800., t_i_2=1800.) # Plot the first volume before and after rescaling from nilearn import plotting import matplotlib.pylab as plt for filename, title in zip([raw_asl_file, out_rescale.outputs.rescaled_file], ['raw', 'rescaled']): figure = plt.figure(figsize=(5, 4))
def _apply_transforms(to_register_filename, target_filename, write_dir, transforms, transformed_filename=None, transforms_kind='nonlinear', interpolation=None, voxel_size=None, inverse=False, caching=False, verbose=True): """ Applies successive transforms to a given image to put it in template space. Parameters ---------- to_register_filename : str Path to the source file to register. target_filename : str Reference file to register to. transforms : list List of transforms in order of 3dNWarpApply application: first must one must be in the target space and last one must be in the source space. transformed_filename : str, optional Path to the output registered file inverse : bool, optional If True, after the transforms composition is computed, invert it. If the input transforms would take a dataset from space A to B, then the inverted transform will do the reverse. interpolation : one of {'nearestneighbour', 'linear', 'cubic', 'quintic', 'wsinc5'} or None, optional Interpolation type. If None, AFNI defaults are used. voxel_size : 3-tuple of floats, optional Voxel size of the registered functional, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. """ environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if caching: memory = Memory(write_dir) catmatvec = memory.cache(afni.CatMatvec) allineate = memory.cache(afni.Allineate) warp_apply = memory.cache(afni.NwarpApply) resample = memory.cache(afni.Resample) for step in [resample, allineate, warp_apply]: step.interface().set_default_terminal_output(terminal_output) else: resample = afni.Resample(terminal_output=terminal_output).run catmatvec = afni.CatMatvec().run allineate = afni.Allineate(terminal_output=terminal_output).run warp_apply = afni.NwarpApply(terminal_output=terminal_output).run if transformed_filename is None: target_basename = os.path.basename(target_filename) target_basename = os.path.splitext(target_basename)[0] target_basename = os.path.splitext(target_basename)[0] transformed_filename = fname_presuffix(to_register_filename, suffix='_to_' + target_basename, newpath=write_dir) if voxel_size is None: resampled_target_filename = target_filename else: out_resample = resample(in_file=target_filename, voxel_size=voxel_size, out_file=fname_presuffix(target_filename, suffix='_resampled', newpath=write_dir), environ=environ) resampled_target_filename = out_resample.outputs.out_file if transforms_kind is not 'nonlinear': affine_transform_filename = fname_presuffix(transformed_filename, suffix='.aff12.1D', use_ext=False) out_catmatvec = catmatvec(in_file=[(transform, 'ONELINE') for transform in transforms], oneline=True, out_file=affine_transform_filename, environ=environ) if inverse: affine_transform_filename = fname_presuffix(transformed_filename, suffix='_INV.aff12.1D', use_ext=False) _ = catmatvec(in_file=[(out_catmatvec.outputs.out_file, 'I')], oneline=True, out_file=affine_transform_filename, environ=environ) if interpolation is None: _ = allineate(in_file=to_register_filename, master=resampled_target_filename, in_matrix=affine_transform_filename, out_file=transformed_filename, environ=environ) else: _ = allineate(in_file=to_register_filename, master=resampled_target_filename, in_matrix=affine_transform_filename, final_interpolation=interpolation, out_file=transformed_filename, environ=environ) else: warp = "'" warp += " ".join(transforms) warp += "'" if interpolation is None: _ = warp_apply(in_file=to_register_filename, master=resampled_target_filename, warp=warp, inv_warp=inverse, out_file=transformed_filename, environ=environ) else: _ = warp_apply(in_file=to_register_filename, master=resampled_target_filename, warp=warp, inv_warp=inverse, interp=interpolation, out_file=transformed_filename, environ=environ) # XXX obliquity information is lost if resampling is done transformed_filename = fix_obliquity(transformed_filename, resampled_target_filename, verbose=verbose, caching=caching, caching_dir=write_dir, environ=environ) return transformed_filename
def _transform_to_template(to_register_filename, template_filename, write_dir, func_to_anat_oned_filename, anat_to_template_oned_filename, anat_to_template_warp_filename, voxel_size=None, caching=False, verbose=True): """ Applies successive transforms to a given image to put it in template space. Parameters ---------- to_register_filename : str Path to functional volume, coregistered to a common space with the anatomical volume. template_filename : str Template to register the functional to. func_to_anat_oned_filename : str Coregistration transform. anat_to_template_oned_filename : str Path to the affine 1D transform from anatomical to template space. anat_to_template_warp_filename : str Path to the warp transform from anatomical to template space. voxel_size : 3-tuple of floats, optional Voxel size of the registered functional, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. """ environ = {} if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if caching: memory = Memory(write_dir) warp_apply = memory.cache(afni.NwarpApply) resample = memory.cache(afni.Resample) warp_apply.interface().set_default_terminal_output(terminal_output) resample.interface().set_default_terminal_output(terminal_output) else: resample = afni.Resample(terminal_output=terminal_output).run warp_apply = afni.NwarpApply(terminal_output=terminal_output).run environ['AFNI_DECONFLICT'] = 'OVERWRITE' current_dir = os.getcwd() os.chdir(write_dir) normalized_filename = fname_presuffix(to_register_filename, suffix='_normalized') if voxel_size is None: resampled_template_filename = template_filename else: out_resample = resample(in_file=template_filename, voxel_size=voxel_size, outputtype='NIFTI_GZ') resampled_template_filename = out_resample.outputs.out_file transforms = [ anat_to_template_warp_filename, anat_to_template_oned_filename, func_to_anat_oned_filename ] warp = "'" warp += " ".join(transforms) warp += "'" _ = warp_apply(in_file=to_register_filename, master=resampled_template_filename, warp=warp, out_file=normalized_filename) os.chdir(current_dir) return normalized_filename
### Convert RAW DICOM data to NIFTI Image Data set import os, sys from os.path import join as oj from glob import glob import nipype.pipeline.engine as pe import nipype.interfaces.utility as util import nipype.interfaces.io as nio from nipype.interfaces.dcm2nii import Dcm2nii from nipype.caching import Memory ## This is the location of the Raw DICOM Files from BITC StoutRawData = '/home/ehecht/BIGDATA/Stout_Homo_Faber/RAWDATA/' NiPypeOutputDir ='/EINSTEIN_BIGDATA/NIPYPE_WD/Stout_Haber/' mem = Memory(base_dir=NiPypeOutputDir) ## Create a memory cache I can use going forward dcmConverter = mem.cache(Dcm2nii) DicomScanSet = { 'T1': { 'dcmDir' : '*t1*', 'outputDirName': 'T1'}, 'diff5B0_PA': { 'dcmDir': 'cmrr_mbep2_diff_*5B0_PA*', 'outputDirName':'DTI/preprocess/diff5B0_PA'}, 'diffAP': { 'dcmDir': 'cmrr_mbep2d_diff_AP_[1-9]*', 'outputDirName': 'DTI/preprocess/AP'}, 'AP_ADC': { 'dcmDir': 'cmrr_mbep2d_diff_AP_ADC_[1-9]*', 'outputDirName': 'DTI/preprocess/AP_ADC'}, 'AP_FA': { 'dcmDir': 'cmrr_mbep2d_diff_AP_FA_[1-9]*', 'outputDirName': 'DTI/preprocess/AP_FA'}, 'AP_TRACEW': { 'dcmDir': 'cmrr_mbep2d_diff_AP_TRACEW_[1-9]*', 'outputDirName': 'DTI/preprocess/AP_TRACEW'}, } #QFE *t1* for *t1*mprage*??? # # convert dicoms # $statement = " dcm2nii -o $WORKINGDATAPATH/" . $subj[$i] . "/T1/ "; # $statement .= " $RAWDATAPATH/" . $subjID[$i] . "/t1*/ ";
elif hc_or_pd == 'pd': sub_workflow_dir = os.path.join(workflow_dir, subjects[sb], pd_on_off, "train", "run-" + run_nr, "feedback") bold_filename = os.path.join( datadir, subjects[sb], pd_on_off, "func", subjects[sb] + "_task-train_run-%s_bold.nii.gz" % (run_nr)) events_filename = os.path.join( datadir, subjects[sb], pd_on_off, "func", subjects[sb] + "_task-train_run-%s_events.tsv" % (run_nr)) if not os.path.exists(sub_workflow_dir): os.makedirs(sub_workflow_dir) from nipype.caching import Memory mem = Memory(base_dir=sub_workflow_dir) events = pd.read_csv(events_filename, sep="\t") confounds = pd.read_csv(os.path.join( fmriprep_dir, "fmriprep", subjects[sb], "func", subjects[sb] + "_task-train_run-%s_bold_confounds.tsv" % (run_nr)), sep="\t", na_values="n/a") # Note: onsets from events files are already with first 2 TRs removed (= 4.3 secs) # Get design matrix info trials, feedback_onset_per_trial, feedback_duration_per_trial = [ [] for i in range(3) ]
#!/home/groups/russpold/software/miniconda/envs/fmri/bin/python from argparse import ArgumentParser import glob import nibabel as nib from nilearn.image import concat_imgs, smooth_img, mean_img, math_img, resample_to_img from nipype.interfaces import fsl from nipype.caching import Memory mem = Memory(base_dir='.') import numpy as np import os import pandas as pd import pickle import re import sys sys.path.append(os.path.join(os.environ['SERVER_SCRIPTS'], 'nistats/level_3')) from save_randomise import save_randomise randomise = mem.cache(fsl.Randomise) #Usage: python level_3.py -m MNUM -r REG parser = ArgumentParser() parser.add_argument("-m", "--mnum", help="model number") parser.add_argument("-r", "--reg", help="regressor name") parser.add_argument("-tf", "--tfce", help="tfce", action='store_true') parser.add_argument("-c", "--c_thresh", help="cluster_threshold", default=3) parser.add_argument("-np", "--num_perm", help="number of permutations", default=1000) parser.add_argument("-vs", "--var_smooth", help="variance smoothing", default=5) parser.add_argument("-s", "--sign", help="calculate p values for positive t's") args = parser.parse_args() mnum = args.mnum reg = args.reg
out.runtime.cwd """ from nipype.interfaces import fsl fsl.FSLCommand.set_default_output_type('NIFTI') from nipype.caching import Memory import glob # First retrieve the list of files that we want to work upon in_files = glob.glob('data/*/f3.nii') # Create a memory context mem = Memory('.') # Apply an arbitrary (and pointless, here) threshold to the files) threshold = [ mem.cache(fsl.Threshold)(in_file=f, thresh=i) for i, f in enumerate(in_files) ] # Merge all these files along the time dimension out_merge = mem.cache(fsl.Merge)( dimension="t", in_files=[t.outputs.out_file for t in threshold], ) # And finally compute the mean out_mean = mem.cache(fsl.MeanImage)(in_file=out_merge.outputs.merged_file)
def check_input(self, gui=True): print '**** Check Inputs ****' diffusion_available = False bvecs_available = False bvals_available = False t1_available = False t2_available = False valid_inputs = False dwi_file = os.path.join(self.subject_directory, 'dwi', self.subject + '_dwi.nii.gz') bval_file = os.path.join(self.subject_directory, 'dwi', self.subject + '_dwi.bval') bvec_file = os.path.join(self.subject_directory, 'dwi', self.subject + '_dwi.bvec') T1_file = os.path.join(self.subject_directory, 'anat', self.subject + '_T1w.nii.gz') T2_file = os.path.join(self.subject_directory, 'anat', self.subject + '_T2w.nii.gz') print "Looking for...." print "dwi_file : %s" % dwi_file print "bvecs_file : %s" % bvec_file print "bvals_file : %s" % bval_file print "T1_file : %s" % T1_file print "T2_file : %s" % T2_file try: layout = BIDSLayout(self.base_directory) print "Valid BIDS dataset with %s subjects" % len( layout.get_subjects()) for subj in layout.get_subjects(): self.global_conf.subjects.append('sub-' + str(subj)) # self.global_conf.subjects = ['sub-'+str(subj) for subj in layout.get_subjects()] self.global_conf.modalities = [ str(mod) for mod in layout.get_modalities() ] # mods = layout.get_modalities() types = layout.get_types() # print "Available modalities :" # for mod in mods: # print "-%s" % mod for typ in types: if typ == 'dwi' and os.path.isfile(dwi_file): print "%s available" % typ diffusion_available = True if typ == 'T1w' and os.path.isfile(T1_file): print "%s available" % typ t1_available = True if typ == 'T2w' and os.path.isfile(T2_file): print "%s available" % typ t2_available = True except: error( message= "Invalid BIDS dataset. Please see documentation for more details.", title="Error", buttons=['OK', 'Cancel'], parent=None) if os.path.isfile(bval_file): bvals_available = True if os.path.isfile(bvec_file): bvecs_available = True mem = Memory(base_dir=os.path.join(self.derivatives_directory, 'cmp', self.subject, 'tmp', 'nipype')) swap_and_reorient = mem.cache(SwapAndReorient) if diffusion_available: if bvals_available and bvecs_available: self.stages[ 'Diffusion'].config.diffusion_imaging_model_choices = self.diffusion_imaging_model #Copy diffusion data to derivatives / cmp / subject / dwi out_dwi_file = os.path.join(self.derivatives_directory, 'cmp', self.subject, 'dwi', self.subject + '_dwi.nii.gz') out_bval_file = os.path.join(self.derivatives_directory, 'cmp', self.subject, 'dwi', self.subject + '_dwi.bval') out_bvec_file = os.path.join(self.derivatives_directory, 'cmp', self.subject, 'dwi', self.subject + '_dwi.bvec') shutil.copy(src=dwi_file, dst=out_dwi_file) shutil.copy(src=bvec_file, dst=out_bvec_file) shutil.copy(src=bval_file, dst=out_bval_file) if t2_available: print "Swap and reorient T2" swap_and_reorient( src_file=os.path.join(self.subject_directory, 'anat', self.subject + '_T2w.nii.gz'), ref_file=os.path.join(self.subject_directory, 'dwi', self.subject + '_dwi.nii.gz'), out_file=os.path.join(self.derivatives_directory, 'cmp', self.subject, 'anat', self.subject + '_T2w.nii.gz')) if t1_available: swap_and_reorient( src_file=os.path.join(self.subject_directory, 'anat', self.subject + '_T1w.nii.gz'), ref_file=os.path.join(self.subject_directory, 'dwi', self.subject + '_dwi.nii.gz'), out_file=os.path.join(self.derivatives_directory, 'cmp', self.subject, 'anat', self.subject + '_T1w.nii.gz')) valid_inputs = True input_message = 'Inputs check finished successfully.\nDiffusion and morphological data available.' else: input_message = 'Error during inputs check.\nMorphological data (T1) not available.' else: input_message = 'Error during inputs check.\nDiffusion bvec or bval files not available.' elif t1_available: input_message = 'Error during inputs check. \nDiffusion data not available (DSI/DTI/HARDI).' else: input_message = 'Error during inputs check. No diffusion or morphological data available in folder ' + os.path.join( self.base_directory, 'RAWDATA') + '!' #diffusion_imaging_model = diffusion_imaging_model[0] if gui: #input_notification = Check_Input_Notification(message=input_message, diffusion_imaging_model_options=diffusion_imaging_model,diffusion_imaging_model=diffusion_imaging_model) #input_notification.configure_traits() print input_message self.global_conf.diffusion_imaging_model = self.diffusion_imaging_model diffusion_file = os.path.join(self.subject_directory, 'dwi', self.subject + '_dwi.nii.gz') n_vol = nib.load(diffusion_file).shape[3] if self.stages['Preprocessing'].config.end_vol == 0 or self.stages[ 'Preprocessing'].config.end_vol == self.stages[ 'Preprocessing'].config.max_vol or self.stages[ 'Preprocessing'].config.end_vol >= n_vol - 1: self.stages['Preprocessing'].config.end_vol = n_vol - 1 self.stages['Preprocessing'].config.max_vol = n_vol - 1 self.stages[ 'Registration'].config.diffusion_imaging_model = self.diffusion_imaging_model self.stages[ 'Diffusion'].config.diffusion_imaging_model = self.diffusion_imaging_model else: print input_message self.global_conf.diffusion_imaging_model = self.diffusion_imaging_model diffusion_file = os.path.join(self.subject_directory, 'dwi', self.subject + '_dwi.nii.gz') n_vol = nib.load(diffusion_file).shape[3] if self.stages['Preprocessing'].config.end_vol == 0 or self.stages[ 'Preprocessing'].config.end_vol == self.stages[ 'Preprocessing'].config.max_vol or self.stages[ 'Preprocessing'].config.end_vol >= n_vol - 1: self.stages['Preprocessing'].config.end_vol = n_vol - 1 self.stages['Preprocessing'].config.max_vol = n_vol - 1 self.stages[ 'Registration'].config.diffusion_imaging_model = self.diffusion_imaging_model self.stages[ 'Diffusion'].config.diffusion_imaging_model = self.diffusion_imaging_model if t2_available: self.stages['Registration'].config.registration_mode_trait = [ 'Linear + Non-linear (FSL)' ] #,'BBregister (FS)','Nonlinear (FSL)'] if (t1_available and diffusion_available): valid_inputs = True else: print "Missing required inputs." error( message= "Missing required inputs. Please see documentation for more details.", title="Error", buttons=['OK', 'Cancel'], parent=None) for stage in self.stages.values(): if stage.enabled: print stage.name print stage.stage_dir self.fill_stages_outputs() return valid_inputs
}) current_directory = os.getcwd() # Loop over subjects for (func_file, anat_file) in zip(heroes['BOLD EPI'], heroes['anat']): # Create a memory context subject_directory = os.path.relpath(anat_file, subjects_parent_directory) subject_directory = subject_directory.split(os.sep)[0] cache_directory = os.path.join(os.path.expanduser('~/CODE/process-asl'), 'procasl_cache', 'heroes', subject_directory) if not os.path.exists(cache_directory): os.mkdir(cache_directory) os.chdir(cache_directory) # nipype saves .m scripts in current directory mem = Memory(cache_directory) # Realign EPIs realign = mem.cache(spm.Realign) out_realign = realign(in_files=func_file, register_to_mean=True) # Coregister anat to mean EPIs coregister = mem.cache(spm.Coregister) out_coregister = coregister(target=out_realign.outputs.mean_image, source=anat_file, write_interp=3, jobtype='estimate') # Segment anat segment = mem.cache(spm.Segment) out_segment = segment(data=anat_file,
def from_native_to_mni(img, sub_id, include_trans=[True, True, True], interpolation='Linear'): '''Maps image from native space to mni. WARNING THERE IS A CLEAR PROBLEM IN THE UNDERSTANDING OF TRANSFORM ORDER WHEN ONLY USING THE LAST TWO TRANSFORMS THE ORDER SHOULD BE INVERTED We assume that the transformation files already exist for the mappings between: 1) mean bold and anatomy 2) anatomy and oasis template 3) oasis template and mni template The transforms to include are: 1) From bold to anat 2) From anat to oasis 3) From oasis to mni The include transforms should be sequential to have meaninful output, which means that transformations sequence [True, False, True] is invalid. ''' check = (include_trans == [True, False, True]) if check: raise Exception('Invalid transformation sequence') pipeline_dir = 'pipelines/transformations' if not os.path.exists(pipeline_dir): os.makedirs(pipeline_dir) mem = Memory(pipeline_dir) transform = mem.cache(ApplyTransforms) anat = os.path.join('pipelines', 'preprocessing', 'sub{0}'.format(sub_id), 'highres001.nii') oasis_template = os.path.join('pipelines', 'OASIS-30_Atropos_template', 'T_template0.nii.gz') mni_template = os.path.join('pipelines', 'mni_icbm152_nlin_asym_09a_nifti', 'mni_icbm152_nlin_asym_09a', 'mni_icbm152_t1_tal_nlin_asym_09a.nii') bold_to_anat = os.path.join('pipelines', 'preprocessing', 'sub{0}'.format(sub_id), 'bold_to_anat.txt') anat_to_oasis = os.path.join('pipelines', 'preprocessing', 'sub{0}'.format(sub_id), 'anat_to_oasis.h5') oasis_to_mni = os.path.join('pipelines', 'preprocessing', 'registered_templates', 'oasis_to_mni.h5') all_references = [anat, oasis_template, mni_template] all_trans = [bold_to_anat, anat_to_oasis, oasis_to_mni] all_inv_trans = [False, False, False] transforms = [] inv_trans_flags = [] reference = None for idx, flag in enumerate(include_trans): if flag: transforms.append(all_trans[idx]) inv_trans_flags.append(all_inv_trans[idx]) # Use latest transformation as reference reference = all_references[idx] trans = transform(args='--float', input_image_type=3, interpolation=interpolation, invert_transform_flags=inv_trans_flags[::-1], num_threads=n_proc, reference_image=reference, terminal_output='file', transforms=transforms[::-1], input_image=img) return trans.outputs.output_image
randomize.inputs.tfce = True randomize.inputs.vox_p_values = True randomize.inputs.num_perm = 200 #randomize.inputs.var_smooth = 5 randomize.run() #%% Graph it fig = nilearn.plotting.plot_stat_map('/media/Data/work/KPE_SPM/fslRandomize/randomize/randomise_tstat1.nii.gz', alpha=0.7 , cut_coords=(0, 45, -7)) fig.add_contours('/media/Data/work/custom_modelling_spm/randomize/randomise_tfce_corrp_tstat1.nii.gz', levels=[0.99], colors='w') #%% opposite image run fig = nilearn.plotting.plot_stat_map('/media/Data/work/custom_modelling_spm/neg/randomize/randomise_tstat1.nii.gz', alpha=0.7 , cut_coords=(0, 45, -7)) fig.add_contours('/media/Data/work/custom_modelling_spm/neg/randomize/randomise_tfce_corrp_tstat1.nii.gz', levels=[0.95], colors='w') #%% from nipype.caching import Memory datadir = "/media/Data/work/" mem = Memory(base_dir='/media/Data/work/custom_modelling_spm') randomise = mem.cache(fsl.Randomise) randomise_results = randomise(in_file=os.path.join(datadir, "custom_modelling_spm", "GainvsAmb_cope.nii.gz"), mask=os.path.join(datadir, "custom_modelling_spm", "group_mask.nii.gz"), one_sample_group_mean=True, tfce=True, vox_p_values=True, num_perm=500) randomise_results.outputs #%% Look at results fig = nilearn.plotting.plot_stat_map(randomise_results.outputs.tstat_files[0], alpha=0.7)# , cut_coords=(-20, -80, 18)) fig.add_contours(randomise_results.outputs.t_corrected_p_files[0], levels=[0.95], colors='w') #%% F contrasts
def from_mni_to_native(img, sub_id, include_trans=[True, True, True], interpolation='Linear'): '''Maps image from native space to mni. We assume that the transformation files already exist for the mappings between: 1) mean bold and anatomy 2) anatomy and oasis template 3) oasis template and mni template The transforms to include are: 1) From mni to oasis 2) From oasis to anat 3) From anat to bold The include transforms should be sequential to have meaninful output, which means that transformations sequence [True, False, True] is invalid. ''' check = (include_trans == [True, False, True]) if check: raise Exception('Invalid transformation sequence') pipeline_dir = 'pipelines/transformations' if not os.path.exists(pipeline_dir): os.makedirs(pipeline_dir) mem = Memory(pipeline_dir) transform = mem.cache(ApplyTransforms) oasis_template = os.path.join('pipelines', 'OASIS-30_Atropos_template', 'T_template0.nii.gz') anat = os.path.join('pipelines', 'preprocessing', 'sub{0}'.format(sub_id), 'highres001.nii') mean_bold = os.path.join('pipelines', 'preprocessing', 'sub{0}'.format(sub_id), 'mean_bold.nii') mni_to_oasis = os.path.join('pipelines', 'preprocessing', 'registered_templates', 'mni_to_oasis.h5') oasis_to_anat = os.path.join('pipelines', 'preprocessing', 'sub{0}'.format(sub_id), 'oasis_to_anat.h5') bold_to_anat = os.path.join('pipelines', 'preprocessing', 'sub{0}'.format(sub_id), 'bold_to_anat.txt') all_references = [oasis_template, anat, mean_bold] all_trans = [mni_to_oasis, oasis_to_anat, bold_to_anat] all_inv_trans = [False, False, True] transforms = [] inv_trans_flags = [] reference = None for idx, flag in enumerate(include_trans): if flag: transforms.append(all_trans[idx]) inv_trans_flags.append(all_inv_trans[idx]) # Use latest transformation as reference reference = all_references[idx] trans = transform(args='--float', input_image_type=3, interpolation=interpolation, invert_transform_flags=inv_trans_flags[::-1], num_threads=n_proc, reference_image=reference, terminal_output='file', transforms=transforms[::-1], input_image=img) return trans.outputs.output_image