From d47c22fc2ba21d31b46ae7816eba054d5e13add9 Mon Sep 17 00:00:00 2001 From: Jacob Woessner Date: Fri, 6 Dec 2024 10:59:42 -0600 Subject: [PATCH] Fix cnt response (#13007) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Larson --- doc/changes/devel/13007.bugfix.rst | 1 + mne/io/cnt/cnt.py | 22 +++++++++++++++++++--- mne/io/cnt/tests/test_cnt.py | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 doc/changes/devel/13007.bugfix.rst diff --git a/doc/changes/devel/13007.bugfix.rst b/doc/changes/devel/13007.bugfix.rst new file mode 100644 index 00000000000..e39d44eae5e --- /dev/null +++ b/doc/changes/devel/13007.bugfix.rst @@ -0,0 +1 @@ +Correct :func:`mne.io.read_raw_cnt` to read responses and fix exceptions by `Jacob Woessner`_. \ No newline at end of file diff --git a/mne/io/cnt/cnt.py b/mne/io/cnt/cnt.py index 16c074269bf..da91ee59f9e 100644 --- a/mne/io/cnt/cnt.py +++ b/mne/io/cnt/cnt.py @@ -14,7 +14,7 @@ from ..._fiff.utils import _create_chs, _find_channels, _mult_cal_one, read_str from ...annotations import Annotations from ...channels.layout import _topo_to_sphere -from ...utils import _check_option, _validate_type, fill_doc, warn +from ...utils import _check_option, _explain_exception, _validate_type, fill_doc, warn from ..base import BaseRaw from ._utils import ( CNTEventType3, @@ -150,7 +150,22 @@ def _update_bad_span_onset(accept_reject, onset, duration, description): np.array([e.KeyPad_Accept for e in my_events]) ) - description = np.array([str(e.StimType) for e in my_events]) + # Check to see if there are any button presses + description = [] + for event in my_events: + # Extract the 4-bit fields + # Upper nibble (4 bits) currently not used + # accept = (event.KeyPad_Accept[0] & 0xF0) >> 4 + # Lower nibble (4 bits) keypad button press + keypad = event.KeyPad_Accept[0] & 0x0F + if str(keypad) != "0": + description.append(f"KeyPad Response {keypad}") + elif event.KeyBoard != 0: + description.append(f"Keyboard Response {event.KeyBoard}") + else: + description.append(str(event.StimType)) + + description = np.array(description) onset, duration, description = _update_bad_span_onset( accept_reject, onset / sfreq, duration, description @@ -532,7 +547,8 @@ def __init__( ) except Exception: raise RuntimeError( - "Could not read header from *.cnt file. mne.io.read_raw_cnt " + f"{_explain_exception()}\n" + "WARNING: mne.io.read_raw_cnt " "supports Neuroscan CNT files only. If this file is an ANT Neuro CNT, " "please use mne.io.read_raw_ant instead." ) diff --git a/mne/io/cnt/tests/test_cnt.py b/mne/io/cnt/tests/test_cnt.py index c098b58e6f3..f98253b1317 100644 --- a/mne/io/cnt/tests/test_cnt.py +++ b/mne/io/cnt/tests/test_cnt.py @@ -57,7 +57,8 @@ def test_auto_data(): third = pytest.warns(RuntimeWarning, match="Omitted 6 annot") with first, second, third: raw = read_raw_cnt(input_fname=fname_bad_spans) - + # Test that responses are read properly + assert "KeyPad Response 1" in raw.annotations.description assert raw.info["bads"] == ["F8"] with _no_parse, pytest.warns(RuntimeWarning, match="number of bytes"):