Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

248 inconsistency between edgepopulationiter connections and edgesiter connections #249

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
Changelog
=========

Version v2.1.0
Version v3.0.0
--------------

New Features
~~~~~~~~~~~~
- Added simulation config validation
- Added a new commandline subcommand: ``validate-simulation``
- Added an alias ``validate-circuit`` for the old ``validate`` subcommand

- deprecated ``validate``

- Added a new commandline subcommands: ``validate-simulation``, ``validate-circuit``

Breaking Changes
~~~~~~~~~~~~~~~~
- Deprecated the commandline subcommand ``validate`` in favor of new ``validate-circuit`` command
- Edge populations' ``iter_connections`` returns ``CircuitNodeId`` instead of ``int``
- Removed the commandline subcommand ``validate`` in favor of new ``validate-circuit`` command


Version v2.0.2
Expand Down
1 change: 1 addition & 0 deletions bluepysnap/circuit_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

The idea here is to not depend on libsonata if possible, so we can use this in all situations
"""

import logging
from pathlib import Path

Expand Down
24 changes: 1 addition & 23 deletions bluepysnap/cli.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"""The project's command line launcher."""

import functools
import logging
import warnings

import click

from bluepysnap import circuit_validation, simulation_validation
from bluepysnap.utils import Deprecate

CLICK_EXISTING_FILE = click.Path(exists=True, file_okay=True, dir_okay=False)

Expand Down Expand Up @@ -43,27 +42,6 @@ def wrapper(*args, **kwargs):
return wrapper


@cli.command()
@circuit_validation_params
def validate(config_file, skip_slow, only_errors):
"""[DEPRECATED] Validate Sonata circuit based on config file.

Args:
config_file (str): path to Sonata circuit config file
skip_slow (bool): skip slow tests
only_errors (bool): only print fatal errors
"""
with warnings.catch_warnings():
# Making sure the warning is shown
warnings.simplefilter("always", DeprecationWarning)
Deprecate.warn(
"Calling circuit validation with 'validate' is deprecated. "
"Please use 'validate-circuit' instead."
)

circuit_validation.validate(config_file, skip_slow, only_errors)


@cli.command()
@circuit_validation_params
def validate_circuit(config_file, skip_slow, only_errors):
Expand Down
45 changes: 39 additions & 6 deletions bluepysnap/edges/edge_population.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from more_itertools import first

from bluepysnap import query, utils
from bluepysnap.circuit_ids import CircuitEdgeIds
from bluepysnap.circuit_ids import CircuitEdgeIds, CircuitNodeId
from bluepysnap.circuit_ids_types import IDS_DTYPE, CircuitEdgeId
from bluepysnap.exceptions import BluepySnapError
from bluepysnap.sonata_constants import DYNAMICS_PREFIX, ConstContainer, Edge
Expand Down Expand Up @@ -518,6 +518,41 @@ def _optimal_direction():
secondary_node_ids_used.add(conn_node_id)
break

def _add_circuit_ids(self, its):
"""Completes the CircuitNodeId."""

return (
(
CircuitNodeId(self.source.name, source_id),
CircuitNodeId(self.target.name, target_id),
count,
)
for source_id, target_id, count in its
)

def _add_edge_ids(self, its):
"""Completes the CircuitNodeId and adds the CircuitEdgeIds."""

return (
(
CircuitNodeId(self.source.name, source_id),
CircuitNodeId(self.target.name, target_id),
CircuitEdgeIds.from_dict({self.name: self.pair_edges(source_id, target_id)}),
)
for source_id, target_id, _ in its
)

def _omit_edge_count(self, its):
"""Completes the CircuitNodeId and removes the edge count."""

return (
(
CircuitNodeId(self.source.name, source_id),
CircuitNodeId(self.target.name, target_id),
)
for source_id, target_id, _ in its
)

