예제 #1
0
    def reg_dd(change):
        # move location to the center of that region

        if change["type"] == "change" and change["name"] == "value":

            change_loc = utils.vox_to_um(
                atlas.region_vox.loc[change["new"], "coords_vox"],
                atlas.voxel_data.loc["Brain", "affine"],
                atlas.um_mult,
                atlas.y_sinus_um_transform,
            )
            dv_loc, ap_loc, ml_loc = change_loc

            vec.origins = [
                dv_loc - 5000,
                ap_loc,
                ml_loc,
                dv_loc,
                ap_loc - 5000,
                ml_loc,
                dv_loc,
                ap_loc,
                ml_loc - 5000,
            ]
            # set sliders
            y_slider.value = ap_loc
            x_slider.value = dv_loc
            z_slider.value = ml_loc

            # move the rotational axis
            pc = copy.deepcopy(plot.camera)
            plot.camera = pc[:3] + [dv_loc, ap_loc, ml_loc] + pc[-3:]
예제 #2
0
    def reg_dd(change):
        # move location to the center of that region

        if change["type"] == "change" and change["name"] == "value":

            change_loc = vox_to_um(
                atlas.region_vox.loc[change["new"], "coords_vox"],
                atlas.voxel_data.loc["Brain", "affine"],
                atlas.um_mult,
                atlas.y_sinus_um_transform,
            )
            reset_controls(change_loc)
예제 #3
0
파일: atlas.py 프로젝트: timsainb/birdbrain
    def update_y_sinus(self, updated_y_sinus):
        """update y sinus voxel location


        Arguments:
            updated_y_sinus {[list]} -- [list in voxels]
        """
        # update the y_sinus
        self.y_sinus_um_transform = np.array(updated_y_sinus)

        # 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,
        )
예제 #4
0
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
예제 #5
0
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
예제 #6
0
파일: atlas.py 프로젝트: timsainb/birdbrain
    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")