Skip to content

Commit 45a363d

Browse files
authored
Merge pull request #1544 from samuelgarcia/add_signal_buffer_id
Simple proposal for `buffer_id` in rawio
2 parents 293f35a + fee1537 commit 45a363d

39 files changed

+371
-92
lines changed

neo/rawio/alphaomegarawio.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
from .baserawio import (
3737
BaseRawIO,
38+
_signal_buffer_dtype,
3839
_signal_stream_dtype,
3940
_signal_channel_dtype,
4041
_spike_channel_dtype,
@@ -652,8 +653,9 @@ def _parse_header(self):
652653
# could be loaded in any order
653654
self._merge_segments()
654655

656+
buffer_id = ""
655657
signal_streams = set(
656-
(stream_name, stream_id)
658+
(stream_name, stream_id, buffer_id)
657659
for segment in self._segments
658660
for stream in segment["streams"]
659661
for stream_name, _, stream_id in self.STREAM_CHANNELS
@@ -662,7 +664,9 @@ def _parse_header(self):
662664
signal_streams = list(signal_streams)
663665
signal_streams.sort(key=lambda x: x[1])
664666
signal_streams = np.array(signal_streams, dtype=_signal_stream_dtype)
667+
signal_buffers = np.array([], dtype=_signal_buffer_dtype)
665668

669+
buffer_id = ""
666670
signal_channels = set(
667671
(
668672
channel["name"],
@@ -672,11 +676,12 @@ def _parse_header(self):
672676
"uV",
673677
channel["gain"] / channel["bit_resolution"],
674678
0,
675-
stream,
679+
stream_id,
680+
buffer_id,
676681
)
677682
for segment in self._segments
678-
for stream in segment["streams"]
679-
for channel_id, channel in segment["streams"][stream].items()
683+
for stream_id in segment["streams"]
684+
for channel_id, channel in segment["streams"][stream_id].items()
680685
)
681686
signal_channels = list(signal_channels)
682687
signal_channels.sort(key=lambda x: (x[7], x[0]))
@@ -709,6 +714,7 @@ def _parse_header(self):
709714
self.header = {}
710715
self.header["nb_block"] = 1
711716
self.header["nb_segment"] = [len(self._segments)]
717+
self.header["signal_buffers"] = signal_buffers
712718
self.header["signal_streams"] = signal_streams
713719
self.header["signal_channels"] = signal_channels
714720
self.header["spike_channels"] = spike_channels

neo/rawio/axographrawio.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
158158
BaseRawIO,
159159
_signal_channel_dtype,
160160
_signal_stream_dtype,
161+
_signal_buffer_dtype,
161162
_spike_channel_dtype,
162163
_event_channel_dtype,
163164
)
@@ -811,7 +812,9 @@ def _scan_axograph_file(self):
811812
self.logger.debug("initial data: {array[:5] * gain + offset}")
812813

813814
# channel_info will be cast to _signal_channel_dtype
814-
channel_info = (name, str(i), 1 / sampling_period, f.byte_order + dtype, units, gain, offset, "0")
815+
buffer_id = ""
816+
stream_id = "0"
817+
channel_info = (name, str(i), 1 / sampling_period, f.byte_order + dtype, units, gain, offset, stream_id, buffer_id)
815818

816819
self.logger.debug("channel_info: {channel_info}")
817820
self.logger.debug("")
@@ -1230,13 +1233,15 @@ def _scan_axograph_file(self):
12301233
event_channels.append(("AxoGraph Intervals", "", "epoch"))
12311234

12321235
if len(sig_channels) > 0:
1233-
signal_streams = [("Signals", "0")]
1236+
signal_streams = [("Signals", "0", "")]
12341237
else:
12351238
signal_streams = []
1239+
signal_buffers = []
12361240

12371241
# organize header
12381242
self.header["nb_block"] = 1
12391243
self.header["nb_segment"] = [1]
1244+
self.header["signal_buffers"] = np.array(signal_buffers, dtype=_signal_buffer_dtype)
12401245
self.header["signal_streams"] = np.array(signal_streams, dtype=_signal_stream_dtype)
12411246
self.header["signal_channels"] = np.array(sig_channels, dtype=_signal_channel_dtype)
12421247
self.header["event_channels"] = np.array(event_channels, dtype=_event_channel_dtype)

neo/rawio/axonarawio.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
BaseRawIO,
2626
_signal_channel_dtype,
2727
_signal_stream_dtype,
28+
_signal_buffer_dtype,
2829
_spike_channel_dtype,
2930
_event_channel_dtype,
3031
)
@@ -199,6 +200,7 @@ def _parse_header(self):
199200
params["set"]["sampling_rate"] = int(set_dict["rawRate"])
200201

