Skip to content

Fix read_raw_eyelink() failure when recording blocks are empty or starting with empty values - #13571

Merged
scott-huberty merged 23 commits into
mne-tools:mainfrom
qian-chu:fix-read-eyelink
Jul 31, 2026
Merged

Fix read_raw_eyelink() failure when recording blocks are empty or starting with empty values#13571
scott-huberty merged 23 commits into
mne-tools:mainfrom
qian-chu:fix-read-eyelink

Conversation

@qian-chu

@qian-chu qian-chu commented Dec 30, 2025

Copy link
Copy Markdown
Contributor

Reference issue (if any)

Fixes #13567 and extend testing to the case mentioned in #13550.

What does this implement/fix?

As described in #13567, when a recording block starts with missing data, the status column sometimes is not present until actual data is present:

889502	   .	   .	    0.0
889503	   .	   .	    0.0
889504	  916.5	  575.5	  655.0	...
889505	  916.3	  575.2	  655.0	...

While it does not prevent the block to be read into a DataFrame (with four columns, in this case), the status column would start with None instead of any subscriptable string, causing a TypeError.

The fix instead gets the first valid value to infer if the column is status or not. Further, it updates the method to infer if the first value is numeric by trying to convert it to float.

Question: If not len(first_value) in [3, 5, 13, 17], should the code emit a warning/error to contact MNE developers?

Moreover, #13550 mentioned a scenerio that a recording block could be completely empty. While it doesn't seem to trigger any error anymore, this is not explicitly tested in the current tests. So we will also add this to the test coverage.

Minor fixes
  1. Correct typo ("occular" -> "ocular")
  2. if "PUPIL" in units, warn "Raw pupil position data detected" instead of "Raw eyegaze coordinates detected".

Additional information

The main focus of the PR is expanding _simulate_eye_tracking_data (which is already simulating multi-block data) to simulate more edge cases.

@qian-chu

Copy link
Copy Markdown
Contributor Author

Just noticed that #13550 and #13555 are also related. It seems the two problems are complementary - users will want to discard any empty recording block AND read blocks with an empty start

@qian-chu qian-chu changed the title Fix read_raw_eyelink() failure when status column starts with empty values Fix read_raw_eyelink() failure when recording blocks are empty or starting with empty values Jan 2, 2026
@qian-chu
qian-chu marked this pull request as draft January 2, 2026 13:24
@scott-huberty

Copy link
Copy Markdown
Contributor

thanks @qian-chu ! And thanks in advance for your patience, just getting back to the office after the holiday break. I will take a closer look this week.

@qian-chu

qian-chu commented Jan 5, 2026

Copy link
Copy Markdown
Contributor Author

thanks @qian-chu ! And thanks in advance for your patience, just getting back to the office after the holiday break. I will take a closer look this week.

No worries! Not expecting people to be back from holidays this soon. This PR is also still in progress anyways (I have yet to add new tests)

@Cathaway

Cathaway commented Jan 19, 2026

Copy link
Copy Markdown
Minor fixes
  1. Correct typo ("occular" -> "ocular")
  2. if "PUPIL" in units, warn "Raw pupil position data detected" instead of "Raw eyegaze coordinates detected".

just a note 'pupil' channels in Eyelink measure pupil size (or diameter), not positions, so the warning message should be 'pupil size data detected', if a warning is needed

@qian-chu

Copy link
Copy Markdown
Contributor Author
Minor fixes
  1. Correct typo ("occular" -> "ocular")
  2. if "PUPIL" in units, warn "Raw pupil position data detected" instead of "Raw eyegaze coordinates detected".

just a note 'pupil' channels in Eyelink measure pupil size (or diameter), not positions, so the warning message should be 'pupil size data detected', if a warning is needed

This PUPIL unit, if I'm not mistaken, indicates the user used edf2asc -sp. According to edf2asc: "-sp outputs sample raw pupil position if present". This is not about pupil size, but what measurement the x and y are (default is gaze, could also be href and pupil).

@scott-huberty

Copy link
Copy Markdown
Contributor
Minor fixes
  1. Correct typo ("occular" -> "ocular")
  2. if "PUPIL" in units, warn "Raw pupil position data detected" instead of "Raw eyegaze coordinates detected".

just a note 'pupil' channels in Eyelink measure pupil size (or diameter), not positions, so the warning message should be 'pupil size data detected', if a warning is needed

