.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "generated/tutorials/00_stream_player.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_generated_tutorials_00_stream_player.py: StreamPlayer: simulate an LSL stream ==================================== Testing designs for online paradigm can be difficult. Access to hardware measuring real-time brain signals can be limited and time-consuming. With a `~bsl.StreamPlayer`, a fake data stream can be created and used to test code and experiment designs. .. GENERATED FROM PYTHON SOURCE LINES 12-18 .. code-block:: Python # Authors: Mathieu Scheltienne # # License: LGPL-2.1 .. GENERATED FROM PYTHON SOURCE LINES 20-33 .. warning:: Both `~bsl.StreamPlayer` and `~bsl.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 :ref:`bsl.datasets `. The dataset is stored in the user home directory, in the folder ``bsl_data``. .. GENERATED FROM PYTHON SOURCE LINES 35-42 .. code-block:: Python import time from bsl import StreamPlayer, datasets from bsl.lsl import resolve_streams from bsl.triggers import TriggerDef .. GENERATED FROM PYTHON SOURCE LINES 43-50 Starting a StreamPlayer ----------------------- A `~bsl.StreamPlayer` requires at least 2 arguments: - ``stream_name``, indicating a the name of the stream on the LSL network. - ``fif_file``, path to a valid `~mne.io.Raw` fif file. .. GENERATED FROM PYTHON SOURCE LINES 50-55 .. code-block:: Python stream_name = "StreamPlayer" fif_file = datasets.eeg_resting_state.data_path() print(fif_file) .. rst-class:: sphx-glr-script-out .. code-block:: none /home/runner/bsl_data/eeg_sample/resting_state-raw.fif .. GENERATED FROM PYTHON SOURCE LINES 56-67 Instance ^^^^^^^^ To create an LSL stream, create a `~bsl.StreamPlayer` and use the `~bsl.StreamPlayer.start` method. .. note:: By default, the `~bsl.StreamPlayer.start` method is blocking and will wait for the streaming to start on the network. This behavior can be changed with the ``blocking`` argument. .. GENERATED FROM PYTHON SOURCE LINES 67-72 .. code-block:: Python player = StreamPlayer(stream_name, fif_file) player.start() print(player) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 73-74 To verify if the stream is accessible on the network, use directly ``pylsl``: .. GENERATED FROM PYTHON SOURCE LINES 75-79 .. code-block:: Python streams = [stream.name for stream in resolve_streams()] print(streams) .. rst-class:: sphx-glr-script-out .. code-block:: none ['StreamPlayer'] .. GENERATED FROM PYTHON SOURCE LINES 80-81 To stop the streaming, use the `~bsl.StreamPlayer.stop` method. .. GENERATED FROM PYTHON SOURCE LINES 82-86 .. code-block:: Python player.stop() print(player) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 87-93 Context manager ^^^^^^^^^^^^^^^ A `~bsl.StreamPlayer` can also be used as a context manager with a ``with`` statement. The context manager takes care of starting and stopping the LSL stream. .. GENERATED FROM PYTHON SOURCE LINES 93-98 .. code-block:: Python with StreamPlayer(stream_name, fif_file): streams = [stream.name for stream in resolve_streams()] print(streams) .. rst-class:: sphx-glr-script-out .. code-block:: none ['StreamPlayer'] .. GENERATED FROM PYTHON SOURCE LINES 99-115 CLI ^^^ Finally, a `~bsl.StreamPlayer` can be called from the terminal with a command line. This is the recommended way of starting a `~bsl.StreamPlayer`. Example assuming the current working directory is ``bsl_data``: .. code-block:: console $ bsl_stream_player StreamPlayer eeg_sample\resting_state-raw.fif Hitting ``ENTER`` will stop the `~bsl.StreamPlayer`. .. image:: ../../_static/stream_player/stream_player_cli.gif :alt: StreamPlayer :align: center .. GENERATED FROM PYTHON SOURCE LINES 117-130 Additional arguments -------------------- A `~bsl.StreamPlayer` has 4 optional arguments: - ``repeat``, indicating the number of time the data in the file is repeated. - ``trigger_def``, either the path to a :class:`~bsl.triggers.TriggerDef` definition file or a :class:`~bsl.triggers.TriggerDef` instance, improving the logging of events found in the `~mne.io.Raw` fif file. - ``chunk_size``, indicating the number of samples push at once on the LSL outlet. - ``high_resolution``, indicating if `~time.sleep` or `~time.perf_counter` is used to wait between 2 push on the LSL outlet. .. GENERATED FROM PYTHON SOURCE LINES 132-143 repeat ^^^^^^ ``repeat`` is set by default to ``+inf``, returning to the beginning of the data in the `~mne.io.Raw` fif file each time the entire file has been 2 streamed. To limit the number of replay, an `int` can be passed. .. note:: ``eeg_resting_state_short`` is similar to ``eeg_resting_state`` but last 2 seconds instead of 40 seconds. .. GENERATED FROM PYTHON SOURCE LINES 143-149 .. code-block:: Python fif_file = datasets.eeg_resting_state_short.data_path() player = StreamPlayer(stream_name, fif_file, repeat=1) player.start() print(player) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 150-152 The dataset is streamed only once. A call to the `~bsl.StreamPlayer.stop` method is not necessary. .. GENERATED FROM PYTHON SOURCE LINES 153-157 .. code-block:: Python time.sleep(2) # duration of this dataset. print(player) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 158-169 trigger_def ^^^^^^^^^^^ :class:`~bsl.triggers.TriggerDef` can be used to assign a user-readable string to an event id. Providing a valid :class:`bsl.triggers.TriggerDef` to a `~bsl.StreamPlayer` improves the logging of events found on the ``TRIGGER`` channel. .. note:: ``eeg_auditory_stimuli`` contains a` alternation of rest events (1) lasting 1 second and of auditory stimuli events (4) lasting 0.8 second. .. GENERATED FROM PYTHON SOURCE LINES 169-182 .. code-block:: Python fif_file = datasets.eeg_auditory_stimuli.data_path() player = StreamPlayer(stream_name, fif_file) player.start() print(player) # wait a bit to get some events logged time.sleep(4) # stop player.stop() print(player) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 183-186 By default, the logging of events uses the ID with ``Events: ID``. If a :class:`bsl.triggers.TriggerDef` is provided, the logging message will include the corresponding event name if it exists with ``Events: ID (NAME)``. .. GENERATED FROM PYTHON SOURCE LINES 187-202 .. code-block:: Python tdef = TriggerDef() tdef.add("rest", 1) player = StreamPlayer(stream_name, fif_file, trigger_def=tdef) player.start() print(player) # wait a bit to get some events logged time.sleep(4) # stop player.stop() print(player) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 203-222 .. note:: A path to a valid ``.ini`` trigger definition file can be passed instead of a :class:`~bsl.triggers.TriggerDef` instance. The file is read with `configparser` and has to be structured as follows: .. code-block:: python [events] event_str_1 = event_id_1 # comment event_str_2 = event_id_2 # comment Example: .. code-block:: python [events] rest = 1 stim = 2 .. GENERATED FROM PYTHON SOURCE LINES 225-232 chunk_size ^^^^^^^^^^ ``chunk_size`` defines how many samples are pushed at once on the LSL oulet each time the `~bsl.StreamPlayer` sends data. The default ``16`` should work most of the time. A warning is emitted if the value is different from the usual ``16`` or ``32``. .. GENERATED FROM PYTHON SOURCE LINES 234-240 high_resolution ^^^^^^^^^^^^^^^ Between 2 push of samples on the LSL outlet, the `~bsl.StreamPlayer` waits. This sleep duration can be achieved either with `~time.sleep` or with `~time.perf_counter`. The second is more precise, but also uses more CPU. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 16.041 seconds) **Estimated memory usage:** 264 MB .. _sphx_glr_download_generated_tutorials_00_stream_player.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 00_stream_player.ipynb <00_stream_player.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 00_stream_player.py <00_stream_player.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 00_stream_player.zip <00_stream_player.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_