Skip to content

Commit

Permalink
now handles all Neo objects, including ChannelViews and RegionsOfInte…
Browse files Browse the repository at this point in the history
…rest
  • Loading branch information
apdavison committed Jan 30, 2024
1 parent 74e9415 commit b76672a
Show file tree
Hide file tree
Showing 8 changed files with 426 additions and 218 deletions.
4 changes: 3 additions & 1 deletion neo/core/baseneo.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class BaseNeo:
class must have. The tuple can have 2-4 elements.
The first element is the attribute name.
The second element is the attribute type.
The third element is the number of dimensions
The third element is the number of dimensions
(only for numpy arrays and quantities).
The fourth element is the dtype of array
(only for numpy arrays and quantities).
Expand Down Expand Up @@ -253,6 +253,8 @@ class attributes. :_recommended_attrs: should append
# Attributes that are used for pretty-printing
_repr_pretty_attrs_keys_ = ("name", "description", "annotations")

is_view = False

def __init__(self, name=None, description=None, file_origin=None,
**annotations):
"""
Expand Down
11 changes: 7 additions & 4 deletions neo/core/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,16 +251,19 @@ def _data_child_containers(self):
"""
Containers for child objects that have data and have a single parent.
"""
return tuple([_container_name(child) for child in
self._data_child_objects])
# the following construction removes the duplicate 'regionsofinterest'
# while preserving the child order (which `set()` would not do)
# I don't know if preserving the author is important, but I'm playing it safe
return tuple({_container_name(child): None for child in
self._data_child_objects}.keys())

@property
def _child_containers(self):
"""
Containers for child objects with a single parent.
"""
return tuple([_container_name(child) for child in
self._child_objects])
return tuple({_container_name(child): None for child in
self._child_objects}.keys())

@property
def _single_children(self):
Expand Down
33 changes: 32 additions & 1 deletion neo/core/regionofinterest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ class RegionOfInterest(BaseNeo):
_parent_objects = ('Group',)
_parent_attrs = ('group',)
_necessary_attrs = (
('obj', ('ImageSequence', ), 1),
('image_sequence', ('ImageSequence', ), 1),
)
is_view = True

def __init__(self, image_sequence, name=None, description=None, file_origin=None, **annotations):
super().__init__(name=name, description=description,
Expand All @@ -22,6 +23,16 @@ def __init__(self, image_sequence, name=None, description=None, file_origin=None
raise ValueError("Can only take a RegionOfInterest of an ImageSequence")
self.image_sequence = image_sequence

def _get_obj(self):
# for consistency with ChannelView
return self.image_sequence

def _set_obj(self, value):
assert isinstance(value, ImageSequence)
self.image_sequence = value

obj = property(fget=_get_obj, fset=_set_obj)

def resolve(self):
"""
Return a signal from within this region of the underlying ImageSequence.
Expand All @@ -44,6 +55,13 @@ class CircularRegionOfInterest(RegionOfInterest):
Radius of the ROI in pixels
"""

_necessary_attrs = (
('image_sequence', ('ImageSequence', ), 1),
('x', int),
('y', int),
('radius', int)
)

def __init__(self, image_sequence, x, y, radius, name=None, description=None,
file_origin=None, **annotations):
super().__init__(image_sequence, name, description, file_origin, **annotations)
Expand Down Expand Up @@ -94,6 +112,14 @@ class RectangularRegionOfInterest(RegionOfInterest):
Height (y-direction) of the ROI in pixels
"""

_necessary_attrs = (
('image_sequence', ('ImageSequence', ), 1),
('x', int),
('y', int),
('width', int),
('height', int)
)

def __init__(self, image_sequence, x, y, width, height, name=None, description=None,
file_origin=None, **annotations):
super().__init__(image_sequence, name, description, file_origin, **annotations)
Expand Down Expand Up @@ -139,6 +165,11 @@ class PolygonRegionOfInterest(RegionOfInterest):
of the vertices of the polygon
"""

_necessary_attrs = (
('image_sequence', ('ImageSequence', ), 1),
('vertices', list),
)

def __init__(self, image_sequence, *vertices, name=None, description=None,
file_origin=None, **annotations):
super().__init__(image_sequence, name, description, file_origin, **annotations)
Expand Down
10 changes: 6 additions & 4 deletions neo/core/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ class ChannelView(BaseNeo):
Note: Any other additional arguments are assumed to be user-specific
metadata and stored in :attr:`annotations`.
"""
_parent_objects = ('Segment',)
_parent_attrs = ('segment',)
_parent_objects = ('Group',)
_parent_attrs = ('group',)
_necessary_attrs = (
('obj', ('AnalogSignal', 'IrregularlySampledSignal'), 1),
('index', np.ndarray, 1, np.dtype('i')),
('obj', ('AnalogSignal', 'IrregularlySampledSignal'), 1)
)
is_view = True

# "mask" would be an alternative name, proposing "index" for
# backwards-compatibility with ChannelIndex

Expand Down Expand Up @@ -73,7 +75,7 @@ def shape(self):
return (self.obj.shape[0], self.index.size)

def _get_arr_ann_length(self):
return self.shape[-1]
return self.index.size

def array_annotate(self, **array_annotations):
self.array_annotations.update(array_annotations)
Expand Down
Loading

0 comments on commit b76672a

Please sign in to comment.