def iter_connections(
self,
source=None,
Expand Down Expand Up @@ -557,13 +592,11 @@ def iter_connections(
it = self._iter_connections(source_node_ids, target_node_ids, unique_node_ids, shuffle)

if return_edge_count:
return it
return self._add_circuit_ids(it)
elif return_edge_ids:
add_edge_ids = lambda x: (x[0], x[1], self.pair_edges(x[0], x[1]))
return map(add_edge_ids, it)
return self._add_edge_ids(it)
else:
omit_edge_count = lambda x: x[:2]
return map(omit_edge_count, it)
return self._omit_edge_count(it)

@property
def h5_filepath(self):
Expand Down
46 changes: 2 additions & 44 deletions bluepysnap/edges/edges.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

from bluepysnap._doctools import AbstractDocSubstitutionMeta
from bluepysnap.circuit_ids import CircuitEdgeIds, CircuitNodeIds
from bluepysnap.circuit_ids_types import CircuitNodeId
from bluepysnap.edges.edge_population import EdgePopulation
from bluepysnap.exceptions import BluepySnapError
from bluepysnap.network import NetworkObject
Expand Down Expand Up @@ -221,39 +220,6 @@ def pair_edges(self, source_node_id, target_node_id, properties=None):
source=source_node_id, target=target_node_id, properties=properties
)

@staticmethod
def _add_circuit_ids(its, source, target):
"""Generator comprehension adding the CircuitIds to the iterator.

Notes:
Using closures or lambda functions would result in override functions and so the
source and target would be the same for all the populations.
"""
return (
(CircuitNodeId(source, source_id), CircuitNodeId(target, target_id), count)
for source_id, target_id, count in its
)

@staticmethod
def _add_edge_ids(its, source, target, pop_name):
"""Generator comprehension adding the CircuitIds to the iterator."""
return (
(
CircuitNodeId(source, source_id),
CircuitNodeId(target, target_id),
CircuitEdgeIds.from_dict({pop_name: edge_id}),
)
for source_id, target_id, edge_id in its
)

@staticmethod
def _omit_edge_count(its, source, target):
"""Generator comprehension adding the CircuitIds to the iterator."""
return (
(CircuitNodeId(source, source_id), CircuitNodeId(target, target_id))
for source_id, target_id in its
)

joni-herttuainen marked this conversation as resolved.
Show resolved Hide resolved
def iter_connections(
self, source=None, target=None, return_edge_ids=False, return_edge_count=False
):
Expand All @@ -276,21 +242,13 @@ def iter_connections(
raise BluepySnapError(
"`return_edge_count` and `return_edge_ids` are mutually exclusive"
)
for name, pop in self.items():
it = pop.iter_connections(
for pop in self.values():
yield from pop.iter_connections(
source=source,
target=target,
return_edge_ids=return_edge_ids,
return_edge_count=return_edge_count,
)
source_pop = pop.source.name
target_pop = pop.target.name
if return_edge_count:
yield from self._add_circuit_ids(it, source_pop, target_pop)
elif return_edge_ids:
yield from self._add_edge_ids(it, source_pop, target_pop, name)
else:
yield from self._omit_edge_count(it, source_pop, target_pop)
joni-herttuainen marked this conversation as resolved.
Show resolved Hide resolved

def __getstate__(self):
"""Make Edges pickle-able, without storing state of caches."""
Expand Down
1 change: 1 addition & 0 deletions bluepysnap/query.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module to process search queries of nodes/edges."""

import operator
from collections.abc import Mapping
from copy import deepcopy
Expand Down
1 change: 1 addition & 0 deletions bluepysnap/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Schemas and schema parser."""

from bluepysnap.schemas.schemas import (
validate_circuit_schema,
validate_edges_schema,
Expand Down
1 change: 1 addition & 0 deletions bluepysnap/schemas/schemas.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Functions for schema based validation of circuit files."""

from pathlib import Path

import h5py
Expand Down
1 change: 1 addition & 0 deletions bluepysnap/simulation_validation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Standalone module that validates Sonata simulation. See ``validate-simulation`` function."""

import contextlib
import io
import os
Expand Down
1 change: 1 addition & 0 deletions tests/data/reporting/create_reports.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Taken from the libsonata lib."""

import h5py
import numpy as np

Expand Down
31 changes: 11 additions & 20 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,31 @@
@patch("bluepysnap.schemas.validate_nodes_schema", Mock(return_value=[]))
@patch("bluepysnap.schemas.validate_edges_schema", Mock(return_value=[]))
@patch("bluepysnap.schemas.validate_circuit_schema", Mock(return_value=[]))
def test_cli_correct():
def test_cli_validate_circuit_correct():
runner = CliRunner()

with pytest.warns(
BluepySnapDeprecationWarning,
match="Calling circuit validation with 'validate' is deprecated",
):
result = runner.invoke(cli, ["validate", str(TEST_DATA_DIR / "circuit_config.json")])

result = runner.invoke(cli, ["validate-circuit", str(TEST_DATA_DIR / "circuit_config.json")])
assert result.exit_code == 0
assert click.style("No Error: Success.", fg="green") in result.stdout


def test_cli_no_config():
def test_cli_validate_circuit_no_config():
runner = CliRunner()
result = runner.invoke(cli, ["validate"])
result = runner.invoke(cli, ["validate-circuit"])
assert result.exit_code == 2
assert "Missing argument 'CONFIG_FILE'" in result.stdout


@patch("bluepysnap.schemas.validate_nodes_schema", Mock(return_value=[]))
@patch("bluepysnap.schemas.validate_edges_schema", Mock(return_value=[]))
@patch("bluepysnap.schemas.validate_circuit_schema", Mock(return_value=[]))
def test_cli_validate_circuit_correct():
runner = CliRunner()
result = runner.invoke(cli, ["validate-circuit", str(TEST_DATA_DIR / "circuit_config.json")])
assert result.exit_code == 0
assert click.style("No Error: Success.", fg="green") in result.stdout


def test_cli_validate_simulation_correct():
runner = CliRunner()
result = runner.invoke(
cli, ["validate-simulation", str(TEST_DATA_DIR / "simulation_config.json")]
)
assert result.exit_code == 0
assert click.style("No Error: Success.", fg="green") in result.stdout


def test_cli_validate_simulation_no_config():
runner = CliRunner()
result = runner.invoke(cli, ["validate-simulation"])
assert result.exit_code == 2
assert "Missing argument 'CONFIG_FILE'" in result.stdout
Loading
Loading