def projectOnSurface(myelin, surface): norm = surface.normal() vert = surface.vertex() Nv = vert.size() surfMap = aims.TimeTexture('FLOAT') surfMap[0].resize(Nv) dx, dy, dz, dt = myelin.getVoxelSize() volVox = aims.Volume(myelin.getSizeX(), myelin.getSizeY(), myelin.getSizeZ(), myelin.getSizeT(), 'FLOAT') volVox.header().update(myelin.header()) volVox.fill(0.0) print dx, dy, dz for i in range(Nv): v = vert[i] + t * norm[i] x = int(round(v[0] / dx)) y = int(round(v[1] / dy)) z = int(round(v[2] / dz)) val = myelin.value(x, y, z) volVox.setValue(val, x, y, z) surfMap[0][i] = val return surfMap, volVox
def convert_raw_map(fname, out_fname): ''' convert one raw map from bdalti (.asc) to .ima format ''' with open(fname) as f: lines = f.readlines() types = { 'ncols': int, 'cellsize': float, 'xllcorner': float, 'yllcorner': float, 'NODATA_value': float, } metadata = {} for l in lines[:6]: item = l.strip().split() k = item[0] metadata[k] = types.get(k, str)(item[1]) # print(metadata) image = aims.Volume((int(metadata['ncols']), int(metadata['nrows'])), dtype='float') array = np.asarray(image) for i, l in enumerate(lines[6:]): array[:, i, 0, 0] = [float(x) for x in l.strip().split()] image.header().update(metadata) aims.write(image, out_fname)
def relabel_conjunction(labels1, labels2): output = aims.Volume(labels1) output.fill(0) size_x = output.getSizeX() size_y = output.getSizeY() size_z = output.getSizeZ() old_to_new_labels = {} next_label = 1 for z in xrange(size_z): for y in xrange(size_y): for x in xrange(size_x): labels = (labels1.at(x, y, z), labels2.at(x, y, z)) # Negative means outside propagation region if labels[0] < 0 or labels[1] < 0: continue # Zeros are failed propagations, they should not be aggregated # together if labels[0] == 0 or labels[1] == 0: new_label = next_label next_label += 1 else: try: new_label = old_to_new_labels[labels] except KeyError: new_label = next_label old_to_new_labels[labels] = new_label next_label += 1 output.setValue(new_label, x, y, z) sys.stderr.write("{0}: {1} regions in conjunction\n".format( sys.argv[0], next_label - 1)) return output
def make_cortex_sphere_classif(inner_radius, outer_radius, voxel_size, margin=None, noise=None, sigma=None): voxel_size = _convert_to_float_triple(voxel_size) if margin is None: margin = 2 * max(voxel_size) margin = _convert_to_float_triple(margin) assert outer_radius > inner_radius > 0 size = [ int(math.ceil(2 * (outer_radius + ax_margin) / ax_voxel_size)) for ax_margin, ax_voxel_size in zip(margin, voxel_size) ] classif_volume = aims.Volume(size[0], size[1], size[2], dtype="S16") classif_volume.setVoxelSize(voxel_size) emplace_cortex_sphere_classif(classif_volume, inner_radius, outer_radius, margin=margin, noise=noise, sigma=sigma) return classif_volume
def aims_resample(src, ref): from soma import aims interp_dict = {"nn": 0, "lin": 1, "quad": 2} conv = aims.Converter(intype=src, outtype=aims.Volume('FLOAT')) src = conv(src) conv = aims.Converter(intype=ref, outtype=aims.Volume('FLOAT')) ref = conv(ref) # resampler resp = aims.ResamplerFactory_FLOAT().getResampler(interp_dict[interp]) resp.setRef(src) # volume to resample resp.setDefaultValue(0) # set background to 0 # resample voxel_size = np.array(ref.header()['voxel_size']) src2ref_trm = get_transformation(src, ref) output_ima = resp.doit(src2ref_trm, ref.getSizeX(), ref.getSizeY(), ref.getSizeZ(), voxel_size) output_ima.header()['referentials'] = ref.header()['referentials'] output_ima.header()['transformations'] = ref.header()['transformations'] return output_ima
def _prepare_classif_for_VipHomotopic_Cortical(classif, filling_size): array_classif = np.asarray(classif) # Dilate the cortex by 1 voxel, otherwise the topologically spherical front # initialized by VipHomotopic (Cortical surface mode) is at the inside of # the border, which means that the final segmentation will be one voxel # off. The default -fclosing parameter prevents this from happening in # sulci by closing them, but it still happens at the top of gyri. Setting a # fake voxel size of 1 mm is a trick for expressing the dilation in terms # of voxels. # # The 1-voxel border is necessary for AimsMorpho{Dilation,Erosion}. aimsdata_classif = aims.Volume_S16(classif.getSize(), [1, 1, 1]) aimsdata_classif[:] = classif[:] saved_voxel_size = classif.header()["voxel_size"][:3] aimsdata_classif.setVoxelSize(1, 1, 1) dilated = aimsalgo.AimsMorphoDilation(aimsdata_classif, 1) # Restore the voxel size in case the header is shared with the aims.Volume # that aimsdata_classif was created from (classif). BUG: restoring the # value like this is not thread-safe! aimsdata_classif.setVoxelSize(saved_voxel_size) del aimsdata_classif array_dilated = dilated.np tmp_classif = aims.Volume(classif) array_tmp_classif = np.asarray(tmp_classif) array_tmp_classif[np.logical_and(array_tmp_classif == CSF_LABEL, array_dilated != 0)] = CORTEX_LABEL del dilated, array_dilated # This almost-white region will serve as a first boundary in VipHomotopic, # before the final dilation towards the white matter. This helps restore # the continuity of the white matter so that the homotopic criterion # chooses the right connections (i.e. do not create spurious strands or # planes through the cortex). white = aims.Volume_S16(classif.gteSize(), [1, 1, 1]) white[:] = classif[:] # Restore the header (in particular the voxel_size), which may not have # been copied in the constructor because a border is requested. white.header().update(classif.header()) array_white = white.np array_white[array_white != WHITE_LABEL] = CSF_LABEL dilated_white = aimsalgo.AimsMorphoDilation(white, filling_size) del white, array_white array_dilated_white = dilated_white.np STEP1_FRONT_BARRIER = 199 array_tmp_classif[array_dilated_white != 0] = STEP1_FRONT_BARRIER del dilated_white, array_dilated_white array_tmp_classif[array_classif == WHITE_LABEL] = WHITE_LABEL return tmp_classif
def get_exchanged_propvol_files(classif_filename, CSF_labels_on_white_filename, white_labels_on_CSF_filename, output_filename): classif = aims.read(classif_filename) CSF_labels_on_white = aims.read(CSF_labels_on_white_filename) white_labels_on_CSF = aims.read(white_labels_on_CSF_filename) output = aims.Volume(CSF_labels_on_white) np_CSF_labels_on_white = np.asarray(CSF_labels_on_white) np_white_labels_on_CSF = np.asarray(white_labels_on_CSF) np_classif = np.asarray(classif) np_output = np.asarray(output) white_mask = (np_classif == 150) CSF_mask = (np_classif == 50) np_output[white_mask] = np_CSF_labels_on_white[white_mask] np_output[CSF_mask] = np_white_labels_on_CSF[CSF_mask] temp_dir = None try: temp_dir = tempfile.mkdtemp(prefix="hcortex") temp_filename = os.path.join(temp_dir, 'raw_exchanged_labels.nii') aims.write(output, temp_filename) # These “failed components” will probably be separated by connexity # AimsReplaceLevel -i raw_exchanged_labels.nii.gz \ # -o exchanged_labels.nii.gz \ # -g 100000000 -n 0 -g 200000000 -n 0 subprocess.check_call(["AimsConnectComp", "-i", "raw_exchanged_labels.nii", "-o", "connected_exchanged_labels.nii"], cwd=temp_dir) # The background is cut in one big region + many small, restore it then # relabel propvol = aims.read( os.path.join(temp_dir, "connected_exchanged_labels.nii")) finally: if temp_dir: shutil.rmtree(temp_dir) np_propvol = np.asarray(propvol) exclusion_mask = (np_CSF_labels_on_white == -1) bulk_mask = (np_CSF_labels_on_white == 0) np_propvol[bulk_mask] = 0 np_propvol[exclusion_mask] = -1 relabel_positive_labels(propvol) aims.write(propvol, output_filename)
def subject_labeling(gfile, dict_bck, translation, mask, vol_size, n_opal, distmap_list, bck_list, proba_list, label_list, patch_sizes): ''' Label a subject sulcal graph (.arg file) for a specific pattern search using the SNIPE method ''' print('Labeling %s' % gfile) distmap_list = [aims.Volume(d) for d in distmap_list] # Extract bucket fm = aims.FastMarching() if gfile not in dict_bck: graph = aims.read(gfile) side = gfile[gfile.rfind('/') + 1:gfile.rfind('/') + 2] data = extract_data(graph, flip=True if side == 'R' else False) sbck = data['bck2'] else: sbck = dict_bck[gfile] sbck = np.array(sbck) sbck += translation sbck = np.asarray(apply_imask(sbck, mask)) # Extract distmap fm = aims.FastMarching() vol = aims.Volume_S16(vol_size[0], vol_size[1], vol_size[2]) vol.fill(0) for p in sbck: vol[p[0], p[1], p[2]] = 1 sdistmap = fm.doit(vol, [0], [1]) adistmap = np.asarray(sdistmap) adistmap[adistmap > pow(10, 10)] = 0 # Compute classification grading_list = [] for ps in patch_sizes: print('** PATCH SIZE %i' % ps) opm = OptimizedPatchMatch(patch_size=[ps, ps, ps], segmentation=False, k=n_opal) list_dfann = opm.run(distmap=sdistmap, distmap_list=distmap_list, bck_list=bck_list, proba_list=proba_list) grading_list.append(grading(list_dfann, label_list)) grade = np.nanmean(np.mean(grading_list, axis=0)) ypred = 1 if grade > 0 else 0 return ypred, grade
def get_float_altitude(img, src_scl, dst_scl): def interpolate(rgb, src_scl, dst_scl): rgb = np.asarray(rgb).astype(float) #if rgb[1] < 10 or rgb[0] > 200: #if rgb[0] > 200: #rgb[0] = 0. #rgb[0] *= 2. #rgb[1] = 255. #rgb[2] = 255. dist = np.sum((dst_scl - rgb)**2, axis=1) #dist = ((dst_scl - rgb) ** 2)[:, 0] #print('dist:', dist) dmin = np.argmin(dist) if dmin == 0: ind = [dmin, dmin + 1] elif dmin == dst_scl.shape[0] - 1: ind = [dmin - 1, dmin] else: if dist[dmin - 1] < dist[dmin + 1]: ind = [dmin - 1, dmin] else: ind = [dmin, dmin + 1] # project axis = dst_scl[ind[1]] - dst_scl[ind[0]] d2 = np.sum(axis**2) if d2 == 0: return src_scl[-1] else: x = (rgb - dst_scl[ind[0]]).dot(axis) / d2 if x < 0: x = 0. elif x > 1: x = 1. return src_scl[ind[0]] + (src_scl[ind[1]] - src_scl[ind[0]]) * x dst_scl = np.asarray(scl_map).astype(float) #dst_scl[:, 0] *= 2. #dst_scl[:, 1] = 255. new_img = aims.Volume(img.getSize(), dtype='FLOAT') new_img.header()['voxel_size'] = img.header()['voxel_size'] for y in range(img.getSize()[1]): for x in range(img.getSize()[0]): rgb = img.at(x, y) alt = interpolate(rgb, src_scl, dst_scl) new_img.setValue(alt, x, y) return new_img
def array_to_vol(array, header=None, dtype=np.float32): """Convert an numpy array into an aims Volume properly: header is updated taking into account array properties """ new_arr = array.astype(dtype) arr = np.array(new_arr, order='F') vol = aims.Volume(arr) if header is not None: shape = list(new_arr.shape) index_max = len(shape) header['sizeX'] = shape[0] header['sizeY'] = shape[1] header['sizeZ'] = shape[2] if index_max == 3: header['sizeT'] = 1 else: header['sizeT'] = shape[3] vol.header().update(header) return vol
def relabel(labels): output = aims.Volume(labels) size_x = output.getSizeX() size_y = output.getSizeY() size_z = output.getSizeZ() old_to_new_labels = {} next_label = 1 for z in range(size_z): for y in range(size_y): for x in range(size_x): label = labels.at(x, y, z) if label == 0: new_label = 0 else: try: new_label = old_to_new_labels[label] except KeyError: new_label = next_label old_to_new_labels[label] = new_label next_label += 1 output.setValue(new_label, x, y, z) return output
def randomize_labels(labels): import numpy as np np_input_labels = np.asarray(labels) max_label = np.max(np_input_labels) nonzero_labels = list(range(1, max_label + 1)) random.shuffle(nonzero_labels) new_labels = [0] + nonzero_labels output = aims.Volume(labels) size_x = output.getSizeX() size_y = output.getSizeY() size_z = output.getSizeZ() for z in range(size_z): for y in range(size_y): for x in range(size_x): old_label = labels.at(x, y, z) if old_label >= 0: new_label = new_labels[old_label] else: new_label = 0 output.setValue(new_label, x, y, z) return output
def mesh_large_clusters(arr, clust_labeled, clust_sizes, labels, output_clusters_large_mesh_filename, tempdir, ima, thresh_size): large_clust_ima = aims.Volume(ima) large_clust_arr = np.asarray(large_clust_ima).squeeze() large_clust_arr[:] = 0 for i in xrange(len(labels)): label = labels[i] if clust_sizes[i] > thresh_size: large_clust_arr[clust_labeled == label] = 1 large_clust_ima_filename = os.path.join(tempdir, "large_clusters.nii") writer = aims.Writer() writer.write(large_clust_ima, large_clust_ima_filename) large_clust_graph_filename = os.path.join(tempdir, "large_clusters.arg") cmd = 'AimsClusterArg --input %s --output %s' % \ (large_clust_ima_filename, large_clust_graph_filename) print "\n=============" print cmd print "=============" os.popen(cmd) graph = aims.read(large_clust_graph_filename) print "-----" large_clust_meshs = None for v in graph.vertices(): if large_clust_meshs is None: large_clust_meshs = v['aims_Tmtktri'] else: aims.SurfaceManip.meshMerge(large_clust_meshs, v['aims_Tmtktri']) if large_clust_meshs is not None: large_clust_meshs.header()['referentials'] = ima.header( )['referentials'] large_clust_meshs.header()['transformations'] = ima.header( )['transformations'] writer.write(large_clust_meshs, output_clusters_large_mesh_filename) return large_clust_meshs else: print "No large cluster generated" return None
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 _make_similar_volume(data_array, ref): volume = aims.Volume(data_array) volume.header().update(ref.header()) return volume
def _make_similar_volume(data_array, ref): volume = aims.Volume(data_array) volume.copyHeaderFrom(ref.header()) return volume
if thresh_norm_ratio < 1: arr, thres = array_utils.arr_threshold_from_norm2_ratio( arr, thresh_norm_ratio) print "Threshold image as %f" % thres clust_bool = np.zeros(arr.shape, dtype=bool) #((arr > thresh_neg_low) & (arr < thresh_neg_high) | (arr > thresh_pos_low) & (arr < thresh_pos_high)).sum() clust_bool[((arr > thresh_neg_low) & (arr < thresh_neg_high)) | ((arr > thresh_pos_low) & (arr < thresh_pos_high))] = True arr[np.logical_not(clust_bool)] = False clust_labeled, n_clusts = scipy.ndimage.label(clust_bool) clust_sizes = scipy.ndimage.measurements.histogram(clust_labeled, 1, n_clusts, n_clusts) labels = np.unique(clust_labeled)[1:] centers = scipy.ndimage.center_of_mass(clust_bool, clust_labeled, labels) # _clusters.nii.gz clusters_values_ima = aims.Volume(ima) clusters_values_ima_arr = np.asarray(clusters_values_ima).squeeze() #clusters_values_ima_arr[clust_bool] = arr[clust_bool] clusters_values_ima_arr[::] = arr[::] writer = aims.Writer() writer.write(clusters_values_ima, output_clusters_values_filename) # _clusters_labels.nii.gz clusters_labels_ima = aims.Volume(ima) clusters_labels_ima_arr = np.asarray(clusters_labels_ima).squeeze() clusters_labels_ima_arr[:] = clust_labeled[:] writer.write(clusters_labels_ima, output_clusters_labels_filename) ########################################################################## # Get clusters information header_info, info = clusters_info(arr, clust_labeled, clust_sizes, labels, centers, trm_xyz_to_mm, atlas_cort,