def test_make_label_data(starling_atlas, regions_to_plot): point_in_um = [0, 1500, -200] point_in_voxels = np.array( um_to_vox( point_in_um, starling_atlas.voxel_data.loc["Brain", "affine"], starling_atlas.um_mult, starling_atlas.y_sinus_um_transform, )) label_data, regions_plotted = make_label_data(starling_atlas, regions_to_plot, point_in_voxels) old_label_data, old_regions_plotted = old_make_label_data( starling_atlas, regions_to_plot, point_in_voxels) assert len(regions_plotted) == len(old_regions_plotted) assert len(label_data) == len(old_label_data) for r2p in label_data: assert np.all(label_data[r2p]['unique_labels'] == old_label_data[r2p] ['unique_labels'])
def test_update_color_labels(starling_atlas, regions_to_plot): point_in_um = [0, 1500, -200] point_in_voxels = np.array( um_to_vox( point_in_um, starling_atlas.voxel_data.loc["Brain", "affine"], starling_atlas.um_mult, starling_atlas.y_sinus_um_transform, )) label_data, regions_plotted = make_label_data(starling_atlas, regions_to_plot, point_in_voxels) old_label_data = copy.deepcopy(label_data) old_regions_plotted = copy.deepcopy(regions_plotted) color_ind = update_color_labels(regions_plotted, label_data, init_color_ind=1) old_color_ind = old_update_color_labels(old_regions_plotted, old_label_data, regions_to_plot, init_color_ind=1) assert color_ind == old_color_ind
def plot_regions_3d( atlas, regions_to_plot=[["HVC", "Nuclei"]], downsample_pct=1, polygon_simplification=0, additional_volumes=[], verbose=False, height=1024, ): """ plots brain regions on top of brain """ # collect data brain_data = np.swapaxes(atlas.voxel_data.loc["Brain", "voxels"], 0, 2) # get axis boundaries bounds = np.array([ atlas.xmin, atlas.xmax, atlas.ymin, atlas.ymax, atlas.zmin, atlas.zmax ]).astype("int") # the zero point in voxels, relative to y sinus zero_point = utils.um_to_vox( [0, 0, 0], atlas.voxel_data.loc["Brain", "affine"], atlas.um_mult, atlas.y_sinus_um_transform, ) # downsample if downsample_pct < 1: brain_data = scipy.ndimage.zoom(brain_data, downsample_pct) # make a volume plot of the brain brain_volume = k3d.volume( brain_data, color_range=[0, 1], color_map=k3d.basic_color_maps.Binary, samples=128, alpha_coef=0.25, bounds=bounds, compression_level=9, ) addl_vols = [] for vol in additional_volumes: bg_image_data = atlas.voxel_data.loc[vol, "voxels"] affine = atlas.voxel_data.loc[vol, "affine"] xm, ym, zm = utils.vox_to_um([0, 0, 0], affine, atlas.um_mult, atlas.y_sinus_um_transform) xma, yma, zma = utils.vox_to_um( list(np.shape(bg_image_data)), affine, atlas.um_mult, atlas.y_sinus_um_transform, ) img_bg_extent = np.concatenate( np.array([[xm, xma], [ym, yma], [zm, zma]])) bg_image_data = np.uint8( utils.norm01(np.swapaxes(bg_image_data, 0, 2)) * 256) addl_vol = k3d.volume( bg_image_data, color_range=[70, 100], color_map=k3d.matplotlib_color_maps.Greys, samples=128, alpha_coef=10.0, bounds=img_bg_extent, compression_level=9, ) addl_vols.append(addl_vol) # set atlas a region for y sinus atlas.region_vox.loc["y_sinus"] = [ "y_sinus", "y_sinus", np.nan, np.nan, np.nan ] atlas.region_vox.loc["y_sinus", "coords_vox"] = zero_point color_pal = atlas.label_cmap.colors # loop through regions regs = [] for ri, (reg, type_) in enumerate(tqdm(regions_to_plot, leave=False)): color = (np.array(color_pal[ri % len(color_pal)]) * 255).astype("int") # get voxel_data lab = atlas.brain_labels[atlas.brain_labels.type_ == type_].loc[ reg, "label"] vox_data = np.swapaxes( np.array(atlas.voxel_data.loc[type_, "voxels"] == lab), 0, 2) """addl_vol = k3d.volume( vox_data, color_range=[0, 1], color_map=k3d.matplotlib_color_maps.Greys, samples=128, alpha_coef=10.0, bounds=bounds, compression_level=9, ) addl_vols.append(addl_vol)""" # convert to vtk format vtk_dat = vox2vtk(vox_data, zero_point=zero_point) # simplify polygon if polygon_simplification > 0: vtk_dat = vtk_reduce(vtk_dat, polygon_simplification=polygon_simplification, verbose=verbose) # shape of voxel data xs, ys, zs = vox_data.shape region_bounds = [ 0, (bounds[1] - bounds[0]) / zs, 0, (bounds[3] - bounds[2]) / ys, 0, (bounds[5] - bounds[4]) / xs, ] # print(np.shape(vox_data), region_bounds, np.sum(vox_data)) # create mesh plot region = k3d.vtk_poly_data( vtk_dat.GetOutput(), color=utils.rgb2hex(color[0], color[1], color[2]), bounds=region_bounds, ) regs.append(region) origins = [-5000, 0, 0, 0, -5000, 0, 0, 0, -5000] vectors = [10000, 0, 0, 0, 10000, 0, 0, 0, 10000] colors = [0xFF0000, 0xFF0000, 0x00FF00, 0x00FF00, 0x0000FF, 0x0000FF] vec = k3d.vectors(origins, vectors, colors=colors, line_width=100, use_head=True, head_size=1000) plot = k3d.plot(height=height, background_color=0xFEFEFE) plot += brain_volume for vol in addl_vols: plot += vol # plot regions for region in regs: plot += region plot += vec plot.display() plot.camera_auto_fit = False # plot.grid_visible = False # camera loc, center or rocation, angle (?) plot.camera = [-22977, 18052, 8696, 0, 0, 0, 0.14, -0.16, 0.997] widget_controllers(atlas, vec, plot, bounds, regions_to_plot) return plot, vec
def plot_2d_coordinates( atlas, point_in_voxels=None, point_in_um=None, regions_to_plot=["Brainregions"], brain_masked_image="T2", bg_image=None, region_alpha=0.25, line_alpha=0.5, zoom=6, ): """ Produce a 2d plot of brain data """ # get the point in either um or voxels if point_in_um is None: point_in_um = np.array( vox_to_um( point_in_voxels, atlas.voxel_data.loc["Brain", "affine"], atlas.um_mult, atlas.y_sinus_um_transform, )) point_in_voxels = np.array(point_in_voxels) if point_in_voxels is None: point_in_voxels = np.array( um_to_vox( point_in_um, atlas.voxel_data.loc["Brain", "affine"], atlas.um_mult, atlas.y_sinus_um_transform, )) point_in_um = np.array(point_in_um) # print the point in um print({ inverse_dict(atlas.axes_dict)[i]: int(point_in_um[i]) for i in range(3) }) # the type of image to plot label_data = { r2p: { "voxels": atlas.voxel_data.loc[r2p, "voxels"] } for r2p in regions_to_plot } brain_data = atlas.voxel_data.loc["Brain", "voxels"] zero_point = um_to_vox( [0, 0, 0], atlas.voxel_data.loc["Brain", "affine"], atlas.um_mult, atlas.y_sinus_um_transform, ) # set atlas a region for y sinus atlas.region_vox.loc["y_sinus"] = [ "y_sinus", "y_sinus", np.nan, np.nan, np.nan ] atlas.region_vox.loc["y_sinus", "coords_vox"] = zero_point # if no image data is provided, do not plot it if bg_image is not None: # get image data bg_image_data = atlas.voxel_data.loc[bg_image, "voxels"] affine = atlas.voxel_data.loc[bg_image, "affine"] # convert point in um into voxel coordinates for this data type point_in_voxels_image = um_to_vox(point_in_um, affine, atlas.um_mult, atlas.y_sinus_um_transform) print(point_in_voxels) x_img = bg_image_data[point_in_voxels_image[0], :, :].squeeze() y_img = bg_image_data[:, point_in_voxels_image[1], :].squeeze() z_img = bg_image_data[:, :, point_in_voxels_image[2]].squeeze() xm, ym, zm = vox_to_um([0, 0, 0], affine, atlas.um_mult, atlas.y_sinus_um_transform) xma, yma, zma = vox_to_um( list(np.shape(bg_image_data)), affine, atlas.um_mult, atlas.y_sinus_um_transform, ) img_bg_extent = np.array([[xm, xma], [ym, yma], [zm, zma]]) if brain_masked_image is not None: brain_masked_img_data = atlas.voxel_data.loc[brain_masked_image, "voxels"] # set voxels where there is no brain to 0 brain_masked_img_data[brain_data == 0] = 0 # get image data x_img_masked = brain_masked_img_data[ point_in_voxels[0], :, :].squeeze() y_img_masked = brain_masked_img_data[:, point_in_voxels[1], :].squeeze() z_img_masked = brain_masked_img_data[:, :, point_in_voxels[2]].squeeze() # get label data for r2p in regions_to_plot: x_lab = label_data[r2p]["voxels"][point_in_voxels[0], :, :].squeeze() y_lab = label_data[r2p]["voxels"][:, point_in_voxels[1], :].squeeze() z_lab = label_data[r2p]["voxels"][:, :, point_in_voxels[2]].squeeze() # subset labels dataframe for only the ones appearing here unique_labels = np.unique( list(x_lab.flatten()) + list(y_lab.flatten()) + list(z_lab.flatten())) label_data[r2p]["x_lab"] = x_lab label_data[r2p]["y_lab"] = y_lab label_data[r2p]["z_lab"] = z_lab label_data[r2p]["unique_labels"] = unique_labels # subset brain_labels dataframe for only the labels shown here regions_plotted = pd.concat([ atlas.brain_labels[(atlas.brain_labels.type_ == r2p) & ([ label in label_data[r2p]["unique_labels"] for label in atlas.brain_labels.label.values ])] for r2p in regions_to_plot ]) regions_plotted.index = np.arange(len(regions_plotted)) # reset values of xlab, ylab, zlab, and regions_plotted colors_plotted = 1 # the number of colors plotted so far for r2p in regions_to_plot: # get regions plotted in this r2p regions = regions_plotted[regions_plotted.type_.values == r2p].region.values # for each of those regions, change the values of x_lab, y_lab, z_lab for region in regions: reg_lab = regions_plotted[regions_plotted.region.values == region].label.values[0] label_data[r2p]["x_lab"][label_data[r2p]["x_lab"] == reg_lab] = colors_plotted label_data[r2p]["y_lab"][label_data[r2p]["y_lab"] == reg_lab] = colors_plotted label_data[r2p]["z_lab"][label_data[r2p]["z_lab"] == reg_lab] = colors_plotted # change the value of regions_plotted.label regions_plotted.loc[regions_plotted.region.values == region, "label"] = colors_plotted # update to next color colors_plotted += 1 # normalize colors to regions being plotted if len(regions_plotted) > 0: cmin = np.min(1) - 1e-4 cmax = len(regions_plotted.label.values) else: cmin = 1 cmax = 2 cnorm = matplotlib.colors.Normalize(vmin=cmin, vmax=cmax) # set colors specific to labels regions_plotted["colors"] = list( atlas.label_cmap(cnorm(regions_plotted.label.values))) # make a dataframe corresponding to each axis (which images belong in which axis) ax_list = [ [0, 0, "anterior-posterior"], [0, 1, "medial-lateral"], [1, 0, "dorsal-ventral"], ] fig, axs = plt.subplots(ncols=2, nrows=2, figsize=(2 * zoom, 2 * zoom)) for ax0, ax1, axis in ax_list: ax = axs[ax0, ax1] # get bounds # axis extents xlims, ylims = get_axis_bounds(atlas, axis=atlas.axes_dict[axis]) # plot background image if bg_image is not None: img_bg_extent_ax = np.concatenate( img_bg_extent[np.arange(3) != atlas.axes_dict[axis]]) xlims = img_bg_extent_ax[:2] ylims = img_bg_extent_ax[2:] img = [x_img, y_img, z_img][atlas.axes_dict[axis]] # rectify img[img < 0] = 0 if np.sum(np.abs(img)) > 0: ax.matshow(np.rot90(img**0.5), cmap=plt.cm.bone, extent=img_bg_extent_ax) else: # plot grid background plot_box_bg(ax, np.concatenate([xlims, ylims])) # get extent from voxels extent = np.concatenate( np.array([ [atlas.xmin, atlas.xmax], [atlas.ymin, atlas.ymax], [atlas.zmin, atlas.zmax], ])[np.arange(3) != atlas.axes_dict[axis]]) # plot shadow background shadow = np.rot90(brain_data.sum(axis=atlas.axes_dict[axis]) > 0) ax.matshow( shadow * 255, cmap=atlas.img_cmap, extent=extent, vmin=1e-4, vmax=1, alpha=0.5, ) # plot brain masked image if brain_masked_image is not None: img = [x_img_masked, y_img_masked, z_img_masked][atlas.axes_dict[axis]] if np.max(img) > 0: ax.matshow(np.rot90(img**0.5), cmap=atlas.img_cmap, extent=extent, vmin=1e-4) # plot labels for r2p in regions_to_plot: labels = [ label_data[r2p]["x_lab"], label_data[r2p]["y_lab"], label_data[r2p]["z_lab"], ][atlas.axes_dict[axis]] ax.matshow( np.rot90(labels), cmap=atlas.label_cmap, extent=extent, vmin=cmin, vmax=cmax, alpha=region_alpha, ) ax.set_xlim(xlims) ax.set_ylim(ylims) # plot line at y sinus ax.axhline(0, color=(1, 1, 1, line_alpha), ls="dashed") ax.axvline(0, color=(1, 1, 1, line_alpha), ls="dashed") # plot line at specified location x_um_loc, y_um_loc = point_in_um[np.arange(3) != atlas.axes_dict[axis]] ax.axhline(y_um_loc, color=(0, 0, 0, line_alpha), ls="dashed") ax.axvline(x_um_loc, color=(0, 0, 0, line_alpha), ls="dashed") # label regions patches = [] for idx, row in regions_plotted.iterrows(): patches.append(mpatches.Patch(color=row.colors, label=row.region)) axs[1, 1].legend(handles=patches, loc="center", ncol=2) plt.tight_layout() axs[1, 1].axis("off") return fig