Designing Real‑Time EEG Pipelines with LSL
When you're working with EEG data streams—especially in a real-time setup where multiple modalities converge—Lab Streaming Layer (LSL) becomes indispensable. In this post, I'll walk through how I designed a real-time EEG processing pipeline that synchronizes across modalities (vision, olfaction, and triggers), performs artifact rejection, and extracts temporal features—all with minimal latency.
The Challenge: Multimodal Synchronization
In behavioral neuroscience experiments, data streams arrive from different sources at different rates:
- EEG at 500 Hz (or higher)
- Sniff triggers at irregular intervals
- Olfactory event markers
- Vision timestamps from cameras
The core problem? Getting all these streams to agree on a single, shared timeline. That's where LSL's network-based time synchronization shines.
Architecture Overview
The pipeline consists of three main stages:
- Stream Acquisition: LSL inlets pull data from multiple outlets with automatic clock synchronization
- Preprocessing: Bandpass filtering (0.5-50 Hz), artifact rejection using amplitude thresholds and gradient checks
- Feature Extraction: Temporal features including Hjorth parameters (activity, mobility, complexity) and sample entropy
Implementation Details
Here's how the real-time processing unfolds:
- Buffering Strategy: Maintain a sliding window (e.g., 2 seconds) that updates with every new chunk
- Filter Design: Butterworth bandpass with minimal phase distortion
- Artifact Detection: Reject epochs where voltage exceeds ±100 μV or gradient exceeds a threshold
- Feature Computation: Calculate Hjorth parameters and entropy metrics on clean epochs
- Downstream ML: Features fed into an LSTM model for behavior prediction (~90% recall)
Key Takeaways
- LSL's time synchronization is rock-solid for multimodal setups
- Real-time artifact rejection is crucial—don't let bad epochs poison your features
- Temporal features (Hjorth, entropy) capture dynamics that frequency-domain features miss
- Keep latency low: process in chunks, but don't let buffer sizes balloon
Tools Used
Python • LSL (pylsl) • SciPy • NumPy • PyTorch (LSTM)