This PUPIL unit, if I'm not mistaken, indicates the user used edf2asc -sp. According to edf2asc: "-sp outputs sample raw pupil position if present". This is not about pupil size, but what measurement the x and y are (default is gaze, could also be href and pupil).

Agreed. It is easy to mix up, but, In EyeLink systems there is a distinction between Pupil Size data and eyegaze pupil position data.

Per the EDF2ASC Manual:

SAMPLES < data type > < eyes > < data options >
This specifies what types of data is present in sample lines, as a sequence of keywords. The < data type > is one of "GAZE", "HREF" or "PUPIL".

And per section 4.4.2.1 PUPIL of the Eyelink 1000 Plus User manual (v1.0.19):

Pupil position data is raw (x, y) coordinate pairs from the camera. It has not been converted to eye angles or to gaze position.

@qian-chu I'm only loosely following this so feel free to ping me when you are ready for review or need my input!

@qian-chu

Copy link
Copy Markdown
Contributor Author

@scott-huberty Absolutely! I think it will be helpful if you could look at the evolution of conversation in #13550. It seems to have been solved by one of your previous PR but would love to hear your opinion. This will help determine the scope of this PR.

@larsoner

larsoner commented Jun 5, 2026

Copy link
Copy Markdown
Member

@behinger yes thanks for the reminder! @scott-huberty let me know if you can't look next week for example and I can take a look

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Fixes read_raw_eyelink() parsing for Eyelink recording blocks that begin with missing values (and aims to cover empty-block edge cases), and updates related warnings/docs.

Changes:

  • Make STATUS-column detection robust to leading missing values by scanning for the first valid sample value.
  • Expand Eyelink test simulation to include blocks that start with missing values and add assertions for the resulting annotations.
  • Minor docstring/spelling fixes and update of the warning text for raw pupil-position units.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
mne/utils/docs.py Fix “occular” → “ocular” in parameter docs.
mne/io/eyelink/tests/test_eyelink.py Extend simulated ASC data for edge cases and update warning/annotation assertions.
mne/io/eyelink/eyelink.py Improve RawEyelink class docstring wording.
mne/io/eyelink/_utils.py Update status-column dropping logic and adjust unit warning text.
doc/changes/dev/13571.bugfix.rst Add changelog entry for the bugfix.

Comment thread mne/io/eyelink/tests/test_eyelink.py Outdated
Comment thread mne/io/eyelink/_utils.py
Comment thread mne/io/eyelink/tests/test_eyelink.py
Comment thread mne/io/eyelink/tests/test_eyelink.py
Comment thread mne/io/eyelink/_utils.py
@larsoner

larsoner commented Jun 5, 2026

Copy link
Copy Markdown
Member

(Side note: I am not sure why an AI review was automatically generated here 😕 @drammock did we enable those? @qian-chu feel free to look at what it said, or not, as you wish...)

@drammock

drammock commented Jun 5, 2026

Copy link
Copy Markdown
Member

(Side note: I am not sure why an AI review was automatically generated here 😕 @drammock did we enable those? @qian-chu feel free to look at what it said, or not, as you wish...)

