Skip to content

Commit

Permalink
Added .points and morphology usage docs (#206)
Browse files Browse the repository at this point in the history
  • Loading branch information
Helveg committed Jan 14, 2021
1 parent d512daa commit 9cd6d5a
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 1 deletion.
13 changes: 13 additions & 0 deletions bsb/morphologies.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ def __init__(self, *args, labels=None):
for v, vector in enumerate(self.__class__.vectors):
self.__dict__[vector] = args[v]

@property
def points(self):
"""
Return the vectors of this branch as a matrix.
"""
return np.column_stack(tuple(getattr(self, v) for v in self.__class__.vectors))

@property
def size(self):
"""
Expand Down Expand Up @@ -176,6 +183,12 @@ def detach_child(self, branch):
raise ValueError("Branch could not be detached, it is not a child branch.")

def to_compartments(self, start_id=0, parent=None):
"""
Convert the branch to compartments.
.. deprecated:: 3.6
Use the vectors and points API instead (``.points``, ``.walk()``)
"""
comp_id = start_id

def to_comp(data, labels):
Expand Down
63 changes: 63 additions & 0 deletions docs/source/morphologies/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,66 @@ extra compartment is prepended between the last point of the parent branch and t
point of the child branch. Compartments are individuals so branches are no longer used to
describe the network of points, instead each compartment lists their own parent
compartment.

Using morphologies
------------------

For this introduction we're going to assume that you have a ``MorphologyRepository`` with
morphologies already present in them. To learn how to create your own morphologies stored
in ``MorphologyRepositories`` see :doc:`morphologies/repository`.

Let's start with loading a morphology and inspecting its root
:class:`~.morphologies.Branch`:

.. code-block:: python
from bsb.core import from_hdf5
from bsb.output import MorphologyRepository
mr = MorphologyRepository("path/to/mr.hdf5")
# Alternatively if you have your MR inside of a compiled network:
network = from_hdf5("network.hdf5")
mr = network.morphology_repository
morfo = mr.get_morphology("my_morphology")
# Use a local reference to the properties if you're not going to manipulate the
# morphology, as they require a full search of the morphology to be determined every
# time the property is accessed.
roots = morfo.roots
branches = morfo.branches
print("Loaded a morphology with", len(roots), "roots, and", len(branches), "branches")
# In most morphologies there will be a single root, representing the soma.
soma_branch = roots[0]
# Use the vectors of the branch (this is the most performant option)
print("A branch can be represented by the following vectors:")
print("x:", soma_branch.x)
print("y:", soma_branch.y)
print("z:", soma_branch.z)
print("r:", soma_branch.radii)
# Use the points property to retrieve a matrix notation of the branch
# (Stacks the vectors into a 2d matrix)
print("The soma can also be represented by the following matrix:", soma_branch.points)
# There's also an iterator to walk over the points in the vectors
print("The soma is defined as the following points:")
for point in soma_branch.walk():
print("*", point)
As you can see an individual branch contains all the positional data of the individual
points in the morphology. The morphology object itself then contains the collection of
branches. Normally you'd use the ``.branches`` but if you want to work with the positional
data of the whole morphology in a object you can do this by flattening the morphology:

.. code-block:: python
from bsb.core import from_hdf5
network = from_hdf5("network.hdf5")
mr = network.morphology_repository
morfo = mr.get_morphology("my_morphology")
print("All the branches in depth-first order:", morfo.branches)
print("All the points on those branches in depth first order:")
print("- As vectors:", morfo.flatten())
print("- As matrix:", morfo.flatten(matrix=True).shape)
3 changes: 3 additions & 0 deletions docs/source/morphologies/repository.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#######################
Morphology repositories
#######################
7 changes: 6 additions & 1 deletion tests/test_morphologies.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ def test_single_branch_single_element(self):
g = g.create_group("M")
b = g.create_group("branches")
b0 = b.create_group("0")
b0.create_dataset("x", data=[1])
b0.create_group("labels")
b0.create_dataset("x", data=[1])
b0.create_dataset("y", data=[1])
b0.create_dataset("z", data=[1])
b0.create_dataset("radii", data=[1])
Expand All @@ -113,6 +113,11 @@ def test_single_branch_single_element(self):
t = m.flatten()
msg = "Single empty branch morfo flatten to vector should produce vectors."
self.assertEqual(len(Branch.vectors), len(t), msg)
p = m.roots[0].points
msg = "Single point branch.points should return (1, 4) ndarray."
self.assertEqual((1, len(Branch.vectors)), p.shape, msg)
msg = "Point data of branch.points incorrect."
self.assertEqual([1, 1, 1, 1], list(p[0]), msg)
msg = "Single point branches should not produce comps"
self.assertEqual(0, len(m.to_compartments()), msg)

Expand Down

0 comments on commit 9cd6d5a

Please sign in to comment.