bsb-nest 6.0.3__tar.gz → 7.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/PKG-INFO +2 -2
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/adapter.py +20 -19
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/connection.py +61 -39
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/device.py +1 -1
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/pyproject.toml +3 -3
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/LICENSE +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/README.md +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/__init__.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/cell.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/devices/__init__.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/devices/dc_generator.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/devices/multimeter.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/devices/poisson_generator.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/devices/sinusoidal_poisson_generator.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/devices/spike_recorder.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/distributions.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/exceptions.py +0 -0
- {bsb_nest-6.0.3 → bsb_nest-7.0.2}/bsb_nest/simulation.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bsb-nest
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.0.2
|
|
4
4
|
Summary: NEST simulation adapter for the BSB framework.
|
|
5
5
|
Author-email: Robin De Schepper <robin@alexandria.sc>, Dimitri Rodarie <dimitri.rodarie@unipv.it>
|
|
6
6
|
Requires-Python: >=3.10,<4
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
9
9
|
License-File: LICENSE
|
|
10
|
-
Requires-Dist: bsb-core~=
|
|
10
|
+
Requires-Dist: bsb-core~=7.0
|
|
11
11
|
Requires-Dist: bsb-core[parallel] ; extra == "parallel"
|
|
12
12
|
Provides-Extra: parallel
|
|
13
13
|
|
|
@@ -5,10 +5,10 @@ import typing
|
|
|
5
5
|
import nest
|
|
6
6
|
from bsb import (
|
|
7
7
|
AdapterError,
|
|
8
|
-
AdapterProgress,
|
|
9
8
|
SimulationData,
|
|
10
9
|
SimulationResult,
|
|
11
10
|
SimulatorAdapter,
|
|
11
|
+
options,
|
|
12
12
|
report,
|
|
13
13
|
warn,
|
|
14
14
|
)
|
|
@@ -17,11 +17,13 @@ from tqdm import tqdm
|
|
|
17
17
|
|
|
18
18
|
from .exceptions import KernelWarning, NestConnectError, NestModelError, NestModuleError
|
|
19
19
|
|
|
20
|
-
if typing.TYPE_CHECKING:
|
|
20
|
+
if typing.TYPE_CHECKING: # pragma: nocover
|
|
21
21
|
from .simulation import NestSimulation
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class NestResult(SimulationResult):
|
|
25
|
+
# It seems that the record method is not used,
|
|
26
|
+
# probably we will have to uniform the behavior with NeuronResult
|
|
25
27
|
def record(self, nc, **annotations):
|
|
26
28
|
recorder = nest.Create("spike_recorder", params={"record_to": "memory"})
|
|
27
29
|
nest.Connect(nc, recorder)
|
|
@@ -38,6 +40,7 @@ class NestResult(SimulationResult):
|
|
|
38
40
|
**annotations,
|
|
39
41
|
)
|
|
40
42
|
)
|
|
43
|
+
# Free the Memory -> not possible to free the memory while sim is running
|
|
41
44
|
|
|
42
45
|
self.create_recorder(flush)
|
|
43
46
|
|
|
@@ -46,6 +49,7 @@ class NestAdapter(SimulatorAdapter):
|
|
|
46
49
|
def __init__(self, comm=None):
|
|
47
50
|
super().__init__(comm=comm)
|
|
48
51
|
self.loaded_modules = set()
|
|
52
|
+
self._prev_chkpoint = 0
|
|
49
53
|
|
|
50
54
|
def simulate(self, *simulations, post_prepare=None):
|
|
51
55
|
try:
|
|
@@ -87,7 +91,8 @@ class NestAdapter(SimulatorAdapter):
|
|
|
87
91
|
report("Creating connections...", level=2)
|
|
88
92
|
self.connect_neurons(simulation)
|
|
89
93
|
report("Creating devices...", level=2)
|
|
90
|
-
self.
|
|
94
|
+
self.implement_components(simulation)
|
|
95
|
+
self.load_controllers(simulation)
|
|
91
96
|
return self.simdata[simulation]
|
|
92
97
|
except Exception:
|
|
93
98
|
del self.simdata[simulation]
|
|
@@ -104,18 +109,21 @@ class NestAdapter(SimulatorAdapter):
|
|
|
104
109
|
if unprepared:
|
|
105
110
|
raise AdapterError(f"Unprepared for simulations: {', '.join(unprepared)}")
|
|
106
111
|
report("Simulating...", level=2)
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
self._duration = max(sim.duration for sim in simulations)
|
|
113
|
+
|
|
109
114
|
try:
|
|
115
|
+
results = [self.simdata[sim].result for sim in simulations]
|
|
110
116
|
with nest.RunManager():
|
|
111
|
-
for
|
|
112
|
-
nest.Run(
|
|
113
|
-
|
|
117
|
+
for t, checkpoint_controllers in self.get_next_checkpoint():
|
|
118
|
+
nest.Run(t - self._prev_chkpoint)
|
|
119
|
+
self.execute_checkpoints(checkpoint_controllers)
|
|
120
|
+
self._prev_chkpoint = t
|
|
121
|
+
|
|
114
122
|
finally:
|
|
115
123
|
results = [self.simdata[sim].result for sim in simulations]
|
|
116
124
|
for sim in simulations:
|
|
117
125
|
del self.simdata[sim]
|
|
118
|
-
|
|
126
|
+
|
|
119
127
|
report("Simulation done.", level=2)
|
|
120
128
|
return results
|
|
121
129
|
|
|
@@ -156,7 +164,7 @@ class NestAdapter(SimulatorAdapter):
|
|
|
156
164
|
simdata = self.simdata[simulation]
|
|
157
165
|
iter = simulation.connection_models.values()
|
|
158
166
|
if self.comm.get_rank() == 0:
|
|
159
|
-
iter = tqdm(iter, desc="", file=sys.stdout)
|
|
167
|
+
iter = tqdm(iter, desc="", file=sys.stdout, disable=options.verbosity < 2)
|
|
160
168
|
for connection_model in iter:
|
|
161
169
|
with contextlib.suppress(AttributeError):
|
|
162
170
|
# Only rank 0 should report progress bar
|
|
@@ -178,15 +186,8 @@ class NestAdapter(SimulatorAdapter):
|
|
|
178
186
|
simdata, pre_nodes, post_nodes, cs, self.comm
|
|
179
187
|
)
|
|
180
188
|
)
|
|
181
|
-
except Exception:
|
|
182
|
-
raise NestConnectError(
|
|
183
|
-
f"{connection_model} error during connect."
|
|
184
|
-
) from None
|
|
185
|
-
|
|
186
|
-
def create_devices(self, simulation):
|
|
187
|
-
simdata = self.simdata[simulation]
|
|
188
|
-
for device_model in simulation.devices.values():
|
|
189
|
-
device_model.implement(self, simulation, simdata)
|
|
189
|
+
except Exception as e:
|
|
190
|
+
raise NestConnectError(f"{connection_model} error during connect.") from e
|
|
190
191
|
|
|
191
192
|
def set_settings(self, simulation: "NestSimulation"):
|
|
192
193
|
nest.set_verbosity(simulation.verbosity)
|
|
@@ -4,11 +4,18 @@ import sys
|
|
|
4
4
|
import nest
|
|
5
5
|
import numpy as np
|
|
6
6
|
import psutil
|
|
7
|
-
from bsb import ConnectionModel, compose_nodes, config, types
|
|
7
|
+
from bsb import ConfigurationError, ConnectionModel, compose_nodes, config, options, types
|
|
8
8
|
from tqdm import tqdm
|
|
9
9
|
|
|
10
10
|
from .distributions import nest_parameter
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _is_delay_required(node):
|
|
14
|
+
model = node.get("model", NestSynapseSettings.model.default)
|
|
15
|
+
if model not in nest.Models(mtype="synapses"):
|
|
16
|
+
raise ConfigurationError(f"Unknown synapse model '{model}'.")
|
|
17
|
+
else:
|
|
18
|
+
return nest.GetDefaults(model)["has_delay"]
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
@config.node
|
|
@@ -21,7 +28,7 @@ class NestSynapseSettings:
|
|
|
21
28
|
"""Importable reference to the NEST model describing the synapse type."""
|
|
22
29
|
weight = config.attr(type=float, required=True)
|
|
23
30
|
"""Weight of the connection between the presynaptic and the postsynaptic cells."""
|
|
24
|
-
delay = config.attr(type=float, required=
|
|
31
|
+
delay = config.attr(type=float, required=_is_delay_required, default=None)
|
|
25
32
|
"""Delay of the transmission between the presynaptic and the postsynaptic cells."""
|
|
26
33
|
receptor_type = config.attr(type=int)
|
|
27
34
|
"""Index of the postsynaptic receptor to target."""
|
|
@@ -36,7 +43,7 @@ class NestConnectionSettings:
|
|
|
36
43
|
"""
|
|
37
44
|
|
|
38
45
|
rule = config.attr(type=str)
|
|
39
|
-
"""Importable reference to the
|
|
46
|
+
"""Importable reference to the NEST connection rule used to connect the cells."""
|
|
40
47
|
constants = config.catch_all(type=types.any_())
|
|
41
48
|
"""Dictionary of parameters to assign to the connection rule."""
|
|
42
49
|
|
|
@@ -76,19 +83,20 @@ class NestConnection(compose_nodes(NestConnectionSettings, ConnectionModel)):
|
|
|
76
83
|
management.
|
|
77
84
|
"""
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
"""
|
|
86
|
+
synapses = config.list(type=NestSynapseSettings, required=True)
|
|
87
|
+
"""List of synapse models to use for a connection."""
|
|
81
88
|
|
|
82
89
|
def create_connections(self, simdata, pre_nodes, post_nodes, cs, comm):
|
|
83
90
|
import nest
|
|
84
91
|
|
|
85
|
-
|
|
86
|
-
if syn_spec["synapse_model"] not in nest.Models(mtype="synapses"):
|
|
87
|
-
raise NestConnectError(
|
|
88
|
-
f"Unknown synapse model '{syn_spec['synapse_model']}'."
|
|
89
|
-
)
|
|
92
|
+
syn_specs = self.get_syn_specs()
|
|
90
93
|
if self.rule is not None:
|
|
91
|
-
nest.Connect(
|
|
94
|
+
nest.Connect(
|
|
95
|
+
pre_nodes,
|
|
96
|
+
post_nodes,
|
|
97
|
+
self.get_conn_spec(),
|
|
98
|
+
nest.CollocatedSynapses(*syn_specs),
|
|
99
|
+
)
|
|
92
100
|
else:
|
|
93
101
|
comm.barrier()
|
|
94
102
|
for pre_locs, post_locs in self.predict_mem_iterator(
|
|
@@ -104,17 +112,21 @@ class NestConnection(compose_nodes(NestConnectionSettings, ConnectionModel)):
|
|
|
104
112
|
)
|
|
105
113
|
prel = pre_nodes.tolist()
|
|
106
114
|
postl = post_nodes.tolist()
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
[
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
# cannot use CollocatedSynapses with a list of weight and delay
|
|
116
|
+
# so loop over the syn_specs
|
|
117
|
+
for syn_spec in syn_specs:
|
|
118
|
+
ssw = {**syn_spec}
|
|
119
|
+
bw = syn_spec["weight"]
|
|
120
|
+
ssw["weight"] = [bw * m for m in multiplicity]
|
|
121
|
+
if "delay" in syn_spec:
|
|
122
|
+
ssw["delay"] = [syn_spec["delay"]] * len(ssw["weight"])
|
|
123
|
+
nest.Connect(
|
|
124
|
+
[prel[x] for x in cell_pairs[:, 0]],
|
|
125
|
+
[postl[x] for x in cell_pairs[:, 1]],
|
|
126
|
+
"one_to_one",
|
|
127
|
+
ssw,
|
|
128
|
+
return_synapsecollection=False,
|
|
129
|
+
)
|
|
118
130
|
comm.barrier()
|
|
119
131
|
return LazySynapseCollection(pre_nodes, post_nodes)
|
|
120
132
|
|
|
@@ -141,7 +153,12 @@ class NestConnection(compose_nodes(NestConnectionSettings, ConnectionModel)):
|
|
|
141
153
|
def block_iter():
|
|
142
154
|
iter = locals
|
|
143
155
|
if comm.get_rank() == 0:
|
|
144
|
-
iter = tqdm(
|
|
156
|
+
iter = tqdm(
|
|
157
|
+
iter,
|
|
158
|
+
desc="hyperblocks",
|
|
159
|
+
file=sys.stdout,
|
|
160
|
+
disable=options.verbosity < 2,
|
|
161
|
+
)
|
|
145
162
|
for local in iter:
|
|
146
163
|
inner_iter = cs.load_connections().as_globals().from_(local)
|
|
147
164
|
if comm.get_rank() == 0:
|
|
@@ -160,7 +177,9 @@ class NestConnection(compose_nodes(NestConnectionSettings, ConnectionModel)):
|
|
|
160
177
|
def local_iterator(self, cs, comm):
|
|
161
178
|
iter = cs.get_local_chunks("out")
|
|
162
179
|
if comm.get_rank() == 0:
|
|
163
|
-
iter = tqdm(
|
|
180
|
+
iter = tqdm(
|
|
181
|
+
iter, desc="hyperblocks", file=sys.stdout, disable=options.verbosity < 2
|
|
182
|
+
)
|
|
164
183
|
yield from (
|
|
165
184
|
cs.load_connections().as_globals().from_(local).all() for local in iter
|
|
166
185
|
)
|
|
@@ -177,17 +196,20 @@ class NestConnection(compose_nodes(NestConnectionSettings, ConnectionModel)):
|
|
|
177
196
|
**self.constants,
|
|
178
197
|
}
|
|
179
198
|
|
|
180
|
-
def
|
|
181
|
-
return
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
199
|
+
def get_syn_specs(self):
|
|
200
|
+
return [
|
|
201
|
+
{
|
|
202
|
+
**{
|
|
203
|
+
label: value
|
|
204
|
+
for attr, label in (
|
|
205
|
+
("model", "synapse_model"),
|
|
206
|
+
["weight"] * 2,
|
|
207
|
+
["delay"] * 2,
|
|
208
|
+
["receptor_type"] * 2,
|
|
209
|
+
)
|
|
210
|
+
if (value := getattr(synapse, attr)) is not None
|
|
211
|
+
},
|
|
212
|
+
**synapse.constants,
|
|
213
|
+
}
|
|
214
|
+
for synapse in self.synapses
|
|
215
|
+
]
|
|
@@ -6,14 +6,14 @@ build-backend = "flit_core.buildapi"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "bsb-nest"
|
|
9
|
-
version = "
|
|
9
|
+
version = "7.0.2"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.10,<4"
|
|
12
12
|
dynamic = [ "description" ]
|
|
13
13
|
classifiers = [
|
|
14
14
|
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)"
|
|
15
15
|
]
|
|
16
|
-
dependencies = [ "bsb-core~=
|
|
16
|
+
dependencies = [ "bsb-core~=7.0" ]
|
|
17
17
|
|
|
18
18
|
[[project.authors]]
|
|
19
19
|
name = "Robin De Schepper"
|
|
@@ -44,7 +44,7 @@ branch = true
|
|
|
44
44
|
source = [ "bsb_nest" ]
|
|
45
45
|
|
|
46
46
|
[tool.coverage.report]
|
|
47
|
-
exclude_lines = [ "if TYPE_CHECKING:" ]
|
|
47
|
+
exclude_lines = [ "if typing.TYPE_CHECKING:", "pragma: nocover" ]
|
|
48
48
|
show_missing = true
|
|
49
49
|
|
|
50
50
|
[tool.ruff]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|