Skip to content

Commit 2f4aee8

Browse files
authored
Merge pull request #833 from apdavison/nest-3.10
Add support for NEST 3.10
2 parents f3af051 + 8ad8161 commit 2f4aee8

14 files changed

Lines changed: 326 additions & 59 deletions

.github/workflows/full-test.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
- name: Install Linux system dependencies
3434
if: startsWith(matrix.os, 'ubuntu')
3535
run: |
36-
sudo apt-get install libltdl-dev libgsl0-dev python3-all-dev openmpi-bin libopenmpi-dev
36+
sudo apt-get install libltdl-dev libgsl0-dev python3-all-dev openmpi-bin libopenmpi-dev libboost-dev
3737
- name: Install basic Python dependencies
3838
run: |
3939
python -m pip install --upgrade pip
@@ -50,15 +50,19 @@ jobs:
5050
if: startsWith(matrix.os, 'ubuntu')
5151
run: |
5252
python -m pip install "cython<3.1.0"
53-
wget https://github.com/nest/nest-simulator/archive/refs/tags/v3.9.tar.gz -O nest-simulator-3.9.tar.gz
54-
tar xzf nest-simulator-3.9.tar.gz
55-
cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local -Dwith-mpi=ON ./nest-simulator-3.9
53+
wget https://github.com/nest/nest-simulator/archive/refs/tags/v3.10_rc2.tar.gz -O nest-simulator-3.10.tar.gz
54+
tar xzf nest-simulator-3.10.tar.gz
55+
cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local -Dwith-mpi=ON ./nest-simulator-3.10_rc2
5656
make
5757
make install
5858
- name: Install Arbor
5959
if: startsWith(matrix.os, 'ubuntu')
6060
run: |
6161
python -m pip install arbor==0.9.0 libNeuroML morphio
62+
- name: Install NESTML
63+
if: startsWith(matrix.os, 'ubuntu')
64+
run: |
65+
python -m pip install https://github.com/nest/nestml/archive/refs/tags/v8.3.0-rc2.tar.gz
6266
- name: Install PyNN itself
6367
run: |
6468
python -m pip install -e ".[test,nestml]"

examples/nestml/stdp_synapse.nestml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ model stdp_synapse:
6363
post_trace real = 0.
6464

6565
parameters:
66-
d ms = 1 ms # Synaptic transmission delay
6766
lambda real = 0.01 # (dimensionless) learning rate for causal updates
6867
alpha real = 1 # relative learning rate for acausal firing
6968
tau_tr_pre ms = 20 ms # time constant of presynaptic trace
@@ -83,7 +82,7 @@ model stdp_synapse:
8382
post_spikes <- spike
8483

8584
output:
86-
spike(weight real, delay ms)
85+
spike
8786

8887
onReceive(post_spikes):
8988
post_trace += 1
@@ -102,7 +101,7 @@ model stdp_synapse:
102101
w = max(Wmin, w_)
103102

104103
# deliver spike to postsynaptic partner
105-
emit_spike(w, d)
104+
emit_spike(w)
106105

107106
update:
108107
integrate_odes()

examples/nestml/tsodyks_synapse.nestml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
model tsodyks_synapse_nestml:
22
parameters:
33
w real = 1 # Synaptic weight
4-
d ms = 1 ms # Dendritic delay (required by PyNESTML; NEST applies transmission delay at connection level)
54
tau_psc ms = 3 ms # Time constant of postsynaptic current
65
tau_fac ms = 0 ms # Time constant for facilitation (0 = no facilitation)
76
tau_rec ms = 800 ms # Time constant for recovery from depression
@@ -10,20 +9,20 @@ model tsodyks_synapse_nestml:
109
state:
1110
x real = 1 # Fraction of synaptic resources available
1211
y real = 0 # Fraction of resources in use
13-
u real = 0.5 # Running value of utilisation
12+
u real = U # Running value of utilisation
1413
t_last_update ms = 0 ms
1514

1615
input:
1716
pre_spikes <- spike
1817

1918
output:
20-
spike(weight real, delay ms)
19+
spike
2120

2221
onReceive(pre_spikes):
2322
dt ms = t - t_last_update
2423
t_last_update = t
2524

26-
Puu real = tau_fac == 0 ms ? 0 : exp(-dt / tau_fac)
25+
Puu real = tau_fac == 0 ? 0 : exp(-dt / tau_fac)
2726
Pyy real = exp(-dt / tau_psc)
2827
Pzz real = exp(-dt / tau_rec)
2928
Pxy real = ((Pzz - 1) * tau_rec - (Pyy - 1) * tau_psc) / (tau_psc - tau_rec)
@@ -39,4 +38,4 @@ model tsodyks_synapse_nestml:
3938
x -= delta_y_tsp
4039
y += delta_y_tsp
4140

42-
emit_spike(delta_y_tsp * w, d)
41+
emit_spike(delta_y_tsp * w)

