EEG_MI / README.md
Twu31's picture
Mirror of github.com/twu3202/EEG_MI at 66726e1
d37c079 verified
|
Raw
History Blame Contribute Delete
4.98 kB
---
license: mit
tags:
- eeg
- motor-imagery
- brain-computer-interface
- bci
- dry-electrode
- ads1299
---
# EEG_MI — Motor imagery on a 32-channel dry-electrode cap
> Mirror of [github.com/twu3202/EEG_MI](https://github.com/twu3202/EEG_MI). Data lives in
> [Twu31/cap32-mi-eeg](https://huggingface.co/datasets/Twu31/cap32-mi-eeg).
Decoding **motor imagery (MI)** from a 32-channel dry-electrode EEG cap
(TI ADS1299, 250 Hz, WiFi/UDP), with two goals: reach usable accuracy with
**minimal per-subject retraining**, and find out whether **EEG foundation models**
actually help on hardware like this.
Everything here is measured on one cap and one subject. The reports say plainly
what the data supports and what it does not.
![acquisition GUI](results/cap_gui_preview.png)
## What we found
| Question | Answer |
|---|---|
| Left hand vs right hand | **Not decodable** (p = 0.41). A dry cap does not resolve C3 vs C4 well enough. |
| Both hands vs rest | **Decodable**, AUC 0.83–0.87 (n = 19, breadth search over 115 pipelines) |
| Hands vs feet | AUC 0.704, p = 0.040 in mu (8–13 Hz) on 17 central+frontal channels — exploratory, selection-biased |
| Do foundation models beat classical? | **No.** Seven frozen backbones, none beat CSP/Riemannian tangent space + LR (0.790) |
| Channel-to-channel crosstalk | Not detectable; bounded at −24 dB by a measurement whose floor was set by open inputs |
The single most useful negative result: the first foundation-model ranking was an
artifact of **zero padding**. Feeding a 3 s trial to a checkpoint built for 15 s made
80 % of LaBraM's input zeros, and the probe read the padding. BENDR's "best-in-class"
0.733 became 0.303 once the input was fixed. `src/foundation/embed_health.py` is the
pre-flight gate that now has to pass before any probe score is interpreted.
## Reports
| | |
|---|---|
| [`docs/mi_pilot_report.pdf`](docs/mi_pilot_report.pdf) | MI pilot: ERD/ERS, breadth search, foundation-model benchmark (中文) |
| [`docs/crosstalk_report.pdf`](docs/crosstalk_report.pdf) · [`_zh`](docs/crosstalk_report_zh.pdf) | Crosstalk measured with an external generator (EN / 中文) |
| [`docs/hardware_acceptance.pdf`](docs/hardware_acceptance.pdf) | Noise, DC, mains, crosstalk acceptance suite (中文) |
| [`docs/impedance_injection_report.pdf`](docs/impedance_injection_report.pdf) | Reverse-engineering the 31.2 Hz impedance injection (中文) |
| [`docs/network_setup.md`](docs/network_setup.md) | Recording over the cap's WiFi AP without losing internet |
| [`research/`](research/) | MI + foundation-model survey, per-model input contracts, OpenBCI notes |
## Data
The recordings are published separately, with a data card and a standalone loader:
**[huggingface.co/datasets/Twu31/cap32-mi-eeg](https://huggingface.co/datasets/Twu31/cap32-mi-eeg)**
Raw µV, unfiltered, pre-CAR, **all 32 channels retained** — including the ones that
were dead in that session. Read the data card before analysing: one session lost 31
of its 50 trials to a receiver stall, and another has a visual confound during imagery.
## Layout
```
src/
common/montage.py 32-ch 10–20 montage + ADC scaling (µV = counts × 0.02235)
acquisition/ cap → GUI/LSL: framing, MI paradigm, impedance, hardware tests
experiment/mi_paradigm.py full-screen cue window (fixation → cue → imagery → rest)
analysis/ epoching, artifact handling, breadth search over pipelines
foundation/ frozen-backbone probing + the representation-health gate
baselines/ CSP / Riemannian baselines on MOABB (BCI IV-2a/2b)
docs/ reports (LaTeX + PDF); preamble.tex is shared by all of them
research/ surveys and notes written before the hardware arrived
results/ figures and metrics reproduced by the scripts above
```
## Getting started
```bash
conda create -n eegmi python=3.11 && conda activate eegmi
pip install -r requirements-cpu.txt # baselines, analysis (no GPU)
pip install -r requirements-dl.txt # torch (MPS) + braindecode + foundation models
```
Without hardware, everything still runs on the synthetic source:
```bash
python src/acquisition/cap_gui.py --source synth
```
With the cap: join its `ESPBCI` access point, set a static IP of `192.168.4.2`
(see [`docs/network_setup.md`](docs/network_setup.md)), then
```bash
python src/acquisition/cap_gui.py --source udp
```
## Notes on the hardware
The cap is a low-cost DIY-class device, and several of its documented behaviours were
wrong or absent, so they were measured rather than trusted: the frame layout, the
lowercase command set, the 31.2 Hz impedance injection current (~24 nA, not µA), and
the vendor's two mutually inconsistent impedance formulas. `src/acquisition/` contains
the test scripts for each. Vendor manuals and software are **not** redistributed here.
## License
MIT for the code. The recordings are CC BY 4.0 — see the dataset card.