Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 35 additions & 15 deletions neo/rawio/openephysbinaryrawio.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,14 @@ def _parse_header(self):
# We then set the stream_id to the sync stream id
channel_stream_id = sync_stream_id

if "ADC" in chan_id:
# These are non-neural channels and their stream should be separated
# We defined their stream_id as the stream_index of neural data plus the number of neural streams
# This is to not break backwards compatbility with the stream_id numbering
channel_stream_id = str(stream_index + len(sig_stream_names))
if "OneBox" not in stream_name:
# If recording system is not OneBox, which has already a separate stream for ADC channels,
# we need to separate ADC channels from neural channels.
if "ADC" in chan_id:
# These are non-neural channels and their stream should be separated
# We defined their stream_id as the stream_index of neural data plus the number of neural streams
# This is to not break backwards compatbility with the stream_id numbering
channel_stream_id = str(stream_index + len(sig_stream_names))

gain = float(chan_info["bit_volts"])
sampling_rate = float(info["sample_rate"])
Expand Down Expand Up @@ -271,10 +274,22 @@ def _parse_header(self):
"SYNC channel must be the last channel in the buffer. Open an issue in python-neo to request this feature."
)

neural_channels = [ch for ch in info["channels"] if "ADC" not in ch["channel_name"]]
adc_channels = [ch for ch in info["channels"] if "ADC" in ch["channel_name"]]
num_neural_channels = len(neural_channels)
num_adc_channels = len(adc_channels)
if "OneBox" not in info["stream_name"]:
# If recording system is not OneBox, which has already a separate stream for ADC channels,
# we need to separate ADC channels from neural channels.
# We do this by defining different stream_ids for ADC and non-ADC channels
# (see above when creating signal_channels and signal_streams)

# Split neural and ADC channels
# SYNC channel is handled separately below
neural_channels = [ch for ch in info["channels"] if "ADC" not in ch["channel_name"]]
adc_channels = [ch for ch in info["channels"] if "ADC" in ch["channel_name"]]
num_neural_channels = len(neural_channels)
num_adc_channels = len(adc_channels) if "OneBox" not in info["stream_name"] else 0
else:
# OneBox already has a separate stream for ADC channels, so no need to split them here
num_neural_channels = num_channels - 1 if has_sync_trace else num_channels
num_adc_channels = 0

if num_adc_channels == 0:
if has_sync_trace and not self.load_sync_channel:
Expand Down Expand Up @@ -498,12 +513,17 @@ def _parse_header(self):
if has_sync_trace:
values = values[:-1]

neural_channels = [ch for ch in info["channels"] if "ADC" not in ch["channel_name"]]
num_neural_channels = len(neural_channels)
if is_neural_stream:
values = values[:num_neural_channels]
else:
values = values[num_neural_channels:]
if "SYNC" in stream_name and not self.load_sync_channel:
# This is the sync stream, we only keep the last value
values = values[-1:]

if "OneBox" not in info["stream_name"]:
neural_channels = [ch for ch in info["channels"] if "ADC" not in ch["channel_name"]]
num_neural_channels = len(neural_channels)
if is_neural_stream:
values = values[:num_neural_channels]
else:
values = values[num_neural_channels:]

sig_ann["__array_annotations__"][key] = values

Expand Down
19 changes: 11 additions & 8 deletions neo/test/rawiotest/test_openephysbinaryrawio.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ class TestOpenEphysBinaryRawIO(BaseTestRawIO, unittest.TestCase):
"openephysbinary/v0.6.x_neuropixels_multiexp_multistream",
"openephysbinary/v0.6.x_neuropixels_with_sync",
"openephysbinary/v0.6.x_neuropixels_missing_folders",
"openephysbinary/v0.6.x_onebox_neuropixels",
"openephysbinary/neural_and_non_neural_data_mixed",
]

def test_sync(self):
rawio_with_sync = OpenEphysBinaryRawIO(
self.get_local_path("openephysbinary/v0.6.x_neuropixels_with_sync"), load_sync_channel=True
)
rawio_with_sync.parse_header()
with self.assertWarns(DeprecationWarning):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What deprecation warning is this asserting for?

Could we use https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertWarnsRegex

to match the message

rawio_with_sync = OpenEphysBinaryRawIO(
self.get_local_path("openephysbinary/v0.6.x_neuropixels_with_sync"), load_sync_channel=True
)
rawio_with_sync.parse_header()
stream_name = [s_name for s_name in rawio_with_sync.header["signal_streams"]["name"] if "AP" in s_name][0]
stream_index = list(rawio_with_sync.header["signal_streams"]["name"]).index(stream_name)

Expand Down Expand Up @@ -69,10 +71,11 @@ def test_sync_channel_access(self):
def test_no_sync(self):
# requesting sync channel when there is none raises an error
with self.assertRaises(ValueError):
rawio_no_sync = OpenEphysBinaryRawIO(
self.get_local_path("openephysbinary/v0.6.x_neuropixels_multiexp_multistream"), load_sync_channel=True
)
rawio_no_sync.parse_header()
with self.assertWarns(DeprecationWarning):
rawio_no_sync = OpenEphysBinaryRawIO(
self.get_local_path("openephysbinary/v0.6.x_neuropixels_multiexp_multistream"), load_sync_channel=True
)
rawio_no_sync.parse_header()

def test_missing_folders(self):
# missing folders should raise an error
Expand Down
Loading