Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Drop annotations with NaN onset in EEGLAB raw files #12484

Merged
merged 10 commits into from
Mar 13, 2024
1 change: 1 addition & 0 deletions doc/changes/devel/12484.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fix problem caused by onsets with NaN values using :func:`mne.io.read_raw_eeglab` by `Jacob Woessner`_
16 changes: 16 additions & 0 deletions mne/io/eeglab/eeglab.py
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,22 @@ def _read_annotations_eeglab(eeg, uint16_codec=None):
)
duration[idx] = np.nan if is_empty_array else event.duration

# Drop events with NaN onset see PR #12484
valid_indices = [
idx for idx, onset_idx in enumerate(onset) if not np.isnan(onset_idx)
]
n_dropped = len(onset) - len(valid_indices)
if len(valid_indices) != len(onset):
warn(
f"{n_dropped} events have an onset that is NaN. These values are "
"usually ignored by EEGLAB and will be dropped from the "
"annotations."
)

onset = np.array([onset[idx] for idx in valid_indices])
duration = np.array([duration[idx] for idx in valid_indices])
description = [description[idx] for idx in valid_indices]

return Annotations(
onset=np.array(onset) / eeg.srate,
duration=duration / eeg.srate,
Expand Down
33 changes: 33 additions & 0 deletions mne/io/eeglab/tests/test_eeglab.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,3 +719,36 @@ def get_bad_information(eeg, get_pos, *, montage_units):
assert len(pos["lpa"]) == 3
assert len(pos["rpa"]) == 3
assert len(raw.info["dig"]) == n_eeg + 3


@testing.requires_testing_data
def test_eeglab_drop_nan_annotations(tmp_path):
"""Test reading file with NaN annotations."""
pytest.importorskip("eeglabio")
from eeglabio.raw import export_set

file_path = tmp_path / "test_nan_anno.set"
raw = read_raw_eeglab(raw_fname_mat, preload=True)
data = raw.get_data()
sfreq = raw.info["sfreq"]
ch_names = raw.ch_names
anno = [
raw.annotations.description,
raw.annotations.onset,
raw.annotations.duration,
]
anno[1][0] = np.nan

export_set(
str(file_path),
data,
sfreq,
ch_names,
ch_locs=None,
annotations=anno,
ref_channels="common",
ch_types=np.repeat("EEG", len(ch_names)),
)

with pytest.raises(RuntimeWarning, match="1 .* have an onset that is NaN.*"):
raw = read_raw_eeglab(file_path, preload=True)
Loading