pyNN/nest/cells.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def get_defaults(model_name):
3939
for name, value in defaults.items():
4040
if name in variables:
4141
default_initial_values[name] = value
42-
elif name not in ignore:
42+
elif name not in ignore and not name.startswith('__'):
4343
if isinstance(value, valid_types):
4444
default_params[name] = conversion.make_pynn_compatible(value)
4545
else:
@@ -53,10 +53,7 @@ def get_receptor_types(model_name):
5353

5454

5555
def get_recordables(model_name):
56-
try:
57-
return [name for name in nest.GetDefaults(model_name, "recordables")]
58-
except nest.NESTError:
59-
return []
56+
return list(nest.GetDefaults(model_name).get("recordables", []))
6057

6158

6259
def native_cell_type(model_name):

pyNN/nest/extensions/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,23 @@ add_custom_target( dist
192192
)
193193

194194

195+
# On macOS, loadable modules need -undefined dynamic_lookup so that NEST
196+
# kernel symbols (provided by nestkernel_api.so at Python import time) are
197+
# resolved at dlopen time rather than requiring a libnest.so at link time.
198+
if ( APPLE )
199+
set( MACOS_LINK_FLAGS "-undefined dynamic_lookup" )
200+
else ()
201+
set( MACOS_LINK_FLAGS "" )
202+
endif ()
203+
195204
# Create a module for loading at runtime
196205
# with the `Install` command.
197206
add_library( ${MODULE_NAME}_module MODULE ${MODULE_SOURCES} )
198207
target_link_libraries(${MODULE_NAME}_module ${USER_LINK_LIBRARIES})
199208
set_target_properties( ${MODULE_NAME}_module
200209
PROPERTIES
201210
COMPILE_FLAGS "${NEST_CXXFLAGS} -DLTX_MODULE"
202-
LINK_FLAGS "${NEST_LIBS}"
211+
LINK_FLAGS "${NEST_LIBS} ${MACOS_LINK_FLAGS}"
203212
PREFIX ""
204213
OUTPUT_NAME ${MODULE_NAME} )
205214
install( TARGETS ${MODULE_NAME}_module

pyNN/nest/extensions/simple_stochastic_synapse.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
// Includes from nestkernel:
1111
#include "connection.h"
12+
#include "dictionary.h"
1213
#include "kernel_manager.h"
1314

1415

@@ -156,15 +157,15 @@ class simple_stochastic_synapse : public nest::Connection< targetidentifierT >
156157
// data member holding the weight.
157158

158159
//! Store connection status information in dictionary
159-
void get_status( DictionaryDatum& d ) const;
160+
void get_status( Dictionary& d ) const;
160161

161162
/**
162163
* Set connection status.
163164
*
164165
* @param d Dictionary with new parameter values
165166
* @param cm ConnectorModel is passed along to validate new delay values
166167
*/
167-
void set_status( const DictionaryDatum& d, nest::ConnectorModel& cm );
168+
void set_status( const Dictionary& d, nest::ConnectorModel& cm );
168169

169170
//! Allows efficient initialization on construction
170171
void
@@ -203,23 +204,23 @@ simple_stochastic_synapse< targetidentifierT >::send( nest::Event& e,
203204
template < typename targetidentifierT >
204205
void
205206
simple_stochastic_synapse< targetidentifierT >::get_status(
206-
DictionaryDatum& d ) const
207+
Dictionary& d ) const
207208
{
208209
ConnectionBase::get_status( d );
209-
def< double >( d, nest::names::weight, weight_ );
210-
def< double >( d, nest::names::p, p_ );
211-
def< long >( d, nest::names::size_of, sizeof( *this ) );
210+
d[ nest::names::weight ] = weight_;
211+
d[ nest::names::p ] = p_;
212+
d[ nest::names::size_of ] = static_cast< long >( sizeof( *this ) );
212213
}
213214

214215
template < typename targetidentifierT >
215216
void
216217
simple_stochastic_synapse< targetidentifierT >::set_status(
217-
const DictionaryDatum& d,
218+
const Dictionary& d,
218219
nest::ConnectorModel& cm )
219220
{
220221
ConnectionBase::set_status( d, cm );
221-
updateValue< double >( d, nest::names::weight, weight_ );
222-
updateValue< double >( d, nest::names::p, p_ );
222+
d.update_value( nest::names::weight, weight_ );
223+
d.update_value( nest::names::p, p_ );
223224
}
224225

225226
} // namespace

pyNN/nest/extensions/stochastic_stp_synapse.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
// Includes from nestkernel:
1313
#include "connection.h"
14+
#include "dictionary.h"
1415

1516
/* BeginUserDocs: synapse, short-term plasticity
1617
@@ -93,13 +94,13 @@ class stochastic_stp_synapse : public nest::Connection< targetidentifierT >
9394
/**
9495
* Get all properties of this connection and put them into a dictionary.
9596
*/
96-
void get_status( DictionaryDatum& d ) const;
97+
void get_status( Dictionary& d ) const;
9798

