Exploring Neurons in Navis
TreeNeurons using navis.Overview
navis is a Python package for analysing, manipulating and visualizing neurons. Official documentation here.
Basic datatypes: neurons and neuron lists
navis knows three types of neurons:
TreeNeurons= skeletons, e.g. from CATMAIDMeshNeurons= meshes, e.g. from the hemibrain segmentationDotprops= points + tangent vectors (typically only used for NBLAST)
Collections of neurons are typically held in a specialized container: a NeuronList.
Neurons
In this notebook we will focus on skeletons - a.k.a. TreeNeurons - since this is what you get out of CATMAID. Let’s kick things off by having a look at what neurons look like once it’s loaded:
import navis
# Load one of the example neurons shipped with navis
# (these are olfactory projection neurons from the hemibrain data set)
n = navis.example_neurons(1, kind='skeleton')
# Print some basic info
n
WARNING: Could not load OpenGL library.
| type | navis.TreeNeuron |
|---|---|
| name | 1734350788 |
| id | 1734350788 |
| n_nodes | 4465 |
| n_connectors | None |
| n_branches | 603 |
| n_leafs | 619 |
| cable_length | 266457.994591 |
| soma | [4176] |
| units | 8 nanometer |
Above summary lists a couple of (computed) properties of the neuron. Each of those can also be accessed directly like so:
n.id
1734350788
There are many more properties that you might find interesting! Typing n. and pressing TAB should give auto-complete suggestions of available properties and methods. If your notebook editor has problems with that, you can fall back to using dir().
Here is an (incomplete) list of some of the more relevant properties:
bbox: bounding box of the neuroncable_length: cable lengthid: every neuron has an IDnodes: the SWC node table underlying the neuron
And some class methods:
reroot: reroot neuronplot2d/plot3d: plot the neuron (see also plotting turorial)copy: make and return a copyprune_twigs: remove small terminal twigs
As an example: this is how you get the ID of this neuron’s root node.
# Current root node of this neuron
n.root
array([1], dtype=int32)
Some of the properties such as .root or .ends are computed on-the-fly from the underlying raw data. For TreeNeurons that’s the node table (and its graph representation). The node table is a pandas DataFrame that looks effectively like a SWC:
# `.head()` gives us the first couple rows
n.nodes.head()
| node_id | label | x | y | z | radius | parent_id | type | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 15784.0 | 37250.0 | 28102.0 | 10.000000 | -1 | root |
| 1 | 2 | 0 | 15764.0 | 37230.0 | 28102.0 | 18.284300 | 1 | slab |
| 2 | 3 | 0 | 15744.0 | 37190.0 | 28142.0 | 34.721401 | 2 | slab |
| 3 | 4 | 0 | 15744.0 | 37150.0 | 28182.0 | 34.721401 | 3 | slab |
| 4 | 5 | 0 | 15704.0 | 37130.0 | 28242.0 | 34.721401 | 4 | slab |
The methods (such as .reroot) are short-hands for main navis functions:
# Reroot neuron to another node
n2 = n.reroot(new_root=2)
# Print the new root -> expect "2"
n2.root
array([2])
# Instead of calling the shorthand method, we can also do this
n3 = navis.reroot_neuron(n, new_root=2)
n3.root
array([2])
NeuronLists
In practice you will likely work with multiple neurons at a time. For that, navis has a convenient container: NeuronLists
# Get more than one example neuron
nl = navis.example_neurons(5)
# `nl` is a NeuronList
type(nl)
navis.core.neuronlist.NeuronList
# You can also create neuron lists yourself
my_nl = navis.NeuronList(n)
In many ways NeuronLists work like Python-lists with a couple of extras:
# Calling just the neuronlist produces a summary
nl
| type | name | id | n_nodes | n_connectors | n_branches | n_leafs | cable_length | soma | units | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | navis.TreeNeuron | 1734350788 | 1734350788 | 4465 | None | 603 | 619 | 266457.994591 | [4176] | 8 nanometer |
| 1 | navis.TreeNeuron | 1734350908 | 1734350908 | 4845 | None | 733 | 760 | 304277.007958 | [6] | 8 nanometer |
| 2 | navis.TreeNeuron | 722817260 | 722817260 | 4336 | None | 635 | 658 | 274910.568784 | None | 8 nanometer |
| 3 | navis.TreeNeuron | 754534424 | 754534424 | 4702 | None | 697 | 727 | 286742.998887 | [4] | 8 nanometer |
| 4 | navis.TreeNeuron | 754538881 | 754538881 | 4890 | None | 626 | 642 | 291434.992623 | [703] | 8 nanometer |
# Get a single neuron from the neuronlist
nl[1]
| type | navis.TreeNeuron |
|---|---|
| name | 1734350908 |
| id | 1734350908 |
| n_nodes | 4845 |
| n_connectors | None |
| n_branches | 733 |
| n_leafs | 760 |
| cable_length | 304277.007958 |
| soma | [6] |
| units | 8 nanometer |
neuronlists also support fancy indexing similar to numpy arrays:
# Get multiple neurons from the neuronlist
nl[[1, 2]]
| type | name | id | n_nodes | n_connectors | n_branches | n_leafs | cable_length | soma | units | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | navis.TreeNeuron | 1734350908 | 1734350908 | 4845 | None | 733 | 760 | 304277.007958 | [6] | 8 nanometer |
| 1 | navis.TreeNeuron | 722817260 | 722817260 | 4336 | None | 635 | 658 | 274910.568784 | None | 8 nanometer |
# Slicing is also supported
nl[1:3]
| type | name | id | n_nodes | n_connectors | n_branches | n_leafs | cable_length | soma | units | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | navis.TreeNeuron | 1734350908 | 1734350908 | 4845 | None | 733 | 760 | 304277.007958 | [6] | 8 nanometer |
| 1 | navis.TreeNeuron | 722817260 | 722817260 | 4336 | None | 635 | 658 | 274910.568784 | None | 8 nanometer |
Strings will be matched against the neurons’ names.
# Get neuron(s) by their name
nl['754534424']
| type | name | id | n_nodes | n_connectors | n_branches | n_leafs | cable_length | soma | units | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | navis.TreeNeuron | 754534424 | 754534424 | 4702 | None | 697 | 727 | 286742.998887 | [4] | 8 nanometer |
neuronlists have a special .idx indexer that let’s you select neurons by their ID
# Get neuron(s) by their ID
# -> note that for example neurons name == id
nl.idx[[754534424, 722817260]]
| type | name | id | n_nodes | n_connectors | n_branches | n_leafs | cable_length | soma | units | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | navis.TreeNeuron | 754534424 | 754534424 | 4702 | None | 697 | 727 | 286742.998887 | [4] | 8 nanometer |
| 1 | navis.TreeNeuron | 722817260 | 722817260 | 4336 | None | 635 | 658 | 274910.568784 | None | 8 nanometer |
# Access properties across neurons -> returns numpy arrays
nl.n_nodes
array([4465, 4845, 4336, 4702, 4890])
# Select neurons by given property
# -> this works with any boolean array
nl[nl.n_nodes >= 4500]
| type | name | id | n_nodes | n_connectors | n_branches | n_leafs | cable_length | soma | units | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | navis.TreeNeuron | 1734350908 | 1734350908 | 4845 | None | 733 | 760 | 304277.007958 | [6] | 8 nanometer |
| 1 | navis.TreeNeuron | 754534424 | 754534424 | 4702 | None | 697 | 727 | 286742.998887 | [4] | 8 nanometer |
| 2 | navis.TreeNeuron | 754538881 | 754538881 | 4890 | None | 626 | 642 | 291434.992623 | [703] | 8 nanometer |
Exercises:
- Select the first and the last neuron in the neuronlist
- Select all neurons with a soma
- Select all neurons with a soma and less than 300,000 cable length
Further reading: https://navis.readthedocs.io/en/latest/source/tutorials/neurons_intro.html
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.