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

[FIX] Reading an EDF with preload=False and mixed frequency #13069

Merged
merged 6 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changes/devel/13069.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix bug cause by unnecessary assertion when loading mixed frequency EDFs without preloading :func:`mne.io.read_raw_edf` by `Simon Kern`_.
1 change: 1 addition & 0 deletions mne/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ def pytest_configure(config: pytest.Config):
ignore:.*builtin type swigvarlink has no.*:DeprecationWarning
# eeglabio
ignore:numpy\.core\.records is deprecated.*:DeprecationWarning
ignore:Starting field name with a underscore.*:
# joblib
ignore:process .* is multi-threaded, use of fork/exec.*:DeprecationWarning
""" # noqa: E501
Expand Down
9 changes: 6 additions & 3 deletions mne/io/edf/edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,21 +436,24 @@ def _read_segment_file(data, idx, fi, start, stop, raw_extras, filenames, cals,
ones[orig_idx, smp_read : smp_read + len(one_i)] = one_i
n_smp_read[orig_idx] += len(one_i)

# resample channels with lower sample frequency
# skip if no data was requested, ie. only annotations were read
if sum(n_smp_read) > 0:
if any(n_smp_read) > 0:
# expected number of samples, equals maximum sfreq
smp_exp = data.shape[-1]
assert max(n_smp_read) == smp_exp

# resample data after loading all chunks to prevent edge artifacts
resampled = False

for i, smp_read in enumerate(n_smp_read):
# nothing read, nothing to resample
if smp_read == 0:
continue
# upsample if n_samples is lower than from highest sfreq
if smp_read != smp_exp:
assert (ones[i, smp_read:] == 0).all() # sanity check
# sanity check that we read exactly how much we expected
assert (ones[i, smp_read:] == 0).all()

ones[i, :] = resample(
ones[i, :smp_read].astype(np.float64),
smp_exp,
Expand Down
18 changes: 18 additions & 0 deletions mne/io/edf/tests/test_edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,24 @@ def test_edf_different_sfreqs(stim_channel):
assert_allclose(times1, times2)


@testing.requires_testing_data
@pytest.mark.parametrize("stim_channel", (None, False, "auto"))
def test_edf_different_sfreqs_nopreload(stim_channel):
"""Test loading smaller sfreq channels without preloading."""
# load without preloading, then load a channel that has smaller sfreq
# as other channels, produced an error, see mne-python/issues/12897

for i in range(1, 13):
raw = read_raw_edf(input_fname=edf_reduced, verbose="error", preload=False)

# this should work for channels of all sfreq, even if larger sfreqs
# are present in the file
x1 = raw.get_data(picks=[f"A{i}"], return_times=False)
# load next ch, this is sometimes with a higher sometimes a lower sfreq
x2 = raw.get_data([f"A{i + 1}"], return_times=False)
assert x1.shape == x2.shape


def test_edf_data_broken(tmp_path):
"""Test edf files."""
raw = _test_raw_reader(
Expand Down
Loading