Skip to content

Commit

Permalink
update tutorials:
Browse files Browse the repository at this point in the history
- rename tutorials from `plot_` to `tutorial_`
- add tutorial on plotting cortical cell types
- fix some broken links
  • Loading branch information
schlegelp committed Sep 24, 2024
1 parent fd16bfb commit 3631d1b
Show file tree
Hide file tree
Showing 41 changed files with 305 additions and 49 deletions.
14 changes: 7 additions & 7 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Properties:
| [`NeuronList.shape`][navis.NeuronList.shape] | {{ autosummary("navis.NeuronList.shape") }} |
| [`NeuronList.types`][navis.NeuronList.types]| {{ autosummary("navis.NeuronList.types") }} |

Please see the [tutorial on ``NeuronList``](../generated/gallery/plot_02_neuronlists_intro/) for more
Please see the [tutorial on ``NeuronList``](../generated/gallery/tutorial_basic_02_neuronlists_intro/) for more
information, including how to index them.

## Visualization
Expand Down Expand Up @@ -428,7 +428,7 @@ like to know which part of a neuron is inside a certain brain region.
## Transforming and Mirroring

Functions to transform spatial data, e.g. move neurons from one brain space to
another. Check out the [tutorials](../generated/gallery/6_misc/plot_01_transforms/) for examples on how to
another. Check out the [tutorials](../generated/gallery/6_misc/tutorial_misc_01_transforms/) for examples on how to
use them.

High-level functions:
Expand Down Expand Up @@ -606,7 +606,7 @@ imported explicitly as they are not imported at top level.
### NEURON simulator

Functions to facilitate creating models of neurons/networks. Please see
the [tutorials](../generated/gallery/3_interfaces/plot_00_interfaces_neuron/) for examples.
the [tutorials](../generated/gallery/3_interfaces/tutorial_interfaces_00_neuron/) for examples.

_Not imported at top level! Must be imported explicitly:_

Expand Down Expand Up @@ -734,12 +734,12 @@ These are the additional functions added by {{ navis }}:
| [`neuprint.fetch_skeletons()`][navis.interfaces.neuprint.fetch_skeletons] | {{ autosummary("navis.interfaces.neuprint.fetch_skeletons") }} |
| [`neuprint.fetch_mesh_neuron()`][navis.interfaces.neuprint.fetch_mesh_neuron] | {{ autosummary("navis.interfaces.neuprint.fetch_mesh_neuron") }} |

Please also check out the [tutorials](../generated/gallery/4_remote/plot_00_remote_neuprint/) for examples of how to fetch and work with data from neuPrint.
Please also check out the [tutorials](../generated/gallery/4_remote/tutorial_remote_00_neuprint/) for examples of how to fetch and work with data from neuPrint.

### InsectBrain DB API

