Skip to content

ENH: Add initial BCI2000 .dat reader (preload-only)#13699

Merged
larsoner merged 31 commits intomne-tools:mainfrom
HansujaB:add-bci2000-reader
Apr 3, 2026
Merged

ENH: Add initial BCI2000 .dat reader (preload-only)#13699
larsoner merged 31 commits intomne-tools:mainfrom
HansujaB:add-bci2000-reader

Conversation

@HansujaB
Copy link
Copy Markdown
Contributor

Reference issue (if any)

Fixes #13151

What does this implement/fix?

This PR adds basic support for reading BCI2000 .dat files via:

mne.io.read_raw_bci2k()

The implementation:

  • Parses minimal required header fields
  • Decodes signal and state vector
  • Maps StimulusCode to STI 014 stim channel
  • Returns a Raw object using RawArray
  • Includes deterministic unit tests with a synthetic demo file

Tests

  • Synthetic .dat generator included in tests

  • Verifies:

    • sampling rate
    • number of samples
    • stim channel creation
    • correct StimulusCode decoding
    • preload=False raises

Scope (Intentional Limitations)

  • preload=False is not supported (raises NotImplementedError)
  • Minimal header parsing (SamplingRate + State Vector Definition only)
  • Generic channel names (EEG1, EEG2, …)
  • No gain/scaling applied
  • Not added to _get_supported() (since .dat is already mapped to Curry)

The goal is to provide a correct, minimal reader that can be safely extended in follow-up PRs.

@HansujaB HansujaB requested a review from larsoner as a code owner February 27, 2026 16:36
Copy link
Copy Markdown
Member

@larsoner larsoner left a comment

Choose a reason for hiding this comment

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

I didn't look too deeply at the code, but looks like a reasonable start! With something like this we'd want to see it used somewhere, too -- is there a good file we could download using pooch in an example and use in an examples/io/something.py or similar? We could do something like what's done here

https://github.com/mne-tools/mne-bids/blob/15ee0e48179181c66705931683e16272dfd97a9a/examples/convert_fieldtrip_emg.py#L61

Also did you use AI tools in developing this code? If so please disclose the nature of AI tool usage

from mne.io.bci2k import RawBCI2k, read_raw_bci2k


