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()

Gallery generated by Sphinx-Gallery