-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Description of the problem
In some experiments we start with a few practice trials that will be excluded from analysis, in some cases we put them outside the usual trial loop and has no calibration stage for them
read_raw_eyelink cannot handle these empty trials and will throw a ValueError because it cannot find eyetracking channels to parse annotations with
I know this looks pretty stupid and doesn't really look like a bug - but unexpected data format - though it'd be nice if read_raw_eyelink() can handle cases like these
Steps to reproduce
the problematic Eyelink files start with trials like these
START 1211913 RIGHT SAMPLES EVENTS
PRESCALER 1
VPRESCALER 1
PUPIL DIAMETER
EVENTS GAZE RIGHT RATE 1000.00 TRACKING CR FILTER 1
SAMPLES GAZE RIGHT RATE 1000.00 TRACKING CR FILTER 1 INPUT
INPUT 1211913 127
1211913 . . 0.0 127.0 ...
SSACC R 1211914
SBLINK R 1211914
1211914 . . 0.0 127.0 ...
1211915 . . 0.0 127.0 ...
1211916 . . 0.0 127.0 ...
MSG 1211917 TRIAL 1 STARTS
MSG 1211917 FIXATION START
MSG 1211917 pre 100 pause
1211917 . . 0.0 127.0 ...
1211918 . . 0.0 127.0 ...
1211919 . . 0.0 127.0 ...
1211920 . . 0.0 127.0 ...
1211921 . . 0.0 127.0 ...
1211922 . . 0.0 127.0 ...
1211923 . . 0.0 127.0 ...
1211924 . . 0.0 127.0 ...
1211925 . . 0.0 127.0 ...
calling read_raw_eyelink() will throw an errorLink to data
No response
Expected results
RawEyelink object with these trials converted to NaN values - or whatever value
Actual results
ValueError Traceback (most recent call last)
Cell In[15], line 10
8 pass
9 else:
---> 10 el_raw = read_eyelink_file(file=f)
11 s01e02_el_rawdict[el_parID] = (el_raw)
Cell In[13], line 24, in read_eyelink_file(file, raw, calib, screen_kwarg, event_id, interpolation_buffer, downsample)
22 file = Path(file) if isinstance(file, str) else file
23 assert isinstance(file, pathlib.Path), r'File needs to be string or pathlib.Path'
---> 24 raw = mne.io.read_raw_eyelink(file)
25 calib = mne.preprocessing.eyetracking.read_eyelink_calibration(file, **screen_kwarg)
26 elif (raw and calib) and not file:
File [~/AppData/Local/anaconda3/envs/mne/Lib/site-packages/mne/io/eyelink/eyelink.py#line=58), in read_raw_eyelink(fname, create_annotations, apply_offsets, find_overlaps, overlap_threshold, verbose)
29 """Reader for an Eyelink .asc file.
30
31 Parameters
(...) 55 'BAD_ACQ_SKIP'.
56 """
57 fname = _check_fname(fname, overwrite="read", must_exist=True, name="fname")
---> 59 raw_eyelink = RawEyelink(
60 fname,
61 create_annotations=create_annotations,
62 apply_offsets=apply_offsets,
63 find_overlaps=find_overlaps,
64 overlap_threshold=overlap_threshold,
65 verbose=verbose,
66 )
67 return raw_eyelink
File :12, in init(self, fname, create_annotations, apply_offsets, find_overlaps, overlap_threshold, verbose)
File [~/AppData/Local/anaconda3/envs/mne/Lib/site-packages/mne/io/eyelink/eyelink.py#line=126), in RawEyelink.init(self, fname, create_annotations, apply_offsets, find_overlaps, overlap_threshold, verbose)
123 eye_annots = _make_eyelink_annots(
124 self._raw_extras[0]["dfs"], create_annotations, apply_offsets
125 )
126 if gap_annots and eye_annots: # set both
--> 127 self.set_annotations(gap_annots + eye_annots)
128 elif gap_annots:
129 self.set_annotations(gap_annots)
File :12, in set_annotations(self, annotations, emit_warning, on_missing, verbose)
File [~/AppData/Local/anaconda3/envs/mne/Lib/site-packages/mne/io/base.py#line=746), in BaseRaw.set_annotations(self, annotations, emit_warning, on_missing, verbose)
745 delta = 1.0 / self.info["sfreq"]
746 new_annotations = annotations.copy()
--> 747 new_annotations._prune_ch_names(self.info, on_missing)
748 if annotations.orig_time is None:
749 new_annotations.crop(
750 0, self.times[-1] + delta, emit_warning=emit_warning
751 )
File [~/AppData/Local/anaconda3/envs/mne/Lib/site-packages/mne/annotations.py#line=653), in Annotations._prune_ch_names(self, info, on_missing)
652 if name not in keep:
653 if not warned:
--> 654 _on_missing(
655 on_missing,
656 "At least one channel name in "
657 f"annotations missing from info: {name}",
658 )
659 warned = True
660 else:
File [~/AppData/Local/anaconda3/envs/mne/Lib/site-packages/mne/utils/check.py#line=1220), in _on_missing(on_missing, msg, name, error_klass)
1219 on_missing = "warn" if on_missing == "warning" else on_missing
1220 if on_missing == "raise":
-> 1221 raise error_klass(msg)
1222 elif on_missing == "warn":
1223 warn(msg)
ValueError: At least one channel name in annotations missing from info: xpos_right
Additional information
Platform Windows-11-10.0.26100-SP0
Python 3.13.5 | packaged by conda-forge | (main, Jun 16 2025, 08:20:19) [MSC v.1943 64 bit (AMD64)]
Executable C:\Users...\AppData\Local\anaconda3\envs\mne\python.exe
CPU Intel(R) Core(TM) Ultra 5 135U (14 cores)
Memory 15.5 GiB
Core
X mne 1.10.1 (outdated, release 1.11.0 is available!) (sorry)
- numpy 2.3.1 (MKL 2023.1-Product with 12 threads)
- scipy 1.16.0
- matplotlib 3.10.5 (backend=module://matplotlib_inline.backend_inline)
Numerical (optional)
- sklearn 1.7.1
- pandas 2.3.1
- h5io 0.2.5
- h5py 3.14.0
- unavailable numba, nibabel, nilearn, dipy, openmeeg, cupy
Visualization (optional)
- qtpy 2.4.1 (PyQt5=5.15.2)
- pyqtgraph 0.13.7
- mne-qt-browser 0.7.2
- ipywidgets 8.1.8
- unavailable pyvista, pyvistaqt, vtk, ipympl, trame_client, trame_server, trame_vtk, trame_vuetify
Ecosystem (optional)
- mne-icalabel 0.7.0
- unavailable mne-bids, mne-nirs, mne-features, mne-connectivity, mne-bids-pipeline, neo, eeglabio, edfio, mffpy, pybv
To update to the latest supported release version to get bugfixes and improvements, visit https://mne.tools/stable/install/updating.html