Standalone PyQt6 app for the EEG reactivation decoder pipeline.
- Phase 1 (offline): operator-driven 5-node workflow — Settings → Load
Data → Preprocess → Evaluate → Train. Produces
decoder_pipeline.joblib. - Phase 2 (online): real-time inference against an LSL stream, consuming the artifact produced by Phase 1.
- Python 3.10+ (3.11 recommended)
- Windows is required for the live LSL stream path
(
tools/lslproxy/LSLProxy.exe). Phase 1 and the full test suite work on Windows, macOS, Linux, and WSL.
cd online_decoder
python -m venv .venvActivate the venv:
- Windows PowerShell:
.venv\Scripts\Activate.ps1(one-time only, if PowerShell blocks the script:Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser) - macOS / Linux / WSL:
source .venv/bin/activate
Then:
pip install -r requirements-dev.txtrequirements-dev.txt transitively includes requirements.txt (via
the first-line -r reference), so this single install covers both the
app's runtime deps and the tooling needed to run tests + debug scripts.
For a strict production-runtime-only install, use
pip install -r requirements.txt instead — but you won't be able to
run pytest or the scripts/ helpers.
# Windows PowerShell
$env:PYTHONPATH = "src"
python -m frontend.main# macOS / Linux / WSL
PYTHONPATH=src python -m frontend.mainThen walk the Phase 1 trail in order:
- Settings — pick
experiment_config.yaml+ output directory → Continue - Load Data — pick a BrainVision folder (
.vhdr+.vmrk+.eeg) → Load Data - Preprocess — Start Preprocessing
- MNE's bad-channel window pops modally; click channels to mark, then close
- MNE's ICA review window pops modally with ICLabel pre-suggestions;
verify/override
ica.exclude, then close
- Evaluation — Run Evaluation → pick a timepoint on the AUC chart → Approve & Continue
- Train — ▶ → "Trained at: N ms" + spatial-pattern topomaps
Output: decoder_pipeline.joblib in the directory chosen in step 1.
Fast path for iterating on UI screens without sitting through ~5 min of real preprocessing each time. One-time seed from a real recording, then drive the whole pipeline with Ctrl+→.
python -m scripts.demo_seed_debug_snapshots --data <path/to/subject>
python -m frontend.debug.mainSee src/frontend/debug/README.md for the full walkthrough mechanics.
pytest -q --deselect tests/online_phase/test_stream_worker.pyExpected: 322 passed, 1 skipped, 11 deselected.
- The 1 skip is
test_lsl_receiver_integration.py, gated behindRUN_LSL_INTEGRATION=1— runs only against a real LSL stream. - The 11 deselections are
test_stream_worker.py, which needspytest-qt/qtbotand a live LSL outlet; it's not a regression.
- Backend:
src/backend/offline_phase/,src/backend/online_phase/ - Frontend (PyQt6):
src/frontend/ - Config:
experiment_config.yaml(schema insrc/backend/core/config_models.py) - Architecture: docs/backend_architecture.md
- Preprocessing migration history: docs/Preprocessing_Migration_Plan.md
- Repo conventions: CLAUDE.md