Note
This page corresponds to a Jupyter notebook you can
try out yourself.
(The original version is here.)
Query Tutorial¶
[1]:
# The plotting examples below require holoviews, hvplot, and bokeh:
# conda install -c conda-forge bokeh holoviews hvplot
import numpy as np
import pandas as pd
import bokeh
import hvplot.pandas
import holoviews as hv
import bokeh.palettes
from bokeh.plotting import figure, show, output_notebook
output_notebook()
Create a Client¶
Before you begin, you must create a Client object. It will be stored globally and used for all communication with the neuprint server.
Initialize it with your personal authentication token. See the Quickstart guide for details.
[2]:
from neuprint import Client
TOKEN = "" # <--- Paste your token here
# (or define NEUPRINT_APPLICATION CREDENTIALS in your environment)
c = Client('neuprint.janelia.org', 'hemibrain:v1.2.1', TOKEN)
ROIs¶
In neuprint, each neuron is annotated with the list of regions (ROIs) it intersects, along with the synapse counts in each.
The ROIs comprise a hierarchy, with smaller ROIs nested within larger ROIs. Furthermore, primary ROIs are guaranteed not to overlap, and they roughly tile the entire brain (with some gaps).
For a quick overview of the ROI hierarchy, use fetch_roi_hierarchy().
[3]:
from neuprint import fetch_roi_hierarchy
# Show the ROI hierarchy, with primary ROIs marked with '*'
print(fetch_roi_hierarchy(False, mark_primary=True, format='text'))
hemibrain
+-- AL(L)*
+-- AL(R)*
+-- AOT(R)
+-- CX
| +-- AB(L)*
| +-- AB(R)*
| +-- EB*
| +-- FB*
| +-- NO*
| +-- PB*
+-- GC
+-- GF(R)
+-- GNG*
+-- INP
| +-- ATL(L)*
| +-- ATL(R)*
| +-- CRE(L)*
| +-- CRE(R)*
| +-- IB*
| +-- ICL(L)*
| +-- ICL(R)*
| +-- SCL(L)*
| +-- SCL(R)*
+-- LH(R)*
+-- LX(L)
| +-- BU(L)*
| +-- LAL(L)*
+-- LX(R)
| +-- BU(R)*
| +-- LAL(R)*
+-- MB(+ACA)(R)
| +-- MB(R)
| | +-- CA(R)*
| | +-- PED(R)*
| | +-- a'L(R)*
| | +-- aL(R)*
| | +-- b'L(R)*
| | +-- bL(R)*
| | +-- gL(R)*
| +-- dACA(R)
| +-- lACA(R)
| +-- vACA(R)
+-- MB(L)
| +-- CA(L)*
| +-- a'L(L)*
| +-- aL(L)*
| +-- b'L(L)*
| +-- bL(L)*
| +-- gL(L)*
+-- OL(R)
| +-- AME(R)*
| +-- LO(R)*
| +-- LOP(R)*
| +-- ME(R)*
+-- PENP
| +-- CAN(R)*
| +-- FLA(R)*
| +-- PRW*
| +-- SAD*
+-- POC
+-- SNP(L)
| +-- SIP(L)*
| +-- SMP(L)*
+-- SNP(R)
| +-- SIP(R)*
| +-- SLP(R)*
| +-- SMP(R)*
+-- VLNP(R)
| +-- AOTU(R)*
| +-- AVLP(R)*
| +-- PLP(R)*
| +-- PVLP(R)*
| +-- WED(R)*
+-- VMNP
| +-- EPA(L)*
| +-- EPA(R)*
| +-- GOR(L)*
| +-- GOR(R)*
| +-- IPS(R)*
| +-- SPS(L)*
| +-- SPS(R)*
| +-- VES(L)*
| +-- VES(R)*
+-- mALT(L)
+-- mALT(R)
Neuron Search Criteria¶
Specify neurons of interest by bodyId
, type
/instance
, or via a NeuronCriteria object. With NeuronCriteria
, you can specify multiple search constraints, including the ROIs in which matched neurons must contain synapses.
[4]:
from neuprint import NeuronCriteria as NC
# Example: Select a specific body
criteria = 387023620
criteria = NC(bodyId=387023620)
# Example: Select several bodies
criteria = [387023620, 387364605, 416642425]
criteria = NC(bodyId=[387023620, 387364605, 416642425])
# Example: Select bodies by exact type
criteria = 'PEN_b(PEN2)'
criteria = NC(type='PENPEN_b(PEN2)')
# Example: Select bodies by exact instance
criteria = 'PEN(PB06)_b_L4'
criteria = NC(type='PEN(PB06)_b_L4')
# Example: Select bodies by type name pattern
criteria = NC(type='PEN.*')
# Example: Select bodies by region (input or output)
criteria = NC(rois=['PB', 'EB'])
# Example: Select traced neurons which intersect the PB ROI with at least 100 inputs (PSDs).
criteria = NC(inputRois=['PB'], min_roi_inputs=100, status='Traced', cropped=False)
Fetch neuron properties¶
Neuron properties and per-ROI synapse distributions can be obtained with fetch_neurons(). Two dataframes are returned: one for neuron properties, and one for the counts of synapses in each ROI.
[5]:
from neuprint import fetch_neurons
neuron_df, roi_counts_df = fetch_neurons(criteria)
The total count of pre-synaptic and post-synaptic points within each neuron are given in the pre
and post
columns:
[6]:
neuron_df[['bodyId', 'instance', 'type', 'pre', 'post', 'status', 'cropped', 'size']]
[6]:
bodyId | instance | type | pre | post | status | cropped | size | |
---|---|---|---|---|---|---|---|---|
0 | 387023620 | PEN_b(PB06b)_L4 | PEN_b(PEN2) | 343 | 1713 | Traced | False | 686693145 |
1 | 387364605 | EPG(PB08)_L3 | EPG | 645 | 4350 | Traced | False | 1469716322 |
2 | 416642425 | EPG(PB08)_R4 | EPG | 470 | 3834 | Traced | False | 1169220265 |
3 | 417998204 | PFNv(PB05)_R4_C7 | PFNv | 229 | 999 | Traced | False | 476702093 |
4 | 419060083 | PFGs(PB10)_L2_C2 | PFGs | 556 | 2395 | Traced | False | 1107227318 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
477 | 5813080979 | PEN_a(PB06a)_L5 | PEN_a(PEN1) | 544 | 1655 | Traced | False | 931602278 |
478 | 5813081494 | PFR_b(PB11b)_R1_C8 | PFR_b | 118 | 1908 | Traced | False | 591660901 |
479 | 5813081686 | PFNa(PB03)_L8_C7 | PFNa | 121 | 510 | Traced | False | 284299919 |
480 | 5813087532 | IbSpsP(PB17)_R9 | IbSpsP | 108 | 445 | Traced | False | 261895522 |
481 | 5813128308 | PFNp_a(PB01a)_L7_C6 | PFNp_a | 71 | 310 | Traced | False | 187284000 |
482 rows × 8 columns
The per-ROI synapse counts are returned in the second DataFrame.
Note: Since ROIs overlap (see hierarchy above), the sum of the per-ROI counts for each body will be more than the pre
and post
columns above.
[7]:
roi_counts_df
[7]:
bodyId | roi | pre | post | downstream | upstream | mito | |
---|---|---|---|---|---|---|---|
0 | 387023620 | ATL(L) | 0 | 5 | 0 | 5 | 0 |
1 | 387023620 | CX | 341 | 1703 | 1653 | 1703 | 142 |
2 | 387023620 | EB | 233 | 559 | 1134 | 559 | 53 |
3 | 387023620 | EBr1 | 0 | 5 | 0 | 5 | 0 |
4 | 387023620 | EBr2r4 | 7 | 22 | 36 | 22 | 1 |
... | ... | ... | ... | ... | ... | ... | ... |
7835 | 5813128308 | PB | 1 | 165 | 2 | 165 | 15 |
7836 | 5813128308 | PB(L6) | 0 | 29 | 0 | 29 | 0 |
7837 | 5813128308 | PB(L7) | 1 | 122 | 2 | 122 | 14 |
7838 | 5813128308 | PB(L8) | 0 | 14 | 0 | 14 | 1 |
7839 | 5813128308 | mALT(L) | 0 | 1 | 0 | 1 | 1 |
7840 rows × 7 columns
Fetch connections¶
Find synaptic connection strengths between one set of neurons and another using fetch_adjacencies().
The “source” and/or “target” neurons are selected using NeuronCriteria
. Additional parameters allow you to filter by connection strength or ROI. Two DataFrames are returned, for neuron properties and per-ROI connection strengths.
[8]:
from neuprint import fetch_adjacencies, NeuronCriteria as NC
# Example: Fetch all downstream connections FROM a set of neurons
neuron_df, conn_df = fetch_adjacencies([387023620, 387364605, 416642425], None)
# Example: Fetch all upstream connections TO a set of neurons
neuron_df, conn_df = fetch_adjacencies(None, [387023620, 387364605, 416642425])
# Example: Fetch all direct connections between a set of upstream neurons and downstream neurons
neuron_df, conn_df = fetch_adjacencies(NC(type='Delta.*'), NC(type='PEN.*'))
[9]:
conn_df.sort_values('weight', ascending=False)
[9]:
bodyId_pre | bodyId_post | roi | weight | |
---|---|---|---|---|
179 | 910783961 | 5813070465 | PB | 184 |
56 | 880880259 | 849421763 | PB | 141 |
319 | 911565419 | 5813070465 | PB | 141 |
92 | 910442723 | 849421763 | PB | 139 |
216 | 911129204 | 724280817 | PB | 127 |
... | ... | ... | ... | ... |
352 | 911578496 | 664645558 | PB | 1 |
351 | 911578496 | 634608104 | ATL(L) | 1 |
349 | 911578496 | 509410587 | PB | 1 |
348 | 911578496 | 387023620 | PB | 1 |
656 | 5813061383 | 5813070465 | PB | 1 |
653 rows × 4 columns
Merge arbitrary neuron properties onto the connection table with merge_neuron_properties()
[10]:
from neuprint import merge_neuron_properties
conn_df = merge_neuron_properties(neuron_df, conn_df, ['type', 'instance'])
conn_df
[10]:
bodyId_pre | bodyId_post | roi | weight | type_pre | instance_pre | type_post | instance_post | |
---|---|---|---|---|---|---|---|---|
0 | 734581598 | 387023620 | PB | 1 | Delta7 | Delta7(PB15)_L6R3_L | PEN_b(PEN2) | PEN_b(PB06b)_L4 |
1 | 734581598 | 508793049 | PB | 1 | Delta7 | Delta7(PB15)_L6R3_L | PEN_a(PEN1) | PEN_a(PB06a)_L7 |
2 | 734581598 | 509410587 | PB | 3 | Delta7 | Delta7(PB15)_L6R3_L | PEN_a(PEN1) | PEN_a(PB06a)_R4 |
3 | 734581598 | 569775058 | PB | 17 | Delta7 | Delta7(PB15)_L6R3_L | PEN_b(PEN2) | PEN_b(PB06b)_R4 |
4 | 734581598 | 570461892 | PB | 21 | Delta7 | Delta7(PB15)_L6R3_L | PEN_a(PEN1) | PEN_a(PB06a)_R3 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
648 | 5813061383 | 1508334312 | PB | 1 | Delta7 | Delta7(PB15)_L1L9R8_R | PEN_a(PEN1) | PEN_a(PB06a)_L3 |
649 | 5813061383 | 1600083889 | PB | 37 | Delta7 | Delta7(PB15)_L1L9R8_R | PEN_b(PEN2) | PEN_b(PB06b)_L9 |
650 | 5813061383 | 1601771527 | PB | 4 | Delta7 | Delta7(PB15)_L1L9R8_R | PEN_b(PEN2) | PEN_b(PB06b)_R9 |
651 | 5813061383 | 5813047157 | PB | 12 | Delta7 | Delta7(PB15)_L1L9R8_R | PEN_b(PEN2) | PEN_b(PB06b)_L2 |
652 | 5813061383 | 5813070465 | PB | 1 | Delta7 | Delta7(PB15)_L1L9R8_R | PEN_b(PEN2) | PEN_b(PB06b)_L3 |
653 rows × 8 columns
Connection Matrix¶
You can convert a connection table into a connectivity matrix via connection_table_to_matrix().
[11]:
from neuprint.utils import connection_table_to_matrix
matrix = connection_table_to_matrix(conn_df, 'bodyId', sort_by='type')
matrix.iloc[:10, :10]
[2023-06-10 00:59:05,235] WARNING /Users/bergs/workspace/neuprint-python/neuprint/utils.py:304: FutureWarning: In a future version of pandas all arguments of DataFrame.pivot will be keyword-only.
matrix = agg_weights_df.pivot(col_pre, col_post, weight_col)
[11]:
bodyId_post | 910447075 | 509410587 | 1002507131 | 5813056953 | 1127471692 | 1125964630 | 849482511 | 1508334312 | 664645558 | 847336755 |
---|---|---|---|---|---|---|---|---|---|---|
bodyId_pre | ||||||||||
734581598 | 0 | 3 | 0 | 0 | 1 | 1 | 0 | 1 | 13 | 0 |
911911193 | 1 | 0 | 1 | 0 | 21 | 8 | 1 | 0 | 0 | 0 |
911911004 | 2 | 0 | 1 | 0 | 3 | 36 | 0 | 0 | 0 | 0 |
911911699 | 0 | 0 | 20 | 0 | 0 | 0 | 1 | 16 | 0 | 0 |
911919044 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 2 | 0 |
911919917 | 1 | 0 | 11 | 1 | 0 | 10 | 0 | 0 | 0 | 0 |
911906936 | 0 | 0 | 7 | 0 | 0 | 0 | 0 | 13 | 0 | 15 |
911578496 | 1 | 1 | 29 | 0 | 0 | 0 | 2 | 0 | 1 | 1 |
911578595 | 1 | 0 | 0 | 0 | 22 | 8 | 1 | 1 | 0 | 0 |
911574261 | 0 | 0 | 1 | 0 | 0 | 28 | 0 | 0 | 0 | 0 |
[12]:
matrix.index = matrix.index.astype(str)
matrix.columns = matrix.columns.astype(str)
matrix.hvplot.heatmap(height=600, width=700, xaxis='top').opts(xrotation=60)
[12]:
[13]:
matrix = connection_table_to_matrix(conn_df, ('bodyId_pre', 'type_post'))
matrix.index = matrix.index.astype(str)
matrix.columns = matrix.columns.astype(str)
matrix.hvplot.heatmap(height=600, width=400)
[2023-06-10 00:59:05,768] WARNING /Users/bergs/workspace/neuprint-python/neuprint/utils.py:304: FutureWarning: In a future version of pandas all arguments of DataFrame.pivot will be keyword-only.
matrix = agg_weights_df.pivot(col_pre, col_post, weight_col)
[13]:
Synapses¶
Fetch synapses for a set of bodies using NeuronCriteria
, and optionally apply additional filtering with SynapseCriteria
.
[14]:
from neuprint import fetch_synapses, NeuronCriteria as NC, SynapseCriteria as SC
neuron_criteria = NC(status='Traced', type='FB4Y', cropped=False, inputRois=['EB'], min_roi_inputs=100, min_pre=400)
eb_tbar_criteria = SC(rois='EB', type='pre', primary_only=True)
eb_tbars = fetch_synapses(neuron_criteria, eb_tbar_criteria)
[15]:
# Plot the synapse positions in a 2D projection
p = figure()
p.scatter(eb_tbars['x'], eb_tbars['z'])
p.y_range.flipped = True
show(p)
Synapse Connections¶
Here, we fetch all synapse-synapse connections from a set of neurons. Provide a NeuronCriteria
for the source or target neurons (or both) to filter the neurons of interest, and optionally filter the synapses themselves via SynapseCriteria.
[16]:
from neuprint import fetch_synapse_connections
eb_syn_criteria = SC(rois='EB', primary_only=True)
eb_conns = fetch_synapse_connections(neuron_criteria, None, eb_syn_criteria)
eb_conns.head()
[16]:
bodyId_pre | bodyId_post | roi_pre | roi_post | x_pre | y_pre | z_pre | x_post | y_post | z_post | confidence_pre | confidence_post | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1008378448 | 978733459 | EB | EB | 28216 | 23624 | 20424 | 28218 | 23615 | 20428 | 0.710 | 0.985000 |
1 | 1008378448 | 973566036 | EB | EB | 29462 | 24976 | 22113 | 29460 | 24971 | 22103 | 0.858 | 0.875137 |
2 | 1008378448 | 973566036 | EB | EB | 28169 | 25762 | 22727 | 28164 | 25749 | 22710 | 0.827 | 0.747179 |
3 | 1008378448 | 972892437 | EB | EB | 24850 | 24526 | 22938 | 24839 | 24513 | 22945 | 0.955 | 0.669943 |
4 | 1008378448 | 972892437 | EB | EB | 26598 | 25202 | 23450 | 26616 | 25209 | 23461 | 0.969 | 0.664466 |
Let’s determine the post-synaptic neuron types, and plot the synapses for the top 5 types.
[17]:
# Retrieve the types of the post-synaptic neurons
post_neurons, _ = fetch_neurons(eb_conns['bodyId_post'].unique())
eb_conns = merge_neuron_properties(post_neurons, eb_conns, 'type')
top5_counts = eb_conns['type_post'].value_counts().head(5)
top5_counts
[17]:
EPG 1486
EL 571
PEN_a(PEN1) 374
ExR7 264
PEN_b(PEN2) 185
Name: type_post, dtype: int64
[18]:
colormap = dict(zip(top5_counts.index, bokeh.palettes.Category10[5]))
points = eb_conns.query('type_post in @top5_counts.index').copy()
points['color'] = points['type_post'].map(colormap)
p = figure()
p.scatter(points['x_post'], points['z_post'], color=points['color'])
p.y_range.flipped = True
show(p)
Skeletons¶
Download skeletons with Client.fetch_skeleton().
[19]:
# Download some skeletons as DataFrames and attach columns for bodyId and color
skeletons = []
for i, bodyId in enumerate(eb_conns['bodyId_pre'].unique()):
s = c.fetch_skeleton(bodyId, format='pandas')
s['bodyId'] = bodyId
s['color'] = bokeh.palettes.Accent[5][i]
skeletons.append(s)
# Combine into one big table for convenient processing
skeletons = pd.concat(skeletons, ignore_index=True)
skeletons.head()
[19]:
rowId | x | y | z | radius | link | bodyId | color | |
---|---|---|---|---|---|---|---|---|
0 | 1 | 22020.0 | 28064.0 | 13062.0 | 10.0000 | -1 | 1008378448 | #7fc97f |
1 | 2 | 22040.0 | 28084.0 | 13062.0 | 18.2843 | 1 | 1008378448 | #7fc97f |
2 | 3 | 22060.0 | 28104.0 | 13082.0 | 10.0000 | 2 | 1008378448 | #7fc97f |
3 | 4 | 22060.0 | 28124.0 | 13082.0 | 10.0000 | 3 | 1008378448 | #7fc97f |
4 | 5 | 22060.0 | 28144.0 | 13082.0 | 10.0000 | 4 | 1008378448 | #7fc97f |
[20]:
# Join parent/child nodes for plotting as line segments below.
# (Using each row's 'link' (parent) ID, find the row with matching rowId.)
segments = skeletons.merge(skeletons, 'inner',
left_on=['bodyId', 'link'],
right_on=['bodyId', 'rowId'],
suffixes=['_child', '_parent'])
[21]:
p = figure()
p.y_range.flipped = True
# Plot skeleton segments (in 2D)
p.segment(x0='x_child', x1='x_parent',
y0='z_child', y1='z_parent',
color='color_child',
source=segments)
# Also plot the synapses from the above example
p.scatter(points['x_post'], points['z_post'], color=points['color'])
show(p)