def get_transformation(path_volume, path_reference_volume, path_transfo, path_inverse): volume = aims.read(path_volume) reference_volume = aims.read(path_reference_volume) header = volume.header() header_ref = reference_volume.header() transfo_vol_to_mni = aims.AffineTransformation3d( header["transformations"][0]) transfo_reference_to_mni = aims.AffineTransformation3d( header_ref["transformations"][0]) final_transfo = transfo_reference_to_mni.inverse() * transfo_vol_to_mni inverse = final_transfo.inverse() aims.write(final_transfo, path_transfo) aims.write(inverse, path_inverse) pass
def peaks_as_spheres(path_peaks_volume, path_spheres, radius=2): """ Represent peaks as spheres centered on peaks location and of radius radius :param path_peaks_volume: path of the boolean volume with peaks :param path_spheres: path of the mesh (spheres) representing the peaks :param radius: radius (in mm) of the spheres used for display :return: """ volume = aims.read(path_peaks_volume) data = np.array(volume)[..., 0] voxel_size = volume.header()['voxel_size'] + [1] scaling = aims.AffineTransformation3d() scaling.fromMatrix(np.diag(voxel_size)) peaks_vol_coord = np.transpose(np.vstack(np.where(data != 0))) centers = [aims.Point3df(p) for p in peaks_vol_coord] print(len(centers)) for i, center in enumerate(centers): center = scaling.transform(center) sphere = aims.SurfaceGenerator.sphere(center, radius,300) if i == 0: spheres = sphere else: aims.SurfaceManip.meshMerge(spheres, sphere) aims.write(spheres, path_spheres)
def execution(self, context): tr = aims.AffineTransformation3d() for t in self.MNI_transform_chain: ti = aims.read(t.fullPath()) tr = ti * tr #context.write('transform:', tr) vol = aims.read(self.volume.fullPath()) trl = vol.header().get('transformations', []) refl = vol.header().get('referentials', []) rname = aims.StandardReferentials.mniTemplateReferential() if rname in refl: trl[refl.index(rname)] = tr.toVector() elif len(trl) < 2: #else: trl.append(tr.toVector()) refl.append(rname) else: trl = [list(trl[0]), list(tr.toVector())] \ + [list(t) for t in list(trl)[1:]] refl = [refl[0], rname] + list(refl)[1:] # context.write('now:', refl, trl) vol.header()['referentials'] = refl vol.header()['transformations'] = trl context.write('new header:', vol.header()) aims.write(vol, self.output_volume.fullPath()) self.output_volume.readAndUpdateMinf() tm = registration.getTransformationManager() tm.copyReferential(self.volume, self.output_volume, copy_transformations=False)
def execution( self, context): bvals, bvecs = read_bvals_bvecs(self.bvals.fullPath(), self.bvecs.fullPath()) if self.round_bvals: context.write("Rouding bvalues to : useful for shell based models") bvals = np.round(bvals,-2) try: minf = self.diffusion_data.minf() t = minf['storage_to_memory'] except KeyError: context.write("No storage_to_memory field in the minf file associated to the volume, using the one of the header of the volume") dwi = aims.read(self.diffusion_data.fullPath()) header = dwi.header() t = header['storage_to_memory'] finally: try : t1 = aims.AffineTransformation3d(t).toMatrix() aff = np.diag(t1)[:-1] affine = np.diag(aff) except: context.write("Warning!: there is no storage to memory matrix, I assume bvecs have an RAS (Nifti convention) orientation") affine = -1.0*np.eye(3) context.write("The following transformation is going to be applied:", affine) bvecs = np.dot(bvecs, np.transpose(affine)) context.write("Transforming bvecs coordinate from storage to Aims referential") gtab = gradient_table(bvals, bvecs,b0_threshold=self.b0_threshold) dump(gtab, self.gradient_table.fullPath(), compress=9) #Handling metadata self.gradient_table.setMinf('rounded_bvals', self.round_bvals) self.gradient_table.setMinf('bvalues_uuid', self.bvals.uuid()) self.gradient_table.setMinf('bvectors_uuid',self.bvecs.uuid())
def execution(self, context): from soma import aims, aimsalgo import numpy as np vol = aims.read(self.image_input.fullPath()) old_t1_to_scanner = aims.AffineTransformation3d( vol.header()['transformations'][0]) new_t1 = aims.read(self.target_space_image.fullPath()) new_t1_to_scanner = aims.AffineTransformation3d( new_t1.header()['transformations'][0]) old_to_new = new_t1_to_scanner.inverse() * old_t1_to_scanner rsp = getattr(aims, 'ResamplerFactory_' + aims.typeCode(np.asarray(vol).dtype))().getResampler(0) rsp.setRef(vol) vol_resamp = rsp.doit(old_to_new, new_t1.getSizeX(), new_t1.getSizeY(), new_t1.getSizeZ(), new_t1.getVoxelSize()[:3]) aims.write(vol_resamp, self.image_output.fullPath()) tm = registration.getTransformationManager() tm.copyReferential(self.target_space_image, self.image_output)
def build_transformation(self, trans_path, volume): ref_s = volume.header()['referential'] result_tr = aims.AffineTransformation3d() for tr in trans_path: tr_o = aims.read(tr.fullPath()) ref_s1 = tr_o.header()['source_referential'] ref_d1 = tr_o.header()['destination_referential'] if ref_d1 == ref_s: tr_o = tr_o.inverse() ref_s = ref_s1 else: ref_s = ref_d1 result_tr = tr_o * result_tr return result_tr
def get_aims_to_RAS_transfo(path_volume, path_transformation): """ Retrieve the estimated transformation between AIMS mm and RAS mm space :param path_volume: :param path_transformation: :return: """ vol = aims.read(path_volume) aims_to_RAS = aims.AffineTransformation3d( vol.header()["transformations"][0]) RAS_to_aims = aims_to_RAS.inverse() aff = np.array(aims_to_RAS.toMatrix()) affine = np.array(RAS_to_aims.toMatrix()) np.save(path_transformation, affine) return affine
def execution(self, context): finder = aims.Finder() finder.check(self.read.fullPath()) hdr = finder.header() dims = hdr['volume_dimension'][:3] vs = hdr['voxel_size'][:3] dims[0] += self.added_border * 2 dims[1] += self.added_border * 2 dims[2] += self.added_border * 2 transfile = context.temporary('Transformation matrix') trans = aims.AffineTransformation3d() trans.setTranslation([ self.added_border * vs[0], self.added_border * vs[1], self.added_border * vs[2] ]) aims.write(trans, transfile.fullPath()) cmd = [ 'AimsResample', '-t', 'n', '-i', self.read, '-o', self.write, '--dx', dims[0], '--dy', dims[1], '--dz', dims[2], '-m', transfile ] context.system(*cmd)
def execution(self, context): finder = aims.Finder() finder.check(self.read.fullPath()) hdr = finder.header() dims = hdr['volume_dimension'][:3] vs = hdr['voxel_size'][:3] dims[0] -= self.crop_left + self.crop_right dims[1] -= self.crop_front + self.crop_back dims[2] -= self.crop_top + self.crop_bottom transfile = context.temporary('Transformation matrix') trans = aims.AffineTransformation3d() trans.setTranslation([ -self.crop_right * vs[0], -self.crop_front * vs[1], -self.crop_top * vs[2] ]) print('transfo:') print(trans) aims.write(trans, transfile.fullPath()) cmd = [ 'AimsResample', '-t', 'n', '-i', self.read, '-o', self.write, '--dx', dims[0], '--dy', dims[1], '--dz', dims[2], '-m', transfile ] context.system(*cmd)
# Output file names OUT_DIR = os.path.join(BASE_DIR, 'data/mask_without_cerebellum') RESAMPLED_ATLAS_FILE = os.path.join(OUT_DIR, 'TD_lobe_1.5mm.nii') RESAMPLED_MNI_FILE = os.path.join(OUT_DIR, 'MNI152_T1_1.5mm.nii') if ~os.path.exists(OUT_DIR): os.makedirs(OUT_DIR) # Converters U8_2_S16_converter = aims.Converter(aims.Volume_U8, aims.Volume_S16) S16_2_U8_converter = aims.Converter(aims.Volume_S16, aims.Volume_U8) # Nearest-neighbor resampler resp = aims.ResamplerFactory_S16().getResampler(0) resp.setDefaultValue(-1) # set background to -1 I = aims.AffineTransformation3d() # Open mask and get parameters from it mask = aims.read(MASK_FILE) mask_header = mask.header() VOLUME_SIZE = mask_header['volume_dimension'] VOXEL_SIZE = mask_header['voxel_size'] STOM = mask_header['storage_to_memory'] # Open atlas file & convert it atlas = aims.read(ATLAS_FILE) atlas_S16 = U8_2_S16_converter(atlas) # Resampling resp.setRef(atlas_S16) # volume to resample resampled_atlas_S16 = resp.doit(I, VOLUME_SIZE[0], VOLUME_SIZE[1],
def resample(input_image, transformation, output_vs=None, background=0, values=None): """ Transform and resample a volume that as discret values Parameters ---------- input_image: file Path to the input volume (.nii or .nii.gz file) transformation: file Linear transformation file (.trm file) output_vs: tuple Output voxel size (default: None, no resampling) background: int Background value (default: 0) values: [] Array of unique values ordered by descendent priority. If not given, priority is set by ascendent values Return ------ resampled_vol: Transformed and resampled volume """ # Read inputs vol = aims.read(input_image) vol_dt = vol.__array__() if transformation: trm = aims.read(transformation) else: trm = aims.AffineTransformation3d(np.eye(4)) inv_trm = trm.inverse() if output_vs: output_vs = np.array(output_vs) # New volume dimensions resampling_ratio = np.array(vol.header()['voxel_size'][:3]) / output_vs orig_dim = vol.header()['volume_dimension'][:3] new_dim = list((resampling_ratio * orig_dim).astype(int)) else: output_vs = vol.header()['voxel_size'][:3] new_dim = vol.header()['volume_dimension'][:3] # Transform the background # Using the inverse is more straightforward and supports non-linear # transforms resampled = aims.Volume(new_dim, dtype=vol_dt.dtype) resampled.header()['voxel_size'] = output_vs # 0 order (nearest neightbours) resampling resampler = aimsalgo.ResamplerFactory(vol).getResampler(0) resampler.setDefaultValue(background) resampler.setRef(vol) resampler.resample_inv(vol, inv_trm, 0, resampled) resampled_dt = np.asarray(resampled) if values is None: values = sorted(np.unique(vol_dt[vol_dt != background])) else: # Reverse order as value are passed by descendent priority values = values[::-1] # Create one bucket by value (except background) # FIXME: Create several buckets because I didn't understood how to add # several bucket to a BucketMap for i, v in enumerate(values): bck = aims.BucketMap_VOID() bck.setSizeXYZT(*vol.header()['voxel_size'][:3], 1.) bk0 = bck[0] for p in np.vstack(np.where(vol_dt == v)[:3]).T: bk0[list(p)] = v bck2 = aimsalgo.resampleBucket(bck, trm, inv_trm, output_vs) # FIXME: Could not assign the correct value with the converter. # Using the converter, the new_dim must incremented # conv = aims.Converter(intype=bck2, outtype=aims.AimsData(vol)) # conv.convert(bck2, resampled) # Use a for loop instead: for p in bck2[0].keys(): c = p.list() if c[0] < new_dim[0] and c[1] < new_dim[1] and c[2] < new_dim[2]: resampled_dt[c[0], c[1], c[2]] = values[i] return resampled
def compute_geodesic_depth_map(parameters): DIR_F, DIR_BV, s_id = parameters path_nu = os.path.join(DIR_F, s_id, 'T1w', s_id, 'mri', 'nu.mgz') path_nat = os.path.join(DIR_F, s_id, 'T1w', s_id, 'mri', 'orig', '001.mgz') nu_nii = os.path.join(DIR_BV, s_id, 'mri', 'nu.nii.gz') native_nii = os.path.join(DIR_BV, s_id, 'mri', 'native.nii.gz') outdir = os.path.dirname(nu_nii) if not os.path.isdir(outdir): os.makedirs(outdir) #mri_convert(path_nu, nu_nii) #mri_convert(path_nat, native_nii) path_ribbon = os.path.join(DIR_F, s_id, 'T1w', s_id, 'mri', 'ribbon.mgz') ribbon_nii = os.path.join(DIR_BV, s_id, 'mri', 'ribbon.nii.gz') #mri_convert(path_ribbon, ribbon_nii) for vol in [nu_nii, native_nii, ribbon_nii]: # Convert file to Aims format cmd = " ".join(['AimsFileConvert', '-i %s' % vol, '-o %s' % vol, '-t S16']) print cmd os.system(cmd) # Replace the label in the ribbon with Morphologist expected label ribbon_bv = os.path.join(DIR_BV, s_id, 'mri', 'ribbon_bv.nii.gz') cmd = " ".join(['AimsReplaceLevel', '-i %s' % ribbon_nii, '-o %s' % ribbon_bv, '-g 42 41 2 3', '-n 100 200 200 100']) print cmd os.system(cmd) # Split the hemisphere and replace labels l_gw = os.path.join(DIR_BV, s_id, 'mri', 'Lgrey_white'+s_id+'.nii.gz') r_gw = os.path.join(DIR_BV, s_id, 'mri', 'Rgrey_white'+s_id+'.nii.gz') cmd = " ".join(['AimsReplaceLevel', '-i %s' % ribbon_nii, '-o %s' % l_gw, '-g 42 41 2 3', '-n 0 0 200 100']) print cmd os.system(cmd) cmd = " ".join(['AimsReplaceLevel', '-i %s' % ribbon_nii, '-o %s' % r_gw, '-g 42 41 2 3', '-n 100 200 0 0']) print cmd os.system(cmd) # Compute the grey/white histogram histo = os.path.join(DIR_BV, s_id, 'mri', 'nu_'+s_id+'.his') cmd = " ".join(['VipGreyStatFromClassif', '-i %s' % nu_nii, '-c %s' % ribbon_bv, '-a %s' % histo, '-g 100 -w 200']) print cmd os.system(cmd) # Create the hemi cortex required for the geodesic depth process l_hemcor = os.path.join(DIR_BV, s_id, 'mri', 'Lcortex_'+s_id+'.nii.gz') r_hemcor = os.path.join(DIR_BV, s_id, 'mri', 'Rcortex_'+s_id+'.nii.gz') for gw, hemcor in zip([l_gw, r_gw], [l_hemcor, r_hemcor]): cmd = " ".join(['VipHomotopic', '-i %s' % nu_nii, '-cl %s' % gw, '-h %s' % histo+'.han', '-o %s' % hemcor, '-m C -w t']) print cmd os.system(cmd) # Freesurfer surface are in native space, but not the ribbon # Thus, we tranform the obtained hemicortex to the native space ribbon = aims.read(ribbon_nii) native = aims.read(native_nii) s2sb = aims.AffineTransformation3d(ribbon.header()['transformations'][0]) n2sb = aims.AffineTransformation3d(native.header()['transformations'][0]) s2n = n2sb.inverse() * s2sb transfo_fs2nat = os.path.join(DIR_BV, s_id, 'mri', 'fs2nat.trm') aims.write(s2n, transfo_fs2nat) for hemcor in [l_hemcor, r_hemcor]: cmd = " ".join(['AimsResample', '-i %s' % hemcor, '-o %s' % hemcor, '-m %s' % transfo_fs2nat, '-t 0', '-r %s' % native_nii]) print cmd os.system(cmd) l_white = os.path.join(DIR_BV, s_id, 't1mri/BL/default_analysis', 'segmentation/mesh', s_id+'_Lwhite.gii') l_white_aims = os.path.join(DIR_BV, s_id, 't1mri/BL/default_analysis', 'segmentation/mesh', s_id+'_Lwhite_aims.gii') l_depth = os.path.join(DIR_BV, s_id, 't1mri/BL/default_analysis', 'segmentation/mesh/surface_analysis', s_id+'_Lgeodesic_depth.gii') r_white = os.path.join(DIR_BV, s_id, 't1mri/BL/default_analysis', 'segmentation/mesh', s_id+'_Rwhite.gii') r_white_aims = os.path.join(DIR_BV, s_id, 't1mri/BL/default_analysis', 'segmentation/mesh', s_id+'_Rwhite_aims.gii') r_depth = os.path.join(DIR_BV, s_id, 't1mri/BL/default_analysis', 'segmentation/mesh/surface_analysis', s_id+'_Rgeodesic_depth.gii') # Convert mesh to Aims Referential from freesurfer.freesurferMeshToAimsMesh import freesurferMeshToAimsMesh for white, white_aims in zip([l_white, r_white], [l_white_aims, r_white_aims]): freesurferMeshToAimsMesh(white, native_nii, white_aims) # Finally compute the geodesic depth of interest for white, hemcor, depth in zip([l_white_aims, r_white_aims], [l_hemcor, r_hemcor], [l_depth, r_depth]): cmd = " ".join(['python -m brainvisa.axon.runprocess', 'whitemeshdepthmap', white, hemcor, depth, '10.0']) # closing_size print cmd os.system(cmd) # Another option is to compute the geodesic depth map in the volume # The code is commented below, however it performs sighlty worse """
def aims_get_transformation(src, ref): from soma import aims src3mni = aims.AffineTransformation3d(src.header()['transformations'][0]) ref2mni = aims.AffineTransformation3d(ref.header()['transformations'][0]) src2ref = ref2mni.inverse() * src3mni return src2ref