Skip to content

Fix reading of large multichannel Nihon Kohden EEG-1200A files#14060

Open
mgj05otf wants to merge 2 commits into
mne-tools:mainfrom
mgj05otf:fix/nihon-eeg1200a-large-multichannel
Open

Fix reading of large multichannel Nihon Kohden EEG-1200A files#14060
mgj05otf wants to merge 2 commits into
mne-tools:mainfrom
mgj05otf:fix/nihon-eeg1200a-large-multichannel

Conversation

@mgj05otf

Copy link
Copy Markdown

Summary

mne.io.read_raw_nihon misreads EEG-1200A recordings as a single ~1-second
channel regardless of the file's actual size, channel count, or duration.
This is a known issue reported independently by multiple users:

Root cause

EEG-1200A systems store the real channel count, channel order, and the
start-of-data offset in a chain of "extended blocks" reached via a pointer
at file offset 0x03EE, rather than in the data block that older NK systems
(and the current MNE reader) use. That data-block field is essentially
meaningless for EEG-1200A files, so the reader was picking up junk values
(observed: 1 channel, 10 "duration units" -> 1 second) instead of the real
channel list and sample count.

The extended-block layout was reverse-engineered by the Brainstorm project;
this PR follows the same structure:
https://github.com/brainstorm-tools/brainstorm3/blob/master/toolbox/io/in_fopen_nk.m

Changes

  • mne/io/nihon/nihon.py: for EEG-1200A V01.00 files, follow the
    extended-block chain to get the true channel count/order and data start
    address; infer sample count from remaining file size (EEG-1200A doesn't
    store a usable record count). Non-1200A files are unaffected. Files
    claiming more than one control/data block for EEG-1200A now raise
    NotImplementedError with a clear message instead of silently misreading
    (this combination isn't understood yet, per the same limitation in
    Brainstorm's reference implementation).
  • mne/io/nihon/tests/test_nihon.py: added a synthetic EEG-1200A fixture
    (no real patient data, randomly-generated samples) exercising the new
    code path, plus a test for the multi-block error. Also fixed an unrelated
    test-isolation bug in test_nihon_duplicate_channels, which mutated the
    shared module-level _default_chan_labels list in place without
    restoring it, corrupting state for tests run afterward in the same
    session.

Testing

Verified against a real ~870 MB, 128-channel EEG-1200A clinical recording
(not included, for patient-privacy reasons): before this fix, MNE read it
as 1 channel / 1 second; after, it correctly reads 128 channels / 1684 s,
with lazy chunked reads matching a full preload exactly at arbitrary
offsets. Full existing test suite for this module still passes
(test_nihon_eeg, test_nihon_calibration cross-validate byte-for-byte
against independent EDF exports of the same recordings).

AI assistance disclosure

Per CONTRIBUTING.md: this fix was developed with Claude Code assistance —
diagnosing the bug against a real recording, researching the EEG-1200A
extended-block format via the Brainstorm project's open-source
reverse-engineering, implementing the fix, and writing the synthetic test
fixture. I have reviewed and understand the changes.

EEG-1200A systems store the real channel count, channel order, and the
start-of-data offset in a chain of "extended blocks" rather than in the
data block used by older NK systems. Falling back to the (essentially
meaningless, for this format) data-block field caused large multichannel
EEG-1200A recordings to be misread as a single ~1 second channel, a
symptom reported by multiple users on the MNE forum and GitHub issues.

By mgj05otf.
buf[offset : offset + len(encoded)] = encoded


def _write_synthetic_1200a_eeg(tmp_path, ch_indices, sfreq, samples):

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.

Rather than this, would it be possible to get a real data file from the system for example with 1s data and add it to mne-testing-data?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you for your review. I will look for non-clinical data that can be added to the test data. Please give me some moment.

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.

2 participants