Skip to content

Commit

Permalink
[BBPBGLIB-1120] Remove node loaders for MVD3 and NCS (#117)
Browse files Browse the repository at this point in the history
## Context
After deprecating BlueConfig files, we no longer support legacy node
format, MVD3 or NCS. Therefore, this PR removes the corresponding node
loaders.

## Scope
In `cell_reader.py`: keeping only `load_sonata` and removing the other
readers.
In `metype.py`: removing `Cell_V5`.


## Testing
Adapt the current unit tests to use SONATA nodes.

## Review
* [x] PR description is complete
* [x] Coding style (imports, function length, New functions, classes or
files) are good
* [x] Unit/Scientific test added
* [x] Updated Readme, in-code, developer documentation
  • Loading branch information
WeinaJi authored Feb 7, 2024
1 parent 189f905 commit ea81bd9
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 426 deletions.
5 changes: 1 addition & 4 deletions docs/api/subpackages/io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ neurodamus.io.cell\_readers

.. autosummary::

load_mvd3
load_ncs
load_nodes_mvd3
load_combo_metypes
load_sonata
split_round_robin

.. rubric:: Exceptions
Expand Down
5 changes: 2 additions & 3 deletions docs/architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ BBP v6 circuits would define its own cell hoc templates (/classes, one for each
based on Cell.hoc.

Morphologically detailed neurons are the heart of a Neuron simulation. Neurodamus will read the
cells metadata from a node file (start.ncs, circuit.mvd3 or nodes.h5 sonata) and instantiate each
cells metadata from a node file in SONATA format and instantiate each
individual cell by:

- loading the morphology and instantiate the respective sections
Expand Down Expand Up @@ -138,7 +138,7 @@ Due to extensively different logic, both these cell types inherit directly from
must be handled by their own cell manager classes. To these modules implementing a new `Cell`,
`CellManagers` and eventually `ConnectionManager` types we call **Engine** - more on this later.

For the record, `Cell_V5/V6` and the corresponding `CellDistributor` and `SynapseRuleManager`
For the record, `Cell_V6` and the corresponding `CellDistributor` and `SynapseRuleManager`
were also made components of a special engine: the `METypeEngine`, obviously built-in (find it
in node.py).

Expand Down Expand Up @@ -180,7 +180,6 @@ considered a cell manager, but by far lighter than a full cell manager.

* `CellType`: The default cell class this manager handles.
* `_node_loader`: The default loader function for nodes (cell metadata)
* `_node_format`: The default file format of nodes, .e.g. Sonata

- Instance properties:

Expand Down
2 changes: 1 addition & 1 deletion docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Dry run mode
~~~~~~~~~~~~
In order to obtain a more accurate estimation of the resources needed for a simulation,
users can also run Neurodamus in dry run mode. This functionality is only available
for libsonata circuits. MVD3 circuits are not supported.
for SONATA circuits.

This mode will partially instantiate cells and synapses to get a statistical overview
of the memory used but won't run the actual simulation.
Expand Down
64 changes: 14 additions & 50 deletions neurodamus/cell_distributor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import os
import weakref
from contextlib import contextmanager
from enum import Enum
from io import StringIO
from os import path as ospath
from pathlib import Path
Expand All @@ -24,19 +23,13 @@
from .core.nodeset import NodeSet
from .io import cell_readers
from .lfp_manager import LFPManager
from .metype import Cell_V5, Cell_V6, EmptyCell
from .metype import Cell_V6, EmptyCell
from .target_manager import TargetSpec
from .utils import compat
from .utils.logging import log_verbose, log_all
from .utils.memory import DryRunStats, get_mem_usage_kb


class NodeFormat(Enum):
NCS = 1
MVD3 = 2
SONATA = 3


class VirtualCellPopulation:
"""
A virtual cell population offers a compatible interface with Cell Manager,
Expand Down Expand Up @@ -110,15 +103,11 @@ class CellManagerBase(_CellManager):
"""

_node_loader = None
"""Default function implementing the loading of nodes data, a.k.a. MVD
"""Default function implementing the loading of nodes data
signature:
load(circuit_conf, gidvec, stride=1, stride_offset=0)
"""

_node_format = NodeFormat.SONATA # NCS, Mvd, Sonata...
"""Default Node file format"""

def __init__(self, circuit_conf, target_manager, _run_conf=None, **_kw):
"""Initializes CellDistributor
Expand Down Expand Up @@ -179,12 +168,11 @@ def get_final_gids(self):
return numpy.array(self.local_nodes.final_gids())

def _init_config(self, circuit_conf, pop):
if self._node_format == NodeFormat.SONATA:
if not ospath.isabs(circuit_conf.CellLibraryFile):
circuit_conf.CellLibraryFile = find_input_file(circuit_conf.CellLibraryFile)
if not pop: # Last attempt to get pop name
pop = self._get_sonata_population_name(circuit_conf.CellLibraryFile)
logging.info(" -> Discovered node population name: %s", pop)
if not ospath.isabs(circuit_conf.CellLibraryFile):
circuit_conf.CellLibraryFile = find_input_file(circuit_conf.CellLibraryFile)
if not pop: # Last attempt to get pop name
pop = self._get_sonata_population_name(circuit_conf.CellLibraryFile)
logging.info(" -> Discovered node population name: %s", pop)
if not pop and circuit_conf._name:
pop = circuit_conf._name
logging.warning("(Compat) Assuming population name from Circuit: %s", pop)
Expand Down Expand Up @@ -520,28 +508,11 @@ class CellDistributor(CellManagerBase):
Instantiated cells are stored locally (.cells property)
"""

_cell_loaders = {
"start.ncs": cell_readers.load_ncs,
"circuit.mvd3": cell_readers.load_mvd3,
}

_sonata_with_extra_attrs = True # Enable search extra node attributes

def _init_config(self, circuit_conf, _pop):
if not circuit_conf.CellLibraryFile:
logging.warning("CellLibraryFile not set. Assuming legacy 'start.ncs'")
circuit_conf.CellLibraryFile = "start.ncs"
if circuit_conf.CellLibraryFile.endswith(".ncs"):
self._node_format = NodeFormat.NCS
elif circuit_conf.CellLibraryFile.endswith(".mvd3"):
self._node_format = NodeFormat.MVD3

self._is_v5_circuit = circuit_conf.CellLibraryFile == "start.ncs" or (
circuit_conf.nrnPath and ospath.isfile(ospath.join(circuit_conf.nrnPath, "start.ncs"))
and not ospath.isfile(ospath.join(circuit_conf.CircuitPath, "circuit.mvd3"))
)
if self._is_v5_circuit and self._circuit_conf.DetailedAxon:
raise ConfigurationError("V5 circuits don't support keeping detailed axons")
raise ConfigurationError("CellLibraryFile not set")

super()._init_config(circuit_conf, _pop)

Expand All @@ -553,19 +524,12 @@ def load_nodes(self, load_balancer=None, **kw):
cell_requirements = all_cell_requirements.get(self._population_name) or (
self.is_default and all_cell_requirements.get(None)
)
if self._node_format == NodeFormat.SONATA:
loader = cell_readers.load_sonata
loader_opts["node_population"] = self._population_name # mandatory in Sonata
loader_opts["load_dynamic_props"] = cell_requirements
loader_opts["has_extra_data"] = self._sonata_with_extra_attrs
else:
if cell_requirements:
raise Exception('Additional cell properties only available with SONATA')
nodes_filename = self._circuit_conf.CellLibraryFile
loader = self._cell_loaders.get(nodes_filename, cell_readers.load_mvd3)
loader_opts = {}
loader = cell_readers.load_sonata
loader_opts["node_population"] = self._population_name # mandatory in Sonata
loader_opts["load_dynamic_props"] = cell_requirements
loader_opts["has_extra_data"] = self._sonata_with_extra_attrs

log_verbose("Nodes Format: %s, Loader: %s", self._node_format, loader.__name__)
log_verbose("Nodes Format: SONATA , Loader: %s", loader.__name__)
return super().load_nodes(load_balancer, _loader=loader, loader_opts=loader_opts)

def _instantiate_cells(self, dry_run_stats_obj: DryRunStats = None, **opts):
Expand All @@ -578,7 +542,7 @@ def _instantiate_cells(self, dry_run_stats_obj: DryRunStats = None, **opts):
if self.CellType is not NotImplemented:
return super()._instantiate_cells(self.CellType)
conf = self._circuit_conf
CellType = Cell_V5 if self._is_v5_circuit else Cell_V6
CellType = Cell_V6
if conf.MorphologyType:
CellType.morpho_extension = conf.MorphologyType

Expand Down
3 changes: 0 additions & 3 deletions neurodamus/core/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,6 @@ def _make_circuit_config(config_dict, req_morphology=True):
config_dict["MorphologyPath"] = False
elif config_dict.get("nrnPath") == "<NONE>":
config_dict["nrnPath"] = False
if config_dict.get("CellLibraryFile", "start.ncs") == "start.ncs":
raise ConfigurationError(
"ncs circuits don't support disabling connectivity with nrnPath='<NONE>'")
_validate_circuit_morphology(config_dict, req_morphology)
_validate_file_extension(config_dict.get("CellLibraryFile"))
_validate_file_extension(config_dict.get("nrnPath"))
Expand Down
Loading

0 comments on commit ea81bd9

Please sign in to comment.