Skip to content

Fix EEGLAB events after dropped epochs - #14067

Merged
larsoner merged 10 commits into
mne-tools:mainfrom
viranovskaya:fix/eeglab-epoch-events
Sep 25, 2026
Merged

larsoner merged 10 commits into
mne-tools:mainfrom
viranovskaya:fix/eeglab-epoch-events

Conversation

@viranovskaya

@viranovskaya viranovskaya commented Jul 18, 2026 •

Copy link
Copy Markdown
Contributor

Reference issue

Fixes #13535.

What does this implement/fix?

When epochs had been dropped, epochs.selection still referred to the original trials. Passing these indices to eeglabio could produce out-of-range epoch numbers and latencies, followed by dummy events or an eeg_checkset failure.

This change maps events to the epochs that are actually being exported and recalculates their latencies in the concatenated EEGLAB dataset.

I added a regression test with dropped middle epochs. The exported file now contains one event per retained epoch, valid 1-based epoch numbers, and no dummy events.

Event sample numbers after importing the .set file back into MNE now refer to the exported epoched dataset rather than the original continuous recording. This matches how EEGLAB represents events in epoched data.

Additional information

Tested with eeglabio 0.1.2 and 0.1.3.

Comment thread mne/export/_eeglab.py Outdated
Comment on lines +77 to +78
if "epoch_indices" in getfullargspec(eeglabio.epochs.export_set).kwonlyargs:
kwargs["epoch_indices"] = epochs.selection
kwargs["epoch_indices"] = np.arange(1, len(epochs) + 1)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there any reason to pass this at all anymore? I assume if you don't pass it, it defaults to np.arange, no?

@viranovskaya viranovskaya Jul 18, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good question. In most cases, omitting epoch_indices gives the same result. But when zero time is the final sample (tmax=0), eeglabio assigns the event to the next epoch and resets the latencies. I updated the regression test to cover this case; it fails without the explicit indices and passes with them. So I kept the argument and added a short comment.

Comment thread mne/export/_eeglab.py Outdated
events = epochs.events.copy()
events[:, 0] = (
np.arange(len(epochs)) * len(epochs.times) + epochs.time_as_index(0)[0]
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is odd... if you do this there is no longer any reference to the absolute time in the original recording. It suggests events[:, 2] is the only thing correctly used by eeglabio.epochs.export_set. Is it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, the absolute sample from the original continuous recording is intentionally not retained in this field. For epoched EEGLAB files, eeglabio uses column 0 as latency in the concatenated epochs array and column 2 as the event type; column 1 is unused. Keeping the original sample numbers is what caused events to point to the wrong epochs after dropping epochs. I clarified this in the code comment.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ohhh.... so I think this fix actually belongs in eeglabio. It should handle the translation from MNE-Python events (which it currently takes) to whatever eeglab wants.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That makes sense. I moved the translation into eeglabio and added tests for dropped epochs and the tmax=0 boundary: jackz314/eeglabio#26. I’ll update this PR once the upstream behavior is settled.

@viranovskaya
viranovskaya force-pushed the fix/eeglab-epoch-events branch from 2554ab3 to 5054df6 Compare August 2, 2026 13:25
@larsoner
larsoner marked this pull request as ready for review September 25, 2026 04:45
@larsoner
larsoner enabled auto-merge (squash) September 25, 2026 04:46
@larsoner

Copy link
Copy Markdown
Member

Okay pushed a commit to simplify the checks after making sure it worked on older and newer EEGLABIO, thanks in advance @viranovskaya !

@larsoner
larsoner merged commit 311ce1f into mne-tools:main Sep 25, 2026
25 checks passed
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.

Potential bug in eeglabio exporting

2 participants