|
5 | 5 | import numpy as np |
6 | 6 | import pytest |
7 | 7 |
|
8 | | -from mne import create_info |
| 8 | +from mne import Annotations, create_info |
9 | 9 | from mne.annotations import _annotations_starts_stops |
10 | 10 | from mne.datasets.testing import data_path, requires_testing_data |
11 | 11 | from mne.io import RawArray, read_raw_eyelink |
@@ -71,3 +71,44 @@ def test_interpolate_blinks(buffer, match, cause_error, interpolate_gaze, crop): |
71 | 71 | if interpolate_gaze: |
72 | 72 | assert not np.isnan(data[0, blink_ind]).any() # left eye |
73 | 73 | assert not np.isnan(data[1, blink_ind]).any() # right eye |
| 74 | + |
| 75 | + |
| 76 | +def _pupil_raw_with_gaps(): |
| 77 | + """Synthetic pupil Raw with two missing segments at known sample ranges.""" |
| 78 | + info = create_info(["pupil_left", "pupil_right"], 100.0, ["pupil", "pupil"]) |
| 79 | + data = np.ones((2, 1000)) * 5.0 |
| 80 | + data[:, 100:150] = 0.0 # a blink |
| 81 | + data[:, 600:650] = 0.0 # a non-blink gap (e.g. NaN/dropout) |
| 82 | + raw = RawArray(data, info) |
| 83 | + raw.set_annotations( |
| 84 | + Annotations( |
| 85 | + onset=[1.0, 6.0], |
| 86 | + duration=[0.5, 0.5], |
| 87 | + description=["BAD_blink", "BAD_NAN"], |
| 88 | + ch_names=[("pupil_left", "pupil_right"), ("pupil_left", "pupil_right")], |
| 89 | + ) |
| 90 | + ) |
| 91 | + return raw |
| 92 | + |
| 93 | + |
| 94 | +def test_interpolate_blinks_respects_match(): |
| 95 | + """All descriptions in ``match`` are interpolated, not just ``BAD_blink``. |
| 96 | +
|
| 97 | + Regression test for #13880: ``interpolate_blinks`` exposes a ``match`` |
| 98 | + parameter, but the segment start/stop times were derived from a hardcoded |
| 99 | + ``"BAD_blink"`` query, so any other matched annotation (e.g. ``BAD_NAN`` |
| 100 | + from :func:`mne.preprocessing.annotate_nan`) was silently ignored. |
| 101 | + """ |
| 102 | + # default match="BAD_blink": only the blink gap is filled, the other remains |
| 103 | + raw = _pupil_raw_with_gaps() |
| 104 | + interpolate_blinks(raw, buffer=(0.0, 0.0)) |
| 105 | + data = raw.get_data() |
| 106 | + assert not np.any(data[:, 100:150] == 0.0) # blink interpolated |
| 107 | + assert np.all(data[:, 600:650] == 0.0) # unmatched gap untouched |
| 108 | + |
| 109 | + # match both descriptions: both gaps are interpolated |
| 110 | + raw = _pupil_raw_with_gaps() |
| 111 | + interpolate_blinks(raw, buffer=(0.0, 0.0), match=["BAD_blink", "BAD_NAN"]) |
| 112 | + data = raw.get_data() |
| 113 | + assert not np.any(data[:, 100:150] == 0.0) |
| 114 | + assert not np.any(data[:, 600:650] == 0.0) |
0 commit comments