We can use the CATMAID API to make edits to CATMAID. We can also use 3D volumetric segmentation to inform how we should make edits to CATMAID neurons, or how we sample up/downstream of them.

In this vignette we’ll have a look at catnat‘s functions for working with Greg Jefferis’ package fafbseg, and its use of the brainmaps API to access to a 3D segmentation of FAFB v14 (the female adult fly brain version 14, Bock lab) from Peter Li at Google.

# installation
if (!require("devtools")) install.packages("devtools")
if (!require("catnat")) devtools::install_github("jefferislab/catnat")
if (!require("fafbseg")) install.packages("jefferis/fafbseg")

# Load catnat
library(catnat)
library(fafbseg)

This is useful for several reasons - primarily 1) to help sample a neuron’s synaptic partners, 2) to retrieve a volumetric reconstruction of a neuron, starting with a (probably manually) traced skeleton (fundamentally a 2D line object embedded in 3D space) and 3) import neurons, along with their synapse and tag data, into a live CATMAID instance from another source (say where we have used data from a new segmentation) and join imported skeletons to extant neurons.

In this example, we are going to assume that you want to import new tracing made from concatenating auto-segmented skeletonisations from the CATMAID instance https://neuropil.janelia.org/tracing/fafb/v14-seg/ to the ‘primary’ live CATMAID instance ‘https://neuropil.janelia.org/tracing/fafb/v14-seg/’.

1) Making a sampling sheet for finding strongly connected partners

First, let’s read some neurons from which we want to sample upstream and downstream I’m interested at looking at the connectivity of MBON a2sc in the lateral horn (LH). There are two members of this cell type, one per hemisphere. Let’s get them from CATMAID.

# Login to CATMAID
# see ?catmaid::catmaid_login() for details

# Read some interesting neurons from CATMAID
a2sc = read.neurons.catmaid("name:MBON a2sc")

# Let's see what we have
print(a2sc[,])

Now we can seek to generate a ‘tracing sheet’ that gives us back ‘free’ () upstream connectors or downstream connections, but rather than performing a random sample, we have a ranked list. They are ranked using the FAFB v14 segmentation from Peter Li at Google. Synapses are ranked higher if they connect to an auto-traced fragment that also corresponds to other synapses. The returned object will give synapse locations and their connector IDs, as well as the ngl_segment, the ‘Neuroglancer segment’ read from the brainmaps API. For now, you must have authentication to use this, and you will be prompted for it when you start using functions that rely on the package fafbseg, like this one.

# Generate tracing sheet
tl.incoming = fafb_seg_tracing_list(skids = names(a2sc),connector_ids = NULL, direction = "incoming", unique = FALSE)
tl.outgoing= fafb_seg_tracing_list(skids = names(a2sc),connector_ids = NULL, direction = "outgoing", unique = FALSE)

Now because it takes a long time to trace, I am only interested in looking at the connectivity of the right-side MBON. However, I have generated a tracing sheet using both members of the cell type, i..e both MBOn a2sc Right and Left. This is useful, because they likely connect with the same neuron, and since the auto-segmented fragments are small, using multiple members of a cell type helps to rank our synapses better. But let’s subset for just those that also connect with MBON a2sc Right.

# Generate tracing sheet
tl.incoming = subset(tl.incoming,skid==names(a2sc)[1])
tl.outgoing = subset(tl.outgoing,skid==names(a2sc)[1])

So now if you want you can take these tracing data frames and go straight to CATMAID v14 (https://neuropil.janelia.org/tracing/fafb/v14/), and start working! Just follow the URLs under FAFB.link. However, we can subset the data frame further so that we do not have to look at so many synapses - because we now know which synapses share the same ngl_segment, we can just look at one synapse per segment. If manually tracing, this assumed you’ll flesh out enough to get the other synapses, this is especially useful if tracing in the v14-seg CATMAID instance (https://neuropil.janelia.org/tracing/fafb/v14-seg/) as you already get a little chunk of traced neuron. Let’s assume you are using you are using this approach from now on.

# Generate tracing sheet
tl.incoming = tl.incoming[!duplicated(tl.incoming$ngl_id),]
tl.outgoing = tl.outgoing[!duplicated(tl.outgoing$ngl_id),]

I am mainly interested in connectivity in the LH. Let’s assign a brain area to each of points in these data frames, and choose just the ones in the right LH.

# Assign points to neuropils
pin.in = points_in_neuropil(x=tl.incoming[,c("x","y","z")],brain = elmr::FAFB14NP.surf, alpha = 30000)
pin.out = points_in_neuropil(x=tl.outgoing[,c("x","y","z")],brain = elmr::FAFB14NP.surf, alpha = 30000)

# Add to data frame
tl.incoming$neuropil = pin.in$neuropil
tl.outgoing$neuropil = pin.out$neuropil

# And now if you want, you can subset
tl.incoming = subset(tl.incoming, neuropil=="LH_R")
tl.outgoing = subset(tl.outgoing, neuropil=="LH_R")

You can now save the .csv file (see ?write.csv, or save to a google drive using the googlesheets package, but this can be slow for large data frames).

2) Creating volumetric neurons from, and updating radii information for, skeletons in CATMAID using auto-segmentation data

We can also pull volumes from the brainmaps API in order to create volumetric neurons. Let’s try it. It can take some time, so let’s choose a smaller neuron than a2sc to look at, a favourite from Dolan et al. 2017, PD2a1#1.

# Fetch completely traced neurons from CATMAID
neuron = read.neurons.catmaid("1299700")

# Split into axon, dendrite, primary neurite and primary dendrite automatically
neuron.flow = flow.centrality(neuron, polypre= FALSE, mode = "centrifugal", split = "distance")