def _write_demo_bci2k(
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.

A more modern way to do this would be to

Suggested change
def _write_demo_bci2k(
@pytest.fixture
def bci2k_path(tmp_path):
fname = tmp_path / "something"
...
return fname

and then you use this inside your test

Copy link
Copy Markdown
Contributor Author

@HansujaB HansujaB Mar 2, 2026

Choose a reason for hiding this comment

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

@larsoner Thanks a lot for your review!
I searched for an example file but couldn't really find one, although I came across PhysioNet bigP3BCI dataset. The problem is , they converted .dat files to EDF + file header, so we can't use it !

What we can do is (use the same approach to generate a small example file) :
We can generate a small BCI2000 .dat file using a short P3Speller session with minimal channels and then host a trimmed version (a few seconds only) .
If this approach is acceptable I can work on it , Let me know!

Regarding AI usage , I looked upon the major stuff and algorithm development myself but for debugging and redundancy reduction, I took the help of AI tools to increase my efficiency!

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.

We can generate a small BCI2000 .dat file using a short P3Speller session with minimal channels and then host a trimmed version (a few seconds only) .

This would be great, then we could add it to mne-testing-data and use it here

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.

@larsoner Great! Should I open a separate PR to add the sample file to mne-testing-data, or can I include it in this PR?

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.

@HansujaB you can make a PR to https://github.com/mne-tools/mne-testing-data

Please make sure the new testing file is super small! Like < 1mb if possible. You can crop the data in the file to be only 1-second long if needed.

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.

@scott-huberty Thanks! I’ll generate a small trimmed .dat file and open a PR to mne-testing-data. It might take me a little while since I have exams this week, but I’ll try to get it up as soon as possible.

@HansujaB HansujaB requested a review from larsoner March 2, 2026 22:58
@HansujaB
Copy link
Copy Markdown
Contributor Author

@larsoner @scott-huberty I have opened a PR for test file in mne-testing-data as discussed. While testing the dataset locally with the BCI2000 reader, I noticed a small parsing issue and have pushed a fix for that as well. Apologies for the delay!

@HansujaB
Copy link
Copy Markdown
Contributor Author

@larsoner Since the mne-testing-data PR has been merged, I have updated the test to use the dataset from there. Please let me know if anything else needs to be changed.

@larsoner
Copy link
Copy Markdown
Member

Looks like the style CI is unhappy, can you look? Once that's passing I can approve the other workflows

@larsoner
Copy link
Copy Markdown
Member

Also looks like the main comment from #13699 (review) hasn't been addressed

@HansujaB
Copy link
Copy Markdown
Contributor Author

Hi @larsoner, tests now use mne-testing-data , so the fixture suggestion no longer applies. Could you confirm if there's anything else from that thread that still needs addressing? Also pushed the style CI fixes. Thanks!

@larsoner
Copy link
Copy Markdown
Member

Could you confirm if there's anything else from that thread that still needs addressing?

Yeah, the comment I linked to had this:

I didn't look too deeply at the code, but looks like a reasonable start! With something like this we'd want to see it used somewhere, too -- is there a good file we could download using pooch in an example and use in an examples/io/something.py or similar? We could do something like what's done here

https://github.com/mne-tools/mne-bids/blob/15ee0e48179181c66705931683e16272dfd97a9a/examples/convert_fieldtrip_emg.py#L61

I don't see any examples/io/* file modified usidng pooch or similar (or discussion about it above) ... ?

@HansujaB
Copy link
Copy Markdown
Contributor Author

@larsoner I have added the example file!

@HansujaB
Copy link
Copy Markdown
Contributor Author

@larsoner Right now , we are failing 2 tests

  1. I checked , still version 0.172 of mne-testing-data is used so we are getting File not found error for test test_read_raw_bci2k
  2. read_raw_bci2k is added to doc/api/reading_raw_data.rst but purposefully not added to _get_supported() so we are facing the following error
    `FAILED mne/io/tests/test_read_raw.py::test_all_reader_documented - AssertionError: Functions missing from documentation:

Functions missing from read_raw:
read_raw_bci2k`

Should I remove it from doc/api/reading_raw_data.rst ?

@larsoner
Copy link
Copy Markdown
Member

These errors are likely because it needs to be added to the API reference like other reading functions:

$ git grep "read_raw_edf" doc/api/
doc/api/reading_raw_data.rst:   read_raw_edf

@HansujaB
Copy link
Copy Markdown
Contributor Author

@larsoner Actually it is added to the API reference as well !


fname = pooch.retrieve(
url="https://raw.githubusercontent.com/mne-tools/mne-testing-data/master/BCI2k/bci2k_test.dat",
known_hash="sha256:8efc7b5f700660a044086cb1449806ca408c2e6d32d9338c32e1bf31ce3ca9cb",
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.

We should save to whatever this path is, plus maybe a new folder (if needed) bci_data or similar?

https://mne.tools/stable/generated/mne.datasets.default_path.html#mne.datasets.default_path

So something like

data_dir = mne.datasets.default_path() / "bci2k_data"
data_dir.mkdir(exist_ok=True)
...

params = {}
state_defs = {}

def _parse_sampling_rate(val):
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.

Can you move this outside the function? Nesting like this makes it hard to know which vars are from this function's scope and which are from the parent's

@HansujaB
Copy link
Copy Markdown
Contributor Author

@larsoner I have pushed the changes , let me know if something needs to be modified. Thanks!

@HansujaB
Copy link
Copy Markdown
Contributor Author

HansujaB commented Mar 24, 2026

@larsoner Right now , we are failing 2 tests

  1. I checked , still version 0.172 of mne-testing-data is used so we are getting File not found error for test test_read_raw_bci2k
  2. read_raw_bci2k is added to doc/api/reading_raw_data.rst but purposefully not added to _get_supported() so we are facing the following error
    `FAILED mne/io/tests/test_read_raw.py::test_all_reader_documented - AssertionError: Functions missing from documentation:

Functions missing from read_raw: read_raw_bci2k`

Should I remove it from doc/api/reading_raw_data.rst ?

@larsoner We are still facing these 2 issues :(
I can't really understand how to fix them can you help me out?

@larsoner
Copy link
Copy Markdown
Member

larsoner commented Apr 3, 2026

I'll push a commit to fix the doc linking error and finish the steps from https://github.com/mne-tools/mne-testing-data?tab=readme-ov-file#add-or-change-files-in-the-repo-for-use-with-mne to update the version

@larsoner larsoner enabled auto-merge (squash) April 3, 2026 21:21
@larsoner larsoner added this to the 1.12 milestone Apr 3, 2026
@HansujaB
Copy link
Copy Markdown
Contributor Author

HansujaB commented Apr 3, 2026

@larsoner Thanks a lot for the finishing touches!
Really sorry I missed the last step to change version here my bad.

@larsoner larsoner merged commit 9b14298 into mne-tools:main Apr 3, 2026
32 checks passed
@larsoner
Copy link
Copy Markdown
Member

larsoner commented Apr 4, 2026

Thanks @HansujaB !

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.

BCI2000 .dat file reader

3 participants