This repository contains two EEG tasks completed in Python:
- Sleep spindle detection using a manual signal-processing pipeline and comparison against YASA.
- Motor imagery classification using Common Spatial Patterns (CSP) with LDA and linear SVM baselines.
The work follows the assignment requirements for:
- Part 1: ANPHY-Sleep participants 11-15 (Dataset Link)
- Part 2: PhysioNet EEG Motor Movement/Imagery Dataset (Dataset Link)
Detect sleep spindles in EEG and compare a transparent manual detector against an automated baseline.
The manual detector was built as a simple, interpretable approximation of spindle-band energy tracking:
- broad band-pass filter: 0.5-30 Hz
- single central lead selection
- spindle-band filter: 11-16 Hz
- Hilbert amplitude envelope
- envelope smoothing
- thresholding with mean + k * std
- duration filtering: 0.5-2.0 s
- benchmark comparison against YASA
- Chosen channel:
CZ - Spindle band:
11-16 Hz - Envelope smoothing:
100 ms - Threshold multiplier:
k = 1.2 - Duration bounds:
0.5-2.0 s
C3, CZ, and C4 were visually inspected across early, middle, and late N2 windows. C4 showed repeated drift/noise, while CZ gave stable central activity across participants and was selected as the common lead for comparison.
- The manual detector matched YASA reasonably well on some participants, especially EPCTL11 and EPCTL14.
- It was less stable on others, especially EPCTL13 and EPCTL15, showing the weakness of a fixed global amplitude threshold.
- The manual detector generally produced shorter average spindle durations than YASA.
- The raw Hilbert envelope was noisy, so smoothing was necessary to reduce fragmentation of events.
The manual pipeline is useful as a clear engineering baseline because every step is easy to explain. However, it is also brittle across subjects. In practice, the comparison shows why automated tools such as YASA are often more robust for multi-subject spindle analysis.
Classify left vs right hand motor imagery using a classical EEG decoding pipeline.
- dataset audit across all available subjects
- event parsing for motor imagery runs
- band-pass filtering in the motor-imagery range
- cue-locked epoching
- CSP feature extraction
- classifier comparison:
- LDA
- linear SVM
- subject-wise Leave-One-Session-Out (LOSO) validation
- confusion matrices, PSD plots, and CSP spatial pattern maps
- Filter band:
8-30 Hz - Epoch window:
-1.0 to 4.0 s - Baseline window:
-1.0 to 0.0 s - Classifier window:
0.5 to 3.5 s - CSP components:
4 - LDA:
solver="svd" - SVM:
kernel="linear", C=1.0 - Validation: LOSO across runs
R04,R08,R12
- 109 subjects were audited.
- 106 subjects were used in the clean baseline.
- 3 subjects (
S088,S092,S100) were excluded from the main baseline because their runs were sampled at 128 Hz instead of the expected 160 Hz.
- CSP + LDA: mean LOSO accuracy about 0.615
- CSP + SVM: mean LOSO accuracy about 0.617
- Both models performed very similarly.
- The difference between LDA and SVM was small, so the bigger issue was not classifier choice.
- The harder problem was subject/session variability.
- This makes the project a good example of how much performance in EEG decoding depends on preprocessing, fold design, and signal stability.
A classical CSP + linear classifier pipeline gives a solid and explainable baseline for binary motor imagery. It does not solve all variability issues, but it is a strong first benchmark and aligns well with standard BCI literature.
- Re-running YASA inside plotting code was too expensive, so benchmark detections were cached and reused.
- A fixed amplitude threshold did not generalize equally across all participants.
- Envelope smoothing was required because the unsmoothed Hilbert envelope split real events into short fragments.
- CSP was fit only on training folds to avoid data leakage.
- Random trial splits were avoided because they would be too optimistic for multi-run EEG data.
- Channel names required cleanup because some EDF labels contained trailing dots.
- A subject exclusion decision was documented instead of silently mixing 128 Hz and 160 Hz recordings in the same clean baseline.
.
├── figures/ # Generated plots and visual proofs
├── notebooks/ # Primary analysis notebooks
│ ├── part1_spindles.ipynb
│ └── part2_motor_imagery.ipynb
├── notes/ # Research notes and roadblock docs
├── results/ # CSV summaries and evaluation metrics
│ ├── part1/
│ └── part2/
├── src/ # Reusable Python utility modules
├── main.py # Pipeline entry point
├── pyproject.toml # Python project configuration (uv)
├── requirements.txt # Project dependencies
└── README.md # Project documentation
This project uses uv for lightning-fast dependency management. To set up the exact environment from the provided pyproject.toml and uv.lock files, run:
uv syncRun: notebooks/part1_spindles.ipynb
Expected outputs:
- lead inspection summary
- manual spindle detections
- YASA comparison tables
- overlay plots and PSD plots
Run: notebooks/part2_motor_imagery.ipynb
Expected outputs:
- dataset audit summary
- PSD before/after filtering
- LOSO results for LDA and SVM
- confusion matrices
- CSP spatial pattern plots
- Large EEG datasets are not included in the repository.
- Update dataset paths in the notebooks before running.
- Reproduce figures and CSV summaries by running the notebooks from top to bottom.
- For Part 2, keep the current anti-leakage design: fit CSP only inside each training fold.
[1] Tsanas, A., & Clifford, G. D. (2015). Stage-independent, single lead EEG sleep spindle detection using the continuous wavelet transform and local weighted smoothing. Frontiers in Human Neuroscience, 9, 181. https://doi.org/10.3389/fnhum.2015.00181
[2] Pfurtscheller, G., & Lopes da Silva, F. H. (1999). Event-related EEG/MEG synchronization and desynchronization: basic principles. Clinical Neurophysiology, 110(11), 1842-1857. https://doi.org/10.1016/S1388-2457(99)00141-8
[3] Ramoser, H., Muller-Gerking, J., & Pfurtscheller, G. (2000). Optimal spatial filtering of single trial EEG during imagined hand movement. IEEE Transactions on Rehabilitation Engineering, 8(4), 441-446. https://doi.org/10.1109/86.895946
- Part 1 is grounded in the spindle-detection literature, but the implementation here uses a simplified Hilbert-envelope baseline instead of reproducing the full CWT-based method in [1].
- Part 2 uses the ERD/ERS interpretation from [2] and the CSP-based decoding approach from [3] as the main methodological references.