Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit f2d21f2

Browse files
[NSETM-2226] Add NodeSets adapter to support custom node_sets_file (#22)
Support custom node_sets_file in extraction, neuron_classes and trial_steps
1 parent ce3c457 commit f2d21f2

52 files changed

Lines changed: 522 additions & 99 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Changelog
22
=========
33

4+
Version 0.8.0
5+
-------------
6+
7+
New Features
8+
~~~~~~~~~~~~
9+
10+
- Support custom node_sets_file in extraction, neuron_classes and trial_steps [NSETM-2226]
11+
12+
413
Version 0.7.1
514
-------------
615

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ branch = true
123123
parallel = false
124124
omit = [
125125
"*/blueetl/_version.py",
126-
"*/blueetl/adapters/bluepy/*.py",
126+
"*/blueetl/adapters/impl/bluepy/*.py",
127127
"*/blueetl/external/**/*.py",
128128
]
129129

src/blueetl/adapters/base.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
"""Base Adapter."""
22

33
from abc import ABC, abstractmethod
4+
from pathlib import Path
45
from typing import Any, Generic, Optional, TypeVar
56

67
from blueetl.adapters.interfaces.circuit import CircuitInterface
8+
from blueetl.adapters.interfaces.node_sets import NodeSetsInterface
79
from blueetl.adapters.interfaces.simulation import SimulationInterface
8-
from blueetl.types import StrOrPath
910

10-
InterfaceT = TypeVar("InterfaceT", CircuitInterface, SimulationInterface)
11+
InterfaceT = TypeVar("InterfaceT", CircuitInterface, SimulationInterface, NodeSetsInterface)
1112
BaseAdapterT = TypeVar("BaseAdapterT", bound="BaseAdapter")
1213

1314

@@ -18,13 +19,14 @@ class AdapterError(Exception):
1819
class BaseAdapter(Generic[InterfaceT], ABC):
1920
"""Base Adapter to be subclassed by other adapters."""
2021

21-
def __init__(self, config: StrOrPath) -> None:
22-
"""Init the adapter from the specified config."""
23-
self._impl: Optional[InterfaceT] = self._load_impl(str(config))
22+
def __init__(self, _impl: Optional[InterfaceT]) -> None:
23+
"""Init the adapter from the specified implementation."""
24+
self._impl: Optional[InterfaceT] = _impl
2425

26+
@classmethod
2527
@abstractmethod
26-
def _load_impl(self, config: str) -> Optional[InterfaceT]:
27-
"""Load and return the implementation object, or None if the config file doesn't exist."""
28+
def from_file(cls, filepath: Optional[Path]) -> "BaseAdapter":
29+
"""Load and return a new object from file."""
2830

2931
@property
3032
def _ensure_impl(self) -> InterfaceT:
@@ -41,10 +43,3 @@ def exists(self) -> bool:
4143
def instance(self) -> Any:
4244
"""Return the wrapped instance, or None if it doesn't exist."""
4345
return self._impl.instance if self._impl is not None else None
44-
45-
@classmethod
46-
def from_impl(cls: type[BaseAdapterT], impl: InterfaceT) -> BaseAdapterT:
47-
"""Return a new adapter with the specified implementation."""
48-
result = object.__new__(cls)
49-
result._impl = impl
50-
return result

src/blueetl/adapters/circuit.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,25 @@
66

77
from blueetl.adapters.base import BaseAdapter
88
from blueetl.adapters.interfaces.circuit import CircuitInterface, NodePopulationInterface
9+
from blueetl.adapters.node_sets import NodeSetsAdapter
910

1011

1112
class CircuitAdapter(BaseAdapter[CircuitInterface]):
1213
"""Circuit Adapter."""
1314

14-
def _load_impl(self, config: str) -> Optional[CircuitInterface]:
15-
"""Load and return the implementation object, or None if the config file doesn't exist."""
15+
@classmethod
16+
def from_file(cls, filepath: Optional[Path]) -> "CircuitAdapter":
17+
"""Load and return a new object from file."""
1618
# pylint: disable=import-outside-toplevel
17-
if not config or not Path(config).exists():
18-
return None
19+
if not filepath or not filepath.exists():
20+
return cls(None)
1921
CircuitImpl: type[CircuitInterface]
20-
if config.endswith(".json"):
21-
from blueetl.adapters.bluepysnap.circuit import Circuit, CircuitImpl
22+
if filepath.suffix == ".json":
23+
from blueetl.adapters.impl.bluepysnap.circuit import Circuit, CircuitImpl
2224
else:
23-
from blueetl.adapters.bluepy.circuit import Circuit, CircuitImpl
24-
return CircuitImpl(Circuit(config))
25+
from blueetl.adapters.impl.bluepy.circuit import Circuit, CircuitImpl
26+
impl = CircuitImpl(Circuit(str(filepath)))
27+
return cls(impl)
2528

2629
def checksum(self) -> str:
2730
"""Return a checksum of the relevant keys in the circuit configuration."""
@@ -31,3 +34,13 @@ def checksum(self) -> str:
3134
def nodes(self) -> Mapping[Optional[str], NodePopulationInterface]:
3235
"""Return the nodes as a dict: population -> nodes."""
3336
return self._ensure_impl.nodes
37+
38+
@property
39+
def node_sets_file(self) -> Optional[Path]:
40+
"""Returns the NodeSets file used by the circuit."""
41+
return self._ensure_impl.node_sets_file
42+
43+
@property
44+
def node_sets(self) -> NodeSetsAdapter:
45+
"""Returns the NodeSets file used by the circuit."""
46+
return NodeSetsAdapter(self._ensure_impl.node_sets)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Implementations."""
File renamed without changes.

src/blueetl/adapters/bluepy/circuit.py renamed to src/blueetl/adapters/impl/bluepy/circuit.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
"""Bluepy circuit implementation."""
22

33
from collections.abc import Mapping
4+
from pathlib import Path
45
from typing import Optional
56

67
from bluepy import Circuit
78

89
from blueetl.adapters.interfaces.circuit import CircuitInterface, NodePopulationInterface
10+
from blueetl.adapters.interfaces.node_sets import NodeSetsInterface
911
from blueetl.utils import checksum_json
1012

1113

@@ -40,3 +42,13 @@ def nodes(self) -> Mapping[Optional[str], NodePopulationInterface]:
4042
The population name in the returned dict is always None, because undefined in the config.
4143
"""
4244
return {None: self._circuit.cells}
45+
46+
@property
47+
def node_sets_file(self) -> Optional[Path]:
48+
"""Returns the NodeSets file used by the circuit."""
49+
raise NotImplementedError
50+
51+
@property
52+
def node_sets(self) -> NodeSetsInterface:
53+
"""Returns the NodeSets used by the circuit."""
54+
raise NotImplementedError

src/blueetl/adapters/bluepy/simulation.py renamed to src/blueetl/adapters/impl/bluepy/simulation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from bluepy.impl.spike_report import SpikeReport
1313
from bluepy.simulation import PathHelpers
1414

15-
from blueetl.adapters.bluepy.circuit import CircuitImpl
15+
from blueetl.adapters.impl.bluepy.circuit import CircuitImpl
1616
from blueetl.adapters.interfaces.circuit import CircuitInterface
1717
from blueetl.adapters.interfaces.simulation import (
1818
PopulationReportInterface,
File renamed without changes.

src/blueetl/adapters/bluepysnap/circuit.py renamed to src/blueetl/adapters/impl/bluepysnap/circuit.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
"""Bluepysnap circuit implementation."""
22

33
from collections.abc import Mapping
4+
from pathlib import Path
45
from typing import Optional
56

67
from bluepysnap import Circuit
78

9+
from blueetl.adapters.impl.bluepysnap.node_sets import NodeSetsImpl
810
from blueetl.adapters.interfaces.circuit import CircuitInterface, NodePopulationInterface
11+
from blueetl.adapters.interfaces.node_sets import NodeSetsInterface
912
from blueetl.utils import checksum_json
1013

1114

@@ -23,3 +26,14 @@ def checksum(self) -> str:
2326
def nodes(self) -> Mapping[Optional[str], NodePopulationInterface]:
2427
"""Return the nodes as a dict: population -> nodes."""
2528
return self._circuit.nodes
29+
30+
@property
31+
def node_sets_file(self) -> Optional[Path]:
32+
"""Returns the NodeSets file used by the circuit."""
33+
path = self._circuit.to_libsonata.node_sets_path
34+
return Path(path) if path else None
35+
36+
@property
37+
def node_sets(self) -> NodeSetsInterface:
38+
"""Returns the NodeSets used by the circuit."""
39+
return NodeSetsImpl(self._circuit.node_sets)

0 commit comments

Comments
 (0)