Skip to content

Commit 9e27beb

Browse files
authored
Merge branch 'master' into issue810
2 parents d695b78 + e0742a6 commit 9e27beb

22 files changed

Lines changed: 1579 additions & 12 deletions

.github/workflows/full-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
python -m pip install arbor==0.9.0 libNeuroML morphio
5757
- name: Install PyNN itself
5858
run: |
59-
python -m pip install -e ".[test]"
59+
python -m pip install -e ".[test,nestml]"
6060
- name: Test installation has worked (Ubuntu)
6161
# this is needed because the PyNN tests are just skipped if the simulator
6262
# fails to install, so we need to catch import failures separately

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,18 @@ tmp
9393
doc/logos
9494
docker_*.eggs/
9595
/test/system/tmp_serialization_test
96+
97+
# Test coverage output
98+
coverage.lcov
99+
coverage.xml
100+
101+
# Compiled shared libraries (NEURON, Arbor, NESTML)
102+
*.so
103+
pyNN/neuron/nmodl/*/
104+
105+
# Simulation output and NESTML compilation targets
106+
**/Results/
107+
**/target/
108+
109+
# Scratch directories
110+
tmp_*/

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ $(NEST_STAMP): $(NEST_VENV_STAMP) $(NEST_SRC_UNPACKED)
9999
$(NEST_PIP) install \
100100
"neuron>=9.0.0" nrnutils "arbor==0.9.0" \
101101
brian2 libNeuroML scipy matplotlib Cheetah3 h5py Jinja2 \
102-
pytest pytest-xdist pytest-cov flake8
102+
pytest pytest-xdist pytest-cov flake8 morphio nestml
103103
$(NEST_PIP) install -e .
104104
# Compile NEURON .mod mechanisms against the venv's NEURON.
105105
# The compiled arm64/ dir lives in the source tree and is version-specific,

doc/backends/NEST.txt

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,137 @@ implications for their usage in PyNN:
165165
However, they will only deviate from the default when changed manually.
166166

167167

