Pushing data to the server

pymaid does not only let you fetch data from a CATMAID server but you can also push data back to the server. Most things you can do with your browers (like placing nodes or adding annotations), you can als do programmatically with pymaid.

Notably you can:

  • add/remove (meta-)annotations

  • add/remove node tags

  • rename/reroot/delete existing neurons

  • upload new skeletons

  • upload/delete volumes

  • transfer neurons between CATMAID servers

Another quick primer

First and foremost: be very, very carefull when pushing data to the CATMAID server!

When using pymaid to manipulate data on the server, the same retrictions (e.g. permission to edit somebody’s nodes, annotations, etc.) apply as when you are using a web browser. However, making changes programmatically has the potential to accidentally mess things up at a much larger scale: consider, for example, accidentally renaming 100 neurons instead of 1 because you used the wrong annotation.

Should something like this happen and you can’t fix it yourself, the last resort is to ask a server admin to revert the accidental transactions.

Second: pushing data programmatically requires you to have “API write access”. If you get a permission error using below functions, you need to ask an admin to give you the required permissions.

Annotations

As with the tutorial on fetching data, we won’t be able to cover all functions but rather give you a flavour of what’s available. If you know what you want to do, head over to the API reference and search for keywords to find the respective function - they almost always contain examples of how to use them!

First, we need to set up the connection to the CATMAID server. This should already look familiar - if not check out the quickstart tutorial <tutorial> first:

[1]:
import pymaid

# We will deactivate caching so that we always have the live data
rm = pymaid.connect_catmaid(caching=False)
INFO  : Global CATMAID instance set. Caching is OFF. (pymaid)

Let’s start by adding an annotation to my favourite neuron (skeleton ID 16) using pymaid.add_annotations():

[3]:
resp = pymaid.add_annotations(16, "favourite neuron of Philipp")

resp is just the server’s response which is usually just a confirmation that things have worked:

[4]:
resp
[4]:
{'message': 'success',
 'annotations': [{'name': 'favourite neuron of Philipp',
   'id': 16954141,
   'entities': [17]}],
 'new_annotations': [16954141],
 'existing_annotations': []}

Looks like it worked - let’s check by querying by annotation using pymaid.get_skids_by_annotation()

[5]:
pymaid.get_skids_by_annotation('favourite neuron of Philipp')
[5]:
[16]

It did! But now we want to get rid of it again using pymaid.remove_annotations():

[6]:
resp = pymaid.remove_annotations(16, 'favourite neuron of Philipp')
resp
INFO  : Removed "favourite neuron of Philipp" from 1 entities (0 uses left) (pymaid)
[6]:
{'deleted_annotations': {'16954141': {'targetIds': [17]}},
 'deleted_links': [16954142],
 'left_uses': {'16954141': 0}}

That worked too!

Importing neurons

How about importing neurons? Nothing easier than that! First, you need to load your neuron via pymaid (e.g. from another CATMAID server) or navis (e.g. from an SWC file).

Let’s create a mock neuron consisting of only two nodes:

[7]:
import navis
import pandas as pd

# Create node table
node_table = pd.DataFrame([[0, -1,  0,  0,  0, -1],
                           [1,  0, 10, 10, 10, -1]],
                          columns=['node_id', 'parent_id', 'x', 'y', 'z', 'radius'])
# Turn node table into navis neuron
n = navis.TreeNeuron(node_table)
n
[7]:
type navis.TreeNeuron
name None
n_nodes 2
n_connectors None
n_branches 0
n_leafs None
cable_length 17.3205
soma None
units 1 dimensionless

Upload the mock neuron via pymaid.upload_neuron():

[8]:
# Upload neuron to our CATMAID server
resp = pymaid.upload_neuron(n)
resp
[8]:
{'neuron_id': 16954144,
 'skeleton_id': 16954143,
 'node_id_map': {0: 66611224, 1: 66611225}}

As you can see from the response, our mock neuron was successfully uploaded and now has the skeleton ID 16954143.

[3]:
pymaid.get_neuron(resp['skeleton_id'])
[3]:
type CatmaidNeuron
name neuron 16954144
id 16954143
n_nodes 2
n_connectors 0
n_branches 0
n_leafs None
cable_length 17.3205
soma None
units 1 nanometer

How about giving it a better name using pymaid.rename_neurons()?

[5]:
_ = pymaid.rename_neurons(resp['skeleton_id'], 'Philipps mock neuron')
pymaid.get_names(resp['skeleton_id'])
      Current name              New name Skeleton ID
0  neuron 16954144  Philipps mock neuron    16954143
Please confirm above renaming [Y/N] y
INFO  : All neurons successfully renamed. (pymaid)
[5]:
{'16954143': 'Philipps mock neuron'}

OK that also worked! Let’s put that neuron out of its misery and delete it via pymaid.delete_neuron():

[6]:
pymaid.delete_neuron(resp['skeleton_id'])

Neuron "Philipps mock neuron" (#16954143) has 2 nodes (0 reviewed) and 1 annotation(s)
Please confirm deletion [Y/N] y
[6]:
{'skeleton_ids': [16954143],
 'success': 'Deleted neuron #16954144 as well as its skeletons and annotations.'}

Again, I cannot stress enough that you have to be careful using these functions! In particular if you have broad permissions to edit other people’s tracings. If I had accidentally used the wrong skeleton ID here, I could have deleted a neuron somebody else spent days constructing.