Skip to content

Commit 9edcc8c

Browse files
committed
more asserts -> errors
1 parent 99079ff commit 9edcc8c

File tree

8 files changed

+98
-60
lines changed

8 files changed

+98
-60
lines changed

neo/core/baseneo.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@ class MergeError(Exception):
3535
pass
3636

3737
class NeoReadWriteError(IOError):
38+
"""
39+
This is the main neo-specific error that has to deal with
40+
ephys data that does not follow the requirements for the Neo
41+
object hierarchy.
42+
43+
It should be used for:
44+
1) When an IO does not support a specific read/write functionality
45+
2) A file format does not support the structural requirements
46+
* Different sampling rates among streams
47+
* Different expectations for a file format (could also be
48+
a NotImplementedError depending on circumstances)
49+
50+
It should NOT be used when other errors more accurately describe
51+
the problem:
52+
1) ValueError: for incorrect values (like t_start, t_stop)
53+
2) TypeError: use of an inappropriate type for an argument
54+
3) FileNotFoundError: for use when a file is not found
55+
"""
3856
pass
3957

4058

neo/io/baseio.py

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
RectangularRegionOfInterest,
3636
CircularRegionOfInterest,
3737
PolygonRegionOfInterest,
38+
NeoReadWriteError
3839
)
3940

