Skip to content

Commit

Permalink
v3.6.5 - Fixed lost spikes in NEURON adapter (#218)
Browse files Browse the repository at this point in the history
* release beta fix for lost spikes to test on PizDaint

* removed prints

* v3.6.5 - Fixed NEURON adapter's spike transmitter map

Co-authored-by: Robin De Schepper <robin.deschepper93gmail.com>
  • Loading branch information
Helveg committed Feb 2, 2021
1 parent d37c584 commit 74add0d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 49 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 3.6

## 3.6.5

* Fixed a bug with the NEURON adapter transmitter map causing loss of spike transmission.

## 3.6.4

* Slightly changed the `neuron` install workflow. NEURON is now pip installed
Expand Down
2 changes: 1 addition & 1 deletion bsb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = "3.6.4"
__version__ = "3.6.5"

from .reporting import set_verbosity, report, warn
100 changes: 52 additions & 48 deletions bsb/simulators/neuron/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def collect_output(self):
for node in range(self.scaffold.MPI.COMM_WORLD.size):
self.pc.barrier()
if node == self.pc_id:
print("Node", self.pc_id, "is writing")
report("Node", self.pc_id, "is writing", level=2, all_nodes=True)
with h5py.File(
"results_" + self.name + "_" + timestamp + ".hdf5", "a"
) as f:
Expand Down Expand Up @@ -405,54 +405,56 @@ def collect_output(self):
self.pc.barrier()

def create_transmitters(self):
for connection_model in self.connection_models.values():
self.create_connection_transmitters(connection_model)

def create_connection_transmitters(self, connection_model):
try:
output_handler = self.scaffold.output_formatter
# Get the connectivity set associated with this connection model
connectivity_set = ConnectivitySet(output_handler, connection_model.name)
from_cell_model = self.cell_models[
connectivity_set.connection_types[0].from_cell_types[0].name
]
if from_cell_model.relay:
print(
"Source is a relay; Skipping connection model {} transmitters".format(
connection_model.name
)
)
return
intersections = connectivity_set.intersections
transmitters = [
[i.from_id, i.from_compartment.section_id] for i in intersections
# Concatenates all the `from` locations of all intersections together and creates
# a network wide map of "signal origins" to NEURON parallel spike GIDs.

# Fetch all of the connectivity sets that can be transmitters (excludes relays)
sets = self._collect_transmitter_sets(self.connection_models.values())
# Get the total size of all intersections
total = sum(len(s) for s in sets)
# Allocate an array for them
alloc = np.empty((total, 2), dtype=int)
ptr = 0
for connectivity_set in sets:
# Get the connectivity set's intersection and slice them into the array.
inter = connectivity_set.intersections
alloc[ptr : (ptr + len(inter))] = [
(i.from_id, i.from_compartment.section_id) for i in inter
]
if not transmitters:
# Empty dataset
return
unique_transmitters = [tuple(a) for a in np.unique(transmitters, axis=0)]
transmitter_gids = list(
range(self._next_gid, self._next_gid + len(unique_transmitters))
)
self._next_gid += len(unique_transmitters)
partial_map = dict(zip(unique_transmitters, transmitter_gids))
self.transmitter_map.update(partial_map)

tcount = 0
for (cell_id, section_id), gid in partial_map.items():
cell_id = int(cell_id)
if not cell_id in self.node_cells:
continue
cell = self.cells[cell_id]
cell.create_transmitter(cell.sections[int(section_id)], gid)
tcount += 1
report(
f"Node {self.pc_id} created {tcount} transmitters",
level=3,
all_nodes=True,
)
# Move up the pointer for the next slice.
ptr += len(inter)
unique_transmitters = np.unique(alloc, axis=0)
self.transmitter_map = dict(zip(map(tuple, unique_transmitters), range(total)))
tcount = 0
try:
for (cell_id, section_id), gid in self.transmitter_map.items():
if cell_id in self.node_cells:
cell = self.cells[cell_id]
cell.create_transmitter(cell.sections[section_id], gid)
tcount += 1
except Exception as e:
errr.wrap(TransmitterError, e, prepend=f"[{connection_model.name}] ")
errr.wrap(TransmitterError, e, prepend=f"[{cell_id}] ")

report(
f"Node {self.pc_id} created {tcount} transmitters",
level=3,
all_nodes=True,
)

def _collect_transmitter_sets(self, models):
sets = self._models_to_sets(models)
return [s for s in sets if self._is_transmitter_set(s)]

def _models_to_sets(self, models):
return [self._model_to_set(model) for model in models]

def _model_to_set(self, model):
return ConnectivitySet(self.scaffold.output_formatter, model.name)

def _is_transmitter_set(self, set):
name = set.connection_types[0].from_cell_types[0].name
from_cell_model = self.cell_models[name]
return not from_cell_model.relay

def create_receivers(self):
output_handler = self.scaffold.output_formatter
Expand Down Expand Up @@ -521,7 +523,9 @@ def create_neurons(self):
self.register_spike_recorder(instance, spike_recorder)
cell_model.instances.append(instance)
self.cells[cell_id] = instance
print("Node", self.pc_id, "created", len(self.cells), "cells")
report(
f"Node {self.pc_id} created {len(self.cells)} cells", level=2, all_nodes=True
)

def prepare_devices(self):
device_module = __import__("devices", globals(), level=1)
Expand Down

0 comments on commit 74add0d

Please sign in to comment.