@@ -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
0 commit comments