import numpy
import numpy.linalg
from .mask import Mask
from ..util.event import Event
from ..util.branch import Branch
from .segment import SegmentMask
[docs]class BranchMask(Mask):
"""
Represent a dendrite branch, or part of a dendrite branch.
Provide functionality for splitting, joining and iterating over segments.
"""
def __init__(self, data=None, name=None):
"""Can be constructed as Branch(kind,x,y,z,r) or Branch(swc[start:end])."""
super(BranchMask, self).__init__(name=name)
self.branch = Branch(data=data)
self.segments = []
"""Child masks aka segments of the branch."""
from .polygon import PolygonMask
self.__polygon = PolygonMask(outline=self.outline)
self.changed = Event()
"""The event which will be triggered when the branch mask was changed."""
@property
def outline(self):
"""
:return: return the outline of the wrapped :py:class:`samuroi.util.branch.Branch` object.
"""
return self.branch.outline
@property
def data(self):
"""
:return: return the data of the wrapped :py:class:`samuroi.util.branch.Branch` object.
"""
return self.branch.data
@property
def children(self):
"""
Get the list of child segments of this branch.
.. warning::
Do not modify this list manually. Instead use :py:func:`samuroi.masks.branch.BranchMask.split`.
:return: the list of children.
"""
return self.segments
def __call__(self, data, mask):
return self.__polygon(data, mask)
[docs] def to_hdf5(self, f):
if 'branches' not in f:
f.create_group('branches')
f.create_group('branches/' + self.name)
f.create_dataset('branches/' + self.name + '/data', data=self.data)
f.create_dataset('branches/' + self.name + '/outline', data=self.outline)
if len(self.children) > 0:
f.create_group('branches/' + self.name + '/segments')
for s in self.children:
f.create_group('branches/{}/segments/{}'.format(self.name, s.name))
f.create_dataset('branches/{}/segments/{}/data'.format(self.name, s.name), data=s.data)
f.create_dataset('branches/{}/segments/{}/outline'.format(self.name, s.name), data=s.outline)
@staticmethod
[docs] def from_hdf5(f):
if 'branches' in f:
for name in f['branches'].keys():
data = f['branches/' + name + '/data'].value
branch = BranchMask(name=name, data=data)
if 'segments' in f['branches/' + name]:
for childname in f['branches/' + name + '/segments'].keys():
child = SegmentMask(parent=branch,
data=f['branches/' + name + '/segments/' + childname + '/data'].value)
child.name = childname
branch.children.append(child)
yield branch
[docs] def move(self, offset):
"""Move the branch and all its children."""
new_x = self.data['x'] + offset[0]
new_y = self.data['y'] + offset[1]
dtype = [('x', float), ('y', float), ('z', float), ('radius', float)]
self.branch.data = numpy.rec.fromarrays([new_x, new_y, self.data['z'], self.data['radius']], dtype=dtype)
from .polygon import PolygonMask
self.__polygon = PolygonMask(outline=self.outline)
for child in self.segments:
child.move(offset)
self.changed(self)
[docs] def split(self, nsegments=2, length=None, k=1, s=0):
"""
Split this branch and create a set of child segments.
.. note::
One can either provide a `nsegments` or `length`.
Splitting of a branch will modify the :py:attr:`samuroi.masks.branch.BranchMask.children` attribute
and hence trigger a :py:attr:`samuroi.masks.branch.BranchMask.changed` event.
:param nsegments: the number of segments.
:param length: the length of each segment (the last segment will have the remainder of modulo division).
:param k: smoothness parameter for spline interpolation
:param s: smoothness parameter for spline interpolation
"""
branches = self.branch.split(nsegments=nsegments, length=length, k=k, s=s)
self.segments = [SegmentMask(data=b.data, parent=self) for b in branches]
self.changed(self)
[docs] def linescan(self, data, mask):
"""
Calculate the trace for all children and return a 2D array of traces.
:param data: the data to apply on.
:param mask: some additional overlay mask
:return: 2D numpy array holding traces for all children
"""
return numpy.row_stack((child(data, mask) for child in self.segments))
[docs] def append(self, other, gap=False):
raise NotImplementedError("not supported for branchmask")