python-neo icon indicating copy to clipboard operation
python-neo copied to clipboard

Multiple issues with gettings durations for events from Open Ephys binary files

Open johnmbarrett opened this issue 1 year ago • 1 comments

Describe the bug OpenEphysBinaryRawIO._parse_header refuses to extract durations when the number of rising edges detected exceeds the number of falling edges, even though there is enough information to compute almost all durations in this case, and also incorrectly assumes that successive events always have alternating polarity.

To Reproduce

  1. Download this OpenEphys dataset: https://drive.google.com/file/d/1Hr3-GFOpOkNc1hgXdVr5HTunchQm4enw/view?usp=drive_link
  2. Unzip the dataset somewhere
  3. Run the following code
from neo.rawio.openephysbinaryrawio import OpenEphysBinaryRawIO

folder = # fill in the folder you unzipped the data to

io = OpenEphysBinaryRawIO(folder)

io._parse_header()

timestamps, durations, labels = io._get_event_timestamps(0,0,0,None,None)

Expected behaviour The correct durations are returned for all events

Actual behaviour durations is None

Environment:

  • OS: Windows 10
  • Python version: 3.9
  • Neo version: https://github.com/NeuralEnsemble/python-neo/pull/1430 (you can't load all events from multistream datasets without this PR)
  • NumPy version: 1.26.2

Additional context For the first problem, the check on line 245 of openephysbinaryrawio.py is unnecessarily stringent. It should be less than or equal, not strict equality.

Moreover, the logic in this section doesn't work when events from multiple binary channels are interleaved on the same event stream (which is allowed by the Open Ephys specification and happens for e.g. data from an Intan RHD2000 USB evaluation board), as it incorrectly assumes that events alternate between rising and falling. However, if multiple channels are interleaved, then two rising or two falling events from different channels can follow each other, and so the duration calculation on line 246 is wrong. In the example dataset, this happens for the 26th & 27th events, in which a falling edge on channel 2 follows a falling edge on channel 3. A better approach would be, for each rising edge, to look for the next falling edge with the same absolute state value (and either drop that event from the list or assign it a NaN duration if none is found, rather than Noneing out the entire durations array)

johnmbarrett avatar Mar 19 '24 00:03 johnmbarrett

@johnmbarrett would you have time to make a PR and propose a fix?

alejoe91 avatar Apr 22 '24 14:04 alejoe91