Overview
Neurodecode provides a real-time brain signal decoding framework with a modular software design. Its decoding performance was recognised at the Microsoft Brain Signal Decoding competition with the First Prize Award (2016) for high decoding accuracy — 2nd out of 1863 algorithms.
It has been applied to online decoding projects across a wide range of electrode types — EEG, ECoG, DBS, and microelectrode arrays — and acquisition systems, including AntNeuro eego, g.tec gUSBamp, BioSemi ActiveTwo, BrainProducts actiCHamp, and Wearable Sensing.
Decoding runs at roughly 15 classifications per second (cps) on a 4th-gen i7 laptop with a 64-channel setup at 512 Hz. High-speed decoding of up to 200 cps has been achieved using a process-interleaving technique on 8 cores. Neurodecode is tested on both Linux and Windows with Python 3.8+.
The underlying data communication is built on the Lab Streaming Layer (LSL), which provides sub-millisecond time-synchronization accuracy. Any signal-acquisition system supported natively by LSL or by OpenVibe is supported by Neurodecode. Because the transport is TCP-based, signals can also be transmitted wirelessly.
Modules
| Module | Description |
|---|---|
| StreamReceiver | Base module for acquiring signals, used by Decoder, StreamViewer, and StreamRecorder. |
| StreamViewer | Visualize signals in real time with spectral filtering, common-average filtering, and real-time FFT. |
| StreamRecorder | Record signals into fif format, the standard used by the MNE EEG analysis library. |
| StreamPlayer | Replay recorded signals in real time, as if streamed from a live acquisition server. |
| Decoder | Decoder and trainer modules. Supports LDA, regularized LDA, Random Forests, and Gradient Boosting out of the box; custom (e.g. neural-network) decoders can be added. |
| Protocols | Basic protocols for training and testing. Google Glass visual feedback is supported over USB. |
| Triggers | Mark event (stimulus) timings during recording. Includes common trigger event-definition files. |
| Utils | Various utilities. |
Requirements
- Python 3.8+ (Anaconda is recommended for an easy environment setup)
- numpy, scipy, scikit-learn
- MNE 1.10+
- matplotlib, pyqtgraph, PyQt5
- pylsl
- opencv-python, pyserial, psutil
- xgboost, lightgbm
All of these are installed automatically with the package (see below).
Optional but strongly recommended: OpenVibe. OpenVibe supports a wide range of acquisition servers, all of which become available to Neurodecode through LSL. When you run the acquisition server, tick "LSL_EnableLSLOutput" in Preferences so the data is streamed over the LSL network for Neurodecode to receive.
Installation
Create a fresh virtual environment (Python 3.8 or higher):
conda create --name nd python=3.10
conda activate nd
Install the latest release from PyPI:
pip install neurodecode
Or install the development version from source:
git clone https://github.com/dbdq/neurodecode.git
cd neurodecode
pip install --editable .
Add the scripts directory to your PATH for convenient access to the commonly used command-line tools.
Troubleshooting: PyQt version conflicts
The Qt API is sensitive to versioning and must be compatible with all dependencies. If pyqtgraph complains about an incompatible PyQt version (e.g. PyQt < 5.12), try:
conda remove pyqt
pip install -U PyQt5
This is usually caused by Anaconda not shipping the latest PyQt version.
Windows: increase timer resolution
The default timer resolution on some Windows versions is 16 ms, which limits timing precision. Run the following tool and set the resolution to 1 ms or lower: Windows System Timer Tool
Hardware triggering without a legacy parallel port
We developed an Arduino-based triggering system to send triggers to a parallel port over standard USB, achieving sub-millisecond extra latency compared to a physical parallel port (150 ± 25 µs). Oscilloscope results are in the doc folder.
git clone https://github.com/dbdq/arduino-trigger.git
The customized firmware should be flashed to an Arduino Micro, and the circuit design in the document folder printed to a circuit board.
g.USBamp users
Use the following customized acquisition server instead of the default LSL app, so the trigger channel is streamed as part of the signal channels:
git clone https://github.com/dbdq/gUSBamp_pycnbi.git
The default gUSBamp LSL server streams the event channel as a separate server rather than as part of the signal stream; the customized version supports simultaneous signal + event streaming.
AntNeuro eego users
Use the OpenVibe acquisition server and enable "LSL output" in preferences. If "eego" does not appear in the device list, it is likely that the additional drivers were not installed with OpenVibe.
Running the examples
Copy the /sample folder to a local folder and cd into it.
1. Play data
Replay a pre-recorded EEG sample in real time, as if acquiring live signals, with a chunk size of 8. The sample was recorded from a 24-channel EEG system while a participant performed left- and right-hand motor imagery. Hardware events recorded during the experiment are also streamed over LSL.
nd_stream_player mi_left_right.fif 8
Setting up an LSL server and streaming the recorded data:
2. Record data
Simulate real-time decoding from the brain. Data is streamed with nd_stream_player (above) while the receiver stays source-agnostic, enabling a full simulation of replay and validation of the processing pipeline. You can skip this step by creating a ./fif/ folder and copying the sample fif file into it.
nd_stream_recorder $PWD # Linux
nd_stream_recorder %CD% # Windows
3. Real-time signal visualisation
Choose StreamPlayer from the list. Cursor keys change the amplitude and time scaling.
nd_stream_viewer
4. Run an offline protocol for training
Runs an offline training protocol. This step is illustrative and can be skipped.
nd_train_mi ./config_offline.py
5. Train a decoder
Train a decoder from the fif file using defined events — here, left (event 11) vs. right (event 9) hand motor imagery. Events are defined in mi_left_right_events.ini.
nd_trainer ./config_trainer.py
6. Run an online protocol for testing
The sample is set to a 60-second time-out with no early termination, so you can watch the decoder output shift toward left or right as event 11 (left) or event 9 (right) is emitted from the stream player terminal. Other events, such as rest, are undefined and produce random behaviour.
nd_test_mi config_online.py
Bar position during the protocol:
Decoder output with probabilities and the corresponding bar position (accumulated probabilities):
Events emitted from the stream player:
There is still plenty of room to optimize speed across the codebase, and contributions are very welcome. For comments or feedback, contact lee.kyuh@gmail.com.
License
Released under the GNU General Public License.
Citation
If any of this code was useful for your project, please consider citing below paper that conceived this project:
- Kyuhwa Lee et al., "A Brain-Controlled Exoskeleton with Cascaded Event-Related Desynchronization Classifiers," Robotics and Autonomous Systems, Elsevier, 2016, p. 15–23.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file neurodecode-2.2.tar.gz.
File metadata
- Download URL: neurodecode-2.2.tar.gz
- Upload date:
- Size: 112.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4eee2de6dbac78b8b11cb080ce416b49d4a0f81b4e51d714d8528ace57153e3b
|
|
| MD5 |
182b304c4424464c843c9be28cf5ea4b
|
|
| BLAKE2b-256 |
aacaf057cd3819f853dd0727d1f00d7ce517fa53d576aed070cddf8fc2d24b89
|
File details
Details for the file neurodecode-2.2-py3-none-any.whl.
File metadata
- Download URL: neurodecode-2.2-py3-none-any.whl
- Upload date:
- Size: 138.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
202b810caad1f1dd39466905e85f59b78ae83575b98c96c15392366c50219c24
|
|
| MD5 |
d9c2c5b269d8cc92fc06cc471cc04d13
|
|
| BLAKE2b-256 |
9dd3adca27bb0f513a13f47ba5cb1e1a0aa71d2fc3c294226a36f8f51a624f81
|