Set of functions to grab data from [InsectBrain](https://www.insectbraindb.org)
which hosts some neurons and standard brains (see [tutorials](../generated/gallery/4_remote/plot_03_remote_insect_db/)).
which hosts some neurons and standard brains (see [tutorials](../generated/gallery/4_remote/tutorial_remote_03_insect_db/)).

_Not imported at top level! Must be imported explicitly:_

Expand All @@ -763,7 +763,7 @@ from navis.interfaces import insectbrain_db
Functions to be run inside [Blender 3D](https://www.blender.org/) and import
CATMAID data (see Examples). Please note that this requires Blender >2.8 as
earlier versions are shipped with older Python versions not supported by {{ navis }}.
See the [tutorials](../generated/gallery/3_interfaces/plot_02_interfaces_blender/) for an introduction of how to use {{ navis }} in
See the [tutorials](../generated/gallery/3_interfaces/tutorial_interfaces_02_blender/) for an introduction of how to use {{ navis }} in
Blender.

_Not imported at top level! Must be imported explicitly:_
Expand Down Expand Up @@ -864,7 +864,7 @@ from navis.interfaces import microns
| [`microns.fetch_neurons()`][navis.interfaces.microns.fetch_neurons] | {{ autosummary("navis.interfaces.microns.fetch_neurons") }} |
| [`microns.get_somas()`][navis.interfaces.microns.get_somas] | {{ autosummary("navis.interfaces.microns.get_somas") }} |

Please also see the [MICrONS tutorial](../generated/gallery/4_remote/plot_02_remote_microns/).
Please also see the [MICrONS tutorial](../generated/gallery/4_remote/tutorial_remote_02_microns/).


### R interface
Expand Down
2 changes: 1 addition & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ more consistent and easier to use.

##### Additions
- Added [Octarine](https://github.com/schlegelp/octarine) as the default backend for plotting from terminal
- New Function: [`navis.ivscc_features`][] computes some basic ICSCC features
- New Function: [`navis.ivscc_features`][] computes some basic IVSCC features
- New function: [`navis.graph.skeleton_adjacency_matrix`][] computes the node adjacency for skeletons
- New function: [`navis.graph.simplify_graph`][] simplifies skeleton graphs to only root, branch and leaf nodes while preserving branch length (i.e. weights)
- New [`NeuronList`][navis.NeuronList] method: [`get_neuron_attributes`][navis.NeuronList.get_neuron_attributes] is analagous to `dict.get`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
# %%
# There are a few other ways to construct a [`navis.TreeNeuron`][] (e.g. using a graph) - see the docstring for details.
#
# Also note that all {{ navis }} neurons can be stored to disk using `pickle` - see the [pickling tutorial](../plot_04_io_pickle).
# Also note that all {{ navis }} neurons can be stored to disk using `pickle` - see the [pickling tutorial](../tutorial_io_04_pickle).
#
# Hopefully the above has given you some entry points on how to load your data. See also the [I/O API reference](../../../api.md#importexport).
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
# [`navis.Volume`][] for details.
#
# This tutorial has hopefully given you some entry points on how to load your data. See also the [I/O API reference](../../../api.md#importexport).
# Also note that all {{ navis }} neurons can be stored to disk using ``pickle`` - see the [pickling tutorial](../plot_04_io_pickle).
# Also note that all {{ navis }} neurons can be stored to disk using ``pickle`` - see the [pickling tutorial](../tutorial_io_04_pickle).
#
# Please also keep in mind that you can also convert one neuron type into another - for example by skeletonizing [`MeshNeurons`][navis.MeshNeuron]
# (see also the API reference on [neuron conversion](../../../api.md#converting-between-types)).
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,4 @@

# %%
# There is no established format to store dotprops. But like all other neuron types in navis, you can pickle data for later (re)use
# - see the [pickling tutorial](../plot_04_io_pickle). See also the [I/O API reference](../../../api.md#importexport).
# - see the [pickling tutorial](../tutorial_io_04_pickle). See also the [I/O API reference](../../../api.md#importexport).
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@
#
# Above we demo'ed making a little GIF using matplotlib. While that's certainly fun, it's not
# very high production value. For high quality videos and renderings I recommend you check out
# the tutorial on navis' [Blender interface](../3_interfaces/plot_01_interfaces.blender). Here's a little taster:
# the tutorial on navis' [Blender interface](../3_interfaces/tutorial_interfaces_02_blender). Here's a little taster:
#
# <iframe width="560" height="315" src="https://www.youtube.com/embed/wl3sFG7WQJc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
#
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
This tutorial demonstrates how to adjust colors in NAVis plots.
By now, you should already have a basic understanding on how to plot neurons in {{ navis }} (2d vs 3d plots, the various
backends and plotting methods, etc.) - if not, check out the [plotting tutorial](../plot_00_plotting_intro).
backends and plotting methods, etc.) - if not, check out the [plotting tutorial](../tutorial_plotting_00_intro).
In this tutorial we will focus on how to finetune these plots by changing colors :rainbow:. We will demonstrate
this using `matplotlib` ([`plot2d`][navis.plot2d]) and `plotly` ([`plot3d`][navis.plot3d]) but everything shown here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
In this example we will demonstrate various ways to fine-tune plots with skeletons.
By now, you should already have a basic understanding on how to plot neurons in {{ navis }} (2d vs 3d plots, the various
backends and plotting methods, etc.) - if not, check out the [plotting tutorial](../plot_00_plotting_intro).
backends and plotting methods, etc.) - if not, check out the [plotting tutorial](../tutorial_plotting_00_intro).
We will focus on how to finetune [`plot2d`][navis.plot2d] plots because `matplotlib` is much more flexible than the
[`plot3d`][navis.plot3d] backends when it comes to rendering lines. That said: some of the things we show here will also
Expand Down
255 changes: 255 additions & 0 deletions docs/examples/1_plotting/tutorial_plotting_06_cortex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
"""
Cortical Neurons
================
This tutorial demonstrates how to plot cortical neurons.
In this exercise we will visualize morphological data from ["Integrated Morphoelectric and Transcriptomic Classification of Cortical GABAergic Cells"](https://www.cell.com/cell/pdf/S0092-8674(20)31254-X.pdf)
by Gouwens, Sorensen _et al._, Cell (2020). Specifically, we will re-create a plot similar to their
[Figure 4A](https://www.cell.com/cms/10.1016/j.cell.2020.09.057/asset/c684cc3f-ee17-4a36-98c9-e464a7ce8063/main.assets/gr4_lrg.jpg).
For brevity, we will use some fixed cell IDs and properties from the dataset. These were taken from the
[`20200711_patchseq_metadata_mouse.csv`](https://brainmapportal-live-4cc80a57cd6e400d854-f7fdcae.divio-media.net/filer_public/5e/2a/5e2a5936-61da-4e09-b6da-74ab97ce1b02/20200711_patchseq_metadata_mouse.csv)
file provided alongside the supplementary material of the paper:
"""

# %%

# The cell IDs we will use (it's the first 5 in the meta data file)
ids = [601506507, 601790961, 601803754, 601808698, 601810307]

# The normalized soma depths for these cells (also from the meta data file)
soma_depths = [0.36101451, 0.62182935, 0.16423996, 0.48303029, 0.2956563]

# %%
# ## Part I: Loading and Aligning Neurons
#
# First we need to load the neurons. Here, we will take them straight from their FTP server but you can of course download them first
# and load then from disk!

import navis

nl = navis.read_swc(
"ftp://download.brainlib.org:8811/biccn/zeng/pseq/morph/200526/",
limit=[f"{i}_transformed.swc" for i in ids], # Load only the files we need
fmt="{name,id:int}_transformed.swc", # Parse the name and id from the file name
)

# %%
# To make our lives a bit easier, we will attach the soma depth to the neurons as metadata:

nl.set_neuron_attributes(
soma_depths,
name="cell_soma_normalized_depth",
register=True
)

nl

# %%
# Next, we need to align the neurons according to their soma depth! The normalized `cell_soma_normalized_depth` should
# map to a physical range of `0` to `922.5861720311` microns.
#
# Let's demo with one neuron before we run this for all neurons:

# Grab one of the neurons
n = nl[0]

# This is the normalized soma depth:
print(f"Normalized soma depth: {n.cell_soma_normalized_depth}")

# %%
# The physical soma depth is simply the normalized depth multiplied by the total depth of the cortex.
# Note that we're positioning from the bottom - i.e. 922.586 will be at the surface and 0 at the bottom!
# This is to make our lifes easier when it comes to plotting: the origin in `matplotlib`
# figures is in the bottom left corner.

phys_y = (1 - n.cell_soma_normalized_depth) * 922.5861720311
print(f"Physical soma depth: {phys_y}")

# Current soma
print(f"Current soma coordinates: {n.soma_pos[0]}")

# %%
# We will now offset the neuron such that the soma is at `(0, 589.519, 0)`:

# %%
offset = [0, phys_y, 0] - n.soma_pos[0]
offset

# %%
# Moving or scaling neurons in {{ navis }} is super straight forward: adding, subtracting, dividing or multiplying neurons by a number or an
# `[x, y, z]` vector will change their coordinates:

# Move the neuron to the new centered position
n += offset

# Check the that the soma is now in the correct position
n.soma_pos[0]

# %%
# That looks good! Let's do it for all neurons:

# %%
for n in nl:
phys_y = (1 - n.cell_soma_normalized_depth) * 922.5861720311
offset = [0, phys_y, 0] - n.soma_pos[0]
n += offset

# %%
# Check that all soma positions are correct:
nl.soma_pos.reshape(-1, 3)

# %% [markdown]
# ## Part II: Plotting
#
# Now that we have loaded and aligned the neurons, let's recreate a plot similar to those in Figure 4A:

def plot_neurons(to_plot, color="purple", axon_color="magenta", offset=500):
"""Plot all neurons of a given transcriptomic type.
Parameters
----------
neurons : NeuronList
The aligned neurons to plot.
color : str
The color of the dendrites.
axon_color : str
The color of the axon.
offset : int
The offset between neurons along the x-axis.
Returns
-------
fig, ax
The matplotlib figure and axis.
"""
# Offset the neurons along the x-axis so that they don't overlap
to_plot = [n + [offset * i, 0, 0] for i, n in enumerate(to_plot)]

# The SWC files for this dataset include a `label` column which
# indicates the compartment type:
# 1 = soma
# 2 = axon
# 3 = dendrites
# We will use this `label` to color the neurons' compartments.

# Here we define a color palette for the compartments:
compartment_palette = {1: color, 2: axon_color, 3: color}

# Plot the neuron
fig, ax = navis.plot2d(
to_plot,
radius=False,
lw=1.5,
soma=dict(
fc="black", # soma fill color
ec="white", # highlight the soma with a white outline
radius=10, # override the default soma radius
),
color_by="label", # color by `label` column in node table
palette=compartment_palette,
figsize=(
len(to_plot) * 2,
10,
), # scale the figure size with the number of neurons
method="2d",
)

# Add the layer boundaries (top bound for each layer in microns)
layer_bounds = {
"L1": 0,
"L2/3": 115.1112491335,
"L4": 333.4658190171,
"L5": 453.6227158132,
"L6": 687.6482650269,
"L6b": 883.1308910545,
}

for layer, y in layer_bounds.items():
y = 922.5861720311 - y # flip the y-axis
# Add a dashed line
ax.axhline(y, color="gray", ls="--", lw=1)
# Add the layer name
ax.text(-300, y - 25, layer, color="gray", va="center", size=10)
# Add the bottom bound
ax.axhline(0, color="gray", ls="--", lw=1)

# Set the axis y limits according to the layers
ax.set_ylim(-10, 930)

# Hide axes
ax.axis("off")

return fig, ax


fig, ax = plot_neurons(nl)

# %% [markdown]
# Next, let's calculate the distribution of cable lengths:
#
# We're going to be cheap here and simply generate a histogram over the node positions.
# To make this representative, we should make sure that the number of nodes per unit of cable
# is homogeneous across neurons. For that we will resample the neurons:
print(
f"Sampling rate (nodes per micron of cable) before resampling: {nl.sampling_resolution.mean():.2f}"
)

# Resample to 2 nodes per micron
resampled = navis.resample_skeleton(
nl,
resample_to=0.5,
map_columns="label", # make sure label column is carried over
)

print(
f"Sampling rate (nodes per micron of cable) after resampling: {resampled.sampling_resolution.mean():.2f}"
)

# %%
# Get the combined nodes table:
nodes = resampled.nodes
nodes.head()

# %%
# Now we can plot the distribution of cable lengths for the neurons of the type we're interested in:

import seaborn as sns
from mpl_toolkits.axes_grid1 import make_axes_locatable

# Plot the neurons using the function we defined earlier
fig, ax = plot_neurons(nl)

# Add a new axis to the right of the main plot
divider = make_axes_locatable(ax)
ax_hist = divider.append_axes("right", size=0.75, pad=0.05)

# Add histograms
# For axon:
sns.kdeplot(
data=nodes[nodes.label == 2], y="y", ax=ax_hist, color="purple", linewidth=1.5
)
# For the rest:
sns.kdeplot(
data=nodes[nodes.label != 2], y="y", ax=ax_hist, color="magenta", linewidth=1.5
)

# Add soma positions
soma_pos = nl.soma_pos.reshape(-1, 3)
ax_hist.scatter([0] * len(soma_pos), soma_pos[:, 1], color="black", s=10, clip_on=False)

# Set same axis limits as the main plot
ax_hist.set_ylim(-10, 930)

# Hide axes
ax_hist.set_axis_off()

# %%
# ## Acknowledgements
#
# We thank Staci Sorensen and Casey Schneider-Mizell from the Allen Institute for Brain Science
# for helping with extra information and data for this tutorial!
Original file line number Diff line number Diff line change
Expand Up @@ -351,5 +351,5 @@
# About half the presynapses are in the LH (most of the rest will be in the MB calyx). The large majority of postsynapses are
# outside the LH in the antennal lobe where this neuron has its dendrites.
#
# That's it for now! Please see the [NBLAST tutorial](../../05_nblast/plot_00_nblast_intro.py) for morphological comparisons using NBLAST and the
# That's it for now! Please see the [NBLAST tutorial](../../05_nblast/tutorial_nblast_00_intro.py) for morphological comparisons using NBLAST and the
# [API reference](../../../api.md#neuron-morphology) for a full list of morphology-related functions.
Loading

0 comments on commit 3631d1b

Please sign in to comment.