4
4
See:
5
5
https://www.3brain.com/products/single-well/biocam-x
6
6
7
- Author : Alessio Buccino
7
+ Authors : Alessio Buccino, Robert Wolff
8
8
"""
9
9
10
10
from .baserawio import (BaseRawIO , _signal_channel_dtype , _signal_stream_dtype ,
11
11
_spike_channel_dtype , _event_channel_dtype )
12
12
13
13
import numpy as np
14
+ import json
14
15
15
16
16
17
@@ -118,51 +119,88 @@ def open_biocam_file_header(filename):
118
119
import h5py
119
120
120
121
rf = h5py .File (filename , 'r' )
121
- # Read recording variables
122
- rec_vars = rf .require_group ('3BRecInfo/3BRecVars/' )
123
- bit_depth = rec_vars ['BitDepth' ][0 ]
124
- max_uv = rec_vars ['MaxVolt' ][0 ]
125
- min_uv = rec_vars ['MinVolt' ][0 ]
126
- n_frames = rec_vars ['NRecFrames' ][0 ]
127
- sampling_rate = rec_vars ['SamplingRate' ][0 ]
128
- signal_inv = rec_vars ['SignalInversion' ][0 ]
129
-
130
- # Get the actual number of channels used in the recording
131
- file_format = rf ['3BData' ].attrs .get ('Version' , None )
132
- format_100 = False
133
- if file_format == 100 :
134
- n_channels = len (rf ['3BData/Raw' ][0 ])
135
- format_100 = True
136
- elif file_format in (101 , 102 ) or file_format is None :
137
- n_channels = int (rf ['3BData/Raw' ].shape [0 ] / n_frames )
138
- else :
139
- raise Exception ('Unknown data file format.' )
140
-
141
- # # get channels
142
- channels = rf ['3BRecInfo/3BMeaStreams/Raw/Chs' ][:]
143
-
144
- # determine correct function to read data
145
- if format_100 :
146
- if signal_inv == 1 :
147
- read_function = readHDF5t_100
148
- elif signal_inv == 1 :
149
- read_function = readHDF5t_100_i
122
+
123
+ if '3BRecInfo' in rf .keys (): # brw v3.x
124
+ # Read recording variables
125
+ rec_vars = rf .require_group ('3BRecInfo/3BRecVars/' )
126
+ bit_depth = rec_vars ['BitDepth' ][0 ]
127
+ max_uv = rec_vars ['MaxVolt' ][0 ]
128
+ min_uv = rec_vars ['MinVolt' ][0 ]
129
+ num_frames = rec_vars ['NRecFrames' ][0 ]
130
+ sampling_rate = rec_vars ['SamplingRate' ][0 ]
131
+ signal_inv = rec_vars ['SignalInversion' ][0 ]
132
+
133
+ # Get the actual number of channels used in the recording
134
+ file_format = rf ['3BData' ].attrs .get ('Version' , None )
135
+ format_100 = False
136
+ if file_format == 100 :
137
+ num_channels = len (rf ['3BData/Raw' ][0 ])
138
+ format_100 = True
139
+ elif file_format in (101 , 102 ) or file_format is None :
140
+ num_channels = int (rf ['3BData/Raw' ].shape [0 ] / num_frames )
150
141
else :
151
- raise Exception ("Unknown signal inversion" )
152
- else :
153
- if signal_inv == 1 :
154
- read_function = readHDF5t_101
155
- elif signal_inv == 1 :
156
- read_function = readHDF5t_101_i
142
+ raise Exception ('Unknown data file format.' )
143
+
144
+ # # get channels
145
+ channels = rf ['3BRecInfo/3BMeaStreams/Raw/Chs' ][:]
146
+
147
+ # determine correct function to read data
148
+ if format_100 :
149
+ if signal_inv == 1 :
150
+ read_function = readHDF5t_100
151
+ elif signal_inv == 1 :
152
+ read_function = readHDF5t_100_i
153
+ else :
154
+ raise Exception ("Unknown signal inversion" )
157
155
else :
158
- raise Exception ("Unknown signal inversion" )
159
-
160
- gain = (max_uv - min_uv ) / (2 ** bit_depth )
161
- offset = min_uv
162
-
163
- return dict (file_handle = rf , num_frames = n_frames , sampling_rate = sampling_rate , num_channels = n_channels ,
164
- channels = channels , file_format = file_format , signal_inv = signal_inv ,
165
- read_function = read_function , gain = gain , offset = offset )
156
+ if signal_inv == 1 :
157
+ read_function = readHDF5t_101
158
+ elif signal_inv == 1 :
159
+ read_function = readHDF5t_101_i
160
+ else :
161
+ raise Exception ("Unknown signal inversion" )
162
+
163
+ gain = (max_uv - min_uv ) / (2 ** bit_depth )
164
+ offset = min_uv
165
+
166
+ return dict (file_handle = rf , num_frames = num_frames , sampling_rate = sampling_rate ,
167
+ num_channels = num_channels , channels = channels , file_format = file_format ,
168
+ signal_inv = signal_inv , read_function = read_function , gain = gain , offset = offset )
169
+ else : # brw v4.x
170
+ # Read recording variables
171
+ experiment_settings = json .JSONDecoder ().decode (rf ['ExperimentSettings' ][0 ].decode ())
172
+ max_uv = experiment_settings ['ValueConverter' ]['MaxAnalogValue' ]
173
+ min_uv = experiment_settings ['ValueConverter' ]['MinAnalogValue' ]
174
+ max_digital = experiment_settings ['ValueConverter' ]['MaxDigitalValue' ]
175
+ min_digital = experiment_settings ['ValueConverter' ]['MinDigitalValue' ]
176
+ scale_factor = experiment_settings ['ValueConverter' ]['ScaleFactor' ]
177
+ sampling_rate = experiment_settings ['TimeConverter' ]['FrameRate' ]
178
+
179
+ for key in rf :
180
+ if key [:5 ] == 'Well_' :
181
+ num_channels = len (rf [key ]['StoredChIdxs' ])
182
+ if len (rf [key ]['Raw' ]) % num_channels :
183
+ raise RuntimeError (
184
+ f"Length of raw data array is not multiple of channel number in { key } " )
185
+ num_frames = len (rf [key ]['Raw' ]) // num_channels
186
+ break
187
+ try :
188
+ num_channels_x = num_channels_y = int (np .sqrt (num_channels ))
189
+ except NameError :
190
+ raise RuntimeError ("No Well found in the file" )
191
+ if num_channels_x * num_channels_y != num_channels :
192
+ raise RuntimeError (
193
+ f'Cannot determine structure of the MEA plate with { num_channels } channels' )
194
+ channels = 1 + np .concatenate (np .transpose (np .meshgrid (
195
+ range (num_channels_x ), range (num_channels_y ))))
196
+
197
+ gain = scale_factor * (max_uv - min_uv ) / (max_digital - min_digital )
198
+ offset = min_uv
199
+ read_function = readHDF5t_brw4
200
+
201
+ return dict (file_handle = rf , num_frames = num_frames , sampling_rate = sampling_rate ,
202
+ num_channels = num_channels , channels = channels , read_function = read_function ,
203
+ gain = gain , offset = offset )
166
204
167
205
168
206
def readHDF5t_100 (rf , t0 , t1 , nch ):
@@ -179,3 +217,9 @@ def readHDF5t_101(rf, t0, t1, nch):
179
217
180
218
def readHDF5t_101_i (rf , t0 , t1 , nch ):
181
219
return 4096 - rf ['3BData/Raw' ][nch * t0 :nch * t1 ].reshape ((t1 - t0 , nch ), order = 'C' )
220
+
221
+
222
+ def readHDF5t_brw4 (rf , t0 , t1 , nch ):
223
+ for key in rf :
224
+ if key [:5 ] == 'Well_' :
225
+ return rf [key ]['Raw' ][nch * t0 :nch * t1 ].reshape ((t1 - t0 , nch ), order = 'C' )
0 commit comments