2424
2525import datetime
2626from collections import OrderedDict
27+ import re
2728
2829import numpy as np
2930
@@ -146,7 +147,7 @@ def _parse_header(self):
146147
147148 # Update tqdm with the number of bytes processed in this iteration
148149 if self .progress_bar :
149- progress_bar .update (length )
150+ progress_bar .update (length ) # This was clever, Sam : )
150151
151152 if self .progress_bar :
152153 progress_bar .close ()
@@ -231,6 +232,7 @@ def _parse_header(self):
231232 # signals channels
232233 sig_channels = []
233234 all_sig_length = []
235+ source_id = []
234236 if self .progress_bar :
235237 chan_loop = trange (nb_sig_chan , desc = "Parsing signal channels" , leave = True )
236238 else :
@@ -242,6 +244,7 @@ def _parse_header(self):
242244 length = self ._data_blocks [5 ][chan_id ]["size" ].sum () // 2
243245 if length == 0 :
244246 continue # channel not added
247+ source_id .append (h ["SrcId" ])
245248 all_sig_length .append (length )
246249 sampling_rate = float (h ["ADFreq" ])
247250 sig_dtype = "int16"
@@ -255,7 +258,7 @@ def _parse_header(self):
255258 0.5 * (2 ** global_header ["BitsPerSpikeSample" ]) * h ["Gain" ] * h ["PreampGain" ]
256259 )
257260 offset = 0.0
258- stream_id = "0"
261+ stream_id = "0" # This is overwritten later
259262 sig_channels .append ((name , str (chan_id ), sampling_rate , sig_dtype , units , gain , offset , stream_id ))
260263
261264 sig_channels = np .array (sig_channels , dtype = _signal_channel_dtype )
@@ -264,22 +267,49 @@ def _parse_header(self):
264267 signal_streams = np .array ([], dtype = _signal_stream_dtype )
265268
266269 else :
267- # detect groups (aka streams)
268- all_sig_length = all_sig_length = np .array (all_sig_length )
269- groups = set (zip (sig_channels ["sampling_rate" ], all_sig_length ))
270+ # Detect streams
271+ all_sig_length = np .asarray (all_sig_length )
272+
273+ # names are WB{number}, FPX{number}, SPKCX{number}, AI{number}, etc
274+ pattern = r"^\D+" # Match any non-digit character at the beginning of the string
275+ channels_prefixes = np .asarray ([re .match (pattern , name ).group (0 ) for name in sig_channels ["name" ]])
276+ buffer_stream_groups = set (zip (channels_prefixes , sig_channels ["sampling_rate" ], all_sig_length ))
277+
278+ # There are explanations of the streams based on channel names
279+ # provided by a Plexon Engineer, see here:
280+ # https://github.com/NeuralEnsemble/python-neo/pull/1495#issuecomment-2184256894
281+ channel_prefix_to_stream_name = {
282+ "WB" : "WB-Wideband" ,
283+ "FP" : "FPl-Low Pass Filtered " ,
284+ "SP" : "SPKC-High Pass Filtered" ,
285+ "AI" : "AI-Auxiliary Input" ,
286+ }
287+
288+ # Using a mapping to ensure consistent order of stream_index
289+ channel_prefix_to_stream_id = {
290+ "WB" : "0" ,
291+ "FP" : "1" ,
292+ "SP" : "2" ,
293+ "AI" : "3" ,
294+ }
270295
271296 signal_streams = []
272297 self ._signal_length = {}
273298 self ._sig_sampling_rate = {}
274- for stream_index , (sr , length ) in enumerate (groups ):
275- stream_id = str (stream_index )
299+
300+ for stream_index , (channel_prefix , sr , length ) in enumerate (buffer_stream_groups ):
301+ # The users of plexon can modify the prefix of the channel names (e.g. `my_prefix` instead of `WB`). This is not common but in that case
302+ # We assign the channel_prefix both as stream_name and stream_id
303+ stream_name = channel_prefix_to_stream_name .get (channel_prefix , channel_prefix )
304+ stream_id = channel_prefix_to_stream_id .get (channel_prefix , channel_prefix )
305+
276306 mask = (sig_channels ["sampling_rate" ] == sr ) & (all_sig_length == length )
277307 sig_channels ["stream_id" ][mask ] = stream_id
278308
279309 self ._sig_sampling_rate [stream_index ] = sr
280310 self ._signal_length [stream_index ] = length
281311
282- signal_streams .append (("Signals " + stream_id , stream_id ))
312+ signal_streams .append ((stream_name , stream_id ))
283313
284314 signal_streams = np .array (signal_streams , dtype = _signal_stream_dtype )
285315
@@ -363,8 +393,8 @@ def _segment_t_start(self, block_index, seg_index):
363393 def _segment_t_stop (self , block_index , seg_index ):
364394 t_stop = float (self ._last_timestamps ) / self ._global_ssampling_rate
365395 if hasattr (self , "_signal_length" ):
366- for stream_id in self ._signal_length :
367- t_stop_sig = self ._signal_length [stream_id ] / self ._sig_sampling_rate [stream_id ]
396+ for stream_index in self ._signal_length . keys () :
397+ t_stop_sig = self ._signal_length [stream_index ] / self ._sig_sampling_rate [stream_index ]
368398 t_stop = max (t_stop , t_stop_sig )
369399 return t_stop
370400
0 commit comments