Note
Click here to download the full example code
StreamRecorder: resting-state recording#
A resting-state recording is a simple offline recording during which the brain
activity of a subject is measured in the absence of any stimulus or task. A
resting-state recording can be designed with a StreamRecorder
.
# Authors: Mathieu Scheltienne <mathieu.scheltienne@fcbg.ch>
#
# License: LGPL-2.1
Warning
Both StreamPlayer
and StreamRecorder
create a new process
to stream or record data. On Windows, mutliprocessing suffers a couple of
restrictions. The entry-point of a multiprocessing program should be
protected with if __name__ == '__main__':
to ensure it can safely
import and run the module. More information on the
documentation for multiprocessing on Windows.
This example will use a sample EEG resting-state dataset that can be retrieve
with bsl.datasets. The dataset is stored in the user home
directory in the folder bsl_data
(e.g. C:\Users\User\bsl_data
).
import os
from pathlib import Path
import time
import mne
from bsl import StreamPlayer, StreamRecorder, datasets
from bsl.triggers.software import SoftwareTrigger
To simulate an actual signal coming from an LSL stream, a StreamPlayer
is used with a 40 seconds resting-state recording.
stream_name = 'StreamPlayer'
fif_file = datasets.eeg_resting_state.data_path()
player = StreamPlayer(stream_name, fif_file)
player.start()
print (player)
Out:
<Player: StreamPlayer | ON | /Users/scheltie/bsl_data/eeg_sample/resting_state-raw.fif>
For this example, the folder bsl_data/examples
located in the user home
directory will be used to stored recorded files. To ensure its existence,
os.makedirs
is used.
record_dir = Path('~/bsl_data/examples').expanduser()
os.makedirs(record_dir, exist_ok=True)
print (record_dir)
Out:
/Users/scheltie/bsl_data/examples
For this simple offline recording, the goal is to start a
StreamRecorder
, send an event on a trigger to mark the beginning of
the resting-state recording, wait for a defined duration, and stop the
recording.
By default, a StreamRecorder
does not require any argument. The
current working directory is used to record data from all available streams
in files named based on the date/time timestamp at which the recorder is
started.
To record only a subset of the available streams with a specific file name
and in a specific directory, the arguments record_dir
, fname
and
stream_name
must be provided.
For this example, the directory used to store recordings is
bsl_data/examples
and the file name will start with
example-resting-state
.
Note
By default, the start
method is blocking and will
wait for the recording to start. This behavior can be changed with the
blocking
argument.
recorder = StreamRecorder(record_dir, fname='example-resting-state')
recorder.start()
print (recorder)
Out:
<Recorder: All streams | ON | /Users/scheltie/bsl_data/examples>
Now that a StreamRecorder
is started and is acquiring data, a trigger
to mark the beginning of the segment of interest is created. For this
example, a SoftwareTrigger
is used, but this example
would be equally valid with a different type of trigger.
Note
SoftwareTrigger
must be created after a
StreamRecorder
is started and closed/deleted before a
StreamRecorder
is stopped.
recorder = StreamRecorder()
recorder.start()
trigger = SoftwareTrigger(recorder)
# do stuff
trigger.close() # OR >>> del trigger
recorder.stop()
All triggers do not need an active StreamRecorder
to be created.
trigger = SoftwareTrigger(recorder, verbose=True)
To mark the beginning of the segment of interest in the recording, a signal is sent on the trigger. For this example, the event value (1) is used.
Finally, after the appropriate duration, the recording is interrupted.
Note
SoftwareTrigger
must be closed or deleted before
the recorder is stopped. All triggers do not need to be closed or deleted
before the recorder is stopped.
time.sleep(2) # 2 seconds duration
trigger.close()
recorder.stop()
print (recorder)
Out:
<Recorder: All streams | OFF | /Users/scheltie/bsl_data/examples>
A StreamRecorder
records data in .pcl
format. This file can be
open with pickle.load
, and is automatically converted to a Raw
FIF file in a subdirectory fif
. The recorded files name syntax is:
If
fname
is not provided:[date/time timestamp]-[stream]-raw.fif
If
fname
is provided:[fname]-[stream]-raw.fif
Where stream
is the name of the recorded LSL stream. Thus, one file is
created for each stream being recorded.
fname = record_dir / 'fif' / 'example-resting-state-StreamPlayer-raw.fif'
raw = mne.io.read_raw_fif(fname, preload=True)
print (raw)
events = mne.find_events(raw, stim_channel='TRIGGER')
print (events)
Out:
<Raw | example-resting-state-StreamPlayer-raw.fif, 65 x 1056 (2.1 s), ~606 kB, data loaded>
[[18 0 1]]
As for the StreamPlayer
, the StreamRecorder
can be used as a
context manager. The context manager takes care of starting and stopping the
recording.
with StreamRecorder(record_dir):
time.sleep(1)
As for the StreamPlayer
, the StreamRecorder
can be started via
command-line when a LSL stream is accessible on the network.
Example assuming:
the current working directory is
bsl_data
in the user home directorythe stream to connect to is named
MyStream
the recorded file naming scheme is
test-[stream]-raw.fif
, i.e.test-MyStream-raw.fif
$ bsl_stream_recorder -d examples -f test -s MyStream

Total running time of the script: ( 0 minutes 9.993 seconds)