# We can have a look at this split neuron
nopen3d()
seesplit3d(neuron.flow, soma = 1500, radius = 100, WithConnectors = TRUE)

# Pull many segmented subvolumes from tha brainmaps API and stitch into one cohesive neuron
neuronvolume = fafb_segs_stitch_volumes(neuron = neuron.flow, map = TRUE)

This might be useful for analysis stuff. It’s also pretty, let’s look at it split into its different components:

nopen3d()
neuronvolume3d(neuronvolume, split = "split", type = "volume")

We can also push the radius information to the manually traced CATMAID skeleton in v14, which might aid visualisation and tracing. To do this, we can use the neuronvolume we just created, which will be quicker, or just give the function an annotation to work with. In the latter instance, working from nothing this is faster but less accurate, as radii are calculated for nodes within each brainmaps volume separately, whereas fafb_segs_stitch_volumes makes a single cohesive volume, i.e. a node in the former case may be near a mesh boundary that only exists because the segmentation failed.

# This updates CATMAID. In this example, it updates the fafbseg `v14-seg` envrionment neuron, specified using the conn argument.
fafbseg_update_node_radii(x = neuron, conn = fafb_seg_conn(), method = "ray.cast")
# This is rather slow, but you could run it overnight for a bunch of neurons of interest if you wanted

# If you made a mistake, you can return all radii to -1 (default ) by
catmaid_update_radius(tnids = neuron[[1]]$d$PointNo, radii = -1)

3) Importing neurons from one CATMAID instance to another, retaining connectors and adding in new connectors

Okay, now let’s say you have done some tracing in a CATMAID instance and you want to import it into another instance. In this example, we will assume that you have been following the FAFBseg.link column in our tracing sheet and tracing in there. You want to upload your skeletons with their connector and tag information, connect them to the synapses you were tracing from in the tracing sheet we generated, and also join your new skeletons up to manually traced neurons in the ‘main’ collaborative v14 instance.

It’s important to do a few things while tracing in the v14-seg instance:

  • STOP tracing in v14-seg when you come up against a manually traced neuron. Split off any overlapping cable.
  • Annotate all the neurons you want to upload with the same annotation (or constellation of annotations)
  • Leave a specific tag (e.g. “TODO”) at leaf nodes where you want to join your v14-seg skeleton up to a manually traced neuron once ported to ‘v14’. Place ths leaf node as close to the manual skeleton as possible.
  • Be aware that the importing will take connectors with your neuron, but in v14-seg it will create new connectors, that will not retain any other connectivity information other than theur relationship with the imported skeleton.

There are function to do the import and joining automatically without user interaction (catmaid_uncontrolled_upload), however, it is STRONGLY recommended that you use catmaid_controlled_upload which will walk you through the changes you are making to CATMAID so you can be sure you do not make a mistake. The process is roughly:

  • Skeletons are chosen based on an annotation/name/skeleton IDs that you give
  • These skeletons are checked for annotations that label them as already imported. These are specified by the avoid argument.
  • The space around every node in each v14-seg skeleton is queried (in a bounding box of duplication.range.nm nm) to see if there are any other neurons. If there are, that node is counted as ‘duplicated’. This is better refined by using fafbseg = TRUE, in which case duplication is based on the existence of other skeletons in the same neuroglancer volumes via the brainmaps API (must have access). This can be a slow process, and is made faster (but less accurate) by downsampling the neuron using higher values of downsample.
  • You are shown the neuron and the skeletons that overlap it the most, and asked if you want to continue the upload. If tolerance is set to a value, and the level of duplication is above the tolerance proportion, the skeleton will not be uploaded.
  • Once uploaded, connectors are transferred (if include.connectors = FALSE) and tags (if include.tags = FALSE).
  • The newly uploaded neurons will be given the names and annotations specified with name and annotation.
  • If lock=TRUE the old neurons in v14-seg will also be locked, to prevent others adding to it and maybe accidentally wanting to upload it.
  • If join=TRUE you will now cycle through potential join sites to manual neurons in v14-seg, found by looking in a radius of search.range.nm around the neuron’s lead nodes that contain join.tag. If fafbseg=TRUE this works better, as only neurons in the same neuroglancer volume are considered. You can choose to make joins or not interactively.
# This example annotation may not work, depending on the current state of CATMAID v14-seg. Try with your own small test neuron first, to trial this function
uploaded = catmaid_controlled_upload(x = "name:ASB Tester",name = "ASB Tester from v14-seg",
search.range.nm = 1000, annotations = "ASB Test v14-seg Upload", 
fafbseg = TRUE,  join = TRUE, join,tag = "TODO",
brain = elmr::FAFB14, lock = TRUE)

Now that you have uploaded your neuron, you might want to automatically connect it to stuff. We can do this using extant neurons and Peter Li’s segmentation

# WTPN2017_AL_PN refers to all olfactory projection neurons from the antennal lobe
joins = fafbseg_join_connectors_in_ngl_volumes("annotation:ASB Test v14-seg Upload",
                                       maybe.connected="annotation:WTPN2017_AL_PN",
                                       direction = "presynapses")
print(joins)

If you want to, you can then transfer names and annotations back in v14-seg so you can easily identify these neurons when you go back to tracing in that environment

catmaid_interactive_name_transfer(x="annotation:ASB Test v14-seg Upload", conn = fafb_seg_conn(), conn2 = NULL)

And done! Pretty handy yeh.

4) Deleting neurons

You may accidentally upload something you did not mean to. Or you may only have a slight overlap between your uploaded neuron and an original neuron, and choose to cut it out manually in CATMAID. You now want to delete that neuron. If you have control access over all of its nodes (typically these are just node that you yourself have added or imported) you may delete a neuron.

You can be careful about it and do this interactively:

catmaid_delete_neurons("annotation:ASB Test v14-seg Upload")