diff --git a/mne/io/cnt/cnt.py b/mne/io/cnt/cnt.py index 8adb95521ec..909e248dbc9 100644 --- a/mne/io/cnt/cnt.py +++ b/mne/io/cnt/cnt.py @@ -170,7 +170,7 @@ def read_raw_cnt( data_format="auto", date_format="mm/dd/yy", *, - header="old", + header="auto", preload=False, verbose=None, ): @@ -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 @@ -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 @@ -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 @@ -493,7 +507,7 @@ def __init__( data_format="auto", date_format="mm/dd/yy", *, - header="old", + header="auto", preload=False, verbose=None, ): # noqa: D102 diff --git a/mne/io/cnt/tests/test_cnt.py b/mne/io/cnt/tests/test_cnt.py index 5d29fc1ae12..e530a81ebc5 100644 --- a/mne/io/cnt/tests/test_cnt.py +++ b/mne/io/cnt/tests/test_cnt.py @@ -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."""