Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

648 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Neurodecode

A real-time brain signal decoding framework with a modular software design.

License: GPL v3 Python PyPI Platform Built on LSL


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

ModuleDescription
StreamReceiverBase module for acquiring signals, used by Decoder, StreamViewer, and StreamRecorder.
StreamViewerVisualize signals in real time with spectral filtering, common-average filtering, and real-time FFT.
StreamRecorderRecord signals into fif format, the standard used by the MNE EEG analysis library.
StreamPlayerReplay recorded signals in real time, as if streamed from a live acquisition server.
DecoderDecoder 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.
ProtocolsBasic protocols for training and testing. Google Glass visual feedback is supported over USB.
TriggersMark event (stimulus) timings during recording. Includes common trigger event-definition files.
UtilsVarious 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:

Stream player

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

Stream recorder

3. Real-time signal visualisation

Choose StreamPlayer from the list. Cursor keys change the amplitude and time scaling.

nd_stream_viewer

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

Offline protocol

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:

Online protocol

Decoder output with probabilities and the corresponding bar position (accumulated probabilities):

Decoder output

Events emitted from the stream player:

Events

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.

About

A framework for real-time brain-machine interface

Resources

Stars

55 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages