# Motor imagery decoding: offline study

## Question
Can a participant-specific classifier distinguish imagined left-hand and right-hand movement in a different recording run from the same participant?

## Cohort and results
Attempted 109 participants; included 49; excluded 60. The primary cohort contains 2134 trials: 1081 left and 1053 right. Rejected 69 additional epochs within eligible participants. Run-level retained/rejected trial logs are in quality.json; unparseable recordings have no inferred trial counts.

| Model | Mean participant balanced accuracy | 95% participant-bootstrap interval |
| --- | --- | --- |
| majority | 48.7% | 48.1%–49.2% |
| bandpower_lr | 58.2% | 54.9%–61.6% |
| csp_lda | 60.0% | 55.8%–64.5% |

Each participant contributes equally. Pooled confusion counts in results.json weight trials instead and are not the primary metric. Intervals use 2000 resamples of participants, seed 42.

![All participant scores](participant-distribution.svg)

## Frozen methods
PhysioNet EEGMMIDB v1.0.0; runs 4, 8, 12 only; T1=left, T2=right, T0 excluded. Verify SHA-256 checksums, 64 named channels, 160 Hz, finite values, non-flat channels, and annotation timing. Require all three runs and five retained trials per class per run. Reject epochs above 500 µV peak-to-peak before filtering. Never select participants by accuracy.

Process each run independently. Average-reference, zero-phase FIR 8–30 Hz, then use samples from 1 inclusive to 3 exclusive seconds after the cue (320 samples). Filtering is offline and noncausal. The whole window must lie within the annotated task interval. No ICA, interpolation, tuning, or learned preprocessing outside training folds.

Hold out each run once, training on the other two runs. Compare a training-majority predictor; Welch log-bandpower (8–13 and 13–30 Hz, one-second segments, 50% overlap), training-only standardization and logistic regression C=1; and four-component log-variance CSP with Ledoit-Wolf covariance shrinkage followed by shrinkage LDA. Average referencing removes one spatial degree of freedom; CSP handles that rank reduction. Fixed models, no hyperparameter selection. Every trial receives one prediction per model.

## Paired comparisons
- CSP/LDA minus majority: 11.34 percentage points; 95% interval 7.07 to 15.80.
- CSP/LDA minus bandpower_lr: 1.80 percentage points; 95% interval -1.39 to 4.93.

## Label-shuffle diagnostic
Fixed participants S001–S003 if eligible, 20 repeats per fold. Shuffle labels within each training run and refit the entire pipeline; evaluate against original held-out labels. These repeated, dependent scores are a leakage diagnostic, not an inferential significance test.
- majority: mean shuffled-label balanced accuracy 50.0%.
- bandpower_lr: mean shuffled-label balanced accuracy 50.0%.
- csp_lda: mean shuffled-label balanced accuracy 49.7%.

## Participant exclusions
- S001: Run 4: fewer than five retained trials per class
- S003: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S004: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S009: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S010: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S012: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S013: Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S016: Run 4: fewer than five retained trials per class
- S017: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S019: Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S021: Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S022: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S023: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S024: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S027: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S028: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S032: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S033: Run 8: fewer than five retained trials per class
- S036: Run 12: fewer than five retained trials per class
- S039: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S043: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S044: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S045: Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S048: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S049: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S052: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S053: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S054: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S056: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S057: Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S059: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S060: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S061: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S065: Run 12: fewer than five retained trials per class
- S068: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S069: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S070: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class
- S075: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S077: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S079: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S080: Run 12: fewer than five retained trials per class
- S083: Run 4: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S084: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S086: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class
- S088: Run 4: unexpected sample rate: 128.0; Run 8: unexpected sample rate: 128.0; Run 12: unexpected sample rate: 128.0
- S089: Run 4: overlapping or out-of-bounds event timing; Run 8: overlapping or out-of-bounds event timing; Run 12: overlapping or out-of-bounds event timing
- S090: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S091: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S092: Run 4: unexpected sample rate: 128.0; Run 8: unexpected sample rate: 128.0; Run 12: unexpected sample rate: 128.0
- S094: Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S095: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S096: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S097: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S099: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S100: Run 4: unexpected sample rate: 128.0; Run 8: unexpected sample rate: 128.0; Run 12: unexpected sample rate: 128.0
- S103: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S106: Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S107: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S108: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class
- S109: Run 4: fewer than five retained trials per class; Run 8: fewer than five retained trials per class; Run 12: fewer than five retained trials per class

## Interpretation and limitations
These labels record the instructed task, not direct knowledge of a person's thoughts. Results describe within-participant, between-run offline decoding. They do not establish performance on unseen people, later sessions, live feedback, or clinical populations. Visual cues, eye/muscle artifacts, and run effects may contribute. The fixed amplitude threshold is a project choice, not a clinical threshold. Participants vary, and exclusions limit generalizability. Model probabilities are uncalibrated scores. Zero-phase filtering uses future samples, so neither replay timing nor computation time demonstrates real-time latency. Trial-wise cursor steps are a visualization of saved predictions, not continuous brain control.

## Replay selection
Choose unique participants nearest the 10th, 30th, 50th, 70th and 90th percentiles of CSP/LDA balanced accuracy, resolving ties by participant ID. Include all retained trials for those participants, including mistakes. Export average-referenced, band-pass-filtered C3/Cz/C4 in µV at 160 Hz; predict from 1–3 s, reveal at 3 s. The display contains samples from 0 inclusive to 3 exclusive seconds.

## Reproducibility
Python 3.12.6; seed 42; configuration SHA-256 `2d79f7a7b3e6dd4e1e65af766e9e86c122d4b2ad0f81aa1e71b0eb16ced3a078`. Full configuration, dependency versions, source hashes, source revision and dirty-tree flag are in results.json. File checksums and trial exclusions are in quality.json. See README.md for commands and requirements.lock.txt for all dependencies.

## Attribution
Dataset: https://physionet.org/content/eegmmidb/1.0.0/
License: Open Data Commons Attribution License v1.0 (https://opendatacommons.org/licenses/by/1-0/). Replay traces are derived from this dataset.

Schalk G. (2009). EEG Motor Movement/Imagery Dataset (version 1.0.0). PhysioNet. doi:10.13026/C28G6P.

Schalk G, McFarland DJ, Hinterberger T, Birbaumer N, Wolpaw JR. (2004). BCI2000: A General-Purpose Brain-Computer Interface (BCI) System. IEEE TBME 51(6):1034–1043. doi:10.1109/TBME.2004.827072.

Pollard T et al. (2026). PhysioNet as a global platform for biomedical research. Nature Health. doi:10.1038/s44360-026-00096-z.