168+
Using models defined in NESTML
169+
==============================
170+
171+
`NESTML`_ is a domain-specific language for defining neuron and synapse models that can be
172+
compiled to efficient C++ code for use in NEST. PyNN wraps PyNESTML to compile and install
173+
NESTML models automatically at ``sim.setup()`` time.
174+
175+
Installation
176+
------------
177+
178+
NESTML support requires the ``nestml`` package (imported as ``pynestml``), which is not
179+
installed by default:
180+
181+
.. code-block:: bash
182+
183+
pip install PyNN[nestml] # installs PyNN together with nestml
184+
# or
185+
pip install nestml # installs nestml into an existing PyNN environment
186+
187+
Important: register models before ``sim.setup()``
188+
--------------------------------------------------
189+
190+
All NESTML models registered for a simulation are compiled together in a single PyNESTML
191+
pass when ``sim.setup()`` is called. Both :func:`nestml_cell_type` and
192+
:func:`nestml_synapse_type` must therefore be called *before* ``sim.setup()``. Calling
193+
them afterwards raises a ``RuntimeError``.
194+
195+
The required call order is:
196+
197+
.. code-block:: python
198+
199+
import pyNN.nest as sim
200+
from pyNN.nest import nestml
201+
202+
# 1. Register NESTML models — no compilation yet
203+
MyNeuron = nestml.nestml_cell_type("my_neuron", "my_neuron.nestml")
204+
205+
# 2. setup() triggers the single compile + install pass
206+
sim.setup(timestep=0.1, min_delay=1.0)
207+
208+
# 3. MyNeuron now behaves identically to native_cell_type() results
209+
pop = sim.Population(100, MyNeuron(param=value))
210+
211+
212+
NESTML neuron models
213+
--------------------
214+
215+
Use :func:`~pyNN.nest.nestml.nestml_cell_type` with the model name and either a path to a
216+
``.nestml`` file or a string containing NESTML source code inline:
217+
218+
.. code-block:: python
219+
220+
# From a file
221+
MyNeuron = nestml.nestml_cell_type("my_neuron", "/path/to/my_neuron.nestml")
222+
223+
# Inline NESTML source
224+
nestml_source = """
225+
model my_neuron:
226+
...
227+
"""
228+
MyNeuron = nestml.nestml_cell_type("my_neuron", nestml_source)
229+
230+
After ``sim.setup()`` the returned class behaves identically to one returned by
231+
:func:`native_cell_type`: parameters can be set, state variables initialised, and
232+
variables recorded in the usual way.
233+
234+
See ``examples/nestml/wang_buzsaki_synaptic_input.py`` for a file-based example and
235+
``examples/nestml/wang_buzsaki_current_injection.py`` for the inline variant.
236+
237+
238+
NESTML synapse models
239+
---------------------
240+
241+
Use :func:`~pyNN.nest.nestml.nestml_synapse_type` to register a synapse model. The
242+
``weight_variable`` and ``delay_variable`` arguments identify which variables in the NESTML
243+
model correspond to the connection weight and dendritic delay respectively:
244+
245+
.. code-block:: python
246+
247+
TsodyksSyn = nestml.nestml_synapse_type(
248+
"tsodyks_synapse_nestml",
249+
"/path/to/tsodyks_synapse.nestml",
250+
weight_variable="w",
251+
delay_variable="d",
252+
)
253+
sim.setup(timestep=0.1, min_delay=1.0)
254+
255+
prj = sim.Projection(
256+
source, target,
257+
sim.AllToAllConnector(),
258+
TsodyksSyn(weight=1.0, delay=1.0),
259+
receptor_type="excitatory",
260+
)
261+
262+
263+
Plastic synapses requiring co-generation
264+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
265+
266+
Some NESTML plasticity models (such as STDP) must be co-generated with a specific
267+
postsynaptic neuron model so that PyNESTML can wire up the pre/post spike communication.
268+
Pass the neuron description via ``postsynaptic_neuron_nestml_description``; the
269+
co-generated neuron class is then accessible as an attribute of the synapse class before
270+
and after ``sim.setup()``:
271+
272+
.. code-block:: python
273+
274+
stdp = nestml.nestml_synapse_type(
275+
"stdp_synapse",
276+
"stdp_synapse.nestml",
277+
postsynaptic_neuron_nestml_description="iaf_psc_exp_neuron.nestml",
278+
)
279+
PostNeuron = stdp.postsynaptic_cell_type # available immediately, before setup()
280+
281+
sim.setup(timestep=0.1, min_delay=1.0)
282+
283+
source = sim.Population(10, sim.SpikeSourcePoisson(rate=50.0))
284+
target = sim.Population(10, PostNeuron())
285+
prj = sim.Projection(source, target, sim.AllToAllConnector(),
286+
stdp(weight=1.0, delay=1.0), receptor_type="excitatory")
287+
288+
See ``examples/nestml/stdp.py`` for a complete working example.
289+
290+
291+
Future backends
292+
---------------
293+
294+
NESTML support is currently specific to the NEST backend. The SpiNNaker backend
295+
(developed separately as `sPyNNaker`_) also has partial NESTML support, and it is hoped
296+
that other backends may gain NESTML support in future.
297+
298+
299+
.. _`NESTML`: https://nestml.readthedocs.io/
300+
.. _`sPyNNaker`: https://github.com/SpiNNakerManchester/sPyNNaker
168301
.. _`NEST random number generator`: https://nest-simulator.readthedocs.io/en/stable/guides/random_numbers.html#select-the-type-of-random-number-generator
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# iaf_psc_exp - Leaky integrate-and-fire neuron model
2+
# ###################################################
3+
#
4+
# Description
5+
# +++++++++++
6+
#
7+
# iaf_psc_exp is an implementation of a leaky integrate-and-fire model
8+
# with exponentially decaying synaptic currents according to [1]_.
9+
# Thus, postsynaptic currents have an infinitely short rise time.
10+
#
11+
# The threshold crossing is followed by an absolute refractory period
12+
# during which the membrane potential is clamped to the resting potential
13+
# and spiking is prohibited.
14+
#
15+
# The general framework for the consistent formulation of systems with
16+
# neuron like dynamics interacting by point events is described in
17+
# [1]_. A flow chart can be found in [2]_.
18+
#
19+
# Critical tests for the formulation of the neuron model are the
20+
# comparisons of simulation results for different computation step
21+
# sizes.
22+
#
23+
# .. note::
24+
#
25+
# If tau_m is very close to tau_syn_exc or tau_syn_inh, numerical problems
26+
# may arise due to singularities in the propagator matrics. If this is
27+
# the case, replace equal-valued parameters by a single parameter.
28+
#
29+
# For details, please see ``IAF_neurons_singularity.ipynb`` in
30+
# the NEST source code (``docs/model_details``).
31+
#
32+
#
33+
# References
34+
# ++++++++++
35+
#
36+
# .. [1] Rotter S, Diesmann M (1999). Exact simulation of
37+
# time-invariant linear systems with applications to neuronal
38+
# modeling. Biologial Cybernetics 81:381-402.
39+
# DOI: https://doi.org/10.1007/s004220050570
40+
# .. [2] Diesmann M, Gewaltig M-O, Rotter S, & Aertsen A (2001). State
41+
# space analysis of synchronous spiking in cortical neural
42+
# networks. Neurocomputing 38-40:565-571.
43+
# DOI: https://doi.org/10.1016/S0925-2312(01)00409-X
44+
# .. [3] Morrison A, Straube S, Plesser H E, Diesmann M (2006). Exact
45+
# subthreshold integration with continuous spike times in discrete time
46+
# neural network simulations. Neural Computation, in press
47+
# DOI: https://doi.org/10.1162/neco.2007.19.1.47
48+
#
49+
#
50+
# See also
51+
# ++++++++
52+
#
53+
# iaf_psc_delta, iaf_psc_alpha, iaf_cond_exp
54+
#
55+
#
56+
# Copyright statement
57+
# +++++++++++++++++++
58+
#
59+
# This file is part of NEST.
60+
#
61+
# Copyright (C) 2004 The NEST Initiative
62+
#
63+
# NEST is free software: you can redistribute it and/or modify
64+
# it under the terms of the GNU General Public License as published by
65+
# the Free Software Foundation, either version 2 of the License, or
66+
# (at your option) any later version.
67+
#
68+
# NEST is distributed in the hope that it will be useful,
69+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
70+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71+
# GNU General Public License for more details.
72+
#
73+
# You should have received a copy of the GNU General Public License
74+
# along with NEST. If not, see <http://www.gnu.org/licenses/>.
75+
#
76+
#
77+
model iaf_psc_exp_neuron:
78+
79+
state:
80+
V_m mV = E_L # Membrane potential
81+
refr_t ms = 0 ms # Refractory period timer
82+
I_syn_exc pA = 0 pA
83+
I_syn_inh pA = 0 pA
84+
85+
equations:
86+
I_syn_exc' = -I_syn_exc / tau_syn_exc
87+
I_syn_inh' = -I_syn_inh / tau_syn_inh
88+
V_m' = -(V_m - E_L) / tau_m + (I_syn_exc - I_syn_inh + I_e + I_stim) / C_m
89+
refr_t' = -1e3 * ms/s # refractoriness is implemented as an ODE, representing a timer counting back down to zero. XXX: TODO: This should simply read ``refr_t' = -1 / s`` (see https://github.com/nest/nestml/issues/984)
90+
91+
parameters:
92+
C_m pF = 250 pF # Capacitance of the membrane
93+
tau_m ms = 10 ms # Membrane time constant
94+
tau_syn_inh ms = 2 ms # Time constant of inhibitory synaptic current
95+
tau_syn_exc ms = 2 ms # Time constant of excitatory synaptic current
96+
refr_T ms = 2 ms # Duration of refractory period
97+
E_L mV = -70 mV # Resting potential
98+
V_reset mV = -70 mV # Reset value of the membrane potential
99+
V_th mV = -55 mV # Spike threshold potential
100+
101+
# constant external input current
102+
I_e pA = 0 pA
103+
104+
input:
105+
exc_spikes <- excitatory spike
106+
inh_spikes <- inhibitory spike
107+
I_stim pA <- continuous
108+
109+
output:
110+
spike
111+
112+
update:
113+
if refr_t > 0 ms:
114+
# neuron is absolute refractory, do not evolve V_m
115+
integrate_odes(I_syn_exc, I_syn_inh, refr_t)
116+
else:
117+
# neuron not refractory
118+
integrate_odes(I_syn_exc, I_syn_inh, V_m)
119+
120+
onReceive(exc_spikes):
121+
I_syn_exc += exc_spikes * pA * s
122+
123+
onReceive(inh_spikes):
124+
I_syn_inh += inh_spikes * pA * s
125+
126+
onCondition(refr_t <= 0 ms and V_m >= V_th):
127+
# threshold crossing
128+
refr_t = refr_T # start of the refractory period
129+
V_m = V_reset
130+
emit_spike()

0 commit comments

Comments
 (0)