4041
read_error = "This type is not supported by this file format for reading"
@@ -139,7 +140,7 @@ def read(self, lazy: bool = False, **kargs):
139140
Returns all the data from the file as Blocks
140141
"""
141142
if lazy and not self.support_lazy:
142-
raise ValueError("This IO module does not support lazy loading")
143+
raise NeoReadWriteError("This IO module does not support lazy loading")
143144
if Block in self.readable_objects:
144145
if hasattr(self, "read_all_blocks") and callable(getattr(self, "read_all_blocks")):
145146
return self.read_all_blocks(lazy=lazy, **kargs)
@@ -168,13 +169,13 @@ def write(self, bl, **kargs):
168169
if Block in self.writeable_objects:
169170
if isinstance(bl, Sequence):
170171
if not hasattr(self, "write_all_blocks"):
171-
raise AttributeError(f"{self.__class__.__name__} does not offer to store a sequence of blocks")
172+
raise NeoReadWriteError(f"{self.__class__.__name__} does not offer to store a sequence of blocks")
172173
self.write_all_blocks(bl, **kargs)
173174
else:
174175
self.write_block(bl, **kargs)
175176
elif Segment in self.writeable_objects:
176177
if len(bl.segments) != 1:
177-
raise ValueError(f"{self.__class__.__name__} is based on segment so if you try to write a block it "
178+
raise NeoReadWriteError(f"{self.__class__.__name__} is based on segment so if you try to write a block it "
178179
+ "must contain only one Segment")
179180
self.write_segment(bl.segments[0], **kargs)
180181
else:
@@ -183,105 +184,105 @@ def write(self, bl, **kargs):
183184
######## All individual read methods #######################
184185
def read_block(self, **kargs):
185186
if Block not in self.readable_objects:
186-
raise RuntimeError(read_error)
187+
raise NeoReadWriteError(read_error)
187188

188189
def read_segment(self, **kargs):
189190
if Segment not in self.readable_objects:
190-
raise RuntimeError(read_error)
191+
raise NeoReadWriteError(read_error)
191192

192193
def read_spiketrain(self, **kargs):
193194
if SpikeTrain not in self.readable_objects:
194-
raise RuntimeError(read_error)
195+
raise NeoReadWriteError(read_error)
195196

196197
def read_analogsignal(self, **kargs):
197198
if AnalogSignal not in self.readable_objects:
198-
raise RuntimeError(read_error)
199+
raise NeoReadWriteError(read_error)
199200

200201
def read_imagesequence(self, **kargs):
201202
if ImageSequence not in self.readable_objects:
202-
raise RuntimeError(read_error)
203+
raise NeoReadWriteError(read_error)
203204

204205
def read_rectangularregionofinterest(self, **kargs):
205206
if RectangularRegionOfInterest not in self.readable_objects:
206-
raise RuntimeError(read_error)
207+
raise NeoReadWriteError(read_error)
207208

208209
def read_circularregionofinterest(self, **kargs):
209210
if CircularRegionOfInterest not in self.readable_objects:
210-
raise RuntimeError(read_error)
211+
raise NeoReadWriteError(read_error)
211212

212213
def read_polygonregionofinterest(self, **kargs):
213214
if PolygonRegionOfInterest not in self.readable_objects:
214-
raise RuntimeError(read_error)
215+
raise NeoReadWriteError(read_error)
215216

216217
def read_irregularlysampledsignal(self, **kargs):
217218
if IrregularlySampledSignal not in self.readable_objects:
218-
raise RuntimeError(read_error)
219+
raise NeoReadWriteError(read_error)
219220

220221
def read_channelview(self, **kargs):
221222
if ChannelView not in self.readable_objects:
222-
raise RuntimeError(read_error)
223+
raise NeoReadWriteError(read_error)
223224

224225
def read_event(self, **kargs):
225226
if Event not in self.readable_objects:
226-
raise RuntimeError(read_error)
227+
raise NeoReadWriteError(read_error)
227228

228229
def read_epoch(self, **kargs):
229230
if Epoch not in self.readable_objects:
230-
raise RuntimeError(read_error)
231+
raise NeoReadWriteError(read_error)
231232

232233
def read_group(self, **kargs):
233234
if Group not in self.readable_objects:
234-
raise RuntimeError(read_error)
235+
raise NeoReadWriteError(read_error)
235236

236237
######## All individual write methods #######################
237238
def write_block(self, bl, **kargs):
238239
if Block not in self.writeable_objects:
239-
raise RuntimeError(write_error)
240+
raise NeoReadWriteError(write_error)
240241

241242
def write_segment(self, seg, **kargs):
242243
if Segment not in self.writeable_objects:
243-
raise RuntimeError(write_error)
244+
raise NeoReadWriteError(write_error)
244245

245246
def write_spiketrain(self, sptr, **kargs):
246247
if SpikeTrain not in self.writeable_objects:
247-
raise RuntimeError(write_error)
248+
raise NeoReadWriteError(write_error)
248249

249250
def write_analogsignal(self, anasig, **kargs):
250251
if AnalogSignal not in self.writeable_objects:
251-
raise RuntimeError(write_error)
252+
raise NeoReadWriteError(write_error)
252253

253254
def write_imagesequence(self, imseq, **kargs):
254255
if ImageSequence not in self.writeable_objects:
255-
raise RuntimeError(write_error)
256+
raise NeoReadWriteError(write_error)
256257

257258
def write_rectangularregionofinterest(self, rectroi, **kargs):
258259
if RectangularRegionOfInterest not in self.writeable_objects:
259-
raise RuntimeError(write_error)
260+
raise NeoReadWriteError(write_error)
260261

261262
def write_circularregionofinterest(self, circroi, **kargs):
262263
if CircularRegionOfInterest not in self.writeable_objects:
263-
raise RuntimeError(write_error)
264+
raise NeoReadWriteError(write_error)
264265

265266
def write_polygonregionofinterest(self, polyroi, **kargs):
266267
if PolygonRegionOfInterest not in self.writeable_objects:
267-
raise RuntimeError(write_error)
268+
raise NeoReadWriteError(write_error)
268269

269270
def write_irregularlysampledsignal(self, irsig, **kargs):
270271
if IrregularlySampledSignal not in self.writeable_objects:
271-
raise RuntimeError(write_error)
272+
raise NeoReadWriteError(write_error)
272273

273274
def write_channelview(self, chv, **kargs):
274275
if ChannelView not in self.writeable_objects:
275-
raise RuntimeError(write_error)
276+
raise NeoReadWriteError(write_error)
276277

277278
def write_event(self, ev, **kargs):
278279
if Event not in self.writeable_objects:
279-
raise RuntimeError(write_error)
280+
raise NeoReadWriteError(write_error)
280281

281282
def write_epoch(self, ep, **kargs):
282283
if Epoch not in self.writeable_objects:
283-
raise RuntimeError(write_error)
284+
raise NeoReadWriteError(write_error)
284285

285286
def write_group(self, group, **kargs):
286287
if Group not in self.writeable_objects:
287-
raise RuntimeError(write_error)
288+
raise NeoReadWriteError(write_error)

neo/io/igorproio.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import pathlib
1616
import quantities as pq
1717
from neo.io.baseio import BaseIO
18-
from neo.core import Block, Segment, AnalogSignal
18+
from neo.core import Block, Segment, AnalogSignal, NeoReadWriteError
1919

2020

2121
class IgorIO(BaseIO):
@@ -59,14 +59,16 @@ def __init__(self, filename=None, parse_notes=None):
5959
"""
6060
BaseIO.__init__(self)
6161
filename = pathlib.Path(filename)
62-
assert filename.suffix[1:] in self.extensions, f"Only the following extensions are supported: {self.extensions}"
62+
if filename.suffix[1:] not in self.extensions:
63+
raise NotImplementedError(f"Only the following extensions are supported: {self.extensions}")
6364
self.filename = filename
6465
self.extension = filename.suffix[1:]
6566
self.parse_notes = parse_notes
6667
self._filesystem = None
6768

