write_output=True) _ = expand_coordinate_mapping(os.path.join(path_output, "target2source.nii.gz"), path_output, name_output="target2source", write_output=True) """ apply deformation """ # source -> target apply_coordinate_mappings( file_mean_epi_source, # input os.path.join(path_output, "source2target.nii.gz"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="source2target_example" # base name with file extension for output ) # target -> source apply_coordinate_mappings( file_mean_epi_target, # input os.path.join(path_output, "target2source.nii.gz"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="target2source_example" # base name with file extension for output
if not os.path.exists(path_output): os.makedirs(path_output) if not os.path.exists(path_levelset): os.makedirs(path_levelset) if not os.path.exists(path_border): os.makedirs(path_border) # deformation if file_deformation is not None: wm_label = apply_coordinate_mappings( file_wm, # input file_deformation, # cmap interpolation="nearest", # nearest or linear padding="zero", # closest, zero or max save_data=False, # save output data to file (boolean) overwrite=False, # overwrite existing results (boolean) output_dir=None, # output directory file_name=None # base name with file extension for output ) csf_label = apply_coordinate_mappings( file_csf, # input file_deformation, # cmap interpolation="nearest", # nearest or linear padding="zero", # closest, zero or max save_data=False, # save output data to file (boolean) overwrite=False, # overwrite existing results (boolean) output_dir=None, # output directory file_name=None # base name with file extension for output )
""" do not edit below """ # output folders path_def = os.path.join(path_output,"def") path_surf = os.path.join(path_output,"surf") for i in range(len(file_in)): # apply deformation if deformation_in1 is not None: apply_coordinate_mappings(file_in[i], deformation_in1, deformation_in2, interpolation=interpolation, padding='closest', save_data=True, overwrite=True, output_dir=path_def, file_name=None, ) # get filename of deformed file if deformation_in1 is not None: _, name_file, _ = get_filename(file_in[i]) filename_def = os.path.join(path_def, name_file+"_def-img.nii") else: filename_def = file_in[i] # map to ana for j in range(len(surf_in)):
def get_flash2orig(file_flash, file_inv2, file_orig, path_output, cleanup=False): """ This function computes the deformation field for the registration between a partial coverage GRE image and the freesurfer orig file. The following steps are performed: (1) set output folder structure, (2) get scanner transform GRE <-> inv2 and inv2 -> orig, (3) generate flash cmap, (4) apply scanner transform inv2 -> GRE, (5) get flirt registration GRE -> inv2, (6) apply flirt to GRE cmap, (7) apply scanner transform to GRE cmap, (8) apply final deformation to GRE. The function needs the FSL environment set. Inputs: *file_flash: input path for GRE image. *file_inv2: input path for MP2RAGE INV2 image. *file_orig: input path for freesurfer orig image. *path_output: path where output is saved. *cleanup: delete intermediate files (boolean). created by Daniel Haenelt Date created: 18-04-2019 Last modified: 16-05-2019 """ import os import shutil as sh from nipype.interfaces.fsl import FLIRT from nipype.interfaces.fsl.preprocess import ApplyXFM from nipype.interfaces.freesurfer.preprocess import MRIConvert from nighres.registration import apply_coordinate_mappings from lib.cmap import generate_coordinate_mapping from lib.registration.get_scanner_transform import get_scanner_transform """ set folder structure """ path_temp = os.path.join(path_output, "temp") if not os.path.exists(path_output): os.makedirs(path_output) if not os.path.exists(path_temp): os.makedirs(path_temp) # copy input files sh.copyfile(file_inv2, os.path.join(path_temp, "inv2.nii")) sh.copyfile(file_flash, os.path.join(path_temp, "flash.nii")) """ convert orig to nifti """ mc = MRIConvert() mc.inputs.in_file = file_orig mc.inputs.out_file = os.path.join(path_temp, "orig.nii") mc.inputs.in_type = "mgz" mc.inputs.out_type = "nii" mc.run() """ scanner transformation """ get_scanner_transform(os.path.join(path_temp, "inv2.nii"), os.path.join(path_temp, "flash.nii"), path_temp, False) get_scanner_transform(os.path.join(path_temp, "flash.nii"), os.path.join(path_temp, "inv2.nii"), path_temp, False) get_scanner_transform(os.path.join(path_temp, "inv2.nii"), os.path.join(path_temp, "orig.nii"), path_temp, False) """ generate coordinate mapping """ generate_coordinate_mapping(os.path.join(path_temp, "flash.nii"), 0, path_temp, "flash", False, True) """ scanner transform inv2 to flash """ apply_coordinate_mappings( os.path.join(path_temp, "inv2.nii"), # input os.path.join(path_temp, "inv2_2_flash_scanner.nii"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_temp, # output directory file_name= "inv2_apply_scanner" # base name with file extension for output ) """ flirt flash to inv2 """ os.chdir(path_temp) flirt = FLIRT() flirt.inputs.cost_func = "mutualinfo" flirt.inputs.dof = 6 flirt.inputs.interp = "trilinear" # trilinear, nearestneighbour, sinc or spline flirt.inputs.in_file = os.path.join(path_temp, "flash.nii") flirt.inputs.reference = os.path.join(path_temp, "inv2_apply_scanner_def-img.nii.gz") flirt.inputs.output_type = "NIFTI_GZ" flirt.inputs.out_file = os.path.join(path_temp, "flash_apply_flirt_def-img.nii.gz") flirt.inputs.out_matrix_file = os.path.join(path_temp, "flirt_matrix.txt") flirt.run() """ apply flirt to flash cmap """ applyxfm = ApplyXFM() applyxfm.inputs.in_file = os.path.join(path_temp, "cmap_flash.nii") applyxfm.inputs.reference = os.path.join(path_temp, "flash.nii") applyxfm.inputs.in_matrix_file = os.path.join(path_temp, "flirt_matrix.txt") applyxfm.inputs.interp = "trilinear" applyxfm.inputs.padding_size = 0 applyxfm.inputs.output_type = "NIFTI_GZ" applyxfm.inputs.out_file = os.path.join(path_temp, "cmap_apply_flirt_def-img.nii.gz") applyxfm.inputs.apply_xfm = True applyxfm.run() """ apply scanner transform to flash cmap """ apply_coordinate_mappings( os.path.join(path_temp, "cmap_apply_flirt_def-img.nii.gz"), os.path.join(path_temp, "flash_2_inv2_scanner.nii"), # cmap 1 os.path.join(path_temp, "inv2_2_orig_scanner.nii"), # cmap 2 interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_temp, # output directory file_name= "cmap_apply_scanner" # base name with file extension for output ) """ apply deformation to source image """ apply_coordinate_mappings( os.path.join(path_temp, "flash.nii"), # input os.path.join(path_temp, "cmap_apply_scanner_def-img.nii.gz"), interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_temp, # output directory file_name= "flash_apply_deformation" # base name with file extension for output ) # rename final deformation examples os.rename(os.path.join(path_temp, "cmap_apply_scanner_def-img.nii.gz"), os.path.join(path_output, "flash2orig.nii.gz")) os.rename( os.path.join(path_temp, "flash_apply_deformation_def-img.nii.gz"), os.path.join(path_output, "flash2orig_example.nii.gz")) # clean intermediate files if cleanup: sh.rmtree(path_temp, ignore_errors=True)
get_scanner_transform(os.path.join(path_mpm, "mpm_t1.nii"), os.path.join(path_mp2rage, "mp2rage_t1.nii"), path_deformation, False) get_scanner_transform(os.path.join(path_mp2rage, "mp2rage_t1.nii"), os.path.join(path_mpm, "mpm_t1.nii"), path_deformation, False) # apply scanner transformation to MPM apply_coordinate_mappings( os.path.join(path_mpm, "mpm_t1.nii"), # input os.path.join(path_deformation, "mpm_t1_2_mp2rage_t1_scanner.nii"), # first cmap mapping2=None, # second cmap mapping3=None, # third cmap mapping4=None, # fourth cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_mpm, # output directory file_name="scanner" # base name with file extension for output ) # flirt os.chdir(path_deformation) flirt = FLIRT() flirt.inputs.cost_func = "corratio" flirt.inputs.dof = 6 flirt.inputs.interp = "trilinear" # trilinear, nearestneighbour, sinc or spline flirt.inputs.in_file = os.path.join(path_mpm, "scanner_def-img.nii.gz") flirt.inputs.reference = os.path.join(path_mp2rage, "mp2rage_t1.nii")
def mask_epi(file_epi, file_t1, file_mask, niter, sigma, file_reg=""): """ This function masks a mean epi image based on a skullstrip mask of the corresponding anatomy. The mask is transformed to native epi space via an initial transformation or via scanner coordinates. A rigid registration is applied to ensure a match between mask and epi. Finally, holes in the mask are filled, the mask is dilated and a Gaussian filter is applied. The masked epi is saved in the same folder with the prefix p. Inputs: *file_epi: input mean epi image. *file_t1: input of corresponding skullstripped anatomy. *file_mask: input of skullstrip mask of the corresponding anatomy. *niter: number of dilation iterations. *sigma: gaussian smoothing kernel. *file_reg: filename of ana -> epi coordinate mapping. created by Daniel Haenelt Date created: 13-02-2019 Last modified: 10-09-2020 """ import os import numpy as np import nibabel as nb import shutil as sh from scipy.ndimage import binary_fill_holes, gaussian_filter from scipy.ndimage.morphology import binary_dilation from nighres.registration import embedded_antsreg, apply_coordinate_mappings from lib.registration.get_scanner_transform import get_scanner_transform from lib.io.get_filename import get_filename from lib.cmap.expand_coordinate_mapping import expand_coordinate_mapping # get paths and filenames path_t1, name_t1, _ = get_filename(file_t1) path_epi, name_epi, _ = get_filename(file_epi) if file_reg: _, _, ext_reg = get_filename(file_reg) else: ext_reg = '.nii.gz' # filenames file_cmap_reg = os.path.join(path_t1, "cmap_reg" + ext_reg) file_cmap_ants = os.path.join(path_t1, "cmap_ants.nii.gz") file_cmap_def = os.path.join(path_t1, "cmap_def.nii.gz") file_ana_reg = os.path.join(path_t1, "ana_reg.nii.gz") file_ana_def = os.path.join(path_t1, "ana_def.nii.gz") file_mask_def = os.path.join(path_t1, "mask_def.nii.gz") file_mask_def2 = os.path.join(path_t1, "mask_def2.nii.gz") # get initial ana -> epi transformation from existing cmap or header if file_reg: sh.copyfile(file_reg, file_cmap_reg) else: get_scanner_transform(file_t1, file_epi, path_t1, True) os.rename( os.path.join(path_t1, name_t1 + "_2_" + name_epi + "_scanner.nii.gz"), file_cmap_reg) # scanner transform peeled t1 to epi ana_reg = apply_coordinate_mappings( file_t1, # input file_cmap_reg, # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=False, overwrite=False, output_dir=None, file_name=None) nb.save(ana_reg["result"], file_ana_reg) # rigid registration embedded_antsreg( file_ana_reg, # source image file_epi, # target image run_rigid=True, # whether or not to run a rigid registration first rigid_iterations=1000, # number of iterations in the rigid step run_affine=False, # whether or not to run an affine registration first affine_iterations=0, # number of iterations in the affine step run_syn=False, # whether or not to run a SyN registration coarse_iterations=0, # number of iterations at the coarse level medium_iterations=0, # number of iterations at the medium level fine_iterations=0, # number of iterations at the fine level cost_function= "CrossCorrelation", # CrossCorrelation or MutualInformation interpolation= "Linear", # interpolation for registration result (NeareastNeighbor or Linear) convergence= 1e-6, # threshold for convergence (can make algorithm very slow) ignore_affine= True, # ignore the affine matrix information extracted from the image header ignore_header= True, # ignore the orientation information and affine matrix information extracted from the image header save_data=True, # save output data to file overwrite=True, # overwrite existing results output_dir=path_t1, # output directory file_name="syn", # output basename ) # remove unnecessary files os.remove(os.path.join(path_t1, "syn_ants-def0.nii.gz")) os.remove(os.path.join(path_t1, "syn_ants-invmap.nii.gz")) # rename cmap os.rename(os.path.join(path_t1, "syn_ants-map.nii.gz"), file_cmap_ants) # remove outliers and expand cmap = nb.load(file_cmap_ants) arr_cmap = cmap.get_fdata() pts_cmap0 = arr_cmap[0, 0, 0, 0] pts_cmap1 = arr_cmap[0, 0, 0, 1] pts_cmap2 = arr_cmap[0, 0, 0, 2] arr_cmap[arr_cmap == 0] = 0 arr_cmap[arr_cmap == pts_cmap0] = 0 arr_cmap[arr_cmap == pts_cmap1] = 0 arr_cmap[arr_cmap == pts_cmap2] = 0 output = nb.Nifti1Image(arr_cmap, cmap.affine, cmap.header) nb.save(output, file_cmap_ants) expand_coordinate_mapping(cmap_in=file_cmap_ants, path_output=path_t1, name_output="cmap_ants", write_output=True) # apply ants cmap to header transformation cmap_def = apply_coordinate_mappings( file_cmap_reg, # input file_cmap_ants, interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=False, overwrite=False, output_dir=None, file_name=None) nb.save(cmap_def["result"], file_cmap_def) # remove outliers and expand arr_cmap = cmap_def["result"].get_fdata() pts_cmap0 = arr_cmap[0, 0, 0, 0] pts_cmap1 = arr_cmap[0, 0, 0, 1] pts_cmap2 = arr_cmap[0, 0, 0, 2] arr_cmap[arr_cmap == 0] = 0 arr_cmap[arr_cmap == pts_cmap0] = 0 arr_cmap[arr_cmap == pts_cmap1] = 0 arr_cmap[arr_cmap == pts_cmap2] = 0 output = nb.Nifti1Image(arr_cmap, cmap_def["result"].affine, cmap_def["result"].header) nb.save(output, file_cmap_def) expand_coordinate_mapping(cmap_in=file_cmap_def, path_output=path_t1, name_output="cmap_def", write_output=True) # apply final cmap to t1 and mask ana_def = apply_coordinate_mappings( file_t1, # input file_cmap_def, interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=False, overwrite=False, output_dir=None, file_name=None) nb.save(ana_def["result"], file_ana_def) mask_def = apply_coordinate_mappings( file_mask, # input file_cmap_def, interpolation="nearest", # nearest or linear padding="zero", # closest, zero or max save_data=False, overwrite=False, output_dir=None, file_name=None) nb.save(mask_def["result"], file_mask_def) # finalise mask arr_mask = mask_def["result"].get_fdata() arr_mask = binary_fill_holes(arr_mask).astype(int) # fill holes in mask arr_mask = binary_dilation(arr_mask, iterations=niter).astype( np.float) # dilate mask arr_mask = gaussian_filter(arr_mask, sigma=sigma) # apply gaussian filter # write final epi mask out_img = nb.Nifti1Image(arr_mask, mask_def["result"].affine, mask_def["result"].header) nb.save(out_img, file_mask_def2) # multiply epi and binary mask epi_img = nb.load(file_epi) arr_epi = epi_img.get_fdata() arr_epi *= arr_mask # multiply epi and mask # write masked epi out_img = nb.Nifti1Image(arr_epi, epi_img.affine, epi_img.header) nb.save(out_img, os.path.join(path_epi, "p" + name_epi + ".nii"))
ignore_header= False, # ignore the orientation information and affine matrix information extracted from the image header save_data=True, # save output data to file overwrite=True, # overwrite existing results output_dir=path_syn, # output directory file_name="syn", # output basename ) """ merge deformations """ # ana -> epi apply_coordinate_mappings( file_ana2epi, # input os.path.join(path_syn, "syn_ants-map.nii.gz"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="ana2epi" # base name with file extension for output ) # epi -> ana apply_coordinate_mappings( os.path.join(path_syn, "syn_ants-invmap.nii.gz"), # input file_epi2ana, # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="epi2ana" # base name with file extension for output
def apply_registration(file_in, cmap_in, file_out, interpolation="linear", r=[0.4, 0.4, 0.4]): """ This function applies a coordinate mapping to a volume. Optionally, the voxel size of the output volume can be changed. This is achieved by adjusting the coordinate mapping to the new voxel size before application. Inputs: *file_in: filename of input volume. *cmap_in: filename of coordinate mapping. *file_out: filename of output volume. *interpolation: interpolation type (linear or nearest). *r: destination voxel size after upsampling (performed if not None). Outputs: *nibabel object instance of transformed input. created by Daniel Haenelt Date created: 30-05-2020 Last modified: 02-06-2020 """ import os import numpy as np import nibabel as nb from nighres.registration import apply_coordinate_mappings from lib.io.get_filename import get_filename from lib.utils.upsample_volume import upsample_volume # make output folder path_output = os.path.dirname(file_out) if not os.path.exists(path_output): os.makedirs(path_output) # filename for temporary cmap copy _, _, ext_cmap = get_filename(cmap_in) tmp = np.random.randint(0, 10, 5) tmp_string = ''.join(str(i) for i in tmp) file_tmp = os.path.join(path_output, "tmp_" + tmp_string + ext_cmap) file_tmp2 = os.path.join(path_output, "tmp2_" + tmp_string + ext_cmap) # adjust coordinate mapping if r: # upsample cmap upsample_volume(cmap_in, file_tmp, dxyz=r, rmode="Linear") upsample_volume(cmap_in, file_tmp2, dxyz=r, rmode="NN") # mask upsampled cmap cmap = nb.load(file_tmp) mask = nb.load(file_tmp2) cmap_array = cmap.get_fdata() mask_array = mask.get_fdata() mask_array = np.sum(mask_array, axis=3) mask_array[mask_array != 0] = 1 cmap_array[:, :, :, 0][mask_array == 0] = 0 cmap_array[:, :, :, 1][mask_array == 0] = 0 cmap_array[:, :, :, 2][mask_array == 0] = 0 cmap = nb.Nifti1Image(cmap_array, cmap.affine, cmap.header) else: cmap = nb.load(cmap_in) # apply coordinate mapping res = apply_coordinate_mappings( image=file_in, # input mapping1=cmap, # cmap interpolation=interpolation, # nearest or linear padding="zero", # closest, zero or max save_data=False, # save output data to file (boolean) overwrite=False, # overwrite existing results (boolean) output_dir=None, # output directory file_name=None, # base name with file extension for output ) # write output nb.save(res["result"], file_out) # remove temporary files if r: os.remove(file_tmp) os.remove(file_tmp2) return res["result"]
def get_nuisance_mask(input, pathSPM, deformation, path_output, nerode_white=1, nerode_csf=1, segmentation=True, cleanup=True): """ This function calculates WM and CSF masks in space of the functional time series. It uses SPM to compute WM and CSF probability maps. These maps are masked with a skullstrip mask and transformed to native epi space. Inputs: *input: input anatomy (orig.mgz). *pathSPM: path to spm toolbox. *deformation: coordinate mapping for ana to epi transformation. *path_output: path where output is saved. *nerode_white: number of wm mask eroding steps. *nerode_csf: number of csf mask eroding steps. *segmentation: do not calculate new masks to not rerun everything. *cleanup: delete intermediate files. created by Daniel Haenelt Date created: 01-03-2019 Last modified: 01-03-2019 """ import os import shutil as sh import nibabel as nb from scipy.ndimage.morphology import binary_erosion from nipype.interfaces.fsl import BET from nipype.interfaces.freesurfer.preprocess import MRIConvert from nighres.registration import apply_coordinate_mappings from lib.skullstrip.skullstrip_spm12 import skullstrip_spm12 # make output folder if not os.path.exists(path_output): os.mkdir(path_output) # get filename without file extension of input file file = os.path.splitext(os.path.basename(input))[0] # convert to nifti format mc = MRIConvert() mc.inputs.in_file = input mc.inputs.out_file = os.path.join(path_output, file + ".nii") mc.inputs.out_type = "nii" mc.run() # bet skullstrip mask btr = BET() btr.inputs.in_file = os.path.join(path_output, file + ".nii") btr.inputs.frac = 0.5 btr.inputs.mask = True btr.inputs.no_output = True btr.inputs.out_file = os.path.join(path_output, "bet") btr.inputs.output_type = "NIFTI" btr.run() # segmentation if segmentation: skullstrip_spm12(os.path.join(path_output, file + ".nii"), pathSPM, path_output) # load tissue maps wm_array = nb.load(os.path.join(path_output, "skull", "c2" + file + ".nii")).get_fdata() csf_array = nb.load( os.path.join(path_output, "skull", "c3" + file + ".nii")).get_fdata() mask_array = nb.load(os.path.join(path_output, "bet_mask.nii")).get_fdata() # binarize wm_array[wm_array > 0] = 1 csf_array[csf_array > 0] = 1 # apply brain mask wm_array = wm_array * mask_array csf_array = csf_array * mask_array # erode wm wm_array = binary_erosion( wm_array, structure=None, iterations=nerode_white, mask=None, output=None, border_value=0, origin=0, brute_force=False, ) # erode csf csf_array = binary_erosion( csf_array, structure=None, iterations=nerode_csf, mask=None, output=None, border_value=0, origin=0, brute_force=False, ) # write wm and csf mask data_img = nb.load(input) wm_out = nb.Nifti1Image(wm_array, data_img.affine, data_img.header) nb.save(wm_out, os.path.join(path_output, "wm_mask_orig.nii")) csf_out = nb.Nifti1Image(csf_array, data_img.affine, data_img.header) nb.save(csf_out, os.path.join(path_output, "csf_mask_orig.nii")) # apply deformation to mask apply_coordinate_mappings( os.path.join(path_output, "wm_mask_orig.nii"), # input deformation, # cmap interpolation="nearest", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="wm_mask" # base name with file extension for output ) apply_coordinate_mappings( os.path.join(path_output, "csf_mask_orig.nii"), # input deformation, # cmap interpolation="nearest", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="csf_mask" # base name with file extension for output ) # rename transformed masks os.rename(os.path.join(path_output, "wm_mask_def-img.nii.gz"), os.path.join(path_output, "wm_mask.nii.gz")) os.rename(os.path.join(path_output, "csf_mask_def-img.nii.gz"), os.path.join(path_output, "csf_mask.nii.gz")) # cleanup if cleanup: os.remove(os.path.join(path_output, "bet_mask.nii")) os.remove(os.path.join(path_output, "csf_mask_orig.nii")) os.remove(os.path.join(path_output, "wm_mask_orig.nii")) os.remove(os.path.join(path_output, "orig.nii")) sh.rmtree(os.path.join(path_output, "skull"), ignore_errors=True)
header = data_img.header affine = data_img.affine # get image dimension dim = data_img.header["dim"][1:4] # get outlier dummy array if not outlier input if not len(outlier_input): outlier_input = np.zeros(len(img_input)) # deform mask apply_coordinate_mappings(mask_input, # input epi2orig_input, # cmap1 orig2epi_input, interpolation = "nearest", # nearest or linear padding = "zero", # closest, zero or max save_data = True, # save output data to file (boolean) overwrite = True, # overwrite existing results (boolean) output_dir = path_output, # output directory file_name = "mask" # base name with file extension for output ) # rename final deformations os.rename(os.path.join(path_output,"mask_def-img.nii.gz"), os.path.join(path_output,"mask.nii.gz")) # load mask mask = nb.load(os.path.join(path_output,"mask.nii.gz")).get_fdata() mean_od_index1 = np.zeros(dim) mean_od_index2 = np.zeros(dim) for i in range(len(img_input)):
# nibabel instance of final cmap t2s_header = copy_header(input_source) t2s_header["dim"][0] = 4 t2s_header["dim"][4] = 3 t2s_header["pixdim"][0] = 1 t2s_header["pixdim"][4] = 1 t2s_affine = nb.load(input_source).affine t2s = nb.Nifti1Image(arr_cmap_transformed, t2s_affine, t2s_header) # apply cmap to target t2s_example = apply_coordinate_mappings(input_target, mapping1=t2s, mapping2=None, mapping3=None, mapping4=None, interpolation="linear", padding="closest", save_data=False, overwrite=False, output_dir=None, file_name=None) # source to target transformation cmap_target = generate_coordinate_mapping(input_target, pad=0) arr_cmap_target = cmap_target.get_fdata() xdim = cmap_target.header["dim"][1] ydim = cmap_target.header["dim"][2] zdim = cmap_target.header["dim"][3] # transform source volume
data_array = data_array[:,:,:,:-end_vol] # write single volumes data.header["dim"][4] = 1 data.header["dim"][0] = 3 for i in range(np.shape(data_array)[3]): output = nb.Nifti1Image(data_array[:,:,:,i], data.affine, data.header) nb.save(output, os.path.join(path_native,str(i+1)+".nii")) # apply deformation for i in range(np.shape(data_array)[3]): apply_coordinate_mappings(os.path.join(path_native,str(i+1)+".nii"), input_deformation, interpolation=interpolation, padding='closest', save_data=True, overwrite=True, output_dir=path_def, file_name=None, ) # map to ana for i in range(np.shape(data_array)[3]): for j in range(len(input_surf)): # hemisphere hemi = os.path.splitext(os.path.basename(input_surf[j]))[0] # sample on surface map2surface(input_surf[j], os.path.join(path_def,str(i+1)+"_def-img.nii.gz"),
def mesh_sampling_layer_other(surf_in, file_in, target2source_in, source2target_in, boundaries_in, path_output, layer, smooth_iter=0, r=[0.4, 0.4, 0.4], interpolation="Cu", average_layer=False, write_profile=False, write_upsampled=True, cleanup=True): """ This function samples data from an image volume to a surface mesh which is located in a different space. Boundaries and surface mesh are first transformed to the space of the image volume using coordinate mappings before data sampling. If average_layer is true, the parameter layer should contain only two integers which denote the start and ending layer. The basename of the surface file should have no file extension and the hemisphere should be stated as prefix. Inputs: *surf_in: filename of input surface mesh. *file_in: filename of input volume from which data is sampled. *target2source_in: target to source coordinate mapping. *source2target_in: source to target coordinate mapping. *boundaries_in: filename of 4D levelset image. *path_output: path where output is written. *layer: which layers to sample (array of integers). *smooth_iter: number of smoothing iterations after mesh deformation. *r: destination voxel size after upsampling (performed if not None). *interpolation: interpolation method for upsampling of file from which data is sampled. *average_layer: average across cortex. *write_profile: write sampled profile. *write_upsampled: write upsampled file. *cleanup: remove intermediate files. created by Daniel Haenelt Date created: 13-01-2020 Last modified: 24-06-2020 """ import os import shutil as sh import numpy as np import nibabel as nb from nighres.registration import apply_coordinate_mappings from lib.io.get_filename import get_filename from lib.utils.upsample_volume import upsample_volume from lib.surface.deform_surface import deform_surface from lib.surface.mesh_sampling_layer import mesh_sampling_layer """ set folder structure """ tmp = np.random.randint(0, 10, 5) tmp_string = ''.join(str(i) for i in tmp) path_temp = os.path.join(path_output, "temp_" + tmp_string) path_cmap = os.path.join(path_temp, "cmap") path_data = os.path.join(path_temp, "data") path_surf = os.path.join(path_temp, "surf") if not os.path.exists(path_output): os.makedirs(path_output) if not os.path.exists(path_temp): os.makedirs(path_temp) if not os.path.exists(path_cmap): os.makedirs(path_cmap) if not os.path.exists(path_data): os.makedirs(path_data) if not os.path.exists(path_surf): os.makedirs(path_surf) # get filenames _, hemi, name_surf = get_filename(surf_in) _, name_file, ext_file = get_filename(file_in) _, name_t2s, ext_t2s = get_filename(target2source_in) _, name_s2t, ext_s2t = get_filename(source2target_in) # copy input files sh.copyfile(target2source_in, os.path.join(path_cmap, "t2s" + ext_t2s)) sh.copyfile(source2target_in, os.path.join(path_cmap, "s2t" + ext_s2t)) sh.copyfile(file_in, os.path.join(path_data, name_file + ext_file)) # set filenames data = os.path.join(path_data, name_file + ext_file) data_upsampled = os.path.join(path_data, name_file + "_upsampled" + ext_file) t2s = os.path.join(path_cmap, "t2s" + ext_t2s) t2s_upsampled = os.path.join(path_cmap, "t2s_upsampled" + ext_t2s) t2s_rescaled = os.path.join(path_cmap, "t2s_upsampled_rescaled" + ext_t2s) s2t = os.path.join(path_cmap, "s2t" + ext_s2t) s2t_upsampled = os.path.join(path_cmap, "s2t_upsampled" + ext_s2t) s2t_rescaled = os.path.join(path_cmap, "s2t_upsampled_rescaled" + ext_s2t) """ upsample data """ if r: upsample_volume(data, data_upsampled, dxyz=r, rmode=interpolation) upsample_volume(t2s, t2s_upsampled, dxyz=r, rmode="Linear") upsample_volume(s2t, s2t_upsampled, dxyz=r, rmode="Linear") """ rescale cmap """ dim_target = nb.load(s2t).header["dim"][1:4] - 1 dim_source = nb.load(t2s).header["dim"][1:4] - 1 dim_target_upsampled = nb.load(s2t_upsampled).header["dim"][1:4] - 1 dim_source_upsampled = nb.load(t2s_upsampled).header["dim"][1:4] - 1 cmap_t2s = nb.load(t2s_upsampled) cmap_s2t = nb.load(s2t_upsampled) cmap_t2s_array = cmap_t2s.get_fdata() cmap_s2t_array = cmap_s2t.get_fdata() for i in range(3): cmap_t2s_array[:, :, :, i] = cmap_t2s_array[:, :, :, i] / dim_target[ i] * dim_target_upsampled[i] cmap_s2t_array[:, :, :, i] = cmap_s2t_array[:, :, :, i] / dim_source[ i] * dim_source_upsampled[i] cmap_t2s_rescaled = nb.Nifti1Image(cmap_t2s_array, cmap_t2s.affine, cmap_t2s.header) cmap_s2t_rescaled = nb.Nifti1Image(cmap_s2t_array, cmap_s2t.affine, cmap_s2t.header) nb.save(cmap_t2s_rescaled, t2s_rescaled) nb.save(cmap_s2t_rescaled, s2t_rescaled) """ deform boundaries """ apply_coordinate_mappings( image=boundaries_in, # input mapping1=t2s_rescaled, # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_data, # output directory file_name="boundaries" # base name with file extension for output ) """ deform mesh """ deform_surface(input_surf=surf_in, input_orig=s2t_upsampled, input_deform=s2t_rescaled, input_target=data_upsampled, hemi=hemi, path_output=path_surf, input_mask=None, interp_method="trilinear", smooth_iter=smooth_iter, flip_faces=False, cleanup=True) """ sample data """ if smooth_iter: surf_in = os.path.join(path_surf, hemi + name_surf + "_def_smooth") else: surf_in = os.path.join(path_surf, hemi + name_surf + "_def") mesh_sampling_layer(surf_in=surf_in, file_in=data_upsampled, boundaries_in=os.path.join( path_data, "boundaries_def-img.nii.gz"), path_output=path_output, layer=layer, r=None, average_layer=average_layer, write_profile=write_profile, write_upsampled=write_upsampled) # delete intermediate files if cleanup: sh.rmtree(path_temp, ignore_errors=True)
ignore_header= False, # ignore the orientation information and affine matrix information extracted from the image header save_data=True, # save output data to file overwrite=True, # overwrite existing results output_dir=path_syn, # output directory file_name="syn", # output basename ) """ merge deformations """ # orig -> epi apply_coordinate_mappings( os.path.join(path_scanner, "orig_2_T1_scanner.nii"), # input os.path.join(path_syn, "syn_ants-map.nii.gz"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="orig2epi" # base name with file extension for output ) # epi -> orig apply_coordinate_mappings( os.path.join(path_syn, "syn_ants-invmap.nii.gz"), # input os.path.join(path_scanner, "T1_2_orig_scanner.nii"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="epi2orig" # base name with file extension for output
nt = nb.load(input_epi[i]).header["dim"][4] data.header["dim"][4] = 1 # change header for single 3d volumes for j in range(nt): # save single time frame output = nb.Nifti1Image(data_array[:, :, :, j], data.affine, data.header) nb.save(output, os.path.join(path_tmp, str(j) + ".nii")) apply_coordinate_mappings( os.path.join(path_tmp, str(j) + ".nii"), input_reg[i], interpolation=interpolation, padding=padding, save_data=True, overwrite=True, output_dir=path_tmp, file_name=None, ) # unzip output gunzip(os.path.join(path_tmp, str(j) + "_def-img.nii.gz")) # merge final deformed time series data = nb.load(os.path.join(path_tmp, "0_def-img.nii")) data.header["dim"][4] = nt data_res = np.zeros(data.header["dim"][1:5]) for j in range(nt):
""" get output """ os.rename(os.path.join(path_temp, "orig_2_T1_scanner.nii.gz"), os.path.join(path_output, "orig2T1.nii.gz")) os.rename(os.path.join(path_temp, "T1_2_orig_scanner.nii.gz"), os.path.join(path_output, "T12orig.nii.gz")) """ apply deformation """ # ana -> epi apply_coordinate_mappings( os.path.join(path_temp, "orig.nii"), # input os.path.join(path_output, "orig2T1.nii.gz"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="orig2T1_example" # base name with file extension for output ) # epi -> ana apply_coordinate_mappings( os.path.join(path_temp, "T1.nii"), # input os.path.join(path_output, "T12orig.nii.gz"), # cmap interpolation="linear", # nearest or linear padding="zero", # closest, zero or max save_data=True, # save output data to file (boolean) overwrite=True, # overwrite existing results (boolean) output_dir=path_output, # output directory file_name="T12orig_example" # base name with file extension for output