Skip to content

Commit

Permalink
Support morphology containers
Browse files Browse the repository at this point in the history
* when the `alternative-morphs` has an `h5` version
  use the `morphio.Container`, to both load from a directory of from a
  file
  • Loading branch information
mgeplf committed Oct 30, 2024
1 parent 7ec05a6 commit 0291bb1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 8 deletions.
40 changes: 32 additions & 8 deletions bluepysnap/morph.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
from pathlib import Path

import morph_tool.transform as transformations
import morphio
import numpy as np
from morphio.mut import Morphology

from bluepysnap.exceptions import BluepySnapError
from bluepysnap.sonata_constants import Node
Expand Down Expand Up @@ -51,8 +51,8 @@ def __init__(self, morph_dir, population, alternate_morphologies=None):
self._alternate_morphologies = alternate_morphologies or {}
self._population = population

def get_morphology_dir(self, extension):
"""Return morphology directory based on a given extension."""
def _get_morphology_base(self, extension):
"""Get morphology base path; this will be a directory unless it's a morphology container"""
if extension == "swc":
if not self._morph_dir:
raise BluepySnapError("'morphologies_dir' is not defined in config")
Expand All @@ -68,16 +68,33 @@ def get_morphology_dir(self, extension):

return morph_dir

def get_morphology_dir(self, extension="swc"):
"""Return morphology directory based on a given extension."""
morph_dir = self._get_morphology_base(extension)

if extension == "h5" and Path(morph_dir).is_file():
raise BluepySnapError(
f"'{morph_dir}' is a morphology container, so a directory does not exist"
)

return morph_dir

def get_name(self, node_id):
"""Get the morphology name for a `node_id`."""
if not is_node_id(node_id):
raise BluepySnapError("node_id must be a int or a CircuitNodeId")

name = self._population.get(node_id, Node.MORPHOLOGY)
return name

def get_filepath(self, node_id, extension="swc"):
"""Return path to SWC morphology file corresponding to `node_id`.
Args:
node_id (int/CircuitNodeId): could be a int or CircuitNodeId.
extension (str): expected filetype extension of the morph file.
"""
if not is_node_id(node_id):
raise BluepySnapError("node_id must be a int or a CircuitNodeId")
name = self._population.get(node_id, Node.MORPHOLOGY)
name = self.get_name(node_id)

return Path(self.get_morphology_dir(extension), f"{name}.{extension}")

Expand All @@ -90,11 +107,18 @@ def get(self, node_id, transform=False, extension="swc"):
according to `node_id` position in the circuit.
extension (str): expected filetype extension of the morph file.
"""
filepath = self.get_filepath(node_id, extension=extension)
result = Morphology(filepath)
if extension == "h5":
collection = morphio.Collection(self._get_morphology_base(extension))
name = self.get_name(node_id)
result = collection.load(name, mutable=True)
else:
filepath = self.get_filepath(node_id, extension=extension)
result = morphio.mut.Morphology(filepath)

if transform:
T = np.eye(4)
T[:3, :3] = self._population.orientations(node_id) # rotations
T[:3, 3] = self._population.positions(node_id).values # translations
transformations.transform(result, T)

return result.as_immutable()
Binary file added tests/data/morphologies/container-morphs.h5
Binary file not shown.
Binary file modified tests/data/morphologies/morph-B.h5
Binary file not shown.
19 changes: 19 additions & 0 deletions tests/test_morph.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,25 @@ def test_get_morphology(self):
with pytest.raises(BluepySnapError, match="node_id must be a int or a CircuitNodeId"):
self.test_obj.get([0, 1])

def test_get_alternate_morphology_collection(self):
morph_path = TEST_DATA_DIR / "morphologies/container-morphs.h5"
alternate_morphs = {"h5v1": str(morph_path)}

test_obj = test_module.MorphHelper(
None, self.nodes, alternate_morphologies=alternate_morphs
)

node_id = 0

with pytest.raises(BluepySnapError):
test_obj.get_morphology_dir(extension="h5")

with pytest.raises(BluepySnapError):
test_obj.get_filepath(node_id, extension="h5")

morph_A = test_obj.get(node_id, extension="h5")
assert len(morph_A.points) == 13

def test_get_alternate_morphology(self):
alternate_morphs = {"h5v1": str(self.morph_path)}
test_obj = test_module.MorphHelper(
Expand Down

0 comments on commit 0291bb1

Please sign in to comment.