.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "generated/tutorials/20_player_annotations.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_20_player_annotations.py: .. _tut-player-annotations: Player with annotations ======================= .. include:: ./../../links.inc :class:`~mne.Annotations` from a :class:`~mne.io.Raw` object can be streamed as an event stream by :class:`~mne_lsl.player.PlayerLSL`. The stream will be irregularly sampled, numerical, and of type ``'annotations'``. A :class:`~mne.Annotations` contain 3 information: - the onset of the annotation - the duration of the annotation - the description of the annotation To stream all 3 information, it's duration-hod encoded along the channels. For instance, consider a :class:`~mne.io.Raw` object with 3 different :class:`~mne.Annotations` description: ``'event1'``, ``'event2'``, and ``'event3'``. The event stream will have 3 channels, each corresponding to one of the 3 descriptions. When an annotation is streamed, it's duration is encoded as the value on its channel while the other channels remain to zero. .. GENERATED FROM PYTHON SOURCE LINES 26-47 .. code-block:: Python import uuid import matplotlib.patches as mpatches import numpy as np from matplotlib import pyplot as plt from mne import Annotations, create_info from mne.io import RawArray from mne.viz import set_browser_backend from mne_lsl.player import PlayerLSL from mne_lsl.stream import StreamLSL annotations = Annotations( onset=[1, 2, 3], duration=[0.1, 0.2, 0.3], description=["event1", "event2", "event3"], ) annotations .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 49-69 With the 3 annotations above, the event stream will stream the following samples: - at time ``1``, the annotation ``'event1'`` is pushed. The sample push is ``array([[0.1, 0, 0]])``, of shape (1, 3). - at time ``2``, the annotation ``'event2'`` is pushed. The sample push is ``array([[0, 0.2, 0]])``, of shape (1, 3). - at time ``3``, the annotation ``'event3'`` is pushed. The sample push is ``array([[0, 0, 0.3]])``, of shape (1, 3). If more than one annotations are present in the chunk currently pushed, then a chunk is pushed. For instance, if the annotations at time ``2`` and ``3`` are pushed at the same time, then the chunk push is ``array([[0., 0.2., 0.], [0., 0., 0.3]])``, of shape (2, 3). %% Example on mock signal ---------------------- Let's create a mock :class:`~mne.io.Raw` object with annotations and stream both the signal and the annotations. .. GENERATED FROM PYTHON SOURCE LINES 69-81 .. code-block:: Python data = np.zeros((1, 1000)) # 1 channel, 1000 samples data[0, 100:200] = 1 data[0, 500:700] = 2 info = create_info(["signal"], 1000, "misc") raw = RawArray(data, info) annotations = Annotations(onset=[0.1, 0.5], duration=[0.1, 0.2], description=["1", "2"]) raw.set_annotations(annotations) set_browser_backend("matplotlib") # easier to plot with matplotlib in a documentation raw.plot(scalings=dict(misc=2), show_scrollbars=False, show_scalebars=False) plt.show() .. image-sg:: /generated/tutorials/images/sphx_glr_20_player_annotations_001.png :alt: 20 player annotations :srcset: /generated/tutorials/images/sphx_glr_20_player_annotations_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 82-95 Now that we have the :class:`~mne.io.Raw` object, we can stream it with a :class:`~mne_lsl.player.PlayerLSL` object. .. note:: Note that forcing ``annotations=True`` is not necessary since the :class:`~mne_lsl.player.PlayerLSL` will automatically stream annotations if they are present in the :class:`~mne.io.Raw` object. .. note:: A ``chunk_size`` of 1 is needed here or the timestamps ``ts`` from the signal and annotations streams are not reliable enough. .. GENERATED FROM PYTHON SOURCE LINES 95-105 .. code-block:: Python source_id = uuid.uuid4().hex player = PlayerLSL( raw, chunk_size=1, name="tutorial-annots", source_id=source_id, annotations=True, ).start() .. GENERATED FROM PYTHON SOURCE LINES 106-107 We can now acquire both streams with 2 :class:`~mne_lsl.stream.StreamLSL` objects. .. GENERATED FROM PYTHON SOURCE LINES 107-112 .. code-block:: Python stream = StreamLSL(2, name="tutorial-annots", source_id=source_id) stream.connect(acquisition_delay=0.1, processing_flags="all") stream.info .. raw:: html
General
MNE object type Info
Measurement date Unknown
Participant Unknown
Experimenter Unknown
Acquisition
Sampling frequency 1000.00 Hz
Channels
misc
Head & sensor digitization Not available
Filters
Highpass 0.00 Hz
Lowpass 500.00 Hz


.. GENERATED FROM PYTHON SOURCE LINES 113-118 .. code-block:: Python stream_annotations = StreamLSL(2, stype="annotations", source_id=source_id) stream_annotations.connect(acquisition_delay=0.1, processing_flags="all") stream_annotations.info .. raw:: html
General
MNE object type Info
Measurement date Unknown
Participant Unknown
Experimenter Unknown
Acquisition
Sampling frequency 0.00 Hz
Channels
misc
Head & sensor digitization Not available
Filters
Highpass 0.00 Hz
Lowpass 0.00 Hz


.. GENERATED FROM PYTHON SOURCE LINES 119-121 We can now acquire new samples from both streams and create a matplotlib figure to plot the signal and the annotations in real-time. .. GENERATED FROM PYTHON SOURCE LINES 121-160 .. code-block:: Python if not plt.isinteractive(): plt.ion() fig, ax = plt.subplots() # add legend colors = ["lightcoral", "lightgreen"] patches = [ mpatches.Patch(color=colors[k], label=ch, alpha=0.5) for k, ch in enumerate(stream_annotations.ch_names) ] ax.legend(handles=patches, loc="upper left") plt.show() n = 0 # number of annotations while n <= 10: if stream.n_new_samples == 0: continue data, ts = stream.get_data(winsize=stream.n_new_samples / stream.info["sfreq"]) ax.plot(ts, data.squeeze(), color="teal") if stream_annotations.n_new_samples != 0: data_annotations, ts_annotations = stream_annotations.get_data( winsize=stream_annotations.n_new_samples ) for sample, time in zip(data_annotations.T, ts_annotations): k = np.where(sample != 0)[0][0] # find the annotation ax.axvspan( time, time + sample[k], label=stream_annotations.ch_names[k], color=colors[k], alpha=0.5, ) n += 1 fig.canvas.draw() fig.canvas.flush_events() .. image-sg:: /generated/tutorials/images/sphx_glr_20_player_annotations_002.png :alt: 20 player annotations :srcset: /generated/tutorials/images/sphx_glr_20_player_annotations_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 161-168 Free resources -------------- When you are done with a :class:`~mne_lsl.player.PlayerLSL`, a :class:`~mne_lsl.stream.StreamLSL` or a :class:`~mne_lsl.stream.EpochsStream` don't forget to free the resources they use to continuously mock an LSL stream or receive new data from an LSL stream. .. GENERATED FROM PYTHON SOURCE LINES 168-171 .. code-block:: Python stream.disconnect() .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 172-175 .. code-block:: Python stream_annotations.disconnect() .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 176-178 .. code-block:: Python player.stop() .. rst-class:: sphx-glr-script-out .. code-block:: none .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 10.019 seconds) **Estimated memory usage:** 186 MB .. _sphx_glr_download_generated_tutorials_20_player_annotations.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 20_player_annotations.ipynb <20_player_annotations.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 20_player_annotations.py <20_player_annotations.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 20_player_annotations.zip <20_player_annotations.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_