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
def __init__( self, dset_dir, label_cmap=None, um_mult=100, img_cmap=None, smoothing=[], smoothing_sigma=2, updated_y_sinus=None, species=None, password=None, ): # path of delineations delin_path = os.path.join(os.path.abspath(dset_dir), "delineations/") if species == "canary": self.brain_labels = pd.read_csv( "../../assets/csv/canary_regions.csv", index_col="region") self.brain_labels.columns = ["label", "region", "type_"] dl.get_canary_data() elif species == "starling": dl.get_starling_data() # path of labels text_files = glob(os.path.join(delin_path, "*.txt")) # transcription labels ['label', 'region', 'type_'] if len(text_files) > 0: self.brain_labels = utils.get_brain_labels(text_files) elif species == "zebra_finch": self.brain_labels = pd.read_csv( "../../assets/csv/zebra_finch_regions.csv", index_col="region") self.brain_labels.columns = ["label", "region", "type_"] dl.get_zebra_finch_data(password) elif species == "pigeon": self.brain_labels = pd.read_csv( "../../assets/csv/pigeon_regions.csv", index_col="region") self.brain_labels.columns = ["label", "region", "type_"] self.systems_delineations = dl.get_pigeon_data() elif species == "mustached_bat": self.brain_labels = dl.get_mustached_bat_data() # how axes labels relate to affine transformed data in voxels self.axes_dict = { "medial-lateral": 0, "anterior-posterior": 1, "dorsal-ventral": 2, } self.inverse_axes_dict = inverse_dict(self.axes_dict) # path of images if species == "mustached_bat": img_files = glob(os.path.join(delin_path, "*.nii")) + glob( os.path.join(dset_dir, "*.nii")) else: img_files = glob(os.path.join(delin_path, "*.img")) + glob( os.path.join(dset_dir, "*.img")) # images from each type of scan, as well as transcribed locations ['type_', 'src', 'voxels'] self.voxel_data = utils.get_voxel_data(img_files) if species == "pigeon": dl.join_data_pigeon(self) # smooth the whole brain because the atlas is a bit noisy for img in smoothing: self.voxel_data.loc[img, "voxels"] = utils.smooth_voxels( self.voxel_data.loc[img, "voxels"], sigma=smoothing_sigma) # for some reason, units are um/100 in this dataset self.um_mult = um_mult # make a shadow background for plots self.create_shadows() # set the colormap for labels if label_cmap is None: self.label_cmap = label_cmap = plt.cm.tab20 self.label_cmap.set_under(color=(0, 0, 0, 0)) else: self.label_cmap = label_cmap # set the colormap for images if img_cmap is None: self.img_cmap = img_cmap = plt.cm.Greys self.img_cmap.set_under(color=(0, 0, 0, 0)) else: self.img_cmap = img_cmap # unless the y sinus is updated from the original location (from the files), there is no transform self.y_sinus_um_transform = [0, 0, 0] # get the boundaries of voxel-space in um affine = self.voxel_data.loc["Brain", "affine"] voxels = self.voxel_data.loc["Brain", "voxels"] self.xmin, self.ymin, self.zmin = vox_to_um(np.array([0, 0, 0]), affine, self.um_mult, self.y_sinus_um_transform) self.xmax, self.ymax, self.zmax = vox_to_um( np.array(np.shape(voxels)) - 1, affine, self.um_mult, self.y_sinus_um_transform, ) if updated_y_sinus is not None: self.update_y_sinus(updated_y_sinus) # voxels for individual regions ['region', 'type_', 'nucleus_ID', 'region_bounds', 'coords_vox', 'voxels'] self.region_vox = utils.get_region_voxels(self) # determine where the brain exists (for plotting) self.determine_brain_limits() print("Atlas created")