6869
def read_block(self, lazy=False):
69-
assert not lazy, "This IO does not support lazy mode"
70+
if lazy:
71+
raise NeoReadWriteError("This IO does not support lazy reading")
7072

7173
block = Block(file_origin=str(self.filename))
7274
block.segments.append(self.read_segment(lazy=lazy))
@@ -76,7 +78,8 @@ def read_segment(self, lazy=False):
7678
import igor2.packed as pxp
7779
from igor2.record.wave import WaveRecord
7880

79-
assert not lazy, "This IO does not support lazy mode"
81+
if lazy:
82+
raise NeoReadWriteError("This IO does not support lazy mode")
8083
segment = Segment(file_origin=str(self.filename))
8184

8285
if self.extension == "pxp":
@@ -97,15 +100,17 @@ def read_analogsignal(self, path=None, lazy=False):
97100
import igor2.binarywave as bw
98101
import igor2.packed as pxp
99102

100-
assert not lazy, "This IO does not support lazy mode"
103+
if lazy:
104+
raise NeoReadWriteError("This IO does not support lazy mode")
101105

102106
if self.extension == "ibw":
103107
data = bw.load(str(self.filename))
104108
version = data["version"]
105109
if version > 5:
106110
raise IOError(f"Igor binary wave file format version {version} " "is not supported.")
107111
elif self.extension == "pxp":
108-
assert type(path) is str, "A colon-separated Igor-style path must be provided."
112+
if type(path) is not str:
113+
raise TypeError("A colon-separated Igor-style path must be provided.")
109114
if not self._filesystem:
110115
_, self.filesystem = pxp.load(str(self.filename))
111116
path = path.split(":")
@@ -119,24 +124,23 @@ def read_analogsignal(self, path=None, lazy=False):
119124

120125
def _wave_to_analogsignal(self, content, dirpath):
121126
if "padding" in content:
122-
assert content["padding"].size == 0, "Cannot handle non-empty padding"
127+
if content["padding"].size != 0:
128+
raise NeoReadWriteError("Cannot handle non-empty padding")
123129
signal = content["wData"]
124130
note = content["note"]
125131
header = content["wave_header"]
126132
name = str(header["bname"].decode("utf-8"))
127133
units = "".join([x.decode() for x in header["dataUnits"]])
128-
try:
129-
time_units = "".join([x.decode() for x in header["xUnits"]])
130-
assert len(time_units)
131-
except:
134+
time_units = "".join([x.decode() for x in header["xUnits"]])
135+
if len(time_units) == 0:
132136
time_units = "s"
133137
try:
134138
t_start = pq.Quantity(header["hsB"], time_units)
135139
except KeyError:
136140
t_start = pq.Quantity(header["sfB"][0], time_units)
137141
try:
138142
sampling_period = pq.Quantity(header["hsA"], time_units)
139-
except:
143+
except KeyError:
140144
sampling_period = pq.Quantity(header["sfA"][0], time_units)
141145
if self.parse_notes:
142146
try:

neo/io/rawbinarysignalio.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import quantities as pq
1717

1818
from neo.io.baseio import BaseIO
19-
from neo.core import Segment, AnalogSignal
19+
from neo.core import Segment, AnalogSignal, NeoReadWriteError
2020

