Skip to content

Commit d4b83a6

Browse files
authored
Merge branch 'master' into black-formatting-action
2 parents 33e8bfb + e8f0b12 commit d4b83a6

25 files changed

+410
-230
lines changed

.github/workflows/publish-to-pypi-test.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,19 @@ jobs:
2020
python -m pip install --upgrade pip
2121
pip install setuptools wheel twine build
2222
pip install .
23+
- name: Get the tag version
24+
id: get-version
25+
run: |
26+
echo ${GITHUB_REF#refs/tags/}
27+
echo "TAG::${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
2328
- name: Test version/tag correspondence
2429
id: version-check
2530
run: |
2631
neo_version=$(python -c "import neo; print(neo.__version__)")
32+
tag_version=${{ steps.get-version.outputs.TAG }}
2733
echo $neo_version
28-
TAG=${{ github.event.release.tag_name }}
29-
echo $TAG
30-
if [[ $TAG == $neo_version ]]; then
34+
echo $tag_version
35+
if [[ $tag_version == $neo_version ]]; then
3136
echo "VERSION_TAG_MATCH=true" >> $GITHUB_OUTPUT
3237
echo "Version matches tag, proceeding with release to Test PyPI"
3338
else

neo/core/baseneo.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,11 @@ def _container_name(class_name):
154154
referenced by `block.segments`. The attribute name `segments` is
155155
obtained by calling `_container_name_plural("Segment")`.
156156
"""
157-
return _reference_name(class_name) + 's'
157+
if "RegionOfInterest" in class_name:
158+
# this is a hack, pending a more principled way to handle this
159+
return "regionsofinterest"
160+
else:
161+
return _reference_name(class_name) + 's'
158162

159163

160164
class BaseNeo:

neo/core/block.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from neo.core.container import Container, unique_objs
1313
from neo.core.group import Group
1414
from neo.core.objectlist import ObjectList
15-
from neo.core.regionofinterest import RegionOfInterest
1615
from neo.core.segment import Segment
1716

1817

@@ -91,7 +90,6 @@ def __init__(self, name=None, description=None, file_origin=None,
9190
self.index = index
9291
self._segments = ObjectList(Segment, parent=self)
9392
self._groups = ObjectList(Group, parent=self)
94-
self._regionsofinterest = ObjectList(RegionOfInterest, parent=self)
9593

9694
segments = property(
9795
fget=lambda self: self._get_object_list("_segments"),
@@ -105,12 +103,6 @@ def __init__(self, name=None, description=None, file_origin=None,
105103
doc="list of Groups contained in this block"
106104
)
107105

108-
regionsofinterest = property(
109-
fget=lambda self: self._get_object_list("_regionsofinterest"),
110-
fset=lambda self, value: self._set_object_list("_regionsofinterest", value),
111-
doc="list of RegionOfInterest objects contained in this block"
112-
)
113-
114106
@property
115107
def data_children_recur(self):
116108
'''

neo/core/group.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from neo.core.segment import Segment
1919
from neo.core.spiketrainlist import SpikeTrainList
2020
from neo.core.view import ChannelView
21+
from neo.core.regionofinterest import RegionOfInterest
2122

2223

2324
class Group(Container):
@@ -49,7 +50,8 @@ class Group(Container):
4950
"""
5051
_data_child_objects = (
5152
'AnalogSignal', 'IrregularlySampledSignal', 'SpikeTrain',
52-
'Event', 'Epoch', 'ChannelView', 'ImageSequence'
53+
'Event', 'Epoch', 'ChannelView', 'ImageSequence', 'CircularRegionOfInterest',
54+
'RectangularRegionOfInterest', 'PolygonRegionOfInterest'
5355
)
5456
_container_child_objects = ('Group',)
5557
_parent_objects = ('Block',)
@@ -69,6 +71,7 @@ def __init__(self, objects=None, name=None, description=None, file_origin=None,
6971
self._epochs = ObjectList(Epoch)
7072
self._channelviews = ObjectList(ChannelView)
7173
self._imagesequences = ObjectList(ImageSequence)
74+
self._regionsofinterest = ObjectList(RegionOfInterest)
7275
self._segments = ObjectList(Segment) # to remove?
7376
self._groups = ObjectList(Group)
7477

@@ -119,6 +122,12 @@ def __init__(self, objects=None, name=None, description=None, file_origin=None,
119122
doc="list of ImageSequences contained in this group"
120123
)
121124

125+
regionsofinterest = property(
126+
fget=lambda self: self._get_object_list("_regionsofinterest"),
127+
fset=lambda self, value: self._set_object_list("_regionsofinterest", value),
128+
doc="list of RegionOfInterest objects contained in this group"
129+
)
130+
122131
spiketrains = property(
123132
fget=lambda self: self._get_object_list("_spiketrains"),
124133
fset=lambda self, value: self._set_object_list("_spiketrains", value),

neo/core/imagesequence.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class ImageSequence(BaseSignal):
9797
)
9898
_recommended_attrs = BaseNeo._recommended_attrs
9999

100-
def __new__(cls, image_data, units=None, dtype=None, copy=True, t_start=0 * pq.s,
100+
def __new__(cls, image_data, units=pq.dimensionless, dtype=None, copy=True, t_start=0 * pq.s,
101101
spatial_scale=None, frame_duration=None,
102102
sampling_rate=None, name=None, description=None, file_origin=None,
103103
**annotations):
@@ -127,7 +127,7 @@ def __new__(cls, image_data, units=None, dtype=None, copy=True, t_start=0 * pq.s
127127

128128
return obj
129129

130-
def __init__(self, image_data, units=None, dtype=None, copy=True, t_start=0 * pq.s,
130+
def __init__(self, image_data, units=pq.dimensionless, dtype=None, copy=True, t_start=0 * pq.s,
131131
spatial_scale=None, frame_duration=None,
132132
sampling_rate=None, name=None, description=None, file_origin=None,
133133
**annotations):
@@ -142,7 +142,7 @@ def __array_finalize__spec(self, obj):
142142

143143
self.sampling_rate = getattr(obj, "sampling_rate", None)
144144
self.spatial_scale = getattr(obj, "spatial_scale", None)
145-
self.units = getattr(obj, "units", None)
145+
self.units = getattr(obj, "units", pq.dimensionless)
146146
self._t_start = getattr(obj, "_t_start", 0 * pq.s)
147147

148148
return obj

neo/core/regionofinterest.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,32 @@
11
from math import floor, ceil
22

33
from neo.core.baseneo import BaseNeo
4+
from neo.core.imagesequence import ImageSequence
45

56

67
class RegionOfInterest(BaseNeo):
78
"""Abstract base class"""
8-
pass
9+
10+
_parent_objects = ('Group',)
11+
_parent_attrs = ('group',)
12+
_necessary_attrs = (
13+
('obj', ('ImageSequence', ), 1),
14+
)
15+
16+
def __init__(self, image_sequence, name=None, description=None, file_origin=None, **annotations):
17+
super().__init__(name=name, description=description,
18+
file_origin=file_origin, **annotations)
19+
20+
if not (isinstance(image_sequence, ImageSequence) or (
21+
hasattr(image_sequence, "proxy_for") and issubclass(image_sequence.proxy_for, ImageSequence))):
22+
raise ValueError("Can only take a RegionOfInterest of an ImageSequence")
23+
self.image_sequence = image_sequence
24+
25+
def resolve(self):
26+
"""
27+
Return a signal from within this region of the underlying ImageSequence.
28+
"""
29+
return self.image_sequence.signal_from_region(self)
930

1031

1132
class CircularRegionOfInterest(RegionOfInterest):
@@ -23,8 +44,9 @@ class CircularRegionOfInterest(RegionOfInterest):
2344
Radius of the ROI in pixels
2445
"""
2546

26-
def __init__(self, x, y, radius):
27-
47+
def __init__(self, image_sequence, x, y, radius, name=None, description=None,
48+
file_origin=None, **annotations):
49+
super().__init__(image_sequence, name, description, file_origin, **annotations)
2850
self.y = y
2951
self.x = x
3052
self.radius = radius
@@ -72,7 +94,9 @@ class RectangularRegionOfInterest(RegionOfInterest):
7294
Height (y-direction) of the ROI in pixels
7395
"""
7496

75-
def __init__(self, x, y, width, height):
97+
def __init__(self, image_sequence, x, y, width, height, name=None, description=None,
98+
file_origin=None, **annotations):
99+
super().__init__(image_sequence, name, description, file_origin, **annotations)
76100
self.x = x
77101
self.y = y
78102
self.width = width
@@ -115,7 +139,9 @@ class PolygonRegionOfInterest(RegionOfInterest):
115139
of the vertices of the polygon
116140
"""
117141

118-
def __init__(self, *vertices):
142+
def __init__(self, image_sequence, *vertices, name=None, description=None,
143+
file_origin=None, **annotations):
144+
super().__init__(image_sequence, name, description, file_origin, **annotations)
119145
self.vertices = vertices
120146

121147
def polygon_ray_casting(self, bounding_points, bounding_box_positions):

neo/io/baseio.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
1111
If you want a model for developing a new IO start from exampleIO.
1212
"""
13+
from __future__ import annotations
14+
from pathlib import Path
1315

1416
try:
1517
from collections.abc import Sequence
@@ -96,7 +98,7 @@ class BaseIO:
9698

9799
mode = 'file' # or 'fake' or 'dir' or 'database'
98100

99-
def __init__(self, filename=None, **kargs):
101+
def __init__(self, filename: str | Path = None, **kargs):
100102
self.filename = str(filename)
101103
# create a logger for the IO class
102104
fullname = self.__class__.__module__ + '.' + self.__class__.__name__
@@ -111,7 +113,7 @@ def __init__(self, filename=None, **kargs):
111113
corelogger.addHandler(logging_handler)
112114

113115
######## General read/write methods #######################
114-
def read(self, lazy=False, **kargs):
116+
def read(self, lazy: bool = False, **kargs):
115117
"""
116118
Return all data from the file as a list of Blocks
117119
"""

0 commit comments

Comments
 (0)