9899
/**
99100
* Set default properties of this connection from the values given in
100101
* dictionary.
101102
*/
102-
void set_status( const DictionaryDatum& d, nest::ConnectorModel& cm );
103+
void set_status( const Dictionary& d, nest::ConnectorModel& cm );
103104

104105
/**
105106
* Send an event to the receiver of this connection.

pyNN/nest/extensions/stochastic_stp_synapse_impl.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
#include "connector_model.h"
1717
#include "nest_names.h"
1818

19-
// Includes from sli:
20-
#include "dictutils.h"
19+
// Includes from nestkernel:
20+
#include "dictionary.h"
2121

2222
namespace pynn
2323
{
@@ -55,30 +55,29 @@ stochastic_stp_synapse< targetidentifierT >::stochastic_stp_synapse(
5555
template < typename targetidentifierT >
5656
void
5757
stochastic_stp_synapse< targetidentifierT >::get_status(
58-
DictionaryDatum& d ) const
58+
Dictionary& d ) const
5959
{
6060
ConnectionBase::get_status( d );
61-
def< double >( d, nest::names::weight, weight_ );
62-
def< double >( d, nest::names::dU, U_ );
63-
def< double >( d, nest::names::u, u_ );
64-
def< double >( d, nest::names::tau_rec, tau_rec_ );
65-
def< double >( d, nest::names::tau_fac, tau_fac_ );
61+
d[ nest::names::weight ] = weight_;
62+
d[ nest::names::dU ] = U_;
63+
d[ nest::names::u ] = u_;
64+
d[ nest::names::tau_rec ] = tau_rec_;
65+
d[ nest::names::tau_fac ] = tau_fac_;
6666
}
6767

6868

6969
template < typename targetidentifierT >
7070
void
7171
stochastic_stp_synapse< targetidentifierT >::set_status(
72-
const DictionaryDatum& d,
72+
const Dictionary& d,
7373
nest::ConnectorModel& cm )
7474
{
7575
ConnectionBase::set_status( d, cm );
76-
updateValue< double >( d, nest::names::weight, weight_ );
77-
78-
updateValue< double >( d, nest::names::dU, U_ );
79-
updateValue< double >( d, nest::names::u, u_ );
80-
updateValue< double >( d, nest::names::tau_rec, tau_rec_ );
81-
updateValue< double >( d, nest::names::tau_fac, tau_fac_ );
76+
d.update_value( nest::names::weight, weight_ );
77+
d.update_value( nest::names::dU, U_ );
78+
d.update_value( nest::names::u, u_ );
79+
d.update_value( nest::names::tau_rec, tau_rec_ );
80+
d.update_value( nest::names::tau_fac, tau_fac_ );
8281
}
8382

8483
} // of namespace pynn

pyNN/nest/nestml.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def nestml_synapse_type(
109109
nestml_description,
110110
postsynaptic_neuron_nestml_description=None,
111111
weight_variable="w",
112-
delay_variable="d"
112+
delay_variable=None
113113
):
114114
"""
115115
Register a NESTML synapse description and return a synapse type class.
@@ -270,6 +270,24 @@ def _compile_and_resolve():
270270
codegen_opts=codegen_opts,
271271
)
272272
nest.Install(module_name)
273+
except nest.NESTErrors.DynamicModuleManagementError as e:
274+
missing_delay = [
275+
entry["name"] for entry in _pending
276+
if entry["type"] == "synapse" and entry["delay_variable"] is None
277+
]
278+
hint = ""
279+
if missing_delay:
280+
hint = (
281+
f"Synapse model(s) {missing_delay} have no delay_variable set. "
282+
"If your NESTML model uses an explicit delay variable, "
283+
"pass delay_variable='<name>' to nestml_synapse_type() "
284+
"to match the delay parameter in your model."
285+
)
286+
raise RuntimeError(
287+
f"Failed to install NESTML module '{module_name}'. "
288+
"NESTML model compilation failed silently. "
289+
f"{hint}"
290+
) from e
273291
finally:
274292
for tmpdir in tmpdirs:
275293
shutil.rmtree(tmpdir, ignore_errors=True)

pyNN/nest/populations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def _set_initial_value_array(self, variable, value):
282282
simulator.state.set_status(self.node_collection[self._mask_local],
283283
variable, local_values)
284284
except nest.NESTError as e:
285-
if "Unused dictionary items" in e.args[0]:
285+
if "Unused dictionary items" in e.args[0] or "Unaccessed" in e.args[0]:
286286
logger.warning("NEST does not allow setting an initial value for %s" % variable)
287287
# should perhaps check whether value-to-be-set is the same as current value,
288288
# and raise an Exception if not, rather than just emit a warning.

0 commit comments

Comments
 (0)