1# -*- coding: utf-8 -*-
2#
3# mc_neuron.py
4#
5# This file is part of NEST.
6#
7# Copyright (C) 2004 The NEST Initiative
8#
9# NEST is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 2 of the License, or
12# (at your option) any later version.
13#
14# NEST is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with NEST.  If not, see <http://www.gnu.org/licenses/>.
21
22"""
23Multi-compartment neuron example
24--------------------------------
25
26Simple example of how to use the three-compartment ``iaf_cond_alpha_mc``
27neuron model.
28
29Three stimulation paradigms are illustrated:
30
31 - externally applied current, one compartment at a time
32 - spikes impinging on each compartment, one at a time
33 - rheobase current injected to soma causing output spikes
34
35Voltage and synaptic conductance traces are shown for all compartments.
36
37"""
38
39##############################################################################
40# First, we import all necessary modules to simulate, analyze and plot this
41# example.
42
43
44import nest
45import matplotlib.pyplot as plt
46
47nest.ResetKernel()
48
49##############################################################################
50# We then extract the receptor types and the list of recordable quantities
51# from the neuron model. Receptor types and recordable quantities uniquely
52# define the receptor type and the compartment while establishing synaptic
53# connections or assigning multimeters.
54
55
56syns = nest.GetDefaults('iaf_cond_alpha_mc')['receptor_types']
57print(f"iaf_cond_alpha_mc receptor_types: {syns}")
58
59rqs = nest.GetDefaults('iaf_cond_alpha_mc')['recordables']
60print(f"iaf_cond_alpha_mc recordables   : {rqs}")
61
62###############################################################################
63# The simulation parameters are assigned to variables.
64
65params = {'V_th': -60.0,  # threshold potential
66          'V_reset': -65.0,  # reset potential
67          't_ref': 10.0,  # refractory period
68          'g_sp': 5.0,  # somato-proximal coupling conductance
69          'soma': {'g_L': 12.0},  # somatic leak conductance
70          # proximal excitatory and inhibitory synaptic time constants
71          'proximal': {'tau_syn_ex': 1.0,
72                       'tau_syn_in': 5.0},
73          'distal': {'C_m': 90.0}  # distal capacitance
74          }
75
76###############################################################################
77# The nodes are created using ``Create``. We store the returned handles
78# in variables for later reference.
79
80n = nest.Create('iaf_cond_alpha_mc', params=params)
81
82###############################################################################
83# A ``multimeter`` is created and connected to the neurons. The parameters
84# specified for the multimeter include the list of quantities that should be
85# recorded and the time interval at which quantities are measured.
86
87mm = nest.Create('multimeter', params={'record_from': rqs, 'interval': 0.1})
88nest.Connect(mm, n)
89
90###############################################################################
91# We create one current generator per compartment and configure a stimulus
92# regime that drives distal, proximal and soma dendrites, in that order.
93# Configuration of the current generator includes the definition of the start
94# and stop times and the amplitude of the injected current.
95
96cgs = nest.Create('dc_generator', 3)
97cgs[0].set(start=250.0, stop=300.0, amplitude=50.0)  # soma
98cgs[1].set(start=150.0, stop=200.0, amplitude=-50.0)  # proxim.
99cgs[2].set(start=50.0, stop=100.0, amplitude=100.0)  # distal
100
101###############################################################################
102# Generators are then connected to the correct compartments. Specification of
103# the ``receptor_type`` uniquely defines the target compartment and receptor.
104
105nest.Connect(cgs[0], n, syn_spec={'receptor_type': syns['soma_curr']})
106nest.Connect(cgs[1], n, syn_spec={'receptor_type': syns['proximal_curr']})
107nest.Connect(cgs[2], n, syn_spec={'receptor_type': syns['distal_curr']})
108
109###############################################################################
110# We create one excitatory and one inhibitory spike generator per compartment
111# and configure a regime that drives distal, proximal and soma dendrites, in
112# that order, alternating the excitatory and inhibitory spike generators.
113
114sgs = nest.Create('spike_generator', 6)
115sgs[0].spike_times = [600.0, 620.0]  # soma excitatory
116sgs[1].spike_times = [610.0, 630.0]  # soma inhibitory
117sgs[2].spike_times = [500.0, 520.0]  # proximal excitatory
118sgs[3].spike_times = [510.0, 530.0]  # proximal inhibitory
119sgs[4].spike_times = [400.0, 420.0]  # distal excitatory
120sgs[5].spike_times = [410.0, 430.0]  # distal inhibitory
121
122###############################################################################
123# Connect generators to correct compartments in the same way as in case of
124# current generator
125
126nest.Connect(sgs[0], n, syn_spec={'receptor_type': syns['soma_exc']})
127nest.Connect(sgs[1], n, syn_spec={'receptor_type': syns['soma_inh']})
128nest.Connect(sgs[2], n, syn_spec={'receptor_type': syns['proximal_exc']})
129nest.Connect(sgs[3], n, syn_spec={'receptor_type': syns['proximal_inh']})
130nest.Connect(sgs[4], n, syn_spec={'receptor_type': syns['distal_exc']})
131nest.Connect(sgs[5], n, syn_spec={'receptor_type': syns['distal_inh']})
132
133###############################################################################
134# Run the simulation for 700 ms.
135
136nest.Simulate(700)
137
138###############################################################################
139# Now we set the intrinsic current of soma to 150 pA to make the neuron spike.
140
141n.soma = {'I_e': 150.}
142
143###############################################################################
144# We simulate the network for another 300 ms and retrieve recorded data from
145# the multimeter
146
147nest.Simulate(300)
148rec = mm.events
149
150###############################################################################
151# We create an array with the time points when the quantities were actually
152# recorded
153
154t = rec['times']
155
156###############################################################################
157# We plot the time traces of the membrane potential and the state of each
158# membrane potential for soma, proximal, and distal dendrites (`V_m.s`, `V_m.p`
159# and `V_m.d`).
160
161plt.figure()
162plt.subplot(211)
163plt.plot(t, rec['V_m.s'], t, rec['V_m.p'], t, rec['V_m.d'])
164plt.legend(('Soma', 'Proximal dendrite', 'Distal dendrite'),
165           loc='lower right')
166plt.axis([0, 1000, -76, -59])
167plt.ylabel('Membrane potential [mV]')
168plt.title('Responses of iaf_cond_alpha_mc neuron')
169
170###############################################################################
171# Finally, we plot the time traces of the synaptic conductance measured in
172# each compartment.
173
174plt.subplot(212)
175plt.plot(t, rec['g_ex.s'], 'b-', t, rec['g_ex.p'], 'g-',
176         t, rec['g_ex.d'], 'r-')
177plt.plot(t, rec['g_in.s'], 'b--', t, rec['g_in.p'], 'g--',
178         t, rec['g_in.d'], 'r--')
179plt.legend(('g_ex.s', 'g_ex.p', 'g_in.d', 'g_in.s', 'g_in.p', 'g_in.d'))
180plt.axis([350, 700, 0, 1.15])
181plt.xlabel('Time [ms]')
182plt.ylabel('Synaptic conductance [nS]')
183plt.show()
184