|
2 | 2 | Tests of neo.rawio.examplerawio |
3 | 3 | """ |
4 | 4 |
|
| 5 | +import tempfile |
5 | 6 | import unittest |
| 7 | +from pathlib import Path |
6 | 8 |
|
7 | 9 | from neo.rawio.blackrockrawio import BlackrockRawIO |
8 | 10 | from neo.test.rawiotest.common_rawio_test import BaseTestRawIO |
@@ -374,6 +376,41 @@ def test_gap_tolerance_ms_parameter(self): |
374 | 376 | segments_strict = reader_strict.segment_count(0) |
375 | 377 | self.assertEqual(segments_strict, 3) # |
376 | 378 |
|
| 379 | + def test_nev_22_reads_spikes_on_electrodes_above_255(self): |
| 380 | + """ |
| 381 | + A FileSpec 2.2 NEV with spikes on an electrode above 255 (Ripple Trellis numbers its front-end ports |
| 382 | + 1-128, 129-256, 257-384...) keeps them, as 2.3 does (NeuralEnsemble/python-neo#1918). Built from neo's |
| 383 | + 2.3 test NEV: marked 2.2, with electrode 1 renumbered 300 in its NEUEVWAV header and spike packets. |
| 384 | + """ |
| 385 | + source_base = self.get_local_path("blackrock/FileSpec2.3001") |
| 386 | + original = BlackrockRawIO(filename=source_base, nsx_to_load=None) |
| 387 | + original.parse_header() |
| 388 | + units_on_1 = [i for i, (channel, _) in enumerate(original.internal_unit_ids) if channel == 1] |
| 389 | + self.assertTrue(units_on_1) # electrode 1 has spikes to move |
| 390 | + expected = np.concatenate([original.get_spike_timestamps(0, 0, i, None, None) for i in units_on_1]) |
| 391 | + |
| 392 | + data = bytearray(Path(source_base + ".nev").read_bytes()) |
| 393 | + data[9] = 2 # FileSpec 2.3 -> 2.2 |
| 394 | + header_size, packet_size = np.frombuffer(bytes(data[12:20]), dtype="<u4") |
| 395 | + for at in range(336, int(header_size), 32): # extended headers follow the 336-byte basic header |
| 396 | + if data[at : at + 8] == b"NEUEVWAV" and int.from_bytes(data[at + 8 : at + 10], "little") == 1: |
| 397 | + data[at + 8 : at + 10] = (300).to_bytes(2, "little") |
| 398 | + # 2.x packets: a uint32 timestamp, then the uint16 packet id |
| 399 | + for at in range(int(header_size), len(data) - int(packet_size) + 1, int(packet_size)): |
| 400 | + if int.from_bytes(data[at + 4 : at + 6], "little") == 1: |
| 401 | + data[at + 4 : at + 6] = (300).to_bytes(2, "little") |
| 402 | + |
| 403 | + with tempfile.TemporaryDirectory() as folder: |
| 404 | + base = str(Path(folder) / "trellis_like") |
| 405 | + Path(base + ".nev").write_bytes(bytes(data)) |
| 406 | + reader = BlackrockRawIO(filename=base, nsx_to_load=None) |
| 407 | + reader.parse_header() |
| 408 | + self.assertEqual(reader._nev_spec, "2.2") |
| 409 | + units_on_300 = [i for i, (channel, _) in enumerate(reader.internal_unit_ids) if channel == 300] |
| 410 | + self.assertTrue(units_on_300, "no spike channel on electrode 300") |
| 411 | + got = np.concatenate([reader.get_spike_timestamps(0, 0, i, None, None) for i in units_on_300]) |
| 412 | + assert_equal(np.sort(got), np.sort(expected)) |
| 413 | + |
377 | 414 |
|
378 | 415 | if __name__ == "__main__": |
379 | 416 | unittest.main() |
0 commit comments