@@ -236,105 +236,17 @@ def scan_files(dirname):
236236 info_list = []
237237
238238 for root , dirs , files in os .walk (dirname ):
239-
240239 for file in files :
241240 if not file .endswith ('.meta' ):
242241 continue
243242 meta_filename = Path (root ) / file
244- bin_filename = Path ( root ) / file . replace ( '.meta' , '.bin' )
243+ bin_filename = meta_filename . with_suffix ( '.bin' )
245244 if meta_filename .exists () and bin_filename .exists ():
246245 meta = read_meta_file (meta_filename )
247- else :
248- continue
249-
250- num_chan = int (meta ['nSavedChans' ])
251-
252- # Example file name structure:
253- # Consider the filenames: `Noise4Sam_g0_t0.nidq.bin` or `Noise4Sam_g0_t0.imec0.lf.bin`
254- # The filenames consist of 3 or 4 parts separated by `.`
255- # 1. "Noise4Sam_g0_t0" will be the `name` variable. This choosen by the user
256- # at recording time.
257- # 2. "_gt0_" will give the `seg_index` (here 0)
258- # 3. "nidq" or "imec0" will give the `device` variable
259- # 4. "lf" or "ap" will be the `signal_kind` variable
260- # `stream_name` variable is the concatenation of `device.signal_kind`
261- name = file .split ('.' )[0 ]
262- r = re .findall (r'_g(\d*)_t' , name )
263- seg_index = int (r [0 ][0 ])
264- device = file .split ('.' )[1 ]
265- if 'imec' in device :
266- signal_kind = file .split ('.' )[2 ]
267- stream_name = device + '.' + signal_kind
268- units = 'uV'
269- # please note the 1e6 in gain for this uV
270-
271- # metad['imroTbl'] contain two gain per channel AP and LF
272- # except for the last fake channel
273- per_channel_gain = np .ones (num_chan , dtype = 'float64' )
274- if 'imDatPrb_type' not in meta or meta ['imDatPrb_type' ] == '0' :
275- # This work with NP 1.0 case with different metadata versions
276- # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_3A.md#imec
277- # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_3B1.md#imec
278- # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_3B2.md#imec
279- if signal_kind == 'ap' :
280- index_imroTbl = 3
281- elif signal_kind == 'lf' :
282- index_imroTbl = 4
283- for c in range (num_chan - 1 ):
284- v = meta ['imroTbl' ][c ].split (' ' )[index_imroTbl ]
285- per_channel_gain [c ] = 1. / float (v )
286- gain_factor = float (meta ['imAiRangeMax' ]) / 512
287- channel_gains = gain_factor * per_channel_gain * 1e6
288- elif meta ['imDatPrb_type' ] in ('21' , '24' ) and signal_kind == 'ap' :
289- # This work with NP 2.0 case with different metadata versions
290- # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_20.md#channel-entries-by-type
291- # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_20.md#imec
292- # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_30.md#imec
293- per_channel_gain [:- 1 ] = 1 / 80.
294- gain_factor = float (meta ['imAiRangeMax' ]) / 8192
295- channel_gains = gain_factor * per_channel_gain * 1e6
296- else :
297- raise NotImplementedError ('This meta file version of spikeglx'
298- 'is not implemented' )
299- else :
300- signal_kind = ''
301- stream_name = device
302- units = 'V'
303- channel_gains = np .ones (num_chan )
304-
305- # there are differents kinds of channels with different gain values
306- mn , ma , xa , dw = [int (e ) for e in meta ['snsMnMaXaDw' ].split (sep = ',' )]
307- per_channel_gain = np .ones (num_chan , dtype = 'float64' )
308- per_channel_gain [0 :mn ] = 1. / float (meta ['niMNGain' ])
309- per_channel_gain [mn :mn + ma ] = 1. / float (meta ['niMAGain' ])
310- # this scaling come from the code in this zip
311- # https://billkarsh.github.io/SpikeGLX/Support/SpikeGLX_Datafile_Tools.zip
312- # in file readSGLX.py line76
313- # this is equivalent of 2**15
314- gain_factor = float (meta ['niAiRangeMax' ]) / 32768
315- channel_gains = per_channel_gain * gain_factor
316-
317- info = {}
318- info ['name' ] = name
319- info ['meta' ] = meta
320- info ['meta_file' ] = str (meta_filename )
321- info ['bin_file' ] = str (bin_filename )
322- for k in ('niSampRate' , 'imSampRate' ):
323- if k in meta :
324- info ['sampling_rate' ] = float (meta [k ])
325- info ['num_chan' ] = num_chan
326-
327- info ['sample_length' ] = int (meta ['fileSizeBytes' ]) // 2 // num_chan
328- info ['seg_index' ] = seg_index
329- info ['device' ] = device
330- info ['signal_kind' ] = signal_kind
331- info ['stream_name' ] = stream_name
332- info ['units' ] = units
333- info ['channel_names' ] = [txt .split (';' )[0 ] for txt in meta ['snsChanMap' ]]
334- info ['channel_gains' ] = channel_gains
335- info ['channel_offsets' ] = np .zeros (info ['num_chan' ])
336-
337- info_list .append (info )
246+ info = extract_stream_info (meta_filename , meta )
247+ info ['meta_file' ] = str (meta_filename )
248+ info ['bin_file' ] = str (bin_filename )
249+ info_list .append (info )
338250
339251 return info_list
340252
@@ -344,7 +256,7 @@ def read_meta_file(meta_file):
344256 with open (meta_file , mode = 'r' ) as f :
345257 lines = f .read ().splitlines ()
346258
347- info = {}
259+ meta = {}
348260 # Fix taken from: https://github.com/SpikeInterface/probeinterface/blob/
349261 # 19d6518fbc67daca71aba5e99d8aa0d445b75eb7/probeinterface/io.py#L649-L662
350262 for line in lines :
@@ -356,6 +268,103 @@ def read_meta_file(meta_file):
356268 # replace by the list
357269 k = k [1 :]
358270 v = v [1 :- 1 ].split (')(' )[1 :]
359- info [k ] = v
271+ meta [k ] = v
272+
273+ return meta
274+
275+
276+ def extract_stream_info (meta_file , meta ):
277+ """Extract info from the meta dict"""
278+
279+ num_chan = int (meta ['nSavedChans' ])
280+
281+ # Example file name structure:
282+ # Consider the filenames: `Noise4Sam_g0_t0.nidq.bin` or `Noise4Sam_g0_t0.imec0.lf.bin`
283+ # The filenames consist of 3 or 4 parts separated by `.`
284+ # 1. "Noise4Sam_g0_t0" will be the `name` variable. This choosen by the user
285+ # at recording time.
286+ # 2. "_gt0_" will give the `seg_index` (here 0)
287+ # 3. "nidq" or "imec0" will give the `device` variable
288+ # 4. "lf" or "ap" will be the `signal_kind` variable
289+ # `stream_name` variable is the concatenation of `device.signal_kind`
290+ name = Path (meta_file ).stem
291+ r = re .findall (r'_g(\d*)_t' , name )
292+ if len (r ) == 0 :
293+ # when manual renaming _g0_ can be removed
294+ seg_index = 0
295+ else :
296+ seg_index = int (r [0 ][0 ])
297+ device = name .split ('.' )[1 ]
298+ if 'imec' in device :
299+ signal_kind = name .split ('.' )[2 ]
300+ stream_name = device + '.' + signal_kind
301+ units = 'uV'
302+ # please note the 1e6 in gain for this uV
303+
304+ # metad['imroTbl'] contain two gain per channel AP and LF
305+ # except for the last fake channel
306+ per_channel_gain = np .ones (num_chan , dtype = 'float64' )
307+ if 'imDatPrb_type' not in meta or meta ['imDatPrb_type' ] == '0' :
308+ # This work with NP 1.0 case with different metadata versions
309+ # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_3A.md#imec
310+ # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_3B1.md#imec
311+ # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_3B2.md#imec
312+ if signal_kind == 'ap' :
313+ index_imroTbl = 3
314+ elif signal_kind == 'lf' :
315+ index_imroTbl = 4
316+ for c in range (num_chan - 1 ):
317+ v = meta ['imroTbl' ][c ].split (' ' )[index_imroTbl ]
318+ per_channel_gain [c ] = 1. / float (v )
319+ gain_factor = float (meta ['imAiRangeMax' ]) / 512
320+ channel_gains = gain_factor * per_channel_gain * 1e6
321+ elif meta ['imDatPrb_type' ] in ('21' , '24' ) and signal_kind == 'ap' :
322+ # This work with NP 2.0 case with different metadata versions
323+ # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_20.md#channel-entries-by-type
324+ # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_20.md#imec
325+ # https://github.com/billkarsh/SpikeGLX/blob/gh-pages/Support/Metadata_30.md#imec
326+ per_channel_gain [:- 1 ] = 1 / 80.
327+ gain_factor = float (meta ['imAiRangeMax' ]) / 8192
328+ channel_gains = gain_factor * per_channel_gain * 1e6
329+ else :
330+ raise NotImplementedError ('This meta file version of spikeglx'
331+ 'is not implemented' )
332+ else :
333+ signal_kind = ''
334+ stream_name = device
335+ units = 'V'
336+ channel_gains = np .ones (num_chan )
337+
338+ # there are differents kinds of channels with different gain values
339+ mn , ma , xa , dw = [int (e ) for e in meta ['snsMnMaXaDw' ].split (sep = ',' )]
340+ per_channel_gain = np .ones (num_chan , dtype = 'float64' )
341+ per_channel_gain [0 :mn ] = 1. / float (meta ['niMNGain' ])
342+ per_channel_gain [mn :mn + ma ] = 1. / float (meta ['niMAGain' ])
343+ # this scaling come from the code in this zip
344+ # https://billkarsh.github.io/SpikeGLX/Support/SpikeGLX_Datafile_Tools.zip
345+ # in file readSGLX.py line76
346+ # this is equivalent of 2**15
347+ gain_factor = float (meta ['niAiRangeMax' ]) / 32768
348+ channel_gains = per_channel_gain * gain_factor
349+
350+ info = {}
351+ info ['name' ] = name
352+ info ['meta' ] = meta
353+ for k in ('niSampRate' , 'imSampRate' ):
354+ if k in meta :
355+ info ['sampling_rate' ] = float (meta [k ])
356+ info ['num_chan' ] = num_chan
357+
358+ info ['sample_length' ] = int (meta ['fileSizeBytes' ]) // 2 // num_chan
359+ info ['seg_index' ] = seg_index
360+ info ['device' ] = device
361+ info ['signal_kind' ] = signal_kind
362+ info ['stream_name' ] = stream_name
363+ info ['units' ] = units
364+ info ['channel_names' ] = [txt .split (';' )[0 ] for txt in meta ['snsChanMap' ]]
365+ info ['channel_gains' ] = channel_gains
366+ info ['channel_offsets' ] = np .zeros (info ['num_chan' ])
360367
361368 return info
369+
370+
0 commit comments