Skip to content

Commit

Permalink
Add auto mode for cnt bad chans
Browse files Browse the repository at this point in the history
  • Loading branch information
withmywoessner committed Nov 9, 2023
1 parent 4989271 commit 6f55154
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
30 changes: 22 additions & 8 deletions mne/io/cnt/cnt.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def read_raw_cnt(
data_format="auto",
date_format="mm/dd/yy",
*,
header="old",
header="auto",
preload=False,
verbose=None,
):
Expand Down Expand Up @@ -221,9 +221,11 @@ def read_raw_cnt(
Defaults to ``'auto'``.
date_format : ``'mm/dd/yy'`` | ``'dd/mm/yy'``
Format of date in the header. Defaults to ``'mm/dd/yy'``.
header : ``'new'`` | ``'old'``
header : ``'auto'`` | ``'new'`` | ``'old'``
Defines the header format. Used to describe how bad channels
are formatted.
are formatted. If auto, reads using old and new header and
if either contain a bad channel make channel bad.
Defaults to ``'auto'``.
%(preload)s
%(verbose)s
Expand Down Expand Up @@ -352,12 +354,22 @@ def _get_cnt_info(input_fname, eog, ecg, emg, misc, data_format, date_format, he
ch_names.append(ch_name)

# Some files have bad channels marked differently in the header.
if header == "auto":
fid.seek(data_offset + 75 * ch_idx + 14)
if np.fromfile(fid, dtype="u1", count=1).item():
bads.append(ch_name)
fid.seek(data_offset + 75 * ch_idx + 4)
if np.fromfile(fid, dtype="u1", count=1).item():
bads.append(ch_name)
if header == "new":
fid.seek(data_offset + 75 * ch_idx + 14)
if np.fromfile(fid, dtype="u1", count=1).item():
bads.append(ch_name)
if header == "old":
fid.seek(data_offset + 75 * ch_idx + 4)
if np.fromfile(fid, dtype="u1", count=1).item():
bads.append(ch_name)
if np.fromfile(fid, dtype="u1", count=1).item():
bads.append(ch_name)

fid.seek(data_offset + 75 * ch_idx + 19)
xy = np.fromfile(fid, dtype="f4", count=2)
xy[1] *= -1 # invert y-axis
Expand Down Expand Up @@ -462,9 +474,11 @@ class RawCNT(BaseRaw):
Defaults to ``'auto'``.
date_format : ``'mm/dd/yy'`` | ``'dd/mm/yy'``
Format of date in the header. Defaults to ``'mm/dd/yy'``.
header : ``'new'`` | ``'old'``
header : ``'auto'`` | ``'new'`` | ``'old'``
Defines the header format. Used to describe how bad channels
are formatted.
are formatted. If auto, reads using old and new header and
if either contain a bad channel make channel bad.
Defaults to ``'auto'``.
%(preload)s
stim_channel : bool | None
Add a stim channel from the events. Defaults to None to trigger a
Expand Down Expand Up @@ -493,7 +507,7 @@ def __init__(
data_format="auto",
date_format="mm/dd/yy",
*,
header="old",
header="auto",
preload=False,
verbose=None,
): # noqa: D102
Expand Down
25 changes: 25 additions & 0 deletions mne/io/cnt/tests/test_cnt.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,31 @@ def test_new_data():
assert raw.info["bads"] == ["F8"] # test bads


@testing.requires_testing_data
def test_auto_data():
"""Test reading raw cnt files with automatic header."""
with pytest.warns(RuntimeWarning):
raw = read_raw_cnt(input_fname=fname_bad_spans)

assert raw.info["bads"] == ["F8"]

with pytest.warns(RuntimeWarning, match="number of bytes"):
raw = _test_raw_reader(
read_raw_cnt, input_fname=fname, eog="auto",
misc=["NA1", "LEFT_EAR"]
)

# make sure we use annotations event if we synthesized stim
assert len(raw.annotations) == 6

eog_chs = pick_types(raw.info, eog=True, exclude=[])
assert len(eog_chs) == 2 # test eog='auto'
assert raw.info["bads"] == ["LEFT_EAR", "VEOGR"] # test bads

# the data has "05/10/200 17:35:31" so it is set to None
assert raw.info["meas_date"] is None


@testing.requires_testing_data
def test_compare_events_and_annotations():
"""Test comparing annotations and events."""
Expand Down

0 comments on commit 6f55154

Please sign in to comment.