.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "generated/tutorials/10_low_level_API.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_10_low_level_API.py: .. _tut-low-level-api: Low-level LSL API ================= .. include:: ./../../links.inc LSL is a library designed for streaming time series data across different platforms and programming languages. The `core library `_ is primarily written in C++, and bindings are accessible for Python, C#, Java, MATLAB, and Unity, among others. You can find a comprehensive list `here `_. MNE-LSL provides a reimplementation of the `python binding `_, known as ``pylsl``, within the ``mne_lsl.lsl`` module. It introduces additional functionalities to simplify the low-level interaction with LSL streams. Moreover, it enhances the detection of liblsl on your system and can retrieve a compatible version online if necessary. The differences between ``pylsl`` and ``mne_lsl.lsl`` are detailed :ref:`here`. .. GENERATED FROM PYTHON SOURCE LINES 21-36 .. code-block:: Python import time import uuid import numpy as np from mne_lsl.lsl import ( StreamInfo, StreamInlet, StreamOutlet, local_clock, resolve_streams, ) .. GENERATED FROM PYTHON SOURCE LINES 38-46 Creating a stream ----------------- To create a stream, you must first define its properties. This is achieved by creating a :class:`~mne_lsl.lsl.StreamInfo` object, which specifies the stream's name, type, source and properties. Convenience methods are available to set the channel properties, including :meth:`~mne_lsl.lsl.StreamInfo.set_channel_info`, which uses a :class:`mne.Info` object as source. .. GENERATED FROM PYTHON SOURCE LINES 46-59 .. code-block:: Python sinfo = StreamInfo( name="my-stream", stype="eeg", n_channels=3, sfreq=1024, dtype="float32", source_id=uuid.uuid4().hex, ) sinfo.set_channel_names(["Fz", "Cz", "Oz"]) sinfo.set_channel_types("eeg") sinfo.set_channel_units("microvolts") .. GENERATED FROM PYTHON SOURCE LINES 60-62 Once the :class:`~mne_lsl.lsl.StreamInfo` object is created, a :class:`~mne_lsl.lsl.StreamOutlet` can be instantiated to create the stream. .. GENERATED FROM PYTHON SOURCE LINES 62-65 .. code-block:: Python outlet = StreamOutlet(sinfo) .. GENERATED FROM PYTHON SOURCE LINES 66-77 Discover streams ---------------- At this point, the :class:`~mne_lsl.lsl.StreamOutlet` is available on the network. The function :func:`~mne_lsl.lsl.resolve_streams` discovers all available streams on the network. This operation is commonly named the stream resolution. .. note:: The stream resolution can be restricted by providing the ``name``, ``stype``, and ``source_id`` arguments. .. GENERATED FROM PYTHON SOURCE LINES 77-82 .. code-block:: Python streams = resolve_streams() assert len(streams) == 1 streams[0] .. rst-class:: sphx-glr-script-out .. code-block:: none < sInfo 'my-stream' > | Type: eeg | Sampling: 1024.0 Hz | Number of channels: 3 | Data type: | Source: 010be0b6c5b34d10b96c7c6a9de8e1bb .. GENERATED FROM PYTHON SOURCE LINES 83-86 The resolution retrieves only the stream basic properties. The channel properties, stored in the stream description in an XML element tree, are absent from a :class:`~mne_lsl.lsl.StreamInfo` returned by the resolution function. .. GENERATED FROM PYTHON SOURCE LINES 86-89 .. code-block:: Python assert streams[0].get_channel_names() is None .. GENERATED FROM PYTHON SOURCE LINES 90-97 Connect to a Stream ------------------- To connect to a stream, a :class:`~mne_lsl.lsl.StreamInlet` object must be created using the resolved :class:`~mne_lsl.lsl.StreamInfo`. Once the stream is opened with :meth:`~mne_lsl.lsl.StreamInlet.open_stream`, the connection is established and both the properties and data become available. .. GENERATED FROM PYTHON SOURCE LINES 97-102 .. code-block:: Python inlet = StreamInlet(streams[0]) inlet.open_stream() sinfo = inlet.get_sinfo() # retrieve stream information with all properties .. GENERATED FROM PYTHON SOURCE LINES 103-106 .. code-block:: Python sinfo.get_channel_names() .. rst-class:: sphx-glr-script-out .. code-block:: none ['Fz', 'Cz', 'Oz'] .. GENERATED FROM PYTHON SOURCE LINES 107-110 .. code-block:: Python sinfo.get_channel_types() .. rst-class:: sphx-glr-script-out .. code-block:: none ['eeg', 'eeg', 'eeg'] .. GENERATED FROM PYTHON SOURCE LINES 111-114 .. code-block:: Python sinfo.get_channel_units() .. rst-class:: sphx-glr-script-out .. code-block:: none ['microvolts', 'microvolts', 'microvolts'] .. GENERATED FROM PYTHON SOURCE LINES 115-119 An :class:`mne.Info` can be obtained directly with :meth:`~mne_lsl.lsl.StreamInfo.get_channel_info`. If the information contained in the XML element tree can not be parsed, default values are used. For instance, the channel names are replaced by the channel numbers similarly to :func:`mne.create_info`. .. GENERATED FROM PYTHON SOURCE LINES 119-122 .. code-block:: Python sinfo.get_channel_info() .. raw:: html
General
MNE object type Info
Measurement date Unknown
Participant Unknown
Experimenter Unknown
Acquisition
Sampling frequency 1024.00 Hz
Channels
EEG
Head & sensor digitization Not available
Filters
Highpass 0.00 Hz
Lowpass 512.00 Hz


