Skip to content

Commit 92bd70c

Browse files
authored
Add support for Spinnaker (#925)
1 parent 7a6f2a1 commit 92bd70c

File tree

131 files changed

+6073
-546
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+6073
-546
lines changed

.gitignore

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
.settings/
22
target/
33
.idea/
4+
.vscode
45
.mypy_cache/
6+
.pytest_cache/
57
build/
68
buildNest/
79
venv/
10+
spinnaker-install/
11+
spinnaker-target/
12+
report/
13+
reports/
14+
nestml-*/
15+
*.egg-info
16+
stash/
817

918

1019
__*
@@ -16,7 +25,7 @@ PyNESTML.egg-info/
1625
*.pyc
1726

1827
!__init__.py
19-
28+
!*.jinja2
2029
*.jar
2130
venv
2231

doc/fig/spinnaker_logo.svg

+165
Loading

doc/running.rst

-341
This file was deleted.
Binary file not shown.

doc/running/index.rst

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
Running NESTML
2+
##############
3+
4+
Running NESTML causes several processing steps to occur:
5+
6+
1. The model is parsed from file and checked (syntax, consistent physical units, and so on).
7+
2. Code is generated from the model by one of the "code generators" selected when NESTML was invoked.
8+
3. If necessary, the code is compiled and built by the "builder" that belongs to the selected code generator.
9+
10+
Currently, the following code generators are supported:
11+
12+
* :doc:`NEST Simulator </running/running_nest>`
13+
14+
.. figure:: https://raw.githubusercontent.com/nest/nestml/master/doc/fig/nest-simulator-logo.png
15+
:width: 95px
16+
:height: 40px
17+
:target: #nest-simulator-target
18+
19+
* :doc:`Python-standalone </running/running_python_standalone>`
20+
21+
.. figure:: https://raw.githubusercontent.com/nest/nestml/master/doc/fig/python-logo.png
22+
:width: 40px
23+
:height: 40px
24+
:target: #python-standalone-target
25+
26+
* :doc:`SpiNNaker </running/running_spinnaker>`
27+
28+
.. figure:: https://raw.githubusercontent.com/nest/nestml/master/doc/fig/spinnaker_logo.svg
29+
:width: 40px
30+
:height: 40px
31+
:target: #spinnaker-target
32+
33+
.. warning::
34+
35+
To ensure correct and reproducible results, always inspect the generated code by hand. Run comprehensive numerical testing of the model(s).
36+
37+
In case of doubt, please create a `GitHub Issue <https://github.com/nest/nestml/issues>`_ or write in on the `NEST mailing list <https://nest-simulator.readthedocs.io/en/latest/developer_space/guidelines/mailing_list_guidelines.html#mail-guidelines>`_.
38+
39+
40+
Running NESTML from Python
41+
--------------------------
42+
43+
NESTML can be imported as a Python package, and can therefore be used from within other Python tools and scripts. After PyNESTML has been installed, the following function has to be imported:
44+
45+
.. code-block:: python
46+
47+
from pynestml.frontend.pynestml_frontend import generate_target
48+
49+
Subsequently, it is possible to call PyNESTML from other Python tools and scripts via calls to ``generate_target()``, which generates, builds and installs code for the target platform. ``generate_target()`` can be called as follows:
50+
51+
.. code-block:: python
52+
53+
generate_target(input_path, target_platform, target_path, install_path, logging_level, module_name, store_log, suffix, dev, codegen_opts)
54+
55+
The following default values are used, corresponding to the command line defaults. Possible values for ``logging_level`` are the same as before ("DEBUG", "INFO", "WARNING", "ERROR", "NO"). Note that only the ``input_path`` argument is mandatory:
56+
57+
.. list-table::
58+
:header-rows: 1
59+
:widths: 10 10 10
60+
61+
* - Argument
62+
- Type
63+
- Default
64+
* - input_path
65+
- str or Sequence[str]
66+
- *no default*
67+
* - target_platform
68+
- str
69+
- "NEST"
70+
* - target_path
71+
- str
72+
- None
73+
* - install_path
74+
- str
75+
- None
76+
* - logging_level
77+
- str
78+
- "ERROR"
79+
* - module_name
80+
- str
81+
- "nestmlmodule"
82+
* - suffix
83+
- str
84+
- ""
85+
* - store_log
86+
- bool
87+
- False
88+
* - dev
89+
- bool
90+
- False
91+
* - codegen_opts
92+
- Optional[Mapping[str, Any]]
93+
- (Optional) A JSON equivalent Python dictionary containing additional options for the target platform code generator. A list of available options can be found under the section "Code generation options" for your intended target platform on the page :ref:`Running NESTML`.
94+
95+
For a detailed description of all the arguments of ``generate_target()``, see :func:`pynestml.frontend.pynestml_frontend.generate_target`.
96+
97+
A typical script for the NEST Simulator target could look like the following. First, import the function:
98+
99+
.. code-block:: python
100+
101+
from pynestml.frontend.pynestml_frontend import generate_target
102+
103+
generate_target(input_path="/home/nest/work/pynestml/models",
104+
target_platform="NEST",
105+
target_path="/tmp/nestml_target")
106+
107+
We can also use a shorthand function for each supported target platform (here, NEST):
108+
109+
.. code-block:: python
110+
111+
from pynestml.frontend.pynestml_frontend import generate_nest_target
112+
113+
generate_nest_target(input_path="/home/nest/work/pynestml/models",
114+
target_path="/tmp/nestml_target")
115+
116+
To dynamically load a module with ``module_name`` equal to ``nestmlmodule`` (the default) in PyNEST can be done as follows:
117+
118+
.. code-block:: python
119+
120+
nest.Install("nestmlmodule")
121+
122+
The NESTML models are then available for instantiation, for example as:
123+
124+
.. code-block:: python
125+
126+
pre, post = nest.Create("neuron_nestml", 2)
127+
nest.Connect(pre, post, "one_to_one", syn_spec={"synapse_model": "synapse_nestml"})
128+
129+
130+
Running NESTML from the command line
131+
------------------------------------
132+
133+
The toolchain can also be executed from the command line by running:
134+
135+
.. code-block:: bash
136+
137+
nestml ARGUMENTS
138+
139+
This will generate, compile, build, and install the code for a set of specified NESTML models. The following arguments can be given, corresponding to the arguments in the command line invocation:
140+
141+
.. list-table::
142+
:header-rows: 1
143+
:widths: 10 30
144+
145+
* - Command
146+
- Description
147+
* - ``-h`` or ``--help``
148+
- Print help message.
149+
* - ``--input_path``
150+
- One or more input path(s). Each path is a NESTML file, or a directory containing NESTML files. Directories will be searched recursively for files matching "\*.nestml".
151+
* - ``--target_path``
152+
- (Optional) Path to target directory where generated code will be written into. Default is ``target``, which will be created in the current working directory if it does not yet exist.
153+
* - ``--target_platform``
154+
- (Optional) The name of the target platform to generate code for. Default is ``NEST``.
155+
* - ``--logging_level``
156+
- (Optional) Sets the logging level, i.e., which level of messages should be printed. Default is ERROR, available are [DEBUG, INFO, WARNING, ERROR, NO]
157+
* - ``--module_name``
158+
- (Optional) Sets the name of the module which shall be generated. Default is the name of the directory containing the models. The name has to end in "module". Default is `nestmlmodule`.
159+
* - ``--store_log``
160+
- (Optional) Stores a log.txt containing all messages in JSON notation. Default is OFF.
161+
* - ``--suffix``
162+
- (Optional) A suffix string that will be appended to the name of all generated models.
163+
* - ``--install_path``
164+
- (Optional) Path to the directory where the generated code will be installed.
165+
* - ``--dev``
166+
- (Optional) Enable development mode: code generation is attempted even for models that contain errors, and extra information is rendered in the generated code. Default is OFF.
167+
* - ``--codegen_opts``
168+
- (Optional) Path to a JSON file containing additional options for the target platform code generator. A list of available options can be found under the section "Code generation options" for your intended target platform on the page :ref:`Running NESTML`.

doc/running/running_nest.rst

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
NEST Simulator target
2+
---------------------
3+
4+
*NESTML features supported:* :doc:`neurons </nestml_language/neurons_in_nestml>`, :doc:`synapses </nestml_language/synapses_in_nestml>`, :ref:`vectors <Vectors>`, :ref:`delay differential equations <Delay Differential Equations>`, :ref:`guards <Guards>`
5+
6+
After NESTML completes, the NEST extension module (by default called ``"nestmlmodule"``) can either be statically linked into NEST (see `Writing an extension module <https://nest-extension-module.readthedocs.io/>`_), or loaded dynamically using the ``Install`` API call in Python.
7+
8+
Parameters, internals and state variables can be set and read by the user using ``nest.SetStatus()`` and ``nest.GetStatus()``.
9+
10+
Code generation options
11+
~~~~~~~~~~~~~~~~~~~~~~~
12+
13+
Several code generator options are available; for an overview see :class:`pynestml.codegeneration.nest_code_generator.NESTCodeGenerator`.
14+
15+
16+
Manually building the extension module
17+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18+
19+
Sometimes it can be convenient to directly edit the generated code. To manually build and install the NEST extension module, go into the target directory and run:
20+
21+
.. code-block:: bash
22+
23+
cmake -Dwith-nest=<nest_install_dir>/bin/nest-config .
24+
make all
25+
make install
26+
27+
where ``<nest_install_dir>`` is the installation directory of NEST (e.g. ``/home/nest/work/nest-install``).
28+
29+
30+
Custom templates
31+
~~~~~~~~~~~~~~~~
32+
33+
See :ref:`Running NESTML with custom templates`.
34+
35+
36+
Multiple input ports in NEST
37+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38+
39+
See :ref:`Multiple input ports` to specify multiple input ports in a neuron.
40+
41+
After generating and building the model code, a ``receptor_type`` entry is available in the status dictionary, which maps port names to numeric port indices in NEST. The receptor type can then be selected in NEST during `connection setup <https://nest-simulator.readthedocs.io/en/latest/synapses/connection_management.html#receptor-types>`_:
42+
43+
.. code-block:: python
44+
45+
neuron = nest.Create("iaf_psc_exp_multisynapse_neuron_nestml")
46+
47+
receptor_types = nest.GetStatus(neuron, "receptor_types")[0]
48+
49+
sg = nest.Create("spike_generator", params={"spike_times": [20., 80.]})
50+
nest.Connect(sg, neuron, syn_spec={"receptor_type" : receptor_types["SPIKES_1"], "weight": 1000.})
51+
52+
sg2 = nest.Create("spike_generator", params={"spike_times": [40., 60.]})
53+
nest.Connect(sg2, neuron, syn_spec={"receptor_type" : receptor_types["SPIKES_2"], "weight": 1000.})
54+
55+
sg3 = nest.Create("spike_generator", params={"spike_times": [30., 70.]})
56+
nest.Connect(sg3, neuron, syn_spec={"receptor_type" : receptor_types["SPIKES_3"], "weight": 500.})
57+
58+
Note that in multisynapse neurons, receptor ports are numbered starting from 1.
59+
60+
We furthermore wish to record the synaptic currents ``I_kernel1``, ``I_kernel2`` and ``I_kernel3``. During code generation, one buffer is created for each combination of (kernel, spike input port) that appears in convolution statements. These buffers are named by joining together the name of the kernel with the name of the spike buffer using (by default) the string "__X__". The variables to be recorded are thus named as follows:
61+
62+
.. code-block:: python
63+
64+
mm = nest.Create('multimeter', params={'record_from': ['I_kernel1__X__spikes_1',
65+
'I_kernel2__X__spikes_2',
66+
'I_kernel3__X__spikes_3'],
67+
'interval': .1})
68+
nest.Connect(mm, neuron)
69+
70+
The output shows the currents for each synapse (three bottom rows) and the net effect on the membrane potential (top row):
71+
72+
.. figure:: https://raw.githubusercontent.com/nest/nestml/master/doc/fig/nestml-multisynapse-example.png
73+
:alt: NESTML multisynapse example waveform traces
74+
75+
For a full example, please see `iaf_psc_exp_multisynapse.nestml <https://github.com/nest/nestml/blob/master/tests/nest_tests/resources/iaf_psc_exp_multisynapse.nestml>`_ for the full model and ``test_multisynapse`` in `tests/nest_tests/nest_multisynapse_test.py <https://github.com/nest/nestml/blob/master/tests/nest_tests/nest_multisynapse_test.py>`_ for the corresponding test harness that produced the figure above.
76+
77+
78+
Multiple input ports with vectors in NEST
79+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80+
81+
See :ref:`Multiple input ports with vectors` for an example with input ports defined as vectors.
82+
83+
Each connection in NEST is denoted by a receiver port or ``rport`` number which is an integer that starts with 0. All default connections in NEST have the ``rport`` 0. NESTML routes the spikes with ``excitatory`` and ``inhibitory`` qualifiers into separate input buffers, whereas NEST identifies them with the same ``rport`` number.
84+
85+
During the code generation for NEST, NESTML maintains an internal mapping between NEST ``rports`` and NESTML input ports. A list of port names defined in a model and their corresponding ``rport`` numbers can be queried from the status dictionary using the NEST API. For neurons with multiple input ports, the ``receptor_type`` values in the ``nest.Connect()`` call start from 1 as the default ``receptor_type`` 0 is excluded to avoid any accidental connections.
86+
87+
For the example mentioned :ref:`here <Multiple input ports with vectors>`, the ``receptor_types`` can be queried as shown below:
88+
89+
.. code-block:: python
90+
91+
neuron = nest.Create("multi_synapse_vectors")
92+
receptor_types = nest.GetStatus(neuron, "receptor_types")
93+
94+
The name of the receptors of the input ports are denoted by suffixing the ``vector index + 1`` to the port name. For instance, the receptor name for ``foo[0]`` would be ``FOO_1``.
95+
96+
The above code querying for ``receptor_types`` gives a list of port names and NEST ``rport`` numbers as shown below:
97+
98+
.. list-table::
99+
:header-rows: 1
100+
101+
* - Input port name
102+
- NEST ``rport``
103+
* - AMPA_spikes
104+
- 1
105+
* - GABA_spikes
106+
- 1
107+
* - NMDA_spikes
108+
- 2
109+
* - FOO_1
110+
- 3
111+
* - FOO_2
112+
- 4
113+
* - EXC_SPIKES_1
114+
- 5
115+
* - EXC_SPIKES_2
116+
- 6
117+
* - EXC_SPIKES_3
118+
- 7
119+
* - INH_SPIKES_1
120+
- 5
121+
* - INH_SPIKES_2
122+
- 6
123+
* - INH_SPIKES_3
124+
- 7
125+
126+
For a full example, please see `iaf_psc_exp_multisynapse_vectors.nestml <https://github.com/nest/nestml/blob/master/tests/nest_tests/resources/iaf_psc_exp_multisynapse_vectors.nestml>`_ for the neuron model and ``test_multisynapse_with_vector_input_ports`` in `tests/nest_tests/nest_multisynapse_test.py <https://github.com/nest/nestml/blob/master/tests/nest_tests/nest_multisynapse_test.py>`_ for the corresponding test.
127+
128+
Compatibility with different versions of NEST
129+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130+
131+
To generate code that is compatible with particular versions of NEST Simulator, the code generator option ``nest_version`` can be used. The option value is given as a string that corresponds to a git tag or git branch name. The following values are supported:
132+
133+
- The default is the empty string, which causes the NEST version to be automatically identified from the ``nest`` Python module.
134+
- ``"master"``: Latest NEST GitHub master branch version (https://github.com/nest/nest-simulator/).
135+
- ``"v2.20.2"``: Latest NEST 2 release.
136+
- ``"v3.0"``, ``"v3.1"``, ``"v3.2"``, ``"v3.3"``, ``"v3.4"``: NEST 3 release versions.
137+
138+
For a list of the corresponding NEST Simulator repository tags, please see https://github.com/nest/nest-simulator/tags.
139+
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Python-standalone target
2+
------------------------
3+
4+
*NESTML features supported:* :doc:`neurons </nestml_language/neurons_in_nestml>`
5+
6+
The aim of the Python-standalone target is to facilitate model development and debugging. The generated Python code is intended to be easy to read and understand, rather than to be fast. When satisfied with the Python target results, high-performance code can then be generated by simply switching to a different target platform.
7+
8+
A Python class is generated for each neuron, as well as a very simple simulator that applies some spikes to the model(s) and measures the results. This generated code can be run independently of any installed simulator (only a few common Python packages are required, like scipy for numerical integration). The following files are generated in the target directory:
9+
10+
.. list-table::
11+
:header-rows: 1
12+
:widths: 10 30
13+
14+
* - File
15+
- Description
16+
* - ``<neuron_name>.py``
17+
- Generated code for the neuron model.
18+
* - ``neuron.py``
19+
- Abstract base class for neurons.
20+
* - ``simulator.py``
21+
- A very simple simulator that can be used to instantiate neurons and spike generators, make connections between them, and perform time stepping of the network.
22+
* - ``spike_generator.py``
23+
- Can be used to emit spikes at predefined points in time.
24+
* - ``test_python_standalone_module.py``
25+
- Runnable test file that instantiates the network, runs a simulation, and plots the results.
26+
* - ``utils.py``
27+
- Miscellaneous utility functions.
28+
29+
After the code has been generated, a simple test can can be run by calling:
30+
31+
.. code-block:: bash
32+
33+
python3 test_python_standalone_module.py
34+
35+
36+
Code generation options
37+
~~~~~~~~~~~~~~~~~~~~~~~
38+
39+
Several code generator options are available; for an overview see :class:`pynestml.codegeneration.python_standalone_code_generator.PythonStandaloneCodeGenerator`.

0 commit comments

Comments
 (0)