2121
from neo.io.basefromrawio import BaseFromRaw
2222
from neo.rawio.rawbinarysignalrawio import RawBinarySignalRawIO
@@ -88,19 +88,24 @@ def write_segment(self, segment):
8888
raise NotImplementedError("bytesoffset values other than 0 " + "not supported")
8989

9090
anasigs = segment.analogsignals
91-
assert len(anasigs) > 0, "No AnalogSignal"
91+
if len(anasigs) == 0:
92+
raise NeoReadWriteError("No AnalogSignal to write")
9293

9394
anasig0 = anasigs[0]
9495
if len(anasigs) == 1 and anasig0.ndim == 2:
9596
numpy_sigs = anasig0.magnitude
9697
else:
9798

98-
assert anasig0.ndim == 1 or (anasig0.ndim == 2 and anasig0.shape[1] == 1)
99+
if anasig0.ndim != 1 and (anasig0.ndim == 2 and anasig0.shape[1] != 1):
100+
raise NeoReadWriteError("Incorrect analogsignal shaping for write")
99101
# all AnaologSignal from Segment must have the same length/sampling_rate/dtype
100102
for anasig in anasigs[1:]:
101-
assert anasig.shape == anasig0.shape
102-
assert anasig.sampling_rate == anasig0.sampling_rate
103-
assert anasig.dtype == anasig0.dtype
103+
if anasig.shape != anasig0.shape:
104+
raise ValueError("The shape of one of the analog signals does not match")
105+
if anasig.sampling_rate != anasig0.sampling_rate:
106+
raise ValueError("The sampling_rate of one of the analog signals does not match")
107+
if anasig.dtype != anasig0.dtype:
108+
raise ValueError("The dtype of one the analog signals does not match")
104109

105110
numpy_sigs = np.empty((anasig0.size, len(anasigs)))
106111
for i, anasig in enumerate(anasigs):

neo/rawio/micromedrawio.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
_event_channel_dtype,
1616
)
1717

18+
from neo.core import NeoReadWriteError
19+
1820
import numpy as np
1921

2022
import datetime
@@ -64,7 +66,8 @@ def _parse_header(self):
6466

6567
# header version
6668
(header_version,) = f.read_f("b", offset=175)
67-
assert header_version == 4
69+
if header_version != 4:
70+
raise NotImplementedError(f"`header_version {header_version} is not implemented in neo yet")
6871

6972
# area
7073
f.seek(176)
@@ -89,7 +92,8 @@ def _parse_header(self):
8992
for zname in zone_names:
9093
zname2, pos, length = f.read_f("8sII")
9194
zones[zname] = zname2, pos, length
92-
assert zname == zname2.decode("ascii").strip(" ")
95+
if zname != zname2.decode("ascii").strip(" "):
96+
raise NeoReadWriteError("expected the zone name to match")
9397

9498
# raw signals memmap
9599
sig_dtype = "u" + str(Bytes)
@@ -131,7 +135,8 @@ def _parse_header(self):
131135

132136
signal_streams = np.array([("Signals", "0")], dtype=_signal_stream_dtype)
133137

134-
assert np.unique(signal_channels["sampling_rate"]).size == 1
138+
if np.unique(signal_channels["sampling_rate"]).size != 1:
139+
raise NeoReadWriteError("The sampling rates must be the same across signal channels")
135140
self._sampling_rate = float(np.unique(signal_channels["sampling_rate"])[0])
136141

137142
# Event channels
@@ -201,11 +206,13 @@ def _segment_t_stop(self, block_index, seg_index):
201206
return t_stop
202207

203208
def _get_signal_size(self, block_index, seg_index, stream_index):
204-
assert stream_index == 0
209+
if stream_index != 0:
210+
raise ValueError("`stream_index` must be 0")
205211
return self._raw_signals.shape[0]
206212

207213
def _get_signal_t_start(self, block_index, seg_index, stream_index):
208-
assert stream_index == 0
214+
if stream_index != 0:
215+
raise ValueError("`stream_index` must be 0")
209216
return 0.0
210217

211218
def _get_analogsignal_chunk(self, block_index, seg_index, i_start, i_stop, stream_index, channel_indexes):

0 commit comments

Comments
 (0)