Note
Go to the end to download the full example code.
Multi-compartment neuron exampleΒΆ
Run this example as a Jupyter notebook:
See our guide for more information and troubleshooting.
Simple example of how to use the three-compartment iaf_cond_alpha_mc
neuron model.
Three stimulation paradigms are illustrated:
externally applied current, one compartment at a time
spikes impinging on each compartment, one at a time
rheobase current injected to soma causing output spikes
Voltage and synaptic conductance traces are shown for all compartments.
First, we import all necessary modules to simulate, analyze and plot this example.
import matplotlib.pyplot as plt
import nest
nest.ResetKernel()
We then extract the receptor types and the list of recordable quantities from the neuron model. Receptor types and recordable quantities uniquely define the receptor type and the compartment while establishing synaptic connections or assigning multimeters.
syns = nest.GetDefaults("iaf_cond_alpha_mc")["receptor_types"]
print(f"iaf_cond_alpha_mc receptor_types: {syns}")
rqs = nest.GetDefaults("iaf_cond_alpha_mc")["recordables"]
print(f"iaf_cond_alpha_mc recordables : {rqs}")
The simulation parameters are assigned to variables.
params = {
"V_th": -60.0, # threshold potential
"V_reset": -65.0, # reset potential
"t_ref": 10.0, # refractory period
"g_sp": 5.0, # somato-proximal coupling conductance
"soma": {"g_L": 12.0}, # somatic leak conductance
# proximal excitatory and inhibitory synaptic time constants
"proximal": {"tau_syn_ex": 1.0, "tau_syn_in": 5.0},
"distal": {"C_m": 90.0}, # distal capacitance
}
The nodes are created using Create
. We store the returned handles
in variables for later reference.
n = nest.Create("iaf_cond_alpha_mc", params=params)
A multimeter
is created and connected to the neurons. The parameters
specified for the multimeter include the list of quantities that should be
recorded and the time interval at which quantities are measured.
mm = nest.Create("multimeter", params={"record_from": rqs, "interval": 0.1})
nest.Connect(mm, n)
We create one current generator per compartment and configure a stimulus regime that drives distal, proximal and soma dendrites, in that order. Configuration of the current generator includes the definition of the start and stop times and the amplitude of the injected current.
cgs = nest.Create("dc_generator", 3)
cgs[0].set(start=250.0, stop=300.0, amplitude=50.0) # soma
cgs[1].set(start=150.0, stop=200.0, amplitude=-50.0) # proxim.
cgs[2].set(start=50.0, stop=100.0, amplitude=100.0) # distal
Generators are then connected to the correct compartments. Specification of
the receptor_type
uniquely defines the target compartment and receptor.
nest.Connect(cgs[0], n, syn_spec={"receptor_type": syns["soma_curr"]})
nest.Connect(cgs[1], n, syn_spec={"receptor_type": syns["proximal_curr"]})
nest.Connect(cgs[2], n, syn_spec={"receptor_type": syns["distal_curr"]})
We create one excitatory and one inhibitory spike generator per compartment and configure a regime that drives distal, proximal and soma dendrites, in that order, alternating the excitatory and inhibitory spike generators.
sgs = nest.Create("spike_generator", 6)
sgs[0].spike_times = [600.0, 620.0] # soma excitatory
sgs[1].spike_times = [610.0, 630.0] # soma inhibitory
sgs[2].spike_times = [500.0, 520.0] # proximal excitatory
sgs[3].spike_times = [510.0, 530.0] # proximal inhibitory
sgs[4].spike_times = [400.0, 420.0] # distal excitatory
sgs[5].spike_times = [410.0, 430.0] # distal inhibitory
Connect generators to correct compartments in the same way as in case of current generator
nest.Connect(sgs[0], n, syn_spec={"receptor_type": syns["soma_exc"]})
nest.Connect(sgs[1], n, syn_spec={"receptor_type": syns["soma_inh"]})
nest.Connect(sgs[2], n, syn_spec={"receptor_type": syns["proximal_exc"]})
nest.Connect(sgs[3], n, syn_spec={"receptor_type": syns["proximal_inh"]})
nest.Connect(sgs[4], n, syn_spec={"receptor_type": syns["distal_exc"]})
nest.Connect(sgs[5], n, syn_spec={"receptor_type": syns["distal_inh"]})
Run the simulation for 700 ms.
nest.Simulate(700)
Now we set the intrinsic current of soma to 150 pA to make the neuron spike.
n.soma = {"I_e": 150.0}
We simulate the network for another 300 ms and retrieve recorded data from the multimeter
nest.Simulate(300)
rec = mm.events
We create an array with the time points when the quantities were actually recorded
t = rec["times"]
We plot the time traces of the membrane potential and the state of each membrane potential for soma, proximal, and distal dendrites (V_m.s, V_m.p and V_m.d).
plt.figure()
plt.subplot(211)
plt.plot(t, rec["V_m.s"], t, rec["V_m.p"], t, rec["V_m.d"])
plt.legend(("Soma", "Proximal dendrite", "Distal dendrite"), loc="lower right")
plt.axis([0, 1000, -76, -59])
plt.ylabel("Membrane potential [mV]")
plt.title("Responses of iaf_cond_alpha_mc neuron")
Finally, we plot the time traces of the synaptic conductance measured in each compartment.
plt.subplot(212)
plt.plot(t, rec["g_ex.s"], "b-", t, rec["g_ex.p"], "g-", t, rec["g_ex.d"], "r-")
plt.plot(t, rec["g_in.s"], "b--", t, rec["g_in.p"], "g--", t, rec["g_in.d"], "r--")
plt.legend(("g_ex.s", "g_ex.p", "g_in.d", "g_in.s", "g_in.p", "g_in.d"))
plt.axis([350, 700, 0, 1.15])
plt.xlabel("Time [ms]")
plt.ylabel("Synaptic conductance [nS]")
plt.show()