BrainStreamingLayer real-time framework for online neuroscience research through LSL-compatible devices.
BrainStreamingLayer provides a real-time brain signal streaming framework. BSL is a wrapper around the python interface to the Lab Streaming Layer (LSL). BSL goal is to simplify the design of a study using the Lab Streaming Layer which provides sub-millisecond time synchronization accuracy.
Any signal acquisition system supported by native LSL or OpenVibe is also supported by BSL. Since the data communication is based on TCP, signals can be transmitted wirelessly. For more information about LSL, please visit the LSL github.
BSL is based on NeuroDecode. The original version developped by Kyuhwa Lee was recognised at Microsoft Brain Signal Decoding competition with the First Prize Award (2016) after achieving high decoding accuracy. BSL is based on the refactor version by Arnaud Desvachez for the Fondation Campus Biotech Geneva (FCBG). The low-level functionnalities have been reworked and improved, while the decoding functionnalities have been dropped.
python >= 3.6 and requires:
Optional dependencies for trigger via an Arduino to LPT converter:
Optional dependencies for StreamViewer alternative backends:
BSL can be installed in normal mode with
python setup.py install or in
developement mode with
python setup.py develop. Optional dependencies can be
installed using the keywords:
BSL is centered around 4 main modules:
The stream receiver connects to one or more LSL streams and acquires data from those. Supported streams are:
from bsl import StreamReceiver # Connects to all available streams sr = StreamReceiver(bufsize=1, winsize=1, stream_name=None) # Update each stream buffer with new data sr.acquire() # Retrieve buffer/window for the stream named 'StreamPlayer' data, timestamps = sr.get_window(stream_name='StreamPlayer')
The data and its timestamps are returned as numpy array:
data.shape = (samples, channels)
timestamps.shape = (samples, )
The data can be returned as an MNE raw instance if
return_raw is set to
The stream recorder connects to one or more LSL streams and periodically
acquires data from those until stopped, and then saves the acquired data to
disk in pickle
.pcl and in FIF
import time from bsl import StreamRecorder # Connects to all available streams recorder = StreamRecorder(record_dir=None, fname=None, stream_name=None, verbose=True) recorder.start() time.sleep(10) recorder.stop()
When the argument
record_dir is set to None, the current folder obtained with
pathlib.Path.cwd() is used. When the argument
fname is set to None, the
created files' stem use the start datetime.
CLI: The stream recorder can be called by command-line in a terminal by
bsl stream_recorder or
bsl_stream_recorder followed by the
-s respectively for
stream_name, and the optional flags
bsl_stream_recorder -d "D:/Data" bsl_stream_recorder -d "D:/Data" -f test bsl_stream_recorder -d "D:/Data" -f test -s openvibeSignals
The stream player loads a previously recorded
.fif file and creates a LSL
server streaming data from this file. The stream player can be used to test
code with a fake LSL data stream.
import time from bsl import StreamPlayer sp = StreamPlayer(stream_name='StreamPlayer', fif_file=r'path to .fif') sp.start() time.sleep(10) sp.stop()
CLI: The stream player can be called by command-line in a terminal by
bsl stream_player or
bsl_stream_player followed by positional
fif_file and the optional arguments
-t respectively for
trigger_def, and the
bsl_stream_player StreamPlayer "D:/Data/data-raw.fif" bsl_stream_player StreamPlayer "D:/Data/data-raw.fif" -c 16 bsl_stream_player StreamPlayer "D:/Data/data-raw.fif" -c 16 -t "D:/triggerdef.ini"
The stream viewer creates a 2-window GUI composed of a control GUI and a plotter GUI to display the data acquired from an LSL server in real-time.
CLI: The stream viewer can be called by command-line in a terminal by using
bsl stream_viewer or
bsl_stream_viewer followed by the optional
-b respectively for the
backend. If no
stream name is provided, a prompt will ask the user to select the desired
non-marker stream to display. The supported backends are
pyqt5 (default) and
bsl_stream_viewer bsl_stream_viewer -s StreamPlayer bsl_stream_viewer -s StreamPlayer -b vispy
Triggers includes functions to mark time event by sending a trigger which will be saved on the TRIGGER channel of the on-going recording. Triggers can be achieved either through hardware or through software.
Currently, the supported hardware triggers use an LPT port.
import time from bsl import StreamRecorder from bsl.triggers.software import TriggerSoftware from bsl.triggers.lpt import TriggerArduino2LPT # Software trigger recorder = StreamRecorder() recorder.start() trigger = TriggerSoftware(recorder) for k in range(1, 5): trigger.signal(k) time.sleep(1) trigger.close() recorder.stop() # Hardware trigger through Arduino LPT converter recorder = StreamRecorder() recorder.start() trigger = TriggerArduino2LPT() for k in range(1, 5): trigger.signal(k) time.sleep(1) trigger.close() recorder.stop()
Note that closing the trigger before stopping the recording may not be required for all kind of triggers.
Copyright and license
The codes are released under GNU Lesser General Public License.
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.