From faa47cd63dd83a9619441408bda6c559a785952c Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Fri, 20 Sep 2024 18:11:05 +0200 Subject: [PATCH 01/10] fix: make ByIdTargetting bsb-neuron compatible. Find cell_model ids in placement --- .github/devops/generate_public_api.py | 5 +++++ .pre-commit-config.yaml | 4 +++- bsb/simulation/targetting.py | 16 +++++++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.github/devops/generate_public_api.py b/.github/devops/generate_public_api.py index 378bfa23d..fc9b0f7f5 100644 --- a/.github/devops/generate_public_api.py +++ b/.github/devops/generate_public_api.py @@ -4,6 +4,11 @@ import sys from pathlib import Path +try: + functools.cache +except AttributeError: + functools.cache = functools.lru_cache + def _assign_targets(assign: ast.Assign, id_: str): return any( diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 02848a043..b4475401b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: hooks: - id: api-test name: api-test - entry: python3 .github/devops/generate_public_api.py + entry: python3.9 .github/devops/generate_public_api.py language: system - repo: https://github.com/compilerla/conventional-pre-commit rev: v3.3.0 @@ -24,3 +24,5 @@ repos: name: conventional-commit stages: [ commit-msg ] args: [ ] +default_language_version: + python: python3.9 diff --git a/bsb/simulation/targetting.py b/bsb/simulation/targetting.py index 84148ae30..3e2908c1e 100755 --- a/bsb/simulation/targetting.py +++ b/bsb/simulation/targetting.py @@ -141,12 +141,18 @@ class ByIdTargetting(FractionFilter, CellTargetting, classmap_entry="by_id"): @FractionFilter.filter def get_targets(self, adapter, simulation, simdata): - by_name = {model.name: model for model in simdata.populations.keys()} - return { - model: simdata.populations[model][ids] - for model_name, ids in self.ids.items() - if (model := by_name.get(model_name)) is not None + by_name = { + model.name: model + for model, pop in simdata.populations.items() + if len(pop) > 0 } + dict_target = {} + for model_name, ids in self.ids.items(): + if (model := by_name.get(model_name)) is not None: + ps_ids = list(simdata.placement[model].load_ids()) + ids_here = [ps_ids.index(ids_i) for ids_i in ids if ids_i in ps_ids] + dict_target[model] = simdata.populations[model][ids_here] + return dict_target @config.node From b97409322c07d426c296907d0991ea5ace6c5070 Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Fri, 20 Sep 2024 18:14:21 +0200 Subject: [PATCH 02/10] fix: python version pre-commit config --- .pre-commit-config.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b4475401b..14078bd29 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,5 +24,3 @@ repos: name: conventional-commit stages: [ commit-msg ] args: [ ] -default_language_version: - python: python3.9 From 59cdf5a5c1febae165f832aa6bae933d6ab16e2a Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Fri, 20 Sep 2024 18:35:27 +0200 Subject: [PATCH 03/10] fix: python version pre-commit config (undo) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 14078bd29..02848a043 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: hooks: - id: api-test name: api-test - entry: python3.9 .github/devops/generate_public_api.py + entry: python3 .github/devops/generate_public_api.py language: system - repo: https://github.com/compilerla/conventional-pre-commit rev: v3.3.0 From 978ba2a39850aeb8c5605e76dd6db54d209b5176 Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Fri, 20 Sep 2024 19:03:21 +0200 Subject: [PATCH 04/10] fix: undo changes, back as it was --- .github/devops/generate_public_api.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/devops/generate_public_api.py b/.github/devops/generate_public_api.py index fc9b0f7f5..378bfa23d 100644 --- a/.github/devops/generate_public_api.py +++ b/.github/devops/generate_public_api.py @@ -4,11 +4,6 @@ import sys from pathlib import Path -try: - functools.cache -except AttributeError: - functools.cache = functools.lru_cache - def _assign_targets(assign: ast.Assign, id_: str): return any( From 0fcadb6a8871ec8c6e06eeeda0f9f63a559f971a Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Fri, 20 Sep 2024 19:32:56 +0200 Subject: [PATCH 05/10] fix: sorted import --- bsb/simulation/targetting.py | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/bsb/simulation/targetting.py b/bsb/simulation/targetting.py index 3e2908c1e..6fbe43dca 100755 --- a/bsb/simulation/targetting.py +++ b/bsb/simulation/targetting.py @@ -9,6 +9,7 @@ from ..config import refs, types if typing.TYPE_CHECKING: + from ..cell_types import CellType from .cell import CellModel @@ -58,6 +59,17 @@ def get_targets(self, adapter, simulation, simdata): } +class CellTypeFilter: + cell_types: list["CellType"] = config.reflist(refs.cell_type_ref, required=False) + + def get_targets(self, adapter, simulation, simdata): + return { + cell_name: cell_type.get_placement_set(chunks=simdata.chunks) + for cell_name, cell_type in simulation.scaffold.cell_types.items() + if not self.cell_types or cell_type in self.cell_types + } + + class FractionFilter: count = config.attr( type=int, required=types.mut_excl("fraction", "count", required=False) @@ -212,6 +224,36 @@ def get_targets(self, adapter, simulation, simdata): } +@config.node +class SphericalTargettingCellTypes( + CellTypeFilter, FractionFilter, Targetting, classmap_entry="sphere_cell_types" +): + """ + Targets all cell types in a sphere. + """ + + origin: list[float] = config.attr(type=types.list(type=float, size=3), required=True) + radius: float = config.attr(type=float, required=True) + + @FractionFilter.filter + def get_targets(self, adapter, simulation, simdata): + """ + Target all or certain cells within a sphere of specified radius. + """ + return { + model: ps.load_ids()[ + ( + np.sum( + (ps.load_positions() - self.origin) ** 2, + axis=1, + ) + < self.radius**2 + ) + ] + for model, ps in super().get_targets(adapter, simulation, simdata).items() + } + + @config.node class SphericalTargetting( CellModelFilter, FractionFilter, CellTargetting, classmap_entry="sphere" From cdf580e66a16674d2e39af2bac93b734980356bb Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Fri, 20 Sep 2024 19:32:56 +0200 Subject: [PATCH 06/10] feat: targetting cell types (only spherical right now) --- bsb/simulation/targetting.py | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/bsb/simulation/targetting.py b/bsb/simulation/targetting.py index 3e2908c1e..6fbe43dca 100755 --- a/bsb/simulation/targetting.py +++ b/bsb/simulation/targetting.py @@ -9,6 +9,7 @@ from ..config import refs, types if typing.TYPE_CHECKING: + from ..cell_types import CellType from .cell import CellModel @@ -58,6 +59,17 @@ def get_targets(self, adapter, simulation, simdata): } +class CellTypeFilter: + cell_types: list["CellType"] = config.reflist(refs.cell_type_ref, required=False) + + def get_targets(self, adapter, simulation, simdata): + return { + cell_name: cell_type.get_placement_set(chunks=simdata.chunks) + for cell_name, cell_type in simulation.scaffold.cell_types.items() + if not self.cell_types or cell_type in self.cell_types + } + + class FractionFilter: count = config.attr( type=int, required=types.mut_excl("fraction", "count", required=False) @@ -212,6 +224,36 @@ def get_targets(self, adapter, simulation, simdata): } +@config.node +class SphericalTargettingCellTypes( + CellTypeFilter, FractionFilter, Targetting, classmap_entry="sphere_cell_types" +): + """ + Targets all cell types in a sphere. + """ + + origin: list[float] = config.attr(type=types.list(type=float, size=3), required=True) + radius: float = config.attr(type=float, required=True) + + @FractionFilter.filter + def get_targets(self, adapter, simulation, simdata): + """ + Target all or certain cells within a sphere of specified radius. + """ + return { + model: ps.load_ids()[ + ( + np.sum( + (ps.load_positions() - self.origin) ** 2, + axis=1, + ) + < self.radius**2 + ) + ] + for model, ps in super().get_targets(adapter, simulation, simdata).items() + } + + @config.node class SphericalTargetting( CellModelFilter, FractionFilter, CellTargetting, classmap_entry="sphere" From acd36977d7e613db80b9c135c29a8d667d50abbc Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Thu, 31 Oct 2024 12:26:16 +0100 Subject: [PATCH 07/10] fix: make CellTypeFilter to look outside the chunk --- bsb/simulation/targetting.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bsb/simulation/targetting.py b/bsb/simulation/targetting.py index be078b248..5be4bd888 100755 --- a/bsb/simulation/targetting.py +++ b/bsb/simulation/targetting.py @@ -61,10 +61,14 @@ def get_targets(self, adapter, simulation, simdata): class CellTypeFilter: cell_types: list["CellType"] = config.reflist(refs.cell_type_ref, required=False) + only_local: bool = config.attr(type=bool, default=True) def get_targets(self, adapter, simulation, simdata): + chunks = simdata.chunks + if not self.only_local: + chunks = None return { - cell_name: cell_type.get_placement_set(chunks=simdata.chunks) + cell_name: cell_type.get_placement_set(chunks=chunks) for cell_name, cell_type in simulation.scaffold.cell_types.items() if not self.cell_types or cell_type in self.cell_types } From b911b7a5d23d7bc27aa859170fde38f1456a86b8 Mon Sep 17 00:00:00 2001 From: danilobenozzo Date: Mon, 16 Dec 2024 11:45:11 +0100 Subject: [PATCH 08/10] Update bsb/simulation/targetting.py shortcut Co-authored-by: Robin De Schepper --- bsb/simulation/targetting.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bsb/simulation/targetting.py b/bsb/simulation/targetting.py index 5be4bd888..d109bf81b 100755 --- a/bsb/simulation/targetting.py +++ b/bsb/simulation/targetting.py @@ -64,9 +64,7 @@ class CellTypeFilter: only_local: bool = config.attr(type=bool, default=True) def get_targets(self, adapter, simulation, simdata): - chunks = simdata.chunks - if not self.only_local: - chunks = None + chunks = simdata.chunks if self.only_local else None return { cell_name: cell_type.get_placement_set(chunks=chunks) for cell_name, cell_type in simulation.scaffold.cell_types.items() From e814d96257bc44ff2792eefa4bdb6e570d19cd63 Mon Sep 17 00:00:00 2001 From: filimarc Date: Tue, 18 Feb 2025 16:08:40 +0100 Subject: [PATCH 09/10] fix: Adapt targetting to use the convert_to_local method --- bsb/simulation/targetting.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bsb/simulation/targetting.py b/bsb/simulation/targetting.py index d109bf81b..429986701 100755 --- a/bsb/simulation/targetting.py +++ b/bsb/simulation/targetting.py @@ -160,12 +160,13 @@ def get_targets(self, adapter, simulation, simdata): for model, pop in simdata.populations.items() if len(pop) > 0 } + dict_target = {} for model_name, ids in self.ids.items(): if (model := by_name.get(model_name)) is not None: - ps_ids = list(simdata.placement[model].load_ids()) - ids_here = [ps_ids.index(ids_i) for ids_i in ids if ids_i in ps_ids] - dict_target[model] = simdata.populations[model][ids_here] + pop = simdata.populations[model] + my_ids = simdata.placement[model].convert_to_local(ids) + dict_target[model] = pop[my_ids] return dict_target From c63ca76249bc0199beabea80fdf573cdab6db9d0 Mon Sep 17 00:00:00 2001 From: filimarc Date: Thu, 6 Mar 2025 13:54:24 +0100 Subject: [PATCH 10/10] fix: make LocationTargetting everywhere compatible with other LocationTargetting --- bsb/simulation/targetting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsb/simulation/targetting.py b/bsb/simulation/targetting.py index 429986701..50708b9b4 100755 --- a/bsb/simulation/targetting.py +++ b/bsb/simulation/targetting.py @@ -298,7 +298,7 @@ def get_targets(self, adapter, simulation, simdata): ) class LocationTargetting: def get_locations(self, cell): - return cell.locations + return [v for v in cell.locations.values()] @config.node