201202
# SCAN BIN FILE
203+
signal_buffers = []
202204
signal_streams = []
203205
signal_channels = []
204206
if self.bin_file:
@@ -289,6 +291,7 @@ def _parse_header(self):
289291
self.header = {}
290292
self.header["nb_block"] = 1
291293
self.header["nb_segment"] = [1]
294+
self.header["signal_buffers"] = np.array(signal_buffers, dtype=_signal_buffer_dtype)
292295
self.header["signal_streams"] = np.array(signal_streams, dtype=_signal_stream_dtype)
293296
self.header["signal_channels"] = np.array(signal_channels, dtype=_signal_channel_dtype)
294297
self.header["spike_channels"] = np.array(spike_channels, dtype=_spike_channel_dtype)
@@ -315,7 +318,7 @@ def _parse_header(self):
315318

316319
def _get_signal_streams_header(self):
317320
# create signals stream information (we always expect a single stream)
318-
return np.array([("stream 0", "0")], dtype=_signal_stream_dtype)
321+
return np.array([("stream 0", "0", "")], dtype=_signal_stream_dtype)
319322

320323
def _segment_t_start(self, block_index, seg_index):
321324
return 0.0
@@ -638,10 +641,11 @@ def _get_signal_chan_header(self):
638641
chan_id = str(cntr)
639642
gain = gain_list[cntr]
640643
stream_id = "0"
644+
buffer_id = ""
641645
# the sampling rate information is stored in the set header
642646
# and not in the bin file
643647
sr = self.file_parameters["set"]["sampling_rate"]
644-
sig_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id))
648+
sig_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id, buffer_id))
645649

646650
return np.array(sig_channels, dtype=_signal_channel_dtype)
647651

neo/rawio/axonrawio.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
BaseRawIO,
5757
_signal_channel_dtype,
5858
_signal_stream_dtype,
59+
_signal_buffer_dtype,
5960
_spike_channel_dtype,
6061
_event_channel_dtype,
6162
)
@@ -227,12 +228,14 @@ def _parse_header(self):
227228
else:
228229
gain, offset = 1.0, 0.0
229230
stream_id = "0"
230-
signal_channels.append((name, str(chan_id), self._sampling_rate, sig_dtype, units, gain, offset, stream_id))
231+
buffer_id = "0"
232+
signal_channels.append((name, str(chan_id), self._sampling_rate, sig_dtype, units, gain, offset, stream_id, buffer_id))
231233

232234
signal_channels = np.array(signal_channels, dtype=_signal_channel_dtype)
233235

234-
# one unique signal stream
235-
signal_streams = np.array([("Signals", "0")], dtype=_signal_stream_dtype)
236+
# one unique signal stream and buffer
237+
signal_buffers = np.array([("Signals", "0")], dtype=_signal_buffer_dtype)
238+
signal_streams = np.array([("Signals", "0", "0")], dtype=_signal_stream_dtype)
236239

237240
# only one events channel : tag
238241
# In ABF timstamps are not attached too any particular segment
@@ -258,6 +261,7 @@ def _parse_header(self):
258261
self.header = {}
259262
self.header["nb_block"] = 1
260263
self.header["nb_segment"] = [nb_segment]
264+
self.header["signal_buffers"] = signal_buffers
261265
self.header["signal_streams"] = signal_streams
262266
self.header["signal_channels"] = signal_channels
263267
self.header["spike_channels"] = spike_channels

neo/rawio/baserawio.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,15 @@
8686

8787
error_header = "Header is not read yet, do parse_header() first"
8888

89+
_signal_buffer_dtype = [
90+
("name", "U64"), # not necessarily unique
91+
("id", "U64"), # must be unique
92+
]
93+
# To be left an empty array if the concept of buffer is undefined for a reader.
8994
_signal_stream_dtype = [
9095
("name", "U64"), # not necessarily unique
9196
("id", "U64"), # must be unique
97+
("buffer_id", "U64"), # should be "" (empty string) when the stream is not nested under a buffer or the buffer is undefined for some reason.
9298
]
9399

94100
_signal_channel_dtype = [
@@ -100,6 +106,7 @@
100106
("gain", "float64"),
101107
("offset", "float64"),
102108
("stream_id", "U64"),
109+
("buffer_id", "U64"),
103110
]
104111

105112
# TODO for later: add t_start and length in _signal_channel_dtype

