Note

This page corresponds to a Jupyter notebook you can try out yourself.
(The original version is here.)

https://mybinder.org/badge_logo.svg

Simulation Tutorial

This notebook shows how to estimate the delay and amplitude response between primary brain regions for a given neuron. In general, the delay within a compartment tends to be isopotential meaning a region to region response matrix is a reasonable characterization of the output response of a neuron.

The electrical simulation uses a simple linear passive model using a network of resistors and capacitors based on a skeleton representation of the neuron. Users can specify specific membrane resistance and capacitance values and cytoplasm resitance.

Note: You must install some additional dependencies before using simulation functions:

conda install -c conda-forge ngspice umap-learn scikit-learn matplotlib

Setup neuron model

  • create neuprint client using the public hemibrain dataset

  • build a neuron spice model for a given body id

[1]:
from neuprint import Client

TOKEN = "" # <--- Paste your token here
           # (or define NEUPRINT_APPLICATION CREDENTIALS in your environment)

client = Client("neuprint.janelia.org", "hemibrain:v1.2.1", TOKEN)
[2]:
# simulate a PEG neuron (same type as in hemibrain paper)
from neuprint import NeuronModel
nm = NeuronModel(449438847)

Estimate neuron timing

Run simulation for the given neuron

Specify the number of inputs per brain region (randomly selected) which will be tested. A current is injected at each input site one at a time and delay and amplitude response is measured.

[3]:
res = nm.simulate(2)

Examine the response results

compute_region_delay_matrix reports the delay between regions where the row index is the input brain region and the column names represent the output region. A delay (ms) and amplitude (mV) are returned. They are averages over all the response for a given region input-output pair.

Note: the results to synapses that are not in brain regions (“none”) are shown for completeness. But those output responses are not necessarily co-located and cannot be treated as an ROI.

[4]:
delay, amp = res.compute_region_delay_matrix()
[5]:
# delay matrix in ms
delay
[5]:
EB LAL(R) PB none
CRE(R) 2.074233 0.427321 3.208169 2.539196
EB 1.258467 2.456816 3.166434 2.483917
FB 1.657618 2.120017 1.880404 1.058834
LAL(R) 2.356702 0.329966 3.474082 2.809558
PB 3.143595 3.550282 0.437841 0.713781
none 2.590528 3.010865 0.676969 0.154951
[6]:
# amplitude in mV
amp
[6]:
EB LAL(R) PB none
CRE(R) 0.153407 0.489385 0.122230 0.134334
EB 0.181624 0.143877 0.121702 0.134000
FB 0.160437 0.149854 0.149690 0.167537
LAL(R) 0.146963 0.749892 0.117411 0.128987
PB 0.123022 0.116236 0.416325 0.261497
none 0.134309 0.126698 0.283109 0.311731

Plot response from one brain region to others

Each dot represents the response from each input from the specified input region (LAL(R) here) to every output in the neuron (each output brain region is indicated).

[7]:
res.plot_response_from_region("LAL(R)")
[7]:
../_images/notebooks_SimulationTutorial_14_0.png

Decompose neuron connections by electrical domain

Use simple linear passive delay progragation through the neuron to determine distinct domains for representing the neuron. The decomposition can be used to derive ROIs using electrical delay.

Simulate the delay ‘distances’ between parts of the neuron

This function checks propagation delays throughout the neuron based on the number of specified points. The points are randomly chosen even between inputs and outputs. In principle, any points could be chosen.

[8]:
res = nm.estimate_intra_neuron_delay(num_points=100)

Show delay propogation closeness between simulated points

This plot should show whether there are distinct electrical domains for the neuron. The primary ROI labels are provided to show how well the points correspond to the annotated regions.

[9]:
res.plot_neuron_domains()
[9]:
../_images/notebooks_SimulationTutorial_19_0.png

Partition the neuron into different domains based on simulated points

Cluster the simulated points and map a partition id to each synapse in the neuron. The function returns input and output connections broken down by these domain ids.

[10]:
summary, detailed_io, plot = res.estimate_neuron_domains(3, plot=True)
[11]:
# input / output table broken down by domain id from partitioning
summary
[11]:
io partner weight domain_id rois
0 output 696682163 147 0 [EB]
1 output 974300015 97 1 [PB, none]
2 output 858587718 88 0 [EB]
3 output 858587718 72 2 [LAL(R)]
4 output 1228692168 66 0 [EB]
... ... ... ... ... ...
720 input 5813057963 1 0 [EB]
721 input 5813062805 1 0 [CRE(R)]
722 input 5813061383 1 1 [PB]
723 input 5813070465 1 0 [EB]
724 input 5813080269 1 0 [EB]

725 rows × 5 columns

[12]:
# domain id for each x,y,z location
detailed_io
[12]:
type x y z roi partner domain_id
0 post 21510 26069 20648 EB 387364605 0
1 post 23679 24857 20538 EB 387364605 0
2 post 22135 26177 20494 EB 387364605 0
3 post 21613 25974 20679 EB 387364605 0
4 post 23870 23196 20455 EB 387364605 0
... ... ... ... ... ... ... ...
7092 pre 23030 24895 20167 EB 1002507131 0
7093 pre 23621 24908 20429 EB 1002507131 0
7094 pre 22615 24507 19708 EB 1002507131 0
7095 pre 22992 24888 20123 EB 1002507131 0
7096 pre 23278 24606 20178 EB 1002507131 0

7097 rows × 7 columns

[13]:
plot
[13]:
../_images/notebooks_SimulationTutorial_24_0.png