.. GENERATED FROM PYTHON SOURCE LINES 123-133 Push/Pull operations -------------------- For new data to be received, it first need to be pushed on the :class:`~mne_lsl.lsl.StreamOutlet`. 2 methods are available: * :meth:`~mne_lsl.lsl.StreamOutlet.push_sample` to push an individual sample of shape (n_channels,) * :meth:`~mne_lsl.lsl.StreamOutlet.push_chunk` to push a chunk of samples of shape (n_samples, n_channels) .. GENERATED FROM PYTHON SOURCE LINES 133-136 .. code-block:: Python outlet.push_sample(np.array([1, 2, 3])) .. GENERATED FROM PYTHON SOURCE LINES 137-144 Once pushed, samples become available at the client end. 2 methods are available to retrieve samples: * :meth:`~mne_lsl.lsl.StreamInlet.pull_sample` to pull an individual sample of shape (n_channels,) * :meth:`~mne_lsl.lsl.StreamInlet.pull_chunk` to pull a chunk of samples of shape (n_samples, n_channels) .. GENERATED FROM PYTHON SOURCE LINES 144-152 .. code-block:: Python # give a bit of time to the documentation build after the execution of the last cell time.sleep(0.01) assert inlet.samples_available == 1 data, ts = inlet.pull_sample() assert inlet.samples_available == 0 data .. rst-class:: sphx-glr-script-out .. code-block:: none array([1., 2., 3.], dtype=float32) .. GENERATED FROM PYTHON SOURCE LINES 153-158 LSL clock --------- The local system timestamp is retrieved with :func:`~mne_lsl.lsl.local_clock`. This local timestamp can be compared with the LSL timestamp from acquired data. .. GENERATED FROM PYTHON SOURCE LINES 158-164 .. code-block:: Python now = local_clock() print(f"Timestamp of the acquired data: {ts}") print(f"Current time: {now}") print(f"Delta: {now - ts} seconds") .. rst-class:: sphx-glr-script-out .. code-block:: none Timestamp of the acquired data: 2353.094684675 Current time: 2353.217014134 Delta: 0.12232945899995684 seconds .. GENERATED FROM PYTHON SOURCE LINES 165-170 Free resources -------------- When you are done with a :class:`~mne_lsl.lsl.StreamInlet` or :class:`~mne_lsl.lsl.StreamOutlet`, don't forget to free the resources they both use. .. GENERATED FROM PYTHON SOURCE LINES 170-174 .. code-block:: Python inlet.close_stream() del inlet del outlet .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.900 seconds) **Estimated memory usage:** 184 MB .. _sphx_glr_download_generated_tutorials_10_low_level_API.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 10_low_level_API.ipynb <10_low_level_API.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 10_low_level_API.py <10_low_level_API.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 10_low_level_API.zip <10_low_level_API.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_