neo/rawio/bci2000rawio.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
BaseRawIO,
1616
_signal_channel_dtype,
1717
_signal_stream_dtype,
18+
_signal_buffer_dtype,
1819
_spike_channel_dtype,
1920
_event_channel_dtype,
2021
)
@@ -49,8 +50,10 @@ def _parse_header(self):
4950
self.header["nb_block"] = 1
5051
self.header["nb_segment"] = [1]
5152

52-
# one unique stream
53-
signal_streams = np.array([("Signals", "0")], dtype=_signal_stream_dtype)
53+
# one unique stream and buffer
54+
signal_buffers = np.array(("Signals", "0"), dtype=_signal_buffer_dtype)
55+
signal_streams = np.array([("Signals", "0", "0")], dtype=_signal_stream_dtype)
56+
self.header["signal_buffers"] = signal_buffers
5457
self.header["signal_streams"] = signal_streams
5558

5659
sig_channels = []
@@ -78,7 +81,8 @@ def _parse_header(self):
7881
offset = float(offset)
7982

8083
stream_id = "0"
81-
sig_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id))
84+
buffer_id = "0"
85+
sig_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id, buffer_id))
8286
self.header["signal_channels"] = np.array(sig_channels, dtype=_signal_channel_dtype)
8387

8488
self.header["spike_channels"] = np.array([], dtype=_spike_channel_dtype)

neo/rawio/biocamrawio.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
BaseRawIO,
1515
_signal_channel_dtype,
1616
_signal_stream_dtype,
17+
_signal_buffer_dtype,
1718
_spike_channel_dtype,
1819
_event_channel_dtype,
1920
)
@@ -66,7 +67,9 @@ def _parse_header(self):
6667
gain = self._header_dict["gain"]
6768
offset = self._header_dict["offset"]
6869

69-
signal_streams = np.array([("Signals", "0")], dtype=_signal_stream_dtype)
70+
# buffer concept cannot be used in this reader because of too complicated dtype across version
71+
signal_buffers = np.array([], dtype=_signal_stream_dtype)
72+
signal_streams = np.array([("Signals", "0", "")], dtype=_signal_stream_dtype)
7073

7174
sig_channels = []
7275
for c, chan in enumerate(self._channels):
@@ -78,7 +81,8 @@ def _parse_header(self):
7881
gain = gain
7982
offset = offset
8083
stream_id = "0"
81-
sig_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id))
84+
buffer_id = ""
85+
sig_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id, buffer_id))
8286
sig_channels = np.array(sig_channels, dtype=_signal_channel_dtype)
8387

8488
# No events
@@ -92,6 +96,7 @@ def _parse_header(self):
9296
self.header = {}
9397
self.header["nb_block"] = 1
9498
self.header["nb_segment"] = [1]
99+
self.header["signal_buffers"] = signal_buffers
95100
self.header["signal_streams"] = signal_streams
96101
self.header["signal_channels"] = sig_channels
97102
self.header["spike_channels"] = spike_channels

neo/rawio/blackrockrawio.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
BaseRawIO,
7373
_signal_channel_dtype,
7474
_signal_stream_dtype,
75+
_signal_buffer_dtype,
7576
_spike_channel_dtype,
7677
_event_channel_dtype,
7778
)
@@ -253,6 +254,7 @@ def _parse_header(self):
253254

254255
event_channels = []
255256
spike_channels = []
257+
signal_buffers = []
256258
signal_streams = []
257259
signal_channels = []
258260

@@ -399,7 +401,11 @@ def _parse_header(self):
399401
ext_header.append(d)
400402

401403
if len(ext_header) > 0:
402-
signal_streams.append((f"nsx{nsx_nb}", str(nsx_nb)))
404+
# in blackrock : one stream per buffer so same id
405+
buffer_id = stream_id = str(nsx_nb)
406+
stream_name = f"nsx{nsx_nb}"
407+
signal_buffers.append((stream_name, buffer_id))
408+
signal_streams.append((stream_name, stream_id, buffer_id))
403409
for i, chan in enumerate(ext_header):
404410
if spec in ["2.2", "2.3", "3.0"]:
405411
ch_name = chan["electrode_label"].decode()
@@ -420,8 +426,8 @@ def _parse_header(self):
420426
float(chan["max_digital_val"]) - float(chan["min_digital_val"])
421427
)
422428
offset = -float(chan["min_digital_val"]) * gain + float(chan["min_analog_val"])
423-
stream_id = str(nsx_nb)
424-
signal_channels.append((ch_name, ch_id, sr, sig_dtype, units, gain, offset, stream_id))
429+
buffer_id = stream_id = str(nsx_nb)
430+
signal_channels.append((ch_name, ch_id, sr, sig_dtype, units, gain, offset, stream_id, buffer_id))
425431

