17
17
_spike_channel_dtype ,
18
18
_event_channel_dtype ,
19
19
)
20
+ from neo .core import NeoReadWriteError
20
21
21
22
22
23
class BiocamRawIO (BaseRawIO ):
@@ -122,15 +123,45 @@ def _get_analogsignal_chunk(self, block_index, seg_index, i_start, i_stop, strea
122
123
i_start = 0
123
124
if i_stop is None :
124
125
i_stop = self ._num_frames
125
- if channel_indexes is None :
126
- channel_indexes = slice ( None )
126
+
127
+ # read functions are different based on the version of biocam
127
128
data = self ._read_function (self ._filehandle , i_start , i_stop , self ._num_channels )
128
- return data [:, channel_indexes ]
129
+
130
+ # older style data returns array of (n_samples, n_channels), should be a view
131
+ # but if memory issues come up we should doublecheck out how the file is being stored
132
+ if data .ndim > 1 :
133
+ if channel_indexes is None :
134
+ channel_indexes = slice (None )
135
+ sig_chunk = data [:, channel_indexes ]
136
+
137
+ # newer style data returns an initial flat array (n_samples * n_channels)
138
+ # we iterate through channels rather than slicing
139
+ else :
140
+ if channel_indexes is None :
141
+ channel_indexes = [ch for ch in range (self ._num_channels )]
142
+
143
+ sig_chunk = np .zeros ((i_stop - i_start , len (channel_indexes )))
144
+ # iterate through channels to prevent loading all channels into memory which can cause
145
+ # memory exhaustion. See https://github.com/SpikeInterface/spikeinterface/issues/3303
146
+ for index , channel_index in enumerate (channel_indexes ):
147
+ sig_chunk [:, index ] = data [channel_index ::self ._num_channels ]
148
+
149
+ return sig_chunk
129
150
130
151
131
- def open_biocam_file_header (filename ):
152
+ def open_biocam_file_header (filename )-> dict :
132
153
"""Open a Biocam hdf5 file, read and return the recording info, pick the correct method to access raw data,
133
- and return this to the caller."""
154
+ and return this to the caller
155
+
156
+ Parameters
157
+ ----------
158
+ filename: str
159
+ The file to be parsed
160
+
161
+ Returns
162
+ -------
163
+ dict
164
+ The information necessary to read a biocam file (gain, n_samples, n_channels, etc)."""
134
165
import h5py
135
166
136
167
rf = h5py .File (filename , "r" )
@@ -154,9 +185,9 @@ def open_biocam_file_header(filename):
154
185
elif file_format in (101 , 102 ) or file_format is None :
155
186
num_channels = int (rf ["3BData/Raw" ].shape [0 ] / num_frames )
156
187
else :
157
- raise Exception ("Unknown data file format." )
188
+ raise NeoReadWriteError ("Unknown data file format." )
158
189
159
- # # get channels
190
+ # get channels
160
191
channels = rf ["3BRecInfo/3BMeaStreams/Raw/Chs" ][:]
161
192
162
193
# determine correct function to read data
@@ -166,14 +197,14 @@ def open_biocam_file_header(filename):
166
197
elif signal_inv == - 1 :
167
198
read_function = readHDF5t_100_i
168
199
else :
169
- raise Exception ("Unknown signal inversion" )
200
+ raise NeoReadWriteError ("Unknown signal inversion" )
170
201
else :
171
202
if signal_inv == 1 :
172
203
read_function = readHDF5t_101
173
204
elif signal_inv == - 1 :
174
205
read_function = readHDF5t_101_i
175
206
else :
176
- raise Exception ("Unknown signal inversion" )
207
+ raise NeoReadWriteError ("Unknown signal inversion" )
177
208
178
209
gain = (max_uv - min_uv ) / (2 ** bit_depth )
179
210
offset = min_uv
@@ -200,19 +231,22 @@ def open_biocam_file_header(filename):
200
231
scale_factor = experiment_settings ["ValueConverter" ]["ScaleFactor" ]
201
232
sampling_rate = experiment_settings ["TimeConverter" ]["FrameRate" ]
202
233
234
+ num_channels = None
203
235
for key in rf :
204
236
if key [:5 ] == "Well_" :
205
237
num_channels = len (rf [key ]["StoredChIdxs" ])
206
238
if len (rf [key ]["Raw" ]) % num_channels :
207
- raise RuntimeError (f"Length of raw data array is not multiple of channel number in { key } " )
239
+ raise NeoReadWriteError (f"Length of raw data array is not multiple of channel number in { key } " )
208
240
num_frames = len (rf [key ]["Raw" ]) // num_channels
209
241
break
210
- try :
242
+
243
+ if num_channels is not None :
211
244
num_channels_x = num_channels_y = int (np .sqrt (num_channels ))
212
- except NameError :
213
- raise RuntimeError ("No Well found in the file" )
245
+ else :
246
+ raise NeoReadWriteError ("No Well found in the file" )
247
+
214
248
if num_channels_x * num_channels_y != num_channels :
215
- raise RuntimeError (f"Cannot determine structure of the MEA plate with { num_channels } channels" )
249
+ raise NeoReadWriteError (f"Cannot determine structure of the MEA plate with { num_channels } channels" )
216
250
channels = 1 + np .concatenate (np .transpose (np .meshgrid (range (num_channels_x ), range (num_channels_y ))))
217
251
218
252
gain = scale_factor * (max_uv - min_uv ) / (max_digital - min_digital )
@@ -231,6 +265,10 @@ def open_biocam_file_header(filename):
231
265
)
232
266
233
267
268
+ ######################################################################
269
+ # Helper functions to obtain the raw data split by Biocam version.
270
+
271
+ # return the full array for the old datasets
234
272
def readHDF5t_100 (rf , t0 , t1 , nch ):
235
273
return rf ["3BData/Raw" ][t0 :t1 ]
236
274
@@ -239,15 +277,16 @@ def readHDF5t_100_i(rf, t0, t1, nch):
239
277
return 4096 - rf ["3BData/Raw" ][t0 :t1 ]
240
278
241
279
280
+ # return flat array that we will iterate through
242
281
def readHDF5t_101 (rf , t0 , t1 , nch ):
243
- return rf ["3BData/Raw" ][nch * t0 : nch * t1 ]. reshape (( t1 - t0 , nch ), order = "C" )
282
+ return rf ["3BData/Raw" ][nch * t0 : nch * t1 ]
244
283
245
284
246
285
def readHDF5t_101_i (rf , t0 , t1 , nch ):
247
- return 4096 - rf ["3BData/Raw" ][nch * t0 : nch * t1 ]. reshape (( t1 - t0 , nch ), order = "C" )
286
+ return 4096 - rf ["3BData/Raw" ][nch * t0 : nch * t1 ]
248
287
249
288
250
289
def readHDF5t_brw4 (rf , t0 , t1 , nch ):
251
290
for key in rf :
252
291
if key [:5 ] == "Well_" :
253
- return rf [key ]["Raw" ][nch * t0 : nch * t1 ]. reshape (( t1 - t0 , nch ), order = "C" )
292
+ return rf [key ]["Raw" ][nch * t0 : nch * t1 ]
0 commit comments