Skip to content

Commit

Permalink
Merge branch 'main' into neuron_v4
Browse files Browse the repository at this point in the history
  • Loading branch information
Helveg committed Nov 9, 2023
2 parents 01692c7 + 7f12b38 commit b6305a0
Show file tree
Hide file tree
Showing 192 changed files with 1,708 additions and 39,060 deletions.
10 changes: 10 additions & 0 deletions .github/devops/install-nest.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
git clone https://github.com/nest/nest-simulator $GITHUB_WORKSPACE/nest
cd $GITHUB_WORKSPACE/nest
git checkout tags/v$1
mkdir build
cd build
pip install cython cmake
cmake .. \
-DCMAKE_INSTALL_PREFIX=$2 \
-Dwith-mpi=ON
make install
43 changes: 15 additions & 28 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,33 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/[email protected]

- name: Set up Python ${{ matrix.python-version }}
uses: actions/[email protected]
with:
python-version: ${{ matrix.python-version }}

- name: Install apt dependencies
run: |
sudo apt-get update
sudo apt-get install openmpi-bin libopenmpi-dev
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
sudo apt update
# Install `libopenmpi` for MPI
sudo apt install openmpi-bin libopenmpi-dev
# Install `libhdf5` for `morphio`
sudo apt install libhdf5-dev
- name: Install dependencies & self
run: |
python -m pip install --upgrade pip
pip install wheel
# Install the regular requirements
pip install -r requirements.txt --prefer-binary
# Install the default plugins, without dependencies, to avoid circular dependency
# conflicts with the BSB itself
pip install -r plugins.txt --prefer-binary --no-deps
# Install the BSB from the repo without dependencies, already installed above.
pip install -e . --no-deps
pip install "dbbs-models>=4.0.0a0"
# Install latest pip
pip install --upgrade pip
# Install bsb-core
pip install .[test,mpi]
- name: Run tests & coverage
run: |
coverage run -p -m unittest discover -v -s ./tests
mpiexec -n 2 coverage run -p -m unittest discover -v -s ./tests
BSB_PROFILING=TRUE coverage run -p -m unittest tests.test_env_options
bash <(curl -s https://codecov.io/bash)
- name: Test default plugins
run: |
git clone https://github.com/dbbs-lab/bsb-hdf5
pip install -e bsb-hdf5/
coverage run -p -m unittest discover bsb-hdf5/test
bash <(curl -s https://codecov.io/bash)
bash <(curl -s https://codecov.io/bash)
6 changes: 3 additions & 3 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ jobs:
python-version: 3.9
- name: Install MPI
run: |
sudo apt-get update
sudo apt-get install -y openmpi-bin libopenmpi-dev
sudo apt update
sudo apt install -y openmpi-bin libopenmpi-dev
- name: Install dependencies
run: |
python -m pip install pip
python -m pip install --upgrade pip
pip install -r docs/requirements.txt
- name: Install self
run: |
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ bsb-*/
*.egg-info/
pip-wheel-metadata/
.python-version
venv/
dev_env/
test_env/
nrnmech.dll
.coverage
htmlcov/
.idea/
!morphologies.hdf5
# Ignore report files
*.io
.vscode/
.idea/
bsb-*/


Expand Down
16 changes: 14 additions & 2 deletions bsb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
__version__ = "4.0.0a56"
"""
`bsb-core` is the backbone package contain the essential code of the BSB: A component
framework for multiscale bottom-up neural modelling.
`bsb-core` needs to be installed alongside a bundle of desired bsb plugins, some of
which are essential for `bsb-core` to function. First time users are recommended to
install the `bsb` package instead.
"""

__version__ = "4.0.0b0"

import functools

Expand All @@ -16,7 +25,10 @@ def _register(self, cls, method=None): # pragma: nocover

functools.singledispatchmethod.register = _register

from .options import profiling as _pr
try:
from .options import profiling as _pr
except Exception:
_pr = False

if _pr:
from .profiling import activate_session
Expand Down
10 changes: 9 additions & 1 deletion bsb/cell_types.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
"""
Module for the CellType configuration node and its dependencies.
"""
import typing

from . import config
from .config import types
from .placement.indicator import PlacementIndications
from ._util import obj_str_insert

if typing.TYPE_CHECKING:
from .core import Scaffold


@config.node
class Plotting:
scaffold: "Scaffold"

display_name = config.attr()
"""
Label used to display this cell type in plots.
Expand All @@ -34,6 +40,8 @@ class CellType:
Information on a population of cells.
"""

scaffold: "Scaffold"

name = config.attr(key=True)
"""
Name of the cell type, equivalent to the key it occurs under in the configuration.
Expand Down Expand Up @@ -123,7 +131,7 @@ def clear_connections(self):
set that this cell type is a part of will be entirely removed.
"""
for conn_set in self.scaffold.get_connectivity_sets():
if self is conn_set.presynaptic or self is conn_set.postsynaptic:
if self is conn_set.pre_type or self is conn_set.post_type:
conn_set.clear()

# This property was mostly added so that accidental assignment to `ct.morphologies`
Expand Down
3 changes: 2 additions & 1 deletion bsb/cli/commands/_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def handler(self, context):
append += ", ".join(f"'{name}'" for name in extra_simulations.keys())
errr.wrap(type(e), e, append=append)
else:
result.write(f"{uuid4()}.nio", "ow")
result.write(getattr(context.arguments, "output", f"{uuid4()}.nio"), "ow")

def get_options(self):
return {
Expand All @@ -220,6 +220,7 @@ def get_options(self):
def add_parser_arguments(self, parser):
parser.add_argument("network")
parser.add_argument("simulation")
parser.add_argument("-o", "--output")


class CacheCommand(BaseCommand, name="cache"): # pragma: nocover
Expand Down
18 changes: 16 additions & 2 deletions bsb/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import sys
import glob
import itertools
import typing
from importlib.machinery import ModuleSpec
from shutil import copy2 as copy_file
import builtins
import traceback
Expand All @@ -35,6 +37,7 @@
from .._util import ichain
from ._make import walk_node_attributes, walk_nodes, compose_nodes, get_config_attributes
from ._hooks import on, before, after, run_hook, has_hook
from ._distributions import Distribution
from .. import plugins
from ..exceptions import ConfigTemplateNotFoundError, ParserError, PluginError
from . import parsers
Expand All @@ -43,6 +46,12 @@
_path = __path__
ConfigurationAttribute.__module__ = __name__

if typing.TYPE_CHECKING:
from ._config import Configuration

# Add some static type hinting, to help tools figure out this dynamic module
Configuration: "Configuration"


# ConfigurationModule should not inherit from `ModuleType`, otherwise Sphinx doesn't
# document all the properties.
Expand Down Expand Up @@ -80,11 +89,14 @@ def __init__(self, name):
run_hook = staticmethod(run_hook)
has_hook = staticmethod(has_hook)

Distribution = Distribution

_parser_classes = {}

# The __path__ attribute needs to be retained to mark this module as a package with
# submodules (config.refs, config.parsers.json, ...)
__path__ = _path
__spec__ = ModuleSpec(__name__, __loader__, origin=__file__)

# Load the Configuration class on demand, not on import, to avoid circular
# dependencies.
Expand Down Expand Up @@ -208,14 +220,16 @@ def _try_parsers(content, classes, ext=None, path=None): # pragma: nocover
if ext is not None:

def file_has_parser_ext(kv):
return ext in getattr(kv[1], "data_extensions", ())
return ext not in getattr(kv[1], "data_extensions", ())

classes = builtins.dict(sorted(classes.items(), key=file_has_parser_ext))
exc = {}
for name, cls in classes.items():
try:
tree, meta = cls().parse(content, path=path)
except Exception as e:
if getattr(e, "_bsbparser_show_user", False):
raise e from None
exc[name] = e
else:
return (name, tree, meta)
Expand Down Expand Up @@ -257,7 +271,7 @@ def parser_method(self, file=None, data=None, path=None):
return _from_parsed(self, name, tree, meta, file)

parser_method.__name__ = "from_" + name
parser_method.__doc__ = _parser_method_docs(parser)
# parser_method.__doc__ = _parser_method_docs(parser)
return parser_method


Expand Down
27 changes: 19 additions & 8 deletions bsb/config/_attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class Example:
:param kwargs: All keyword arguments are passed to the constructor of the
:func:`attribute <.config.attr>`.
"""
if "required" not in kwargs:
if "required" not in kwargs and "default" not in kwargs:
kwargs["required"] = True
if "type" not in kwargs:
kwargs["type"] = str
Expand Down Expand Up @@ -508,15 +508,18 @@ def is_node_type(self):

def tree(self, instance):
val = _getattr(instance, self.attr_name)
return self.tree_of(val)

def tree_of(self, value):
# Allow subnodes and other class values to convert themselves to their tree
# representation
if hasattr(val, "__tree__"):
val = val.__tree__()
if hasattr(value, "__tree__"):
value = value.__tree__()
# Check if the type handler specifies any inversion function to convert tree
# values back to how they were found in the document.
if hasattr(self.type, "__inv__") and val is not None:
val = self.type.__inv__(val)
return val
if hasattr(self.type, "__inv__") and value is not None:
value = self.type.__inv__(value)
return value

def flag_dirty(self, instance):
instance._config_state[self.attr_name] = False
Expand All @@ -538,6 +541,10 @@ def should_call_default(self):


class cfglist(builtins.list):
"""
Extension of the builtin list to manipulate lists of configuration nodes.
"""

def get_node_name(self):
return self._config_parent.get_node_name() + "." + self._config_attr_name

Expand Down Expand Up @@ -675,10 +682,14 @@ def _set_type(self, type, key=None):

def tree(self, instance):
val = _getattr(instance, self.attr_name)
return [e if not hasattr(e, "__tree__") else e.__tree__() for e in val]
return [self.tree_of(e) for e in val]


class cfgdict(builtins.dict):
"""
Extension of the builtin dictionary to manipulate dicts of configuration nodes.
"""

def __getattr__(self, name):
try:
return self[name]
Expand Down Expand Up @@ -815,7 +826,7 @@ def _set_type(self, type, key=None):

def tree(self, instance):
val = _getattr(instance, self.attr_name).items()
return {k: v if not hasattr(v, "__tree__") else v.__tree__() for k, v in val}
return {k: self.tree_of(v) for k, v in val}


class ConfigurationReferenceAttribute(ConfigurationAttribute):
Expand Down
Loading

0 comments on commit b6305a0

Please sign in to comment.