From 3631d1bc539cfc084c1d2b2099ab19ab8288c33b Mon Sep 17 00:00:00 2001 From: Philipp Schlegel Date: Tue, 24 Sep 2024 10:44:36 +0100 Subject: [PATCH] update tutorials: - rename tutorials from `plot_` to `tutorial_` - add tutorial on plotting cortical cell types - fix some broken links --- docs/api.md | 14 +- docs/changelog.md | 2 +- ...eletons.py => tutorial_io_00_skeletons.py} | 2 +- ..._io_meshes.py => tutorial_io_01_meshes.py} | 2 +- ...dotprops.py => tutorial_io_02_dotprops.py} | 2 +- ..._io_pickle.py => tutorial_io_04_pickle.py} | 0 ...intro.py => tutorial_plotting_00_intro.py} | 2 +- ...lors.py => tutorial_plotting_01_colors.py} | 2 +- ...tting_1d.py => tutorial_plotting_02_1d.py} | 0 ...g_dend.py => tutorial_plotting_03_dend.py} | 0 ...s.py => tutorial_plotting_04_skeletons.py} | 2 +- ...depth.py => tutorial_plotting_05_depth.py} | 0 .../1_plotting/tutorial_plotting_06_cortex.py | 255 ++++++++++++++++++ ...g_xkcd.py => tutorial_plotting_07_xkcd.py} | 0 ...te.py => tutorial_morpho_00_manipulate.py} | 2 +- ...alyze.py => tutorial_morpho_01_analyze.py} | 6 +- ...on.py => tutorial_interfaces_00_neuron.py} | 0 ...2.py => tutorial_interfaces_01_neuron2.py} | 2 +- ...r.py => tutorial_interfaces_02_blender.py} | 0 ...rint.py => tutorial_remote_00_neuprint.py} | 0 ...e.py => tutorial_remote_01_cloudvolume.py} | 2 +- ...crons.py => tutorial_remote_02_microns.py} | 2 +- ..._db.py => tutorial_remote_03_insect_db.py} | 0 ...t_intro.py => tutorial_nblast_00_intro.py} | 4 +- ...ast_smat.py => tutorial_nblast_03_smat.py} | 0 ...y => zzz_tutorial_nblast_01_flycircuit.py} | 0 ...py => zzz_tutorial_nblast_02_hemibrain.py} | 0 ...ss.py => tutorial_misc_00_multiprocess.py} | 0 ...orms.py => tutorial_misc_01_transforms.py} | 0 ...neurons.py => tutorial_basic_00_basics.py} | 4 +- ..._intro.py => tutorial_basic_01_neurons.py} | 2 +- ...ro.py => tutorial_basic_02_neuronlists.py} | 2 +- docs/index.md | 18 +- docs/quickstart.md | 8 +- mkdocs.yml | 1 + navis/morpho/ivscc.py | 6 +- navis/plotting/d.py | 2 +- navis/plotting/dd.py | 2 +- navis/plotting/ddd.py | 2 +- navis/plotting/flat.py | 4 +- tests/test_tutorials.py | 2 +- 41 files changed, 305 insertions(+), 49 deletions(-) rename docs/examples/0_io/{plot_00_io_skeletons.py => tutorial_io_00_skeletons.py} (98%) rename docs/examples/0_io/{plot_01_io_meshes.py => tutorial_io_01_meshes.py} (98%) rename docs/examples/0_io/{plot_02_io_dotprops.py => tutorial_io_02_dotprops.py} (95%) rename docs/examples/0_io/{plot_04_io_pickle.py => tutorial_io_04_pickle.py} (100%) rename docs/examples/1_plotting/{plot_00_plotting_intro.py => tutorial_plotting_00_intro.py} (99%) rename docs/examples/1_plotting/{plot_01_plotting_colors.py => tutorial_plotting_01_colors.py} (99%) rename docs/examples/1_plotting/{plot_02_plotting_1d.py => tutorial_plotting_02_1d.py} (100%) rename docs/examples/1_plotting/{plot_03_plotting_dend.py => tutorial_plotting_03_dend.py} (100%) rename docs/examples/1_plotting/{plot_04_plotting_skeletons.py => tutorial_plotting_04_skeletons.py} (97%) rename docs/examples/1_plotting/{plot_05_plotting_depth.py => tutorial_plotting_05_depth.py} (100%) create mode 100644 docs/examples/1_plotting/tutorial_plotting_06_cortex.py rename docs/examples/1_plotting/{plot_07_plotting_xkcd.py => tutorial_plotting_07_xkcd.py} (100%) rename docs/examples/2_morpho/{plot_00_morpho_manipulate.py => tutorial_morpho_00_manipulate.py} (99%) rename docs/examples/2_morpho/{plot_01_morpho_analyze.py => tutorial_morpho_01_analyze.py} (97%) rename docs/examples/3_interfaces/{plot_00_interfaces_neuron.py => tutorial_interfaces_00_neuron.py} (100%) rename docs/examples/3_interfaces/{plot_01_interfaces_neuron2.py => tutorial_interfaces_01_neuron2.py} (98%) rename docs/examples/3_interfaces/{plot_02_interfaces_blender.py => tutorial_interfaces_02_blender.py} (100%) rename docs/examples/4_remote/{plot_00_remote_neuprint.py => tutorial_remote_00_neuprint.py} (100%) rename docs/examples/4_remote/{plot_01_remote_cloudvolume.py => tutorial_remote_01_cloudvolume.py} (97%) rename docs/examples/4_remote/{plot_02_remote_microns.py => tutorial_remote_02_microns.py} (99%) rename docs/examples/4_remote/{plot_03_remote_insect_db.py => tutorial_remote_03_insect_db.py} (100%) rename docs/examples/5_nblast/{plot_00_nblast_intro.py => tutorial_nblast_00_intro.py} (99%) rename docs/examples/5_nblast/{plot_03_nblast_smat.py => tutorial_nblast_03_smat.py} (100%) rename docs/examples/5_nblast/{zzz_no_plot_01_nblast_flycircuit.py => zzz_tutorial_nblast_01_flycircuit.py} (100%) rename docs/examples/5_nblast/{zzz_no_plot_02_nblast_hemibrain.py => zzz_tutorial_nblast_02_hemibrain.py} (100%) rename docs/examples/6_misc/{plot_00_misc_multiprocess.py => tutorial_misc_00_multiprocess.py} (100%) rename docs/examples/6_misc/{plot_01_transforms.py => tutorial_misc_01_transforms.py} (100%) rename docs/examples/{plot_00_basic_neurons.py => tutorial_basic_00_basics.py} (95%) rename docs/examples/{plot_01_neurons_intro.py => tutorial_basic_01_neurons.py} (99%) rename docs/examples/{plot_02_neuronlists_intro.py => tutorial_basic_02_neuronlists.py} (99%) diff --git a/docs/api.md b/docs/api.md index b97ced7e..897b2301 100644 --- a/docs/api.md +++ b/docs/api.md @@ -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 @@ -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: @@ -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:_ @@ -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:_ @@ -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:_ @@ -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 diff --git a/docs/changelog.md b/docs/changelog.md index 62eb06a5..42f99171 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -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` diff --git a/docs/examples/0_io/plot_00_io_skeletons.py b/docs/examples/0_io/tutorial_io_00_skeletons.py similarity index 98% rename from docs/examples/0_io/plot_00_io_skeletons.py rename to docs/examples/0_io/tutorial_io_00_skeletons.py index 3bd20181..af1c196a 100644 --- a/docs/examples/0_io/plot_00_io_skeletons.py +++ b/docs/examples/0_io/tutorial_io_00_skeletons.py @@ -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). # diff --git a/docs/examples/0_io/plot_01_io_meshes.py b/docs/examples/0_io/tutorial_io_01_meshes.py similarity index 98% rename from docs/examples/0_io/plot_01_io_meshes.py rename to docs/examples/0_io/tutorial_io_01_meshes.py index a9ab8151..ab87ed9c 100644 --- a/docs/examples/0_io/plot_01_io_meshes.py +++ b/docs/examples/0_io/tutorial_io_01_meshes.py @@ -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)). \ No newline at end of file diff --git a/docs/examples/0_io/plot_02_io_dotprops.py b/docs/examples/0_io/tutorial_io_02_dotprops.py similarity index 95% rename from docs/examples/0_io/plot_02_io_dotprops.py rename to docs/examples/0_io/tutorial_io_02_dotprops.py index e2029941..cab0166d 100644 --- a/docs/examples/0_io/plot_02_io_dotprops.py +++ b/docs/examples/0_io/tutorial_io_02_dotprops.py @@ -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). diff --git a/docs/examples/0_io/plot_04_io_pickle.py b/docs/examples/0_io/tutorial_io_04_pickle.py similarity index 100% rename from docs/examples/0_io/plot_04_io_pickle.py rename to docs/examples/0_io/tutorial_io_04_pickle.py diff --git a/docs/examples/1_plotting/plot_00_plotting_intro.py b/docs/examples/1_plotting/tutorial_plotting_00_intro.py similarity index 99% rename from docs/examples/1_plotting/plot_00_plotting_intro.py rename to docs/examples/1_plotting/tutorial_plotting_00_intro.py index 865c8d50..a1e9f397 100644 --- a/docs/examples/1_plotting/plot_00_plotting_intro.py +++ b/docs/examples/1_plotting/tutorial_plotting_00_intro.py @@ -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: # # # diff --git a/docs/examples/1_plotting/plot_01_plotting_colors.py b/docs/examples/1_plotting/tutorial_plotting_01_colors.py similarity index 99% rename from docs/examples/1_plotting/plot_01_plotting_colors.py rename to docs/examples/1_plotting/tutorial_plotting_01_colors.py index fec9c8ea..5f42be3d 100644 --- a/docs/examples/1_plotting/plot_01_plotting_colors.py +++ b/docs/examples/1_plotting/tutorial_plotting_01_colors.py @@ -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 diff --git a/docs/examples/1_plotting/plot_02_plotting_1d.py b/docs/examples/1_plotting/tutorial_plotting_02_1d.py similarity index 100% rename from docs/examples/1_plotting/plot_02_plotting_1d.py rename to docs/examples/1_plotting/tutorial_plotting_02_1d.py diff --git a/docs/examples/1_plotting/plot_03_plotting_dend.py b/docs/examples/1_plotting/tutorial_plotting_03_dend.py similarity index 100% rename from docs/examples/1_plotting/plot_03_plotting_dend.py rename to docs/examples/1_plotting/tutorial_plotting_03_dend.py diff --git a/docs/examples/1_plotting/plot_04_plotting_skeletons.py b/docs/examples/1_plotting/tutorial_plotting_04_skeletons.py similarity index 97% rename from docs/examples/1_plotting/plot_04_plotting_skeletons.py rename to docs/examples/1_plotting/tutorial_plotting_04_skeletons.py index e74d75ff..250ed31a 100644 --- a/docs/examples/1_plotting/plot_04_plotting_skeletons.py +++ b/docs/examples/1_plotting/tutorial_plotting_04_skeletons.py @@ -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 diff --git a/docs/examples/1_plotting/plot_05_plotting_depth.py b/docs/examples/1_plotting/tutorial_plotting_05_depth.py similarity index 100% rename from docs/examples/1_plotting/plot_05_plotting_depth.py rename to docs/examples/1_plotting/tutorial_plotting_05_depth.py diff --git a/docs/examples/1_plotting/tutorial_plotting_06_cortex.py b/docs/examples/1_plotting/tutorial_plotting_06_cortex.py new file mode 100644 index 00000000..3a5adbaf --- /dev/null +++ b/docs/examples/1_plotting/tutorial_plotting_06_cortex.py @@ -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! \ No newline at end of file diff --git a/docs/examples/1_plotting/plot_07_plotting_xkcd.py b/docs/examples/1_plotting/tutorial_plotting_07_xkcd.py similarity index 100% rename from docs/examples/1_plotting/plot_07_plotting_xkcd.py rename to docs/examples/1_plotting/tutorial_plotting_07_xkcd.py diff --git a/docs/examples/2_morpho/plot_00_morpho_manipulate.py b/docs/examples/2_morpho/tutorial_morpho_00_manipulate.py similarity index 99% rename from docs/examples/2_morpho/plot_00_morpho_manipulate.py rename to docs/examples/2_morpho/tutorial_morpho_00_manipulate.py index bd8c73e5..c83420ae 100644 --- a/docs/examples/2_morpho/plot_00_morpho_manipulate.py +++ b/docs/examples/2_morpho/tutorial_morpho_00_manipulate.py @@ -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. diff --git a/docs/examples/2_morpho/plot_01_morpho_analyze.py b/docs/examples/2_morpho/tutorial_morpho_01_analyze.py similarity index 97% rename from docs/examples/2_morpho/plot_01_morpho_analyze.py rename to docs/examples/2_morpho/tutorial_morpho_01_analyze.py index 1c616d74..f61c904b 100644 --- a/docs/examples/2_morpho/plot_01_morpho_analyze.py +++ b/docs/examples/2_morpho/tutorial_morpho_01_analyze.py @@ -121,7 +121,7 @@ # %% # ## Sholl Analysis # -# For an example of a Sholl analyses, check out the [MICrONS tutorial](../4_remote/plot_02_remote_microns). +# For an example of a Sholl analyses, check out the [MICrONS tutorial](../4_remote/tutorial_remote_02_microns). # # ## Geodesic Distances # @@ -245,5 +245,5 @@ # %% # As you can see in the heatmap, the dendrites and the axon nicely separate. # -# That's it for now! Please see the [NBLAST tutorial](../../5_nblast/plot_00_nblast_intro) for morphological comparisons using NBLAST and -# the :[API reference](../../../api.md) for a full list of morphology-related functions. +# That's it for now! Please see the [NBLAST tutorial](../../5_nblast/tutorial_nblast_00_intro) for morphological comparisons using NBLAST and +# the [API reference](../../../api.md) for a full list of morphology-related functions. diff --git a/docs/examples/3_interfaces/plot_00_interfaces_neuron.py b/docs/examples/3_interfaces/tutorial_interfaces_00_neuron.py similarity index 100% rename from docs/examples/3_interfaces/plot_00_interfaces_neuron.py rename to docs/examples/3_interfaces/tutorial_interfaces_00_neuron.py diff --git a/docs/examples/3_interfaces/plot_01_interfaces_neuron2.py b/docs/examples/3_interfaces/tutorial_interfaces_01_neuron2.py similarity index 98% rename from docs/examples/3_interfaces/plot_01_interfaces_neuron2.py rename to docs/examples/3_interfaces/tutorial_interfaces_01_neuron2.py index d7e52b2f..ba24d546 100644 --- a/docs/examples/3_interfaces/plot_01_interfaces_neuron2.py +++ b/docs/examples/3_interfaces/tutorial_interfaces_01_neuron2.py @@ -4,7 +4,7 @@ In this tutorial you will learn to visualize a compartment neuron model. -We will jump right in, so please make sure to have a look at the [introductory NEURON tutorial](../plot_00_interfaces_neuron) +We will jump right in, so please make sure to have a look at the [introductory NEURON tutorial](../tutorial_interfaces_00_neuron) first. ## Setup the model diff --git a/docs/examples/3_interfaces/plot_02_interfaces_blender.py b/docs/examples/3_interfaces/tutorial_interfaces_02_blender.py similarity index 100% rename from docs/examples/3_interfaces/plot_02_interfaces_blender.py rename to docs/examples/3_interfaces/tutorial_interfaces_02_blender.py diff --git a/docs/examples/4_remote/plot_00_remote_neuprint.py b/docs/examples/4_remote/tutorial_remote_00_neuprint.py similarity index 100% rename from docs/examples/4_remote/plot_00_remote_neuprint.py rename to docs/examples/4_remote/tutorial_remote_00_neuprint.py diff --git a/docs/examples/4_remote/plot_01_remote_cloudvolume.py b/docs/examples/4_remote/tutorial_remote_01_cloudvolume.py similarity index 97% rename from docs/examples/4_remote/plot_01_remote_cloudvolume.py rename to docs/examples/4_remote/tutorial_remote_01_cloudvolume.py index 84297ab2..d2af0ec1 100644 --- a/docs/examples/4_remote/plot_01_remote_cloudvolume.py +++ b/docs/examples/4_remote/tutorial_remote_01_cloudvolume.py @@ -15,7 +15,7 @@ will to register and apply for access. Check out [FAFBseg](https://fafbseg-py.readthedocs.io) for a fairly mature interface built on top of {{ navis }}. 2. [Google's flood-filling segmentation](http://fafb-ffn1.storage.googleapis.com/landing.html) of an entire *Drosophila* brain. -3. The Allen Institute's [MICrONs datasets](https://www.microns-explorer.org/). We have a separate [tutorial](../plot_02_remote_microns) on this! +3. The Allen Institute's [MICrONs datasets](https://www.microns-explorer.org/). We have a separate [tutorial](../tutorial_remote_02_microns) on this! 4. The Janelia [hemibrain connectome](https://neuprint.janelia.org). `CloudVolume` supports the backends/data formats of these and many up-and-coming datasets. You can use it to query the segmentation directly, diff --git a/docs/examples/4_remote/plot_02_remote_microns.py b/docs/examples/4_remote/tutorial_remote_02_microns.py similarity index 99% rename from docs/examples/4_remote/plot_02_remote_microns.py rename to docs/examples/4_remote/tutorial_remote_02_microns.py index ed3f55a5..ddc457f2 100644 --- a/docs/examples/4_remote/plot_02_remote_microns.py +++ b/docs/examples/4_remote/tutorial_remote_02_microns.py @@ -182,7 +182,7 @@ # ## Render Videos # # Beautiful data like the MICrONS datasets lend themselves to visualizations. For making high quality videos (and renderings) -# I recommend you check out the tutorial on navis' [Blender interface](../../../gallery/3_interfaces/plot_01_interfaces_blender). +# I recommend you check out the tutorial on navis' [Blender interface](../../../gallery/3_interfaces/tutorial_interfaces_02_blender). # Here's a little taster: # # diff --git a/docs/examples/4_remote/plot_03_remote_insect_db.py b/docs/examples/4_remote/tutorial_remote_03_insect_db.py similarity index 100% rename from docs/examples/4_remote/plot_03_remote_insect_db.py rename to docs/examples/4_remote/tutorial_remote_03_insect_db.py diff --git a/docs/examples/5_nblast/plot_00_nblast_intro.py b/docs/examples/5_nblast/tutorial_nblast_00_intro.py similarity index 99% rename from docs/examples/5_nblast/plot_00_nblast_intro.py rename to docs/examples/5_nblast/tutorial_nblast_00_intro.py index 55eef2ab..984fefd3 100644 --- a/docs/examples/5_nblast/plot_00_nblast_intro.py +++ b/docs/examples/5_nblast/tutorial_nblast_00_intro.py @@ -33,7 +33,7 @@ Importantly, these matrices were created using _Drosophila_ neurons from the [FlyCircuit](http://flycircuit.tw/) light-level dataset which are in microns. Consequently, you should make sure your neurons are also in micrometer units for NBLAST! If you are working on non-insect neurons you might have to play around with the scaling to improve results. Alternatively, you can also produce your own scoring function - (see [this tutorial](../plot_03_nblast_smat)). + (see [this tutorial](../tutorial_nblast_03_smat)). 3. Produce a per-pair score: @@ -205,7 +205,7 @@ # Let's try something more elaborate and pull some hemibrain neurons from [neuPrint](https://neuprint.janelia.org/). For this you need to install the # `neuprint-python` package (`pip3 install neuprint-python`), make a neuPrint account and generate/set an authentication token. Sounds complicated # but is all pretty painless - see the [neuPrint documentation](https://connectome-neuprint.github.io/neuprint-python/docs/quickstart.html) for details. -# There is also a separate {{ navis }} tutorial on neuprint [here](../4_remote/plot_00_remote_neuprint). +# There is also a separate {{ navis }} tutorial on neuprint [here](../4_remote/tutorial_remote_00_neuprint). # # Once that's done we can get started by importing the neuPrint interface from {{ navis }}: diff --git a/docs/examples/5_nblast/plot_03_nblast_smat.py b/docs/examples/5_nblast/tutorial_nblast_03_smat.py similarity index 100% rename from docs/examples/5_nblast/plot_03_nblast_smat.py rename to docs/examples/5_nblast/tutorial_nblast_03_smat.py diff --git a/docs/examples/5_nblast/zzz_no_plot_01_nblast_flycircuit.py b/docs/examples/5_nblast/zzz_tutorial_nblast_01_flycircuit.py similarity index 100% rename from docs/examples/5_nblast/zzz_no_plot_01_nblast_flycircuit.py rename to docs/examples/5_nblast/zzz_tutorial_nblast_01_flycircuit.py diff --git a/docs/examples/5_nblast/zzz_no_plot_02_nblast_hemibrain.py b/docs/examples/5_nblast/zzz_tutorial_nblast_02_hemibrain.py similarity index 100% rename from docs/examples/5_nblast/zzz_no_plot_02_nblast_hemibrain.py rename to docs/examples/5_nblast/zzz_tutorial_nblast_02_hemibrain.py diff --git a/docs/examples/6_misc/plot_00_misc_multiprocess.py b/docs/examples/6_misc/tutorial_misc_00_multiprocess.py similarity index 100% rename from docs/examples/6_misc/plot_00_misc_multiprocess.py rename to docs/examples/6_misc/tutorial_misc_00_multiprocess.py diff --git a/docs/examples/6_misc/plot_01_transforms.py b/docs/examples/6_misc/tutorial_misc_01_transforms.py similarity index 100% rename from docs/examples/6_misc/plot_01_transforms.py rename to docs/examples/6_misc/tutorial_misc_01_transforms.py diff --git a/docs/examples/plot_00_basic_neurons.py b/docs/examples/tutorial_basic_00_basics.py similarity index 95% rename from docs/examples/plot_00_basic_neurons.py rename to docs/examples/tutorial_basic_00_basics.py index 3e751ec2..231b01ec 100644 --- a/docs/examples/plot_00_basic_neurons.py +++ b/docs/examples/tutorial_basic_00_basics.py @@ -121,14 +121,14 @@ # # Find out more about the different neuron types in {{ navis }}. # -# [:octicons-arrow-right-24: Neuron types tutorial](../plot_01_neurons_intro) +# [:octicons-arrow-right-24: Neuron types tutorial](../tutorial_basic_01_neurons) # # - :fontawesome-solid-list-ul:{ .lg .middle } __Lists of Neurons__ # --- # # Check out the guide on lists of neurons. # -# [:octicons-arrow-right-24: NeuronLists tutorial](../plot_02_neuronlists_intro) +# [:octicons-arrow-right-24: NeuronLists tutorial](../tutorial_basic_02_neuronlists) # # - :octicons-file-directory-symlink-16:{ .lg .middle } __Neuron I/O__ # --- diff --git a/docs/examples/plot_01_neurons_intro.py b/docs/examples/tutorial_basic_01_neurons.py similarity index 99% rename from docs/examples/plot_01_neurons_intro.py rename to docs/examples/tutorial_basic_01_neurons.py index 9f2a6e9f..6af9139b 100644 --- a/docs/examples/plot_01_neurons_intro.py +++ b/docs/examples/tutorial_basic_01_neurons.py @@ -535,7 +535,7 @@ # # Check out the guide on lists of neurons. # -# [:octicons-arrow-right-24: NeuronLists tutorial](../plot_02_neuronlists_intro) +# [:octicons-arrow-right-24: NeuronLists tutorial](../tutorial_basic_02_neuronlists) # # - :octicons-file-directory-symlink-16:{ .lg .middle } __Neuron I/O__ # diff --git a/docs/examples/plot_02_neuronlists_intro.py b/docs/examples/tutorial_basic_02_neuronlists.py similarity index 99% rename from docs/examples/plot_02_neuronlists_intro.py rename to docs/examples/tutorial_basic_02_neuronlists.py index 440a16ba..43497e7b 100644 --- a/docs/examples/plot_02_neuronlists_intro.py +++ b/docs/examples/tutorial_basic_02_neuronlists.py @@ -5,7 +5,7 @@ This tutorial will show you how to use NeuronLists to efficiently work with many neurons at a time. !!! note - If you haven't please check out the [neuron types tutorial](../plot_01_neurons_intro) first. + If you haven't please check out the [neuron types tutorial](../tutorial_basic_01_neurons) first. {{ navis }} will typically collect multiple neurons into a [`navis.NeuronList`][] as container. This container behaves like a mix of lists, numpy arrays and pandas dataframes, and allows you diff --git a/docs/index.md b/docs/index.md index bc1752ff..3f103040 100644 --- a/docs/index.md +++ b/docs/index.md @@ -28,7 +28,7 @@ morphology. It stands on the shoulders of the excellent --- - Support for all kinds of [neuron types](generated/gallery/plot_01_neurons_intro): skeletons, meshes, dotprops and images. + Support for all kinds of [neuron types](generated/gallery/tutorial_basic_01_neurons): skeletons, meshes, dotprops and images. - :material-eye:{ .lg .middle } __Exploration__ @@ -42,7 +42,7 @@ morphology. It stands on the shoulders of the excellent --- Calculate Strahler indices, cable length, volume, tortuosity, NBLAST - and many other [morphometrics](generated/gallery/2_morpho/plot_01_morpho_analyze). + and many other [morphometrics](generated/gallery/2_morpho/tutorial_morpho_01_analyze). - :fontawesome-solid-brush:{ .lg .middle } __Visualization__ @@ -62,19 +62,19 @@ morphology. It stands on the shoulders of the excellent --- Uses compiled Rust code under-the-hood and - out-of-the-box support for [multiprocessing](generated/gallery/6_misc/plot_00_misc_multiprocess). + out-of-the-box support for [multiprocessing](generated/gallery/6_misc/tutorial_misc_00_multiprocess). - :material-lightbulb-group:{ .lg .middle } __Clustering__ --- - Cluster your neurons by e.g. morphology using [NBLAST](generated/gallery/5_nblast/plot_00_nblast_intro). + Cluster your neurons by e.g. morphology using [NBLAST](generated/gallery/5_nblast/tutorial_nblast_00_intro). - :material-move-resize:{ .lg .middle } __Transforms__ --- - Fully featured [transform system](generated/gallery/5_transforms/plot_00_transforms) to move neurons between brain spaces. + Fully featured [transform system](generated/gallery/6_misc/tutorial_misc_01_transforms) to move neurons between brain spaces. We support CMTK, Elastix, landmark-based transforms and more! - :octicons-file-directory-symlink-24:{ .lg .middle } __Import/Export__ @@ -89,16 +89,16 @@ morphology. It stands on the shoulders of the excellent --- Load neurons straight from Allen's - [MICrONS](generated/gallery/4_remote/plot_02_remote_microns) datasets, - [neuromorpho](http://neuromorpho.org), [neuPrint](generated/gallery/4_remote/plot_00_remote_neuprint) + [MICrONS](generated/gallery/4_remote/tutorial_remote_02_microns) datasets, + [neuromorpho](http://neuromorpho.org), [neuPrint](generated/gallery/4_remote/tutorial_remote_00_neuprint) or any NeuroGlancer source. - :material-connection:{ .lg .middle } __Interfaces__ --- - Load neurons into [Blender 3D](generated/gallery/3_interfaces/plot_01_interfaces_blender), simulate neurons and networks using - [NEURON](generated/gallery/3_interfaces/plot_00_interfaces_neuron), or use the R natverse library via `rpy2`. + Load neurons into [Blender 3D](generated/gallery/3_interfaces/tutorial_interfaces_02_blender), simulate neurons and networks using + [NEURON](generated/gallery/3_interfaces/tutorial_interfaces_00_neuron), or use the R natverse library via `rpy2`. - :material-google-circles-extended:{ .lg .middle } __Extensible__ diff --git a/docs/quickstart.md b/docs/quickstart.md index 6e504b0d..93950dea 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -34,7 +34,7 @@ print(n) # markdown-exec: hide [I/O Tutorials](../generated/gallery#import-export) to learn more! {{ navis }} represents neurons as [`navis.TreeNeuron`][], [`navis.MeshNeuron`][], [`navis.VoxelNeuron`][] or -[`navis.Dotprops`][] - see the tutorial on [Neuron Types](../generated/gallery/plot_01_neurons_intro/) +[`navis.Dotprops`][] - see the tutorial on [Neuron Types](../generated/gallery/tutorial_basic_01_neurons/) for details. In above code we asked for a skeleton, so the neuron returned is a [`TreeNeuron`][navis.TreeNeuron]. @@ -113,7 +113,7 @@ print(buffer.getvalue()) # markdown-exec: hide plt.close() # markdown-exec: hide ``` -See the [Lists of Neurons](../generated/gallery/plot_02_neuronlists_intro/) +See the [Lists of Neurons](../generated/gallery/tutorial_basic_02_neuronlists/) tutorial for more information. ## Methods vs Functions @@ -189,14 +189,14 @@ Note that most functions have helpful `Examples`! Find out more about the different neuron types in {{ navis }}. - [:octicons-arrow-right-24: Neuron types tutorial](../generated/gallery/plot_01_neurons_intro) + [:octicons-arrow-right-24: Neuron types tutorial](../generated/gallery/tutorial_basic_01_neurons) - :material-cube:{ .lg .middle } __Lists of Neurons__ --- Check out the guide on lists of neurons. - [:octicons-arrow-right-24: NeuronLists tutorial](../generated/gallery/plot_02_neuronlists_intro) + [:octicons-arrow-right-24: NeuronLists tutorial](../generated/gallery/tutorial_basic_02_neuronlists) - :octicons-file-directory-symlink-16:{ .lg .middle } __Neuron I/O__ diff --git a/mkdocs.yml b/mkdocs.yml index 018d3fd0..0f20342c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -134,6 +134,7 @@ plugins: - "^__init__$" - glightbox - gallery: + filename_pattern: "/tutorial_" examples_dirs: docs/examples # path to your example scripts gallery_dirs: docs/generated/gallery # where to save generated gallery conf_script: docs/gallery_conf.py # configuration script diff --git a/navis/morpho/ivscc.py b/navis/morpho/ivscc.py index 44984b6e..605da567 100644 --- a/navis/morpho/ivscc.py +++ b/navis/morpho/ivscc.py @@ -333,7 +333,7 @@ def ivscc_features( Parameters ---------- x : TreeNeuron | NeuronList - Neuron(s) to calculate IVCSS for. + Neuron(s) to calculate IVSCC for. features : Sequence[Features], optional Provide specific features to calculate. Must be subclasses of `BasicFeatures`. @@ -347,8 +347,8 @@ def ivscc_features( Returns ------- - ivcss : pd.DataFrame - IVCSS features for the neuron(s). + ivscc : pd.DataFrame + IVSCC features for the neuron(s). """ diff --git a/navis/plotting/d.py b/navis/plotting/d.py index 6638bf79..2e872733 100644 --- a/navis/plotting/d.py +++ b/navis/plotting/d.py @@ -87,7 +87,7 @@ def plot1d(x: 'core.NeuronObject', >>> plt.close('all') - See the [`flat plotting tutorial`](generated/gallery/plotting/plot_02_plotting_1d/) + See the [`flat plotting tutorial`](generated/gallery/1_plotting/tutorial_plotting_02_1d/) for more examples. """ diff --git a/navis/plotting/dd.py b/navis/plotting/dd.py index 14cd6e36..7d6e3b9f 100644 --- a/navis/plotting/dd.py +++ b/navis/plotting/dd.py @@ -344,7 +344,7 @@ def plot2d( >>> fig, ax = navis.plot2d(nl, method='3d', depth_coloring=True, view=('x', '-z')) >>> plt.show() # doctest: +SKIP - See the [plotting intro](../../../generated/gallery/1_plotting/plot_00_plotting_intro) + See the [plotting intro](../../generated/gallery/1_plotting/tutorial_plotting_00_intro) for more examples. See Also diff --git a/navis/plotting/ddd.py b/navis/plotting/ddd.py index 57269807..53f5f2a5 100644 --- a/navis/plotting/ddd.py +++ b/navis/plotting/ddd.py @@ -345,7 +345,7 @@ def plot3d( >>> # Clear viewer (works only with octarine and vispy) >>> v = navis.plot3d(nl, clear=True) - See the [plotting intro](../../../generated/gallery/1_plotting/plot_00_plotting_intro) + See the [plotting intro](../../generated/gallery/1_plotting/tutorial_plotting_00_intro) for even more examples. """ diff --git a/navis/plotting/flat.py b/navis/plotting/flat.py index 15a10222..7ce0d39f 100644 --- a/navis/plotting/flat.py +++ b/navis/plotting/flat.py @@ -124,8 +124,8 @@ def plot_flat( >>> plt.close('all') - See the [plotting intro](../../../generated/gallery/1_plotting/plot_00_plotting_intro) - and the [neuron topology tutorial](../../../generated/gallery/1_plotting/plot_03_plotting_dend) + See the [plotting intro](../../generated/gallery/1_plotting/tutorial_plotting_00_intro) + and the [neuron topology tutorial](../../generated/gallery/1_plotting/tutorial_plotting_03_dend) for more examples. """ diff --git a/tests/test_tutorials.py b/tests/test_tutorials.py index 80b232e9..3954feec 100644 --- a/tests/test_tutorials.py +++ b/tests/test_tutorials.py @@ -21,7 +21,7 @@ from pathlib import Path from contextlib import contextmanager -SKIP = ["zzz_no_plot_01_nblast_flycircuit.py", "zzz_no_plot_02_nblast_hemibrain.py"] +SKIP = ["zzz_tutorial_nblast_01_flycircuit.py", "zzz_tutorial_nblast_02_hemibrain.py"] @contextmanager