@@ -72,6 +72,12 @@ def __init__(self, dirname="", load_sync_channel=False, experiment_names=None):
72
72
experiment_names = [experiment_names ]
73
73
self .experiment_names = experiment_names
74
74
self .load_sync_channel = load_sync_channel
75
+ if load_sync_channel :
76
+ warn (
77
+ "The load_sync_channel=True option is deprecated and will be removed in version 0.15. "
78
+ "Use load_sync_channel=False instead, which will add sync channels as separate streams." ,
79
+ DeprecationWarning , stacklevel = 2
80
+ )
75
81
self .folder_structure = None
76
82
self ._use_direct_evt_timestamps = None
77
83
@@ -123,7 +129,8 @@ def _parse_header(self):
123
129
# signals zone
124
130
# create signals channel map: several channel per stream
125
131
signal_channels = []
126
-
132
+ sync_stream_id_to_buffer_id = {}
133
+ normal_stream_id_to_sync_stream_id = {}
127
134
for stream_index , stream_name in enumerate (sig_stream_names ):
128
135
# stream_index is the index in vector stream names
129
136
stream_id = str (stream_index )
@@ -134,21 +141,28 @@ def _parse_header(self):
134
141
chan_id = chan_info ["channel_name" ]
135
142
136
143
units = chan_info ["units" ]
144
+ channel_stream_id = stream_id
137
145
if units == "" :
138
146
# When units are not provided they are microvolts for neural channels and volts for ADC channels
139
147
# See https://open-ephys.github.io/gui-docs/User-Manual/Recording-data/Binary-format.html#continuous
140
148
units = "uV" if "ADC" not in chan_id else "V"
141
149
142
150
# Special cases for stream
143
151
if "SYNC" in chan_id and not self .load_sync_channel :
144
- # the channel is removed from stream but not the buffer
145
- stream_id = ""
152
+ # Every stream sync channel is added as its own stream
153
+ sync_stream_id = f"{ stream_name } SYNC"
154
+ sync_stream_id_to_buffer_id [sync_stream_id ] = buffer_id
155
+
156
+ # We save this mapping for the buffer description protocol
157
+ normal_stream_id_to_sync_stream_id [stream_id ] = sync_stream_id
158
+ # We then set the stream_id to the sync stream id
159
+ channel_stream_id = sync_stream_id
146
160
147
161
if "ADC" in chan_id :
148
162
# These are non-neural channels and their stream should be separated
149
163
# We defined their stream_id as the stream_index of neural data plus the number of neural streams
150
164
# This is to not break backwards compatbility with the stream_id numbering
151
- stream_id = str (stream_index + len (sig_stream_names ))
165
+ channel_stream_id = str (stream_index + len (sig_stream_names ))
152
166
153
167
gain = float (chan_info ["bit_volts" ])
154
168
sampling_rate = float (info ["sample_rate" ])
@@ -162,7 +176,7 @@ def _parse_header(self):
162
176
units ,
163
177
gain ,
164
178
offset ,
165
- stream_id ,
179
+ channel_stream_id ,
166
180
buffer_id ,
167
181
)
168
182
)
@@ -174,12 +188,21 @@ def _parse_header(self):
174
188
signal_buffers = []
175
189
176
190
unique_streams_ids = np .unique (signal_channels ["stream_id" ])
191
+
192
+ # This is getting too complicated, we probably should just have a table which would be easier to read
193
+ # And for users to understand
177
194
for stream_id in unique_streams_ids :
178
- # Handle special case of Synch channel having stream_id empty
179
- if stream_id == "" :
195
+
196
+ # Handle sync channel on a special way
197
+ if "SYNC" in stream_id :
198
+ # This is a sync channel and should not be added to the signal streams
199
+ buffer_id = sync_stream_id_to_buffer_id [stream_id ]
200
+ stream_name = stream_id
201
+ signal_streams .append ((stream_name , stream_id , buffer_id ))
180
202
continue
181
- stream_index = int ( stream_id )
203
+
182
204
# Neural signal
205
+ stream_index = int (stream_id )
183
206
if stream_index < self ._num_of_signal_streams :
184
207
stream_name = sig_stream_names [stream_index ]
185
208
buffer_id = stream_id
@@ -254,7 +277,12 @@ def _parse_header(self):
254
277
255
278
if num_adc_channels == 0 :
256
279
if has_sync_trace and not self .load_sync_channel :
280
+ # Exclude the sync channel from the main stream
257
281
self ._stream_buffer_slice [stream_id ] = slice (None , - 1 )
282
+
283
+ # Add a buffer slice for the sync channel
284
+ sync_stream_id = normal_stream_id_to_sync_stream_id [stream_id ]
285
+ self ._stream_buffer_slice [sync_stream_id ] = slice (- 1 , None )
258
286
else :
259
287
self ._stream_buffer_slice [stream_id ] = None
260
288
else :
@@ -264,7 +292,12 @@ def _parse_header(self):
264
292
self ._stream_buffer_slice [stream_id_neural ] = slice (0 , num_neural_channels )
265
293
266
294
if has_sync_trace and not self .load_sync_channel :
295
+ # Exclude the sync channel from the non-neural stream
267
296
self ._stream_buffer_slice [stream_id_non_neural ] = slice (num_neural_channels , - 1 )
297
+
298
+ # Add a buffer slice for the sync channel
299
+ sync_stream_id = normal_stream_id_to_sync_stream_id [stream_id ]
300
+ self ._stream_buffer_slice [sync_stream_id ] = slice (- 1 , None )
268
301
else :
269
302
self ._stream_buffer_slice [stream_id_non_neural ] = slice (num_neural_channels , None )
270
303
0 commit comments