Skip to content

Commit b4f0029

Browse files
Merge branch 'master' into fix-regionsofinterest
2 parents fcde718 + 4ef2801 commit b4f0029

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1345
-348
lines changed

.github/workflows/core-test.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
paths:
88
- 'neo/core/**'
99
- 'pyproject.toml'
10+
- '.github/workflows/*.yml'
1011

1112
# run checks on any change of master, including merge of PRs
1213
push:
@@ -26,14 +27,12 @@ jobs:
2627
os: ["ubuntu-latest", "windows-latest"]
2728
# "macos-latest",
2829
python-version: ['3.8', '3.9', '3.10', '3.11']
29-
numpy-version: ['1.19.5', '1.20.3', '1.21.6', '1.22.4', '1.23.5', '1.24.1']
30+
numpy-version: ['1.20.3', '1.21.6', '1.22.4', '1.23.5', '1.24.1', '1.25.1']
3031
exclude:
31-
- python-version: '3.10'
32-
numpy-version: '1.19.5'
32+
- python-version: '3.8'
33+
numpy-version: '1.25.1'
3334
- python-version: '3.10'
3435
numpy-version: '1.20.3'
35-
- python-version: '3.11'
36-
numpy-version: '1.19.5'
3736
- python-version: '3.11'
3837
numpy-version: '1.20.3'
3938
- python-version: '3.11'

.github/workflows/io-test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ jobs:
103103
sudo apt-get install -yqq --allow-downgrades libc6:i386 libgcc-s1:i386 libstdc++6:i386 wine
104104
105105
- name: Test with pytest
106+
env:
107+
HDF5_PLUGIN_PATH: ${{ github.workspace }}/hdf5_local_plugin_path
106108
run: |
107109
# only neo.rawio and neo.io
108110
pytest --cov=neo neo/test/rawiotest

.readthedocs.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
version: 2
22

33
build:
4-
os: ubuntu-20.04
4+
os: ubuntu-22.04
55
tools:
6-
python: "3.8"
6+
python: "3.11"
77

88
sphinx:
99
configuration: doc/source/conf.py
@@ -14,4 +14,3 @@ python:
1414
path: .
1515
extra_requirements:
1616
- docs
17-

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
See http://neo.readthedocs.io/en/latest/developers_guide.html
1+
See https://neo.readthedocs.io/en/latest/contributing.html

doc/source/governance.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ The current maintainers are:
3737
- Samuel Garcia (`@samuelgarcia`_)
3838
- Julia Sprenger (`@JuliaSprenger`_)
3939
- Michael Denker (`@mdenker`_)
40+
- Alessio Buccino (`@alejoe91`_)
4041

4142

4243
.. _`Neo maintainers team`: https://github.com/orgs/NeuralEnsemble/teams/neo-maintainers
@@ -45,3 +46,4 @@ The current maintainers are:
4546
.. _`@samuelgarcia`: https://github.com/samuelgarcia
4647
.. _`@JuliaSprenger`: https://github.com/JuliaSprenger
4748
.. _`@mdenker`: https://github.com/mdenker
49+
.. _`@alejoe91`: https://github.com/alejoe91

neo/core/analogsignal.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -416,12 +416,9 @@ def _repr_pretty_(self, pp, cycle):
416416
'''
417417
Handle pretty-printing the :class:`AnalogSignal`.
418418
'''
419-
pp.text("{cls} with {channels} channels of length {length}; "
420-
"units {units}; datatype {dtype} ".format(cls=self.__class__.__name__,
421-
channels=self.shape[1],
422-
length=self.shape[0],
423-
units=self.units.dimensionality.string,
424-
dtype=self.dtype))
419+
pp.text(f"{self.__class__.__name__} with {self.shape[1]} channels of length "
420+
f"{self.shape[0]}; units {self.units.dimensionality.string}; datatype "
421+
f"{self.dtype}")
425422
if self._has_repr_pretty_attrs_():
426423
pp.breakable()
427424
self._repr_pretty_attrs_(pp, cycle)
@@ -431,8 +428,8 @@ def _pp(line):
431428
with pp.group(indent=1):
432429
pp.text(line)
433430

434-
_pp("sampling rate: {}".format(self.sampling_rate))
435-
_pp("time: {} to {}".format(self.t_start, self.t_stop))
431+
_pp(f"sampling rate: {self.sampling_rate}")
432+
_pp(f"time: {self.t_start} to {self.t_stop}")
436433

437434
def time_index(self, t):
438435
"""Return the array index (or indices) corresponding to the time (or times) `t`"""
@@ -716,9 +713,9 @@ def concatenate(self, *signals, overwrite=False, padding=False):
716713
raise MergeError(f'Signals are not continuous. Can not concatenate signals with gaps. '
717714
f'Please provide a padding value.')
718715
if padding is not False:
719-
logger.warning('Signals will be padded using {}.'.format(padding))
716+
logger.warning(f'Signals will be padded using {padding}.')
720717
if padding is True:
721-
padding = np.NaN * units
718+
padding = np.nan * units
722719
if isinstance(padding, pq.Quantity):
723720
padding = padding.rescale(units).magnitude
724721
else:

neo/core/baseneo.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ def _check_annotations(value):
3333
"""
3434
if isinstance(value, np.ndarray):
3535
if not issubclass(value.dtype.type, ALLOWED_ANNOTATION_TYPES):
36-
raise ValueError("Invalid annotation. NumPy arrays with dtype %s"
37-
"are not allowed" % value.dtype.type)
36+
raise ValueError(f"Invalid annotation. NumPy arrays with dtype {value.dtype.type}"
37+
f"are not allowed")
3838
elif isinstance(value, dict):
3939
for element in value.values():
4040
_check_annotations(element)
4141
elif isinstance(value, (list, tuple)):
4242
for element in value:
4343
_check_annotations(element)
4444
elif not isinstance(value, ALLOWED_ANNOTATION_TYPES):
45-
raise ValueError("Invalid annotation. Annotations of type %s are not"
46-
"allowed" % type(value))
45+
raise ValueError(f"Invalid annotation. Annotations of type {type(value)} are not"
46+
f"allowed")
4747

4848

4949
def merge_annotation(a, b):
@@ -58,8 +58,7 @@ def merge_annotation(a, b):
5858
For strings: concatenate with ';'
5959
Otherwise: fail if the annotations are not equal
6060
"""
61-
assert type(a) == type(b), 'type({}) {} != type({}) {}'.format(a, type(a),
62-
b, type(b))
61+
assert type(a) == type(b), f'type({a})) {type(a)} != type({b}) {type(b)}'
6362
if isinstance(a, dict):
6463
return merge_annotations(a, b)
6564
elif isinstance(a, np.ndarray): # concatenate b to a
@@ -72,7 +71,7 @@ def merge_annotation(a, b):
7271
else:
7372
return a + ";" + b
7473
else:
75-
assert a == b, '{} != {}'.format(a, b)
74+
assert a == b, f'{a} != {b}'
7675
return a
7776

7877

@@ -100,7 +99,7 @@ def merge_annotations(A, *Bs):
10099
# exc.args += ('key %s' % name,)
101100
# raise
102101
merged[name] = "MERGE CONFLICT" # temporary hack
103-
logger.debug("Merging annotations: A=%s Bs=%s merged=%s", A, Bs, merged)
102+
logger.debug(f"Merging annotations: A={A} Bs={Bs} merged={merged}")
104103
return merged
105104

106105

@@ -122,8 +121,7 @@ def intersect_annotations(A, B):
122121

123122
for key in set(A.keys()) & set(B.keys()):
124123
v1, v2 = A[key], B[key]
125-
assert type(v1) == type(v2), 'type({}) {} != type({}) {}'.format(v1, type(v1),
126-
v2, type(v2))
124+
assert type(v1) == type(v2), f'type({v1}) {type(v1)} != type({v2}) {type(v2)}'
127125
if isinstance(v1, dict) and v1 == v2:
128126
result[key] = deepcopy(v1)
129127
elif isinstance(v1, str) and v1 == v2:
@@ -303,7 +301,7 @@ def _repr_pretty_attrs_(self, pp, cycle):
303301
else:
304302
pp.breakable()
305303
with pp.group(indent=1):
306-
pp.text("{}: ".format(key))
304+
pp.text(f"{key}: ")
307305
pp.pretty(value)
308306

309307
def _repr_pretty_(self, pp, cycle):
@@ -370,8 +368,8 @@ def set_parent(self, obj):
370368
according to the type of "obj"
371369
"""
372370
if obj.__class__.__name__ not in self._parent_objects:
373-
raise TypeError("{} can only have parents of type {}, not {}".format(
374-
self.__class__.__name__, self._parent_objects, obj.__class__.__name__))
371+
raise TypeError((f"{self.__class__.__name__} can only have parents of "
372+
f"type {self._parwents_objects}, not {obj.__class__.__name__}"))
375373
loc = self._parent_objects.index(obj.__class__.__name__)
376374
parent_attr = self._parent_attrs[loc]
377375
setattr(self, parent_attr, obj)

neo/core/basesignal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def merge(self, other):
259259
if attr_self == attr_other:
260260
kwargs[name] = attr_self
261261
else:
262-
kwargs[name] = "merge({}, {})".format(attr_self, attr_other)
262+
kwargs[name] = f"merge({attr_self}, {attr_other})"
263263
merged_annotations = merge_annotations(self.annotations, other.annotations)
264264
kwargs.update(merged_annotations)
265265

neo/core/container.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ def _repr_pretty_(self, pp, cycle):
563563
for container in self._child_containers:
564564
objs = getattr(self, container)
565565
if objs:
566-
vals.append('{} {}'.format(len(objs), container))
566+
vals.append(f'{objs} {container}')
567567
pp.text(', '.join(vals))
568568

569569
if self._has_repr_pretty_attrs_():
@@ -573,7 +573,7 @@ def _repr_pretty_(self, pp, cycle):
573573
for container in self._repr_pretty_containers:
574574
pp.breakable()
575575
objs = getattr(self, container)
576-
pp.text("# {} (N={})".format(container, len(objs)))
576+
pp.text(f"# {container} (N={objs})")
577577
for (i, obj) in enumerate(objs):
578578
pp.breakable()
579579
pp.text("%s: " % i)

neo/core/dataobject.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def _normalize_array_annotations(value, length):
7373

7474
if not own_length == val_length:
7575
raise ValueError(
76-
"Incorrect length of array annotation: {} != {}".format(val_length, own_length))
76+
f"Incorrect length of array annotation: {val_length} != {own_length}")
7777

7878
# Local function used to check single elements of a list or an array
7979
# They must not be lists or arrays and fit the usual annotation data types
@@ -264,10 +264,10 @@ def _merge_array_annotations(self, other):
264264

265265
# Warn if keys were omitted
266266
if omitted_keys_other or omitted_keys_self:
267-
warnings.warn("The following array annotations were omitted, because they were only "
268-
"present in one of the merged objects: {} from the one that was merged "
269-
"into and {} from the one that was merged into the other"
270-
"".format(omitted_keys_self, omitted_keys_other), UserWarning)
267+
warnings.warn(f"The following array annotations were omitted, because they were only "
268+
f"present in one of the merged objects: {omitted_keys_self} from the "
269+
f"one that was merged into and {omitted_keys_other} from the one that "
270+
f"was merged into the other", UserWarning)
271271

272272
# Return the merged array_annotations
273273
return merged_array_annotations

neo/core/epoch.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def merge(self, other):
263263
if attr_self == attr_other:
264264
kwargs[name] = attr_self
265265
else:
266-
kwargs[name] = "merge({}, {})".format(attr_self, attr_other)
266+
kwargs[name] = f"merge({attr_self}, {attr_other})"
267267

268268
merged_annotations = merge_annotations(self.annotations, other.annotations)
269269
kwargs.update(merged_annotations)
@@ -354,8 +354,8 @@ def time_shift(self, t_shift):
354354

355355
def set_labels(self, labels):
356356
if self.labels is not None and self.labels.size > 0 and len(labels) != self.size:
357-
raise ValueError("Labels array has different length to times ({} != {})"
358-
.format(len(labels), self.size))
357+
raise ValueError(f"Labels array has different length to times "
358+
f"({len(labels)} != {self.size})")
359359
self._labels = np.array(labels)
360360

361361
def get_labels(self):
@@ -365,8 +365,8 @@ def get_labels(self):
365365

366366
def set_durations(self, durations):
367367
if self.durations is not None and self.durations.size > 0 and len(durations) != self.size:
368-
raise ValueError("Durations array has different length to times ({} != {})"
369-
.format(len(durations), self.size))
368+
raise ValueError("Durations array has different length to times "
369+
f"({len(durations)} != {self.size})")
370370
self._durations = durations
371371

372372
def get_durations(self):

neo/core/event.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def __new__(cls, times=None, labels=None, units=None, name=None, description=Non
101101
# reference dimensionality
102102
if (len(dim) != 1 or list(dim.values())[0] != 1 or not isinstance(list(dim.keys())[0],
103103
pq.UnitTime)):
104-
ValueError("Unit {} has dimensions {}, not [time]".format(units, dim.simplified))
104+
ValueError(f"Unit {units} has dimensions {dim.simplified}, not [time].")
105105

106106
obj = pq.Quantity(times, units=dim).view(cls)
107107
obj._labels = labels
@@ -204,7 +204,7 @@ def merge(self, other):
204204
if attr_self == attr_other:
205205
kwargs[name] = attr_self
206206
else:
207-
kwargs[name] = "merge({}, {})".format(attr_self, attr_other)
207+
kwargs[name] = f"merge({attr_self}, {attr_other})"
208208

209209
print('Event: merge annotations')
210210
merged_annotations = merge_annotations(self.annotations, other.annotations)
@@ -244,8 +244,8 @@ def __getitem__(self, i):
244244

245245
def set_labels(self, labels):
246246
if self.labels is not None and self.labels.size > 0 and len(labels) != self.size:
247-
raise ValueError("Labels array has different length to times ({} != {})"
248-
.format(len(labels), self.size))
247+
raise ValueError(f"Labels array has different length to times "
248+
f"({len(labels)} != {self.size})")
249249
self._labels = np.array(labels)
250250

251251
def get_labels(self):
@@ -353,13 +353,13 @@ def to_epoch(self, pairwise=False, durations=None):
353353
times = self.times[::2]
354354
durations = self.times[1::2] - times
355355
labels = np.array(
356-
["{}-{}".format(a, b) for a, b in zip(self.labels[::2], self.labels[1::2])])
356+
[f"{a}-{b}" for a, b in zip(self.labels[::2], self.labels[1::2])])
357357
elif durations is None:
358358
# Mode 1
359359
times = self.times[:-1]
360360
durations = np.diff(self.times)
361361
labels = np.array(
362-
["{}-{}".format(a, b) for a, b in zip(self.labels[:-1], self.labels[1:])])
362+
[f"{a}-{b}" for a, b in zip(self.labels[:-1], self.labels[1:])])
363363
else:
364364
# Mode 3
365365
times = self.times

neo/core/group.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Group(Container):
5353
'Event', 'Epoch', 'ChannelView', 'ImageSequence', 'CircularRegionOfInterest',
5454
'RectangularRegionOfInterest', 'PolygonRegionOfInterest'
5555
)
56-
_container_child_objects = ('Segment', 'Group')
56+
_container_child_objects = ('Group',)
5757
_parent_objects = ('Block',)
5858

5959
def __init__(self, objects=None, name=None, description=None, file_origin=None,
@@ -150,8 +150,8 @@ def add(self, *objects):
150150
"""Add a new Neo object to the Group"""
151151
for obj in objects:
152152
if self.allowed_types and not isinstance(obj, self.allowed_types):
153-
raise TypeError("This Group can only contain {}, but not {}"
154-
"".format(self.allowed_types, type(obj)))
153+
raise TypeError(f"This Group can only contain {self.allowed_types}, "
154+
f"but not {type(obj)}")
155155
super().add(*objects)
156156

157157
def walk(self):

neo/core/imagesequence.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -188,25 +188,19 @@ def _repr_pretty_(self, pp, cycle):
188188
Handle pretty-printing the :class:`ImageSequence`.
189189
"""
190190
pp.text(
191-
"{cls} {nframe} frames with width {width} px and height {height} px; "
192-
"units {units}; datatype {dtype} ".format(
193-
cls=self.__class__.__name__,
194-
nframe=self.shape[0],
195-
height=self.shape[1],
196-
width=self.shape[2],
197-
units=self.units.dimensionality.string,
198-
dtype=self.dtype,
191+
f"{self.__class__.__name__} {self.shape[0]} frames with "
192+
f"width {self.shape[2]} px and height {self.shape[1]} px; "
193+
f"units {self.units.dimensionality.string}; datatype {self.dtype} "
199194
)
200-
)
201195

202196
def _pp(line):
203197
pp.breakable()
204198
with pp.group(indent=1):
205199
pp.text(line)
206200

207201
for line in [
208-
"sampling rate: {!s}".format(self.sampling_rate),
209-
"spatial_scale: {!s}".format(self.spatial_scale),
202+
f"sampling rate: {self.sampling_rate}",
203+
f"spatial_scale: {self.spatial_scale}"
210204
]:
211205
_pp(line)
212206

0 commit comments

Comments
 (0)