bsb-arbor 4.1.1__tar.gz → 6.0.0a7__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.
Potentially problematic release.
This version of bsb-arbor might be problematic. Click here for more details.
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/LICENSE +0 -0
- bsb_arbor-6.0.0a7/PKG-INFO +36 -0
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/README.md +1 -1
- bsb_arbor-6.0.0a7/bsb_arbor/__init__.py +20 -0
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/adapter.py +36 -37
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/cell.py +13 -8
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/connection.py +7 -6
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/device.py +7 -2
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/devices/__init__.py +6 -0
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/devices/poisson_generator.py +4 -0
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/devices/probe.py +3 -4
- {bsb_arbor-4.1.1 → bsb_arbor-6.0.0a7}/bsb_arbor/devices/spike_recorder.py +4 -5
- bsb_arbor-6.0.0a7/bsb_arbor/simulation.py +38 -0
- bsb_arbor-6.0.0a7/pyproject.toml +83 -0
- bsb_arbor-4.1.1/PKG-INFO +0 -37
- bsb_arbor-4.1.1/bsb_arbor/__init__.py +0 -12
- bsb_arbor-4.1.1/bsb_arbor/simulation.py +0 -23
- bsb_arbor-4.1.1/pyproject.toml +0 -69
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bsb-arbor
|
|
3
|
+
Version: 6.0.0a7
|
|
4
|
+
Summary: Arbor simulation adapter for the BSB framework.
|
|
5
|
+
Author-email: Robin De Schepper <robin@alexandria.sc>, Dimitri Rodarie <dimitri.rodarie@unipv.it>
|
|
6
|
+
Requires-Python: >=3.10,<4
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: numpy~=1.21
|
|
11
|
+
Requires-Dist: bsb-core~=6.0
|
|
12
|
+
Requires-Dist: arborize~=6.0
|
|
13
|
+
Requires-Dist: arbor~=0.10; sys_platform != 'win32'
|
|
14
|
+
Requires-Dist: bsb-arbor[test, docs] ; extra == "dev"
|
|
15
|
+
Requires-Dist: pre-commit~=3.5 ; extra == "dev"
|
|
16
|
+
Requires-Dist: ruff>=0.8.2 ; extra == "dev"
|
|
17
|
+
Requires-Dist: snakeviz~=2.1 ; extra == "dev"
|
|
18
|
+
Requires-Dist: furo~=2024.0 ; extra == "docs"
|
|
19
|
+
Requires-Dist: sphinxext-bsb~=6.0 ; extra == "docs"
|
|
20
|
+
Requires-Dist: bsb-core[parallel] ; extra == "test"
|
|
21
|
+
Requires-Dist: bsb-hdf5~=6.0 ; extra == "test"
|
|
22
|
+
Requires-Dist: bsb-test~=6.0 ; extra == "test"
|
|
23
|
+
Requires-Dist: coverage>=7.3 ; extra == "test"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Provides-Extra: docs
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
|
|
28
|
+
[](https://github.com/dbbs-lab/bsb-arbor/actions/workflows/main.yml)
|
|
29
|
+
[](https://github.com/psf/black)
|
|
30
|
+
|
|
31
|
+
# bsb-arbor
|
|
32
|
+
|
|
33
|
+
bsb-arbor is a plugin of the [BSB](https://github.com/dbbs-lab/bsb) (see also
|
|
34
|
+
[bsb-core](https://github.com/dbbs-lab/bsb-core)).
|
|
35
|
+
It contains the interfaces and tools to simulate BSB circuit with the
|
|
36
|
+
[Arbor simulator](https://arbor-sim.org/).
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# bsb-arbor
|
|
5
5
|
|
|
6
|
-
bsb-
|
|
6
|
+
bsb-arbor is a plugin of the [BSB](https://github.com/dbbs-lab/bsb) (see also
|
|
7
7
|
[bsb-core](https://github.com/dbbs-lab/bsb-core)).
|
|
8
8
|
It contains the interfaces and tools to simulate BSB circuit with the
|
|
9
9
|
[Arbor simulator](https://arbor-sim.org/).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Arbor simulation adapter for the BSB framework.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from bsb import SimulationBackendPlugin
|
|
6
|
+
|
|
7
|
+
from .adapter import ArborAdapter
|
|
8
|
+
from .devices import PoissonGenerator, Probe, SpikeRecorder
|
|
9
|
+
from .simulation import ArborSimulation
|
|
10
|
+
|
|
11
|
+
__plugin__ = SimulationBackendPlugin(Simulation=ArborSimulation, Adapter=ArborAdapter)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"PoissonGenerator",
|
|
16
|
+
"Probe",
|
|
17
|
+
"SpikeRecorder",
|
|
18
|
+
"ArborAdapter",
|
|
19
|
+
"ArborSimulation",
|
|
20
|
+
]
|
|
@@ -7,7 +7,6 @@ import arbor
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
from arbor import units as U
|
|
9
9
|
from bsb import (
|
|
10
|
-
MPI,
|
|
11
10
|
AdapterError,
|
|
12
11
|
Chunk,
|
|
13
12
|
SimulationData,
|
|
@@ -22,9 +21,16 @@ if typing.TYPE_CHECKING:
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class ArborSimulationData(SimulationData):
|
|
24
|
+
"""
|
|
25
|
+
Container class for simulation data.
|
|
26
|
+
"""
|
|
27
|
+
|
|
25
28
|
def __init__(self, simulation):
|
|
29
|
+
"""
|
|
30
|
+
Container class for simulation data.
|
|
31
|
+
"""
|
|
26
32
|
super().__init__(simulation)
|
|
27
|
-
self.arbor_sim:
|
|
33
|
+
self.arbor_sim: arbor.simulation = None
|
|
28
34
|
|
|
29
35
|
|
|
30
36
|
class ReceiverCollection(list):
|
|
@@ -47,7 +53,8 @@ class ReceiverCollection(list):
|
|
|
47
53
|
|
|
48
54
|
class SingleReceiverCollection(list):
|
|
49
55
|
"""
|
|
50
|
-
The single receiver collection redirects all incoming connections to the same
|
|
56
|
+
The single receiver collection redirects all incoming connections to the same
|
|
57
|
+
receiver.
|
|
51
58
|
"""
|
|
52
59
|
|
|
53
60
|
def append(self, rcv):
|
|
@@ -82,13 +89,14 @@ class Population:
|
|
|
82
89
|
|
|
83
90
|
def __getitem__(self, item):
|
|
84
91
|
# Boolean masking, kind of
|
|
85
|
-
if getattr(item, "dtype", None) == bool or _all_bools(item):
|
|
92
|
+
if getattr(item, "dtype", None) == bool or _all_bools(item): # noqa: E721
|
|
86
93
|
if len(item) != len(self):
|
|
87
94
|
raise ValueError(
|
|
88
|
-
f"Dimension mismatch between population ({len(self)})
|
|
95
|
+
f"Dimension mismatch between population ({len(self)}) "
|
|
96
|
+
f"and mask ({len(item)})"
|
|
89
97
|
)
|
|
90
98
|
return self._subpop_np(np.array(self)[item])
|
|
91
|
-
elif getattr(item, "dtype", None) == int or _all_ints(item):
|
|
99
|
+
elif getattr(item, "dtype", None) == int or _all_ints(item): # noqa: E721
|
|
92
100
|
if getattr(item, "ndim", None) == 0:
|
|
93
101
|
return self._subpop_one(item)
|
|
94
102
|
return self._subpop_np(np.array(self)[item])
|
|
@@ -142,9 +150,7 @@ class Population:
|
|
|
142
150
|
ptr += stop - start
|
|
143
151
|
|
|
144
152
|
def __iter__(self):
|
|
145
|
-
yield from itertools.chain.from_iterable(
|
|
146
|
-
range(r[0], r[1]) for r in self._ranges
|
|
147
|
-
)
|
|
153
|
+
yield from itertools.chain.from_iterable(range(r[0], r[1]) for r in self._ranges)
|
|
148
154
|
|
|
149
155
|
|
|
150
156
|
class GIDManager:
|
|
@@ -281,36 +287,27 @@ class ArborRecipe(arbor.recipe):
|
|
|
281
287
|
|
|
282
288
|
|
|
283
289
|
class ArborAdapter(SimulatorAdapter):
|
|
284
|
-
def __init__(self):
|
|
285
|
-
super().__init__()
|
|
286
|
-
self.simdata:
|
|
287
|
-
|
|
288
|
-
def
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
return MPI.get_size()
|
|
293
|
-
|
|
294
|
-
def broadcast(self, data, root=0):
|
|
295
|
-
return MPI.bcast(data, root)
|
|
296
|
-
|
|
297
|
-
def barrier(self):
|
|
298
|
-
return MPI.barrier()
|
|
299
|
-
|
|
300
|
-
def prepare(self, simulation: "ArborSimulation", comm=None):
|
|
290
|
+
def __init__(self, comm=None):
|
|
291
|
+
super().__init__(comm)
|
|
292
|
+
self.simdata: dict[ArborSimulation, ArborSimulationData] = {}
|
|
293
|
+
|
|
294
|
+
def prepare(self, simulation: "ArborSimulation") -> ArborSimulationData:
|
|
295
|
+
"""
|
|
296
|
+
Prepares the arbor simulation engine with the given simulation.
|
|
297
|
+
"""
|
|
301
298
|
simdata = self._create_simdata(simulation)
|
|
302
299
|
try:
|
|
303
300
|
context = arbor.context(arbor.proc_allocation(threads=simulation.threads))
|
|
304
|
-
if
|
|
301
|
+
if self.comm.get_size() > 1:
|
|
305
302
|
if not arbor.config()["mpi4py"]:
|
|
306
303
|
warn(
|
|
307
304
|
f"Arbor does not seem to be built with MPI support, running"
|
|
308
|
-
"duplicate simulations on {
|
|
305
|
+
f"duplicate simulations on {self.comm.get_size()} nodes."
|
|
309
306
|
)
|
|
310
307
|
else:
|
|
311
308
|
context = arbor.context(
|
|
312
309
|
arbor.proc_allocation(threads=simulation.threads),
|
|
313
|
-
mpi=comm
|
|
310
|
+
mpi=self.comm.get_communicator(),
|
|
314
311
|
)
|
|
315
312
|
if simulation.profiling:
|
|
316
313
|
if arbor.config()["profiling"]:
|
|
@@ -318,7 +315,8 @@ class ArborAdapter(SimulatorAdapter):
|
|
|
318
315
|
arbor.profiler_initialize(context)
|
|
319
316
|
else:
|
|
320
317
|
raise RuntimeError(
|
|
321
|
-
"Arbor must be built with profiling support to use the
|
|
318
|
+
"Arbor must be built with profiling support to use the "
|
|
319
|
+
"`profiling` flag."
|
|
322
320
|
)
|
|
323
321
|
simdata.gid_manager = self.get_gid_manager(simulation, simdata)
|
|
324
322
|
simdata.populations = simdata.gid_manager.get_populations()
|
|
@@ -342,12 +340,13 @@ class ArborAdapter(SimulatorAdapter):
|
|
|
342
340
|
|
|
343
341
|
def prepare_samples(self, simulation, simdata):
|
|
344
342
|
for device in simulation.devices.values():
|
|
345
|
-
device.prepare_samples(simdata)
|
|
343
|
+
device.prepare_samples(simdata, comm=self.comm)
|
|
346
344
|
|
|
347
345
|
def run(self, *simulations):
|
|
348
346
|
if len(simulations) != 1:
|
|
349
347
|
raise RuntimeError(
|
|
350
|
-
"Can not run multiple simultaneous simulations. Composition not
|
|
348
|
+
"Can not run multiple simultaneous simulations. Composition not "
|
|
349
|
+
"implemented."
|
|
351
350
|
)
|
|
352
351
|
simulation = simulations[0]
|
|
353
352
|
try:
|
|
@@ -358,7 +357,7 @@ class ArborAdapter(SimulatorAdapter):
|
|
|
358
357
|
f"Can't run unprepared simulation '{simulation.name}'"
|
|
359
358
|
) from None
|
|
360
359
|
try:
|
|
361
|
-
if not
|
|
360
|
+
if not self.comm.get_rank():
|
|
362
361
|
arbor_sim.record(arbor.spike_recording.all)
|
|
363
362
|
|
|
364
363
|
start = time.time()
|
|
@@ -381,7 +380,7 @@ class ArborAdapter(SimulatorAdapter):
|
|
|
381
380
|
return ArborRecipe(simulation, simdata)
|
|
382
381
|
|
|
383
382
|
def _create_simdata(self, simulation):
|
|
384
|
-
self.simdata[simulation] = simdata =
|
|
383
|
+
self.simdata[simulation] = simdata = ArborSimulationData(simulation)
|
|
385
384
|
self._assign_chunks(simulation, simdata)
|
|
386
385
|
return simdata
|
|
387
386
|
|
|
@@ -431,14 +430,14 @@ class ArborAdapter(SimulatorAdapter):
|
|
|
431
430
|
|
|
432
431
|
def _assign_chunks(self, simulation, simdata):
|
|
433
432
|
chunk_stats = simulation.scaffold.storage.get_chunk_stats()
|
|
434
|
-
size =
|
|
435
|
-
all_chunks = [Chunk.from_id(int(chunk), None) for chunk in chunk_stats
|
|
433
|
+
size = self.comm.get_size()
|
|
434
|
+
all_chunks = [Chunk.from_id(int(chunk), None) for chunk in chunk_stats]
|
|
436
435
|
simdata.node_chunk_alloc = [all_chunks[rank::size] for rank in range(0, size)]
|
|
437
436
|
simdata.chunk_node_map = {}
|
|
438
437
|
for node, chunks in enumerate(simdata.node_chunk_alloc):
|
|
439
438
|
for chunk in chunks:
|
|
440
439
|
simdata.chunk_node_map[chunk] = node
|
|
441
|
-
simdata.chunks = simdata.node_chunk_alloc[
|
|
440
|
+
simdata.chunks = simdata.node_chunk_alloc[self.comm.get_rank()]
|
|
442
441
|
|
|
443
442
|
|
|
444
443
|
def _all_bools(arr):
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
import typing
|
|
3
2
|
|
|
4
3
|
import arbor
|
|
5
|
-
from bsb import CellModel, ConfigurationError, config, types
|
|
4
|
+
from bsb import CellModel, ConfigurationError, PlacementSet, config, types
|
|
6
5
|
|
|
7
6
|
from .adapter import SingleReceiverCollection
|
|
8
7
|
|
|
9
|
-
if typing.TYPE_CHECKING:
|
|
10
|
-
from bsb import PlacementSet
|
|
11
|
-
|
|
12
8
|
|
|
13
9
|
@config.dynamic(
|
|
14
10
|
attr_name="model_strategy",
|
|
@@ -17,11 +13,18 @@ if typing.TYPE_CHECKING:
|
|
|
17
13
|
classmap_entry=None,
|
|
18
14
|
)
|
|
19
15
|
class ArborCell(CellModel):
|
|
16
|
+
model_strategy: config.ConfigurationAttribute
|
|
17
|
+
"""
|
|
18
|
+
Optional importable reference to a different modelling strategy than the default
|
|
19
|
+
Arborize strategy.
|
|
20
|
+
"""
|
|
20
21
|
gap = config.attr(type=bool, default=False)
|
|
22
|
+
"""Is this synapse a gap junction?"""
|
|
21
23
|
model = config.attr(type=types.class_(), required=True)
|
|
24
|
+
"""Importable reference to the arborize model describing the cell type."""
|
|
22
25
|
|
|
23
26
|
@abc.abstractmethod
|
|
24
|
-
def cache_population_data(self, simdata, ps:
|
|
27
|
+
def cache_population_data(self, simdata, ps: PlacementSet):
|
|
25
28
|
pass
|
|
26
29
|
|
|
27
30
|
@abc.abstractmethod
|
|
@@ -51,9 +54,11 @@ class ArborCell(CellModel):
|
|
|
51
54
|
@config.node
|
|
52
55
|
class LIFCell(ArborCell, classmap_entry="lif"):
|
|
53
56
|
model = config.unset()
|
|
57
|
+
"""Importable reference to the arborize model describing the cell type."""
|
|
54
58
|
constants = config.dict(type=types.any_())
|
|
59
|
+
"""Dictionary linking the parameters' name to its value."""
|
|
55
60
|
|
|
56
|
-
def cache_population_data(self, simdata, ps:
|
|
61
|
+
def cache_population_data(self, simdata, ps: PlacementSet):
|
|
57
62
|
pass
|
|
58
63
|
|
|
59
64
|
def discard_population_data(self):
|
|
@@ -66,7 +71,7 @@ class LIFCell(ArborCell, classmap_entry="lif"):
|
|
|
66
71
|
return arbor.cell_kind.lif
|
|
67
72
|
|
|
68
73
|
def get_description(self, gid):
|
|
69
|
-
cell = arbor.lif_cell(
|
|
74
|
+
cell = arbor.lif_cell("-1_-1", "-1_-1_0")
|
|
70
75
|
try:
|
|
71
76
|
for k, v in self.constants.items():
|
|
72
77
|
setattr(cell, k, v * getattr(cell, k).units)
|
|
@@ -41,8 +41,11 @@ class Connection:
|
|
|
41
41
|
@config.node
|
|
42
42
|
class ArborConnection(ConnectionModel):
|
|
43
43
|
gap = config.attr(type=bool, default=False)
|
|
44
|
+
"""Is this synapce a gap junction?"""
|
|
44
45
|
weight = config.attr(type=float, required=True)
|
|
46
|
+
"""Weight of the connection between the presynaptic and the postsynaptic cells."""
|
|
45
47
|
delay = config.attr(type=float, required=True)
|
|
48
|
+
"""Delay of the transmission between the presynaptic and the postsynaptic cells."""
|
|
46
49
|
|
|
47
50
|
def create_gap_junctions_on(self, gj_on_gid, conns):
|
|
48
51
|
for pre_loc, post_loc in conns:
|
|
@@ -56,12 +59,10 @@ class ArborConnection(ConnectionModel):
|
|
|
56
59
|
)
|
|
57
60
|
|
|
58
61
|
def create_connections_from(self, conns_from_gid, conns, pop_pre, pop_post):
|
|
59
|
-
for pre_loc,
|
|
62
|
+
for pre_loc, _post_loc in conns:
|
|
60
63
|
conns_from_gid[int(pre_loc[0] + pop_pre.offset)].append(pre_loc[1:])
|
|
61
64
|
|
|
62
65
|
def gap_junction(self, conn):
|
|
63
|
-
|
|
64
|
-
g = arbor.cell_global_label(
|
|
65
|
-
|
|
66
|
-
)
|
|
67
|
-
return arbor.gap_junction_connection(g, l, self.weight)
|
|
66
|
+
l_ = arbor.cell_local_label(f"gap_{conn.to_compartment.id}")
|
|
67
|
+
g = arbor.cell_global_label(int(conn.from_id), f"gap_{conn.from_compartment.id}")
|
|
68
|
+
return arbor.gap_junction_connection(g, l_, self.weight)
|
|
@@ -6,9 +6,14 @@ from bsb import DeviceModel, Targetting, config, types
|
|
|
6
6
|
|
|
7
7
|
@config.dynamic(attr_name="device", auto_classmap=True, classmap_entry=None)
|
|
8
8
|
class ArborDevice(DeviceModel):
|
|
9
|
+
device: config.ConfigurationAttribute
|
|
10
|
+
"""Optional importable reference to the device strategy."""
|
|
9
11
|
targetting = config.attr(type=Targetting, required=True)
|
|
12
|
+
"""Targets of the device, which should be either a population or a nest rule."""
|
|
10
13
|
resolution = config.attr(type=float)
|
|
14
|
+
"""Time resolution of the device."""
|
|
11
15
|
sampling_policy = config.attr(type=types.in_(["exact"]))
|
|
16
|
+
"""Policy used to sample simulation data from the device."""
|
|
12
17
|
|
|
13
18
|
def __init__(self, **kwargs):
|
|
14
19
|
self._probe_ids = []
|
|
@@ -19,7 +24,7 @@ class ArborDevice(DeviceModel):
|
|
|
19
24
|
def register_probe_id(self, gid, tag):
|
|
20
25
|
self._probe_ids.append((gid, tag))
|
|
21
26
|
|
|
22
|
-
def prepare_samples(self, simdata):
|
|
27
|
+
def prepare_samples(self, simdata, comm):
|
|
23
28
|
self._handles = [
|
|
24
29
|
self.sample(simdata.arbor_sim, probe_id) for probe_id in self._probe_ids
|
|
25
30
|
]
|
|
@@ -34,7 +39,7 @@ class ArborDevice(DeviceModel):
|
|
|
34
39
|
|
|
35
40
|
def get_meta(self):
|
|
36
41
|
attrs = ("name", "sampling_policy", "resolution")
|
|
37
|
-
return dict(zip(attrs, (getattr(self, attr) for attr in attrs)))
|
|
42
|
+
return dict(zip(attrs, (getattr(self, attr) for attr in attrs), strict=False))
|
|
38
43
|
|
|
39
44
|
@abc.abstractmethod
|
|
40
45
|
def implement_probes(self, simdata, target):
|
|
@@ -9,9 +9,13 @@ from ..device import ArborDevice
|
|
|
9
9
|
@config.node
|
|
10
10
|
class PoissonGenerator(ArborDevice, classmap_entry="poisson_generator"):
|
|
11
11
|
record = config.attr(type=bool, default=True)
|
|
12
|
+
"""Flag to save the spikes generated to file."""
|
|
12
13
|
rate = config.attr(type=float, required=True)
|
|
14
|
+
"""Frequency of the poisson generator."""
|
|
13
15
|
weight = config.attr(type=float, required=True)
|
|
16
|
+
"""Weight of the connection between the device and its target."""
|
|
14
17
|
delay = config.attr(type=float, required=True)
|
|
18
|
+
"""Delay of the transmission between the device and its target."""
|
|
15
19
|
|
|
16
20
|
def implement_probes(self, simdata, gid):
|
|
17
21
|
return []
|
|
@@ -11,7 +11,6 @@ class Probe(ArborDevice):
|
|
|
11
11
|
return f"cable_probe_{self.probe_type}"
|
|
12
12
|
|
|
13
13
|
def validate_specifics(self):
|
|
14
|
-
|
|
15
14
|
if self.get_probe_name() not in vars(arbor):
|
|
16
15
|
raise ConfigurationError(
|
|
17
16
|
f"`{self.probe_type}` is not a valid probe type for `{self.name}`"
|
|
@@ -22,9 +21,9 @@ class Probe(ArborDevice):
|
|
|
22
21
|
kwargs = dict((k, getattr(self, k)) for k in probe_args if hasattr(self, k))
|
|
23
22
|
return [getattr(arbor, self.get_probe_name())(**kwargs)]
|
|
24
23
|
|
|
25
|
-
def prepare_samples(self, sim):
|
|
26
|
-
super().prepare_samples(sim)
|
|
27
|
-
for probe_id, handle in zip(self._probe_ids, self._handles):
|
|
24
|
+
def prepare_samples(self, sim, comm):
|
|
25
|
+
super().prepare_samples(sim, comm)
|
|
26
|
+
for probe_id, handle in zip(self._probe_ids, self._handles, strict=False):
|
|
28
27
|
self.adapter.result.add(ProbeRecorder(self, sim, probe_id, handle))
|
|
29
28
|
|
|
30
29
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import neo
|
|
2
2
|
from bsb import config
|
|
3
|
-
from bsb.services import MPI
|
|
4
3
|
|
|
5
4
|
from ..device import ArborDevice
|
|
6
5
|
|
|
@@ -10,9 +9,9 @@ class SpikeRecorder(ArborDevice, classmap_entry="spike_recorder"):
|
|
|
10
9
|
def boot(self):
|
|
11
10
|
self._gids = set()
|
|
12
11
|
|
|
13
|
-
def prepare_samples(self, simdata):
|
|
14
|
-
super().prepare_samples(simdata)
|
|
15
|
-
if not
|
|
12
|
+
def prepare_samples(self, simdata, comm):
|
|
13
|
+
super().prepare_samples(simdata, comm)
|
|
14
|
+
if not comm.get_rank():
|
|
16
15
|
|
|
17
16
|
def record_device_spikes(segment):
|
|
18
17
|
spiketrain = list()
|
|
@@ -25,7 +24,7 @@ class SpikeRecorder(ArborDevice, classmap_entry="spike_recorder"):
|
|
|
25
24
|
neo.SpikeTrain(
|
|
26
25
|
spiketrain,
|
|
27
26
|
units="ms",
|
|
28
|
-
|
|
27
|
+
array_annotations={"senders": senders},
|
|
29
28
|
t_stop=self.simulation.duration,
|
|
30
29
|
device=self.name,
|
|
31
30
|
gids=list(self._gids),
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import psutil
|
|
2
|
+
from bsb import Simulation, config, types
|
|
3
|
+
|
|
4
|
+
from .cell import ArborCell
|
|
5
|
+
from .connection import ArborConnection
|
|
6
|
+
from .device import ArborDevice
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@config.node
|
|
10
|
+
class ArborSimulation(Simulation):
|
|
11
|
+
"""
|
|
12
|
+
Interface between the scaffold model and the Arbor simulator.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
resolution = config.attr(type=types.float(min=0.0), default=0.1)
|
|
16
|
+
"""Simulation time step size in milliseconds."""
|
|
17
|
+
profiling = config.attr(type=bool)
|
|
18
|
+
"""Flag to perform profiling during the simulation."""
|
|
19
|
+
cell_models: config._attrs.cfgdict[ArborCell] = config.dict(
|
|
20
|
+
type=ArborCell, required=True
|
|
21
|
+
)
|
|
22
|
+
"""Dictionary of cell models in the simulation."""
|
|
23
|
+
connection_models: config._attrs.cfgdict[ArborConnection] = config.dict(
|
|
24
|
+
type=ArborConnection, required=True
|
|
25
|
+
)
|
|
26
|
+
"""Dictionary of connection models in the simulation."""
|
|
27
|
+
devices: config._attrs.cfgdict[ArborDevice] = config.dict(
|
|
28
|
+
type=ArborDevice, required=True
|
|
29
|
+
)
|
|
30
|
+
"""Dictionary of devices in the simulation."""
|
|
31
|
+
|
|
32
|
+
@config.property(default=1)
|
|
33
|
+
def threads(self):
|
|
34
|
+
return self._threads
|
|
35
|
+
|
|
36
|
+
@threads.setter
|
|
37
|
+
def threads(self, value):
|
|
38
|
+
self._threads = value if value != "all" else psutil.cpu_count(logical=False)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
dependency-groups = { }
|
|
2
|
+
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = [ "flit_core >=3.2,<4" ]
|
|
5
|
+
build-backend = "flit_core.buildapi"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "bsb-arbor"
|
|
9
|
+
version = "6.0.0-a7"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.10,<4"
|
|
12
|
+
dynamic = [ "description" ]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)"
|
|
15
|
+
]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"numpy~=1.21",
|
|
18
|
+
"bsb-core~=6.0",
|
|
19
|
+
"arborize~=6.0",
|
|
20
|
+
"arbor~=0.10; sys_platform != 'win32'"
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[[project.authors]]
|
|
24
|
+
name = "Robin De Schepper"
|
|
25
|
+
email = "robin@alexandria.sc"
|
|
26
|
+
|
|
27
|
+
[[project.authors]]
|
|
28
|
+
name = "Dimitri Rodarie"
|
|
29
|
+
email = "dimitri.rodarie@unipv.it"
|
|
30
|
+
|
|
31
|
+
[project.license]
|
|
32
|
+
file = "LICENSE"
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
test = [
|
|
36
|
+
"bsb-core[parallel]",
|
|
37
|
+
"bsb-hdf5~=6.0",
|
|
38
|
+
"bsb-test~=6.0",
|
|
39
|
+
"coverage>=7.3"
|
|
40
|
+
]
|
|
41
|
+
docs = [ "furo~=2024.0", "sphinxext-bsb~=6.0" ]
|
|
42
|
+
dev = [
|
|
43
|
+
"bsb-arbor[test,docs]",
|
|
44
|
+
"pre-commit~=3.5",
|
|
45
|
+
"ruff>=0.8.2",
|
|
46
|
+
"snakeviz~=2.1"
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[project.entry-points."bsb.simulation_backends"]
|
|
50
|
+
arbor = "bsb_arbor"
|
|
51
|
+
|
|
52
|
+
[tool.flit.module]
|
|
53
|
+
name = "bsb_arbor"
|
|
54
|
+
|
|
55
|
+
[tool.uv]
|
|
56
|
+
sources = { }
|
|
57
|
+
|
|
58
|
+
[tool.coverage.run]
|
|
59
|
+
branch = true
|
|
60
|
+
source = [ "bsb_arbor" ]
|
|
61
|
+
|
|
62
|
+
[tool.coverage.report]
|
|
63
|
+
exclude_lines = [ "if TYPE_CHECKING:" ]
|
|
64
|
+
show_missing = true
|
|
65
|
+
|
|
66
|
+
[tool.ruff]
|
|
67
|
+
exclude = [ ".ruff_cache", ".svn", ".tox", ".venv", "dist" ]
|
|
68
|
+
line-length = 90
|
|
69
|
+
indent-width = 4
|
|
70
|
+
|
|
71
|
+
[tool.ruff.format]
|
|
72
|
+
quote-style = "double"
|
|
73
|
+
indent-style = "space"
|
|
74
|
+
skip-magic-trailing-comma = false
|
|
75
|
+
line-ending = "auto"
|
|
76
|
+
docstring-code-format = true
|
|
77
|
+
docstring-code-line-length = 90
|
|
78
|
+
|
|
79
|
+
[tool.ruff.lint]
|
|
80
|
+
select = [ "E", "F", "UP", "B", "SIM", "I" ]
|
|
81
|
+
ignore = [ ]
|
|
82
|
+
fixable = [ "ALL" ]
|
|
83
|
+
unfixable = [ ]
|
bsb_arbor-4.1.1/PKG-INFO
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: bsb-arbor
|
|
3
|
-
Version: 4.1.1
|
|
4
|
-
Summary: Arbor simulation adapter for the BSB framework
|
|
5
|
-
Author-email: Robin De Schepper <robingilbert.deschepper@unipv.it>
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
8
|
-
Requires-Dist: numpy~=1.21
|
|
9
|
-
Requires-Dist: bsb-core~=5.0
|
|
10
|
-
Requires-Dist: arbor~=0.10
|
|
11
|
-
Requires-Dist: arborize[arbor]~=4.0
|
|
12
|
-
Requires-Dist: bsb-arbor[test] ; extra == "dev"
|
|
13
|
-
Requires-Dist: build~=1.0 ; extra == "dev"
|
|
14
|
-
Requires-Dist: twine~=4.0 ; extra == "dev"
|
|
15
|
-
Requires-Dist: pre-commit~=3.5 ; extra == "dev"
|
|
16
|
-
Requires-Dist: black~=24.1.1 ; extra == "dev"
|
|
17
|
-
Requires-Dist: isort~=5.12 ; extra == "dev"
|
|
18
|
-
Requires-Dist: snakeviz~=2.1 ; extra == "dev"
|
|
19
|
-
Requires-Dist: bump-my-version~=0.24 ; extra == "dev"
|
|
20
|
-
Requires-Dist: bsb-core[parallel] ; extra == "parallel"
|
|
21
|
-
Requires-Dist: bsb-core[parallel] ; extra == "test"
|
|
22
|
-
Requires-Dist: bsb-hdf5~=5.0 ; extra == "test"
|
|
23
|
-
Requires-Dist: bsb-test~=4.0 ; extra == "test"
|
|
24
|
-
Requires-Dist: coverage~=7.0 ; extra == "test"
|
|
25
|
-
Provides-Extra: dev
|
|
26
|
-
Provides-Extra: parallel
|
|
27
|
-
Provides-Extra: test
|
|
28
|
-
|
|
29
|
-
[](https://github.com/dbbs-lab/bsb-arbor/actions/workflows/main.yml)
|
|
30
|
-
[](https://github.com/psf/black)
|
|
31
|
-
|
|
32
|
-
# bsb-arbor
|
|
33
|
-
|
|
34
|
-
bsb-nest is a plugin of the [BSB](https://github.com/dbbs-lab/bsb) (see also
|
|
35
|
-
[bsb-core](https://github.com/dbbs-lab/bsb-core)).
|
|
36
|
-
It contains the interfaces and tools to simulate BSB circuit with the
|
|
37
|
-
[Arbor simulator](https://arbor-sim.org/).
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Arbor simulation adapter for the BSB framework
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from bsb import SimulationBackendPlugin
|
|
6
|
-
|
|
7
|
-
from . import devices
|
|
8
|
-
from .adapter import ArborAdapter
|
|
9
|
-
from .simulation import ArborSimulation
|
|
10
|
-
|
|
11
|
-
__version__ = "4.1.1"
|
|
12
|
-
__plugin__ = SimulationBackendPlugin(Simulation=ArborSimulation, Adapter=ArborAdapter)
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import psutil
|
|
2
|
-
from bsb import Simulation, config, types
|
|
3
|
-
|
|
4
|
-
from .cell import ArborCell
|
|
5
|
-
from .connection import ArborConnection
|
|
6
|
-
from .device import ArborDevice
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@config.node
|
|
10
|
-
class ArborSimulation(Simulation):
|
|
11
|
-
resolution = config.attr(type=types.float(min=0.0), default=0.1)
|
|
12
|
-
profiling = config.attr(type=bool)
|
|
13
|
-
cell_models = config.dict(type=ArborCell, required=True)
|
|
14
|
-
connection_models = config.dict(type=ArborConnection, required=True)
|
|
15
|
-
devices = config.dict(type=ArborDevice, required=True)
|
|
16
|
-
|
|
17
|
-
@config.property(default=1)
|
|
18
|
-
def threads(self):
|
|
19
|
-
return self._threads
|
|
20
|
-
|
|
21
|
-
@threads.setter
|
|
22
|
-
def threads(self, value):
|
|
23
|
-
self._threads = value if value != "all" else psutil.cpu_count(logical=False)
|
bsb_arbor-4.1.1/pyproject.toml
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["flit_core >=3.2,<4"]
|
|
3
|
-
build-backend = "flit_core.buildapi"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "bsb-arbor"
|
|
7
|
-
authors = [{name = "Robin De Schepper", email = "robingilbert.deschepper@unipv.it"}]
|
|
8
|
-
readme = "README.md"
|
|
9
|
-
license = {file = "LICENSE"}
|
|
10
|
-
classifiers = ["License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)"]
|
|
11
|
-
dynamic = ["version", "description"]
|
|
12
|
-
dependencies = [
|
|
13
|
-
"numpy~=1.21",
|
|
14
|
-
"bsb-core~=5.0",
|
|
15
|
-
"arbor~=0.10",
|
|
16
|
-
"arborize[arbor]~=4.0"
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
[project.entry-points."bsb.simulation_backends"]
|
|
20
|
-
arbor = "bsb_arbor"
|
|
21
|
-
|
|
22
|
-
[tool.flit.module]
|
|
23
|
-
name = "bsb_arbor"
|
|
24
|
-
|
|
25
|
-
[project.optional-dependencies]
|
|
26
|
-
parallel = ["bsb-core[parallel]"]
|
|
27
|
-
test = [
|
|
28
|
-
"bsb-core[parallel]",
|
|
29
|
-
"bsb-hdf5~=5.0",
|
|
30
|
-
"bsb-test~=4.0",
|
|
31
|
-
"coverage~=7.0"
|
|
32
|
-
]
|
|
33
|
-
dev = [
|
|
34
|
-
"bsb-arbor[test]",
|
|
35
|
-
"build~=1.0",
|
|
36
|
-
"twine~=4.0",
|
|
37
|
-
"pre-commit~=3.5",
|
|
38
|
-
"black~=24.1.1",
|
|
39
|
-
"isort~=5.12",
|
|
40
|
-
"snakeviz~=2.1",
|
|
41
|
-
"bump-my-version~=0.24"
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
[tool.isort]
|
|
45
|
-
profile = "black"
|
|
46
|
-
|
|
47
|
-
[tool.bumpversion]
|
|
48
|
-
current_version = "4.1.1"
|
|
49
|
-
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
50
|
-
serialize = ["{major}.{minor}.{patch}"]
|
|
51
|
-
search = "{current_version}"
|
|
52
|
-
replace = "{new_version}"
|
|
53
|
-
regex = false
|
|
54
|
-
ignore_missing_version = false
|
|
55
|
-
tag = true
|
|
56
|
-
sign_tags = false
|
|
57
|
-
tag_name = "v{new_version}"
|
|
58
|
-
tag_message = "Bump version: {current_version} → {new_version}"
|
|
59
|
-
allow_dirty = false
|
|
60
|
-
commit = true
|
|
61
|
-
message = "Bump version: {current_version} → {new_version}"
|
|
62
|
-
commit_args = "--no-verify"
|
|
63
|
-
|
|
64
|
-
[tool.bumpversion.parts.pre_l]
|
|
65
|
-
values = ["dev", "a", "b", "rc", "final"]
|
|
66
|
-
optional_value = "final"
|
|
67
|
-
|
|
68
|
-
[[tool.bumpversion.files]]
|
|
69
|
-
filename = "bsb_arbor/__init__.py"
|