426432
# check nb segment per nsx
427433
nb_segments_for_nsx = [len(self.nsx_datas[nsx_nb]) for nsx_nb in self.nsx_to_load]
@@ -509,10 +515,12 @@ def _parse_header(self):
509515
event_channels = np.array(event_channels, dtype=_event_channel_dtype)
510516
signal_channels = np.array(signal_channels, dtype=_signal_channel_dtype)
511517
signal_streams = np.array(signal_streams, dtype=_signal_stream_dtype)
518+
signal_buffers = np.array(signal_buffers, dtype=_signal_buffer_dtype)
512519

513520
self.header = {}
514521
self.header["nb_block"] = 1
515522
self.header["nb_segment"] = [self._nb_segment]
523+
self.header["signal_buffers"] = signal_buffers
516524
self.header["signal_streams"] = signal_streams
517525
self.header["signal_channels"] = signal_channels
518526
self.header["spike_channels"] = spike_channels

neo/rawio/brainvisionrawio.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
BaseRawIO,
1717
_signal_channel_dtype,
1818
_signal_stream_dtype,
19+
_signal_buffer_dtype,
1920
_spike_channel_dtype,
2021
_event_channel_dtype,
2122
)
@@ -83,7 +84,8 @@ def _parse_header(self):
8384
sigs = sigs[: -sigs.size % nb_channel]
8485
self._raw_signals = sigs.reshape(-1, nb_channel)
8586

86-
signal_streams = np.array([("Signals", "0")], dtype=_signal_stream_dtype)
87+
signal_buffers = np.array(("Signals", "0"), dtype=_signal_buffer_dtype)
88+
signal_streams = np.array([("Signals", "0", "0")], dtype=_signal_stream_dtype)
8789

8890
sig_channels = []
8991
channel_infos = vhdr_header["Channel Infos"]
@@ -115,7 +117,8 @@ def _parse_header(self):
115117
gain = 1
116118
offset = 0
117119
stream_id = "0"
118-
sig_channels.append((name, chan_id, self._sampling_rate, sig_dtype, units, gain, offset, stream_id))
120+
buffer_id = "0"
121+
sig_channels.append((name, chan_id, self._sampling_rate, sig_dtype, units, gain, offset, stream_id, buffer_id))
119122
sig_channels = np.array(sig_channels, dtype=_signal_channel_dtype)
120123

121124
# No spikes
@@ -152,6 +155,7 @@ def _parse_header(self):
152155
self.header = {}
153156
self.header["nb_block"] = 1
154157
self.header["nb_segment"] = [1]
158+
self.header["signal_buffers"] = signal_buffers
155159
self.header["signal_streams"] = signal_streams
156160
self.header["signal_channels"] = sig_channels
157161
self.header["spike_channels"] = spike_channels

neo/rawio/cedrawio.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
BaseRawIO,
2727
_signal_channel_dtype,
2828
_signal_stream_dtype,
29+
_signal_buffer_dtype,
2930
_spike_channel_dtype,
3031
_event_channel_dtype,
3132
)
@@ -102,7 +103,8 @@ def _parse_header(self):
102103
dtype = "int16"
103104
# set later after grouping
104105
stream_id = "0"
105-
signal_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id))
106+
buffer_id = ""
107+
signal_channels.append((ch_name, chan_id, sr, dtype, units, gain, offset, stream_id, buffer_id))
106108

107109
elif chan_type == sonpy.lib.DataType.AdcMark:
108110
# spike and waveforms : only spike times is used here
@@ -142,8 +144,11 @@ def _parse_header(self):
142144
signal_channels["stream_id"][mask] = stream_id
143145
num_chans = np.sum(mask)
144146
stream_name = f"{stream_id} {num_chans}chans"
145-
signal_streams.append((stream_name, stream_id))
147+
buffer_id = ""
148+
signal_streams.append((stream_name, stream_id, buffer_id))
146149
signal_streams = np.array(signal_streams, dtype=_signal_stream_dtype)
150+
# buffer is unknown because using a close source API
151+
signal_buffers = np.array([], dtype=_signal_buffer_dtype)
147152

148153
# spike channels not handled
149154
spike_channels = np.array(spike_channels, dtype=_spike_channel_dtype)
@@ -162,6 +167,7 @@ def _parse_header(self):
162167
self.header = {}
163168
self.header["nb_block"] = 1
164169
self.header["nb_segment"] = [1]
170+
self.header["signal_buffers"] = signal_buffers
165171
self.header["signal_streams"] = signal_streams
166172
self.header["signal_channels"] = signal_channels
167173
self.header["spike_channels"] = spike_channels

0 commit comments

Comments
 (0)