|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "id": "5823062b-e25f-45aa-96d7-65c83845af61", |
| 6 | + "metadata": {}, |
| 7 | + "source": [ |
| 8 | + "# Working with cortical streamlines\n", |
| 9 | + "\n", |
| 10 | + "In this example we walk through various methods that use the Allen streamlines. Streamlines are the paths that connect the surface of the isocortex to the lower white matter surface while following the curvature of these surfaces." |
| 11 | + ] |
| 12 | + }, |
| 13 | + { |
| 14 | + "cell_type": "markdown", |
| 15 | + "id": "46e7e0e7-4295-40a5-a5b3-1bc0fc84f07e", |
| 16 | + "metadata": {}, |
| 17 | + "source": [ |
| 18 | + "## Depth lookup\n", |
| 19 | + "We can use the streamlines to find the depth of coordinates in 3D space relative to the surface of the cortex. Note as the streamlines are only defined in the cortex so this lookup will only work for coordinates that lie within the Isocortex of the Allen atlas volume. In this example we obtain the depths in percentage, where 0 % indicates the surface of the isocortex and 100 % the white matter boundary." |
| 20 | + ] |
| 21 | + }, |
| 22 | + { |
| 23 | + "cell_type": "code", |
| 24 | + "execution_count": null, |
| 25 | + "id": "0a3fddd1-9ddd-4dca-b256-3dd7d29bad67", |
| 26 | + "metadata": {}, |
| 27 | + "outputs": [], |
| 28 | + "source": [ |
| 29 | + "from iblatlas.streamlines.utils import xyz_to_depth\n", |
| 30 | + "from iblatlas.atlas import AllenAtlas\n", |
| 31 | + "import numpy as np\n", |
| 32 | + "import matplotlib.pyplot as plt\n", |
| 33 | + "\n", |
| 34 | + "ba = AllenAtlas()\n", |
| 35 | + "# In this example we are going to get out the coordinates of the voxels that lie within the region MOp\n", |
| 36 | + "region_id = ba.regions.acronym2index('MOp')[1][0][0]\n", |
| 37 | + "# MOp is in the beryl mapping so we map our label volume to this mapping\n", |
| 38 | + "ba.label = ba.regions.mappings['Beryl-lr'][ba.label]\n", |
| 39 | + "# These are the indices in the volume, order is AP, ML, DV\n", |
| 40 | + "ixyz = np.where(ba.label == region_id)\n", |
| 41 | + "# Convert these to xyz coordinates relative to bregma in order ML, AP, DV\n", |
| 42 | + "xyz = ba.bc.i2xyz(np.c_[ixyz[1], ixyz[0], ixyz[2]])\n", |
| 43 | + "\n", |
| 44 | + "depth_per = xyz_to_depth(xyz) * 100\n", |
| 45 | + "\n", |
| 46 | + "# We can assign a volume\n", |
| 47 | + "depth_per_vol = np.full(ba.image.shape, np.nan)\n", |
| 48 | + "depth_per_vol[ixyz[0], ixyz[1], ixyz[2]] = depth_per\n", |
| 49 | + "\n", |
| 50 | + "fig, ax = plt.subplots()\n", |
| 51 | + "ba.plot_cslice(620/1e6, volume='image', ax=ax)\n", |
| 52 | + "ba.plot_cslice(620/1e6, volume='volume', region_values=depth_per_vol, ax=ax, cmap='viridis', vmin=0, vmax=100)\n", |
| 53 | + "ax.set_axis_off()\n", |
| 54 | + "cbar = fig.colorbar(ax.get_images()[1], ax=ax)\n", |
| 55 | + "cbar.set_label('Depth from surface of cortex (%)')" |
| 56 | + ] |
| 57 | + }, |
| 58 | + { |
| 59 | + "cell_type": "markdown", |
| 60 | + "id": "c1da61f0-7281-45d8-8bd7-33be0d373302", |
| 61 | + "metadata": {}, |
| 62 | + "source": [ |
| 63 | + "We can also do this look up in um relative to the surface of the cortex." |
| 64 | + ] |
| 65 | + }, |
| 66 | + { |
| 67 | + "cell_type": "code", |
| 68 | + "execution_count": null, |
| 69 | + "id": "047509db-fb6b-46f3-8cb2-817b12223bed", |
| 70 | + "metadata": {}, |
| 71 | + "outputs": [], |
| 72 | + "source": [ |
| 73 | + "depth_um = xyz_to_depth(xyz, per=False)\n", |
| 74 | + "\n", |
| 75 | + "# We can assign a volume\n", |
| 76 | + "depth_um_vol = np.full(ba.image.shape, np.nan)\n", |
| 77 | + "depth_um_vol[ixyz[0], ixyz[1], ixyz[2]] = depth_um\n", |
| 78 | + "\n", |
| 79 | + "fig, ax = plt.subplots()\n", |
| 80 | + "ba.plot_cslice(620/1e6, volume='image', ax=ax)\n", |
| 81 | + "ba.plot_cslice(620/1e6, volume='volume', region_values=depth_um_vol, ax=ax, cmap='tab20', vmin=0, vmax=2000)\n", |
| 82 | + "ax.set_axis_off()\n", |
| 83 | + "cbar = fig.colorbar(ax.get_images()[1], ax=ax)\n", |
| 84 | + "cbar.set_label('Depth from surface of cortex (um)')" |
| 85 | + ] |
| 86 | + }, |
| 87 | + { |
| 88 | + "cell_type": "markdown", |
| 89 | + "id": "bdbe5c0b-d7e3-441e-82ab-8bbcbd013bdd", |
| 90 | + "metadata": {}, |
| 91 | + "source": [ |
| 92 | + "## Flatmap projection\n", |
| 93 | + "The streamlines can also be used to project a volume or xyz coordinates onto a flattened view of the dorsal cortex. The volume or points can be aggregated along the streamlines in different ways, e.g max, mean, median.\n", |
| 94 | + "\n", |
| 95 | + "In this example we will project the Allen Atlas dwi volume onto the dorsal cortex projection. We will take the maximum value along the streamline for each voxel on the surface" |
| 96 | + ] |
| 97 | + }, |
| 98 | + { |
| 99 | + "cell_type": "code", |
| 100 | + "execution_count": null, |
| 101 | + "id": "7b61405d-8589-4cb8-8afc-6f8a87dc4588", |
| 102 | + "metadata": {}, |
| 103 | + "outputs": [], |
| 104 | + "source": [ |
| 105 | + "from iblatlas.streamlines.utils import project_volume_onto_flatmap\n", |
| 106 | + "\n", |
| 107 | + "ba = AllenAtlas(25)\n", |
| 108 | + "proj, fig, ax = project_volume_onto_flatmap(ba.image, res_um=25, aggr='max', plot=True, cmap='bone')\n", |
| 109 | + "ax.set_axis_off()" |
| 110 | + ] |
| 111 | + }, |
| 112 | + { |
| 113 | + "cell_type": "markdown", |
| 114 | + "id": "702b9abd-f97d-4a4e-967a-e9967e630293", |
| 115 | + "metadata": {}, |
| 116 | + "source": [ |
| 117 | + "We can also do the same with xyz coordinates (we will use the same xyz coordinates for the region MOp and assign random values to each coordinate)" |
| 118 | + ] |
| 119 | + }, |
| 120 | + { |
| 121 | + "cell_type": "code", |
| 122 | + "execution_count": null, |
| 123 | + "id": "19bf31f8-8f22-4f0e-91bb-7998f9379dc6", |
| 124 | + "metadata": {}, |
| 125 | + "outputs": [], |
| 126 | + "source": [ |
| 127 | + "from iblatlas.streamlines.utils import project_points_onto_flatmap, get_mask\n", |
| 128 | + "\n", |
| 129 | + "# Get a mask to plot our results on, options are 'image', 'annotation' or 'boundary\n", |
| 130 | + "mask = get_mask('boundary')\n", |
| 131 | + "\n", |
| 132 | + "values = np.random.rand(xyz.shape[0])\n", |
| 133 | + "\n", |
| 134 | + "proj = project_points_onto_flatmap(xyz, values, aggr='mean', plot=False)\n", |
| 135 | + "# Mask values with 0 with nan for display purposes\n", |
| 136 | + "proj[proj == 0] = np.nan\n", |
| 137 | + "\n", |
| 138 | + "fig, ax = plt.subplots()\n", |
| 139 | + "ax.imshow(mask, cmap='Greys')\n", |
| 140 | + "ax.imshow(proj)\n", |
| 141 | + "ax.set_axis_off()" |
| 142 | + ] |
| 143 | + } |
| 144 | + ], |
| 145 | + "metadata": { |
| 146 | + "kernelspec": { |
| 147 | + "display_name": "Python 3 (ipykernel)", |
| 148 | + "language": "python", |
| 149 | + "name": "python3" |
| 150 | + }, |
| 151 | + "language_info": { |
| 152 | + "codemirror_mode": { |
| 153 | + "name": "ipython", |
| 154 | + "version": 3 |
| 155 | + }, |
| 156 | + "file_extension": ".py", |
| 157 | + "mimetype": "text/x-python", |
| 158 | + "name": "python", |
| 159 | + "nbconvert_exporter": "python", |
| 160 | + "pygments_lexer": "ipython3", |
| 161 | + "version": "3.11.9" |
| 162 | + } |
| 163 | + }, |
| 164 | + "nbformat": 4, |
| 165 | + "nbformat_minor": 5 |
| 166 | +} |
0 commit comments