I didn't change any settings. At present, GitHub offers repos and orgs no way of disabling copilot reviews if they're requested (or triggered automatically by a user account setting) by the PR author. (And I'll add: despite numerous requests in the maintainers forum for such org- or repo-level controls.) So even if our org and repo have copilot fully disabled, the most we can do for user-triggered copilot reviews is moderate it after-the-fact (e.g., hide as off-topic or spam)

@drammock

drammock commented Jun 5, 2026

Copy link
Copy Markdown
Member

Actually I'm just seeing this:

Screenshot 2026-06-05 at 15-08-42 Fix` read_raw_eyelink()` failure when recording blocks are empty or starting with empty values by qian-chu · Pull Request #13571 · mne-tools_mne-python

If it's not your settings @larsoner, it's possible that @qian-chu didn't have auto-copilot-review enabled before, but does now, and it was triggered by @larsoner merging main into this PR

@larsoner

larsoner commented Jun 5, 2026

Copy link
Copy Markdown
Member

Yeah I saw it was triggered by me but don't know why it would have been 🤷

@qian-chu

Copy link
Copy Markdown
Contributor Author

Hi all! Thanks for reminding me of the PR. I will take a look at copilot's comments and make sure the PR is still up to date. The maintainers are of course welcome to review already.

@qian-chu

Copy link
Copy Markdown
Contributor Author

Actually I'm just seeing this:

Screenshot 2026-06-05 at 15-08-42 Fix` read_raw_eyelink()` failure when recording blocks are empty or starting with empty values by qian-chu · Pull Request #13571 · mne-tools_mne-python If it's not your settings @larsoner, it's possible that @qian-chu didn't have auto-copilot-review enabled before, but does now, and it was triggered by @larsoner merging main into this PR

I just checked and I do have auto copilot review on. This might be the reason. I will probably turn it off for future use, and the good thing is at least it didn't automatically commit changes.

@larsoner

Copy link
Copy Markdown
Member

LGTM @behinger can you verify this fixes your issue?

@scott-huberty scott-huberty left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@scott-huberty scott-huberty left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't merge yet. Coincidentally a user just emailed me about a problematic file that needs this patch. I'm working through this PR with said file, and I think we need to tweak some things.

@qian-chu

Copy link
Copy Markdown
Contributor Author

Please don't merge yet. Coincidentally a user just emailed me about a problematic file that needs this patch. I'm working through this PR with said file, and I think we need to tweak some things.

Happy to look at the file together if you would like me to! And of course I'm open to tweaking the patch to cover more edge cases.

@behinger

Copy link
Copy Markdown
Contributor

@jshanna100 had a look at a previously broken file, and with the PR it works now again. Thanks for pinging us!

@larsoner

Copy link
Copy Markdown
Member

@scott-huberty want to merge this as-is and make a follow-up PR? Might make sense if you think it'll take you some days/weeks to make fixes for the other problematic file(s)

@scott-huberty

Copy link
Copy Markdown
Contributor

@scott-huberty want to merge this as-is and make a follow-up PR? Might make sense if you think it'll take you some days/weeks to make fixes for the other problematic file(s)

Yes, go ahead!

@qian-chu

Copy link
Copy Markdown
Contributor Author

Hi @scott-huberty @larsoner just wanted to give this a gentle nudge. I’m happy to take a look at an edge case file together and discuss possible solutions, or we can merge this as-is if you prefer.

@scott-huberty
scott-huberty enabled auto-merge (squash) July 31, 2026 20:49
@scott-huberty
scott-huberty merged commit d491745 into mne-tools:main Jul 31, 2026
28 checks passed
@scott-huberty

Copy link
Copy Markdown
Contributor

Sorry for the delay @qian-chu thanks for the ping!

@qian-chu
qian-chu deleted the fix-read-eyelink branch August 2, 2026 12:22
@qian-chu

qian-chu commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

Sorry for the delay @qian-chu thanks for the ping!

No worries! Thanks for merging :)

larsoner added a commit to larsoner/mne-python that referenced this pull request Aug 4, 2026
* upstream/main: (35 commits)
  Fix bug with coreg scaling (mne-tools#14132)
  MAINT: Update code credit (mne-tools#14131)
  Fix bugs with dark mode panels (mne-tools#14109)
  Improve code credit workflow (mne-tools#14120)
  Align _AbstractRenderer.tube with the PyVista implementation (mne-tools#14125)
  Assign instead of compare when marking explicit zeros in spatio_temporal_dist_adjacency (mne-tools#14124)
  MAINT: Update pre-commit hook versions (mne-tools#14122)
  MAINT: Update dependency specifiers (mne-tools#14121)
  fix: correct typo in comment (mne-tools#14117)
  [dependabot]: Bump the actions group with 2 updates (mne-tools#14123)
  Fix` read_raw_eyelink()` failure when recording blocks are empty or starting with empty values (mne-tools#13571)
  ENH: Add `event_key` parameter to `read_raw_egi` for MFF event metadata (mne-tools#14086)
  fix for scipy sparse deprecations (mne-tools#14118)
  Fix notch spectrum fit (mne-tools#14116)
  Speed up notch filter spectrum fit (mne-tools#14114)
  fix MNE-RT links and update roadmap (mne-tools#14096)
  Clarify `docdict["filter_length_notch"]` (mne-tools#14113)
  Refactor test_plot_alignment_basic() (mne-tools#13472)
  BUG: Cleanup cHPI filtering using smooth interpolation (mne-tools#14112)
  Use redirector app (mne-tools#14111)
  ...

# Conflicts:
#	mne/tests/test_filter.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

read_raw_eyelink() fails to find and drop status column

8 participants