Skip to content

Conversation

@Arnav1709
Copy link

Reference issue (if any)

Fixes #13429.

What does this implement/fix?

This PR addresses a critical bug where MNE-Python would silently load EDF+D (discontinuous) and BDF+D files with acquisition gaps between data records, treating them as continuous data. This could lead to:

  • Incorrect time alignment: The RawEDF.times array would show continuous timestamps, ignoring gaps
  • Missing annotations: Annotations occurring after gaps could be dropped or incorrectly positioned
  • Silent data corruption: Users would be unaware that their data contains discontinuities

Changes made:

  1. Detection of EDF+D/BDF+D files: Modified _read_edf_header() to read and check the 44-byte reserved header field for EDF+D or BDF+D markers.

  2. Gap detection: Added two helper functions:

    • _get_tal_record_times(): Extracts onset times of each data record from TAL (Time-stamped Annotation List) annotations
    • _check_edf_discontinuity(): Compares expected vs. actual record timestamps to detect gaps
  3. Error handling: Modified both RawEDF and RawBDF classes to check for discontinuities after reading TAL data. When gaps are detected, a NotImplementedError is raised with:

    • Clear explanation of the issue
    • Location of gaps (onset time and duration)
    • Suggestions for alternatives (luna/lunapi or conversion to EDF+C/BDF+C)
  4. Backward compatibility: EDF+D/BDF+D files that are marked as discontinuous but have no actual gaps (e.g., from some Nihon Kohden systems) continue to load normally.

  5. Documentation: Updated docstrings for read_raw_edf() and read_raw_bdf() to document this limitation.

  6. Tests: Added comprehensive tests covering:

    • Detection of gaps in EDF+D files
    • Successful loading of continuous EDF+C files
    • Successful loading of EDF+D files without actual gaps
    • Edge cases in gap detection logic

Additional information

  • This is a breaking change in behavior: files that previously loaded (incorrectly) will now raise an error. However, this is intentional as the previous behavior was incorrect and could lead to data analysis errors.

  • The error message provides actionable guidance, suggesting specialized tools (luna/lunapi) for handling discontinuous files or converting to continuous format if gaps are not significant.

  • The implementation follows the EDF+ specification for detecting discontinuous files and uses TAL annotations (which are required in EDF+ files) to detect actual gaps.

  • Related discussion in the GitHub issue suggests that full support for EDF+D would require filling gaps with NaN data (similar to how Eyelink handles gaps), which is a more complex feature that could be implemented in a future PR.

larsoner and others added 2 commits January 9, 2026 16:06
Detect and raise NotImplementedError when loading EDF+D or BDF+D files
that contain actual gaps between data records, instead of silently
treating them as continuous data. This prevents incorrect time alignment.

Fixes mne-tools#13429
- Validate n_records matches len(record_times), raise ValueError on mismatch
- Validate record_times are numeric (no strings or invalid types)
- Check for non-finite values (NaN, inf) and raise ValueError
- Warn and sort if record_times are not monotonically increasing
- Add comprehensive tests for all validation scenarios
@welcome
Copy link

welcome bot commented Jan 9, 2026

Hello! 👋 Thanks for opening your first pull request here! ❤️ We will try to get back to you soon. 🚴

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_edf silently loads EDF+D files without accounting for time gaps/acquisition skips between records

2 participants