Recording Data

PhysioLabXR’s recording interface lets you record multi-stream data with synchronized timestamps from various sources, for example, EEG and screen capturing from your experiment.

Supported File Formats

The platform supports various data formats to best fit your donwstream pipeline:

  • .dats (dictionary of array and timestamps): PhysioLabXR’s native data format, which is a binary format that stores data in a compact way. This format is optimized for quick serialization during a recording session. It can take a while to load back. If you will use Python for downstream analysis, we recommend using the pickle format instead.

  • .p (pickle): Python’s native data format. This format is optimized for quick serialization and deserialization. It is recommended if you will use Python for downstream analysis.

  • .m (MATLAB): MATLAB’s native data format. It is recommended if you will use MATLAB for downstream analysis.

  • .csv (comma-separated values): A text-based data format. Not best for saving a large amount of data, but it is human-readable and can be easily imported to other software.

  • .xdf (Extensible Data Format): A data format often used for physiological data, compatible with many software packages and analysis tools.

What is saved

Regardless of the data format, for all streams, PhysioLabXR saves data by each frame and the time when it captured that frame. When loaded back, if you are in Python, the data is returned as a dictionary of arrays and timestamps. The keys of the dictionary are the stream names. The values are a tuple of (data, timestamps). If you are in MATLAB, the data is returned as a struct with the same fields. Check out this section for more details on how to use the recorded file.

Simple Example: How to Record Data

In this example, we will record two data streams: a randomly generated stream and screen capturing.

Create a Dummy Stream

First, make sure you have the following packages installed in your Python environment:

  • pylsl

  • numpy

You can install them with pip install pylsl numpy, or if you use a conda environment, you can install them with conda install -c conda-forge pylsl numpy.

We will create a dummy stream to record. Create a new python file, put in the following snippet.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
"""Example program to demonstrate how to send a multi-channel time series to
LSL."""
import random
import sys
import getopt
import string
import numpy as np
import time
from random import random as rand

from pylsl import StreamInfo, StreamOutlet, local_clock


def main(argv):
    srate = 128
    name = 'Dummy-8Chan'
    print('Stream name is ' + name)
    type = 'EEG'
    n_channels = 8
    help_string = 'SendData.py -s <sampling_rate> -n <stream_name> -t <stream_type>'
    try:
        opts, args = getopt.getopt(argv, "hs:c:n:t:", longopts=["srate=", "channels=", "name=", "type"])
    except getopt.GetoptError:
        print(help_string)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(help_string)
            sys.exit()
        elif opt in ("-s", "--srate"):
            srate = float(arg)
        elif opt in ("-c", "--channels"):
            n_channels = int(arg)
        elif opt in ("-n", "--name"):
            name = arg
        elif opt in ("-t", "--type"):
            type = arg
    info = StreamInfo(name, type, n_channels, srate, 'float32', 'someuuid1234')

    # next make an outlet
    outlet = StreamOutlet(info)

    print("now sending data...")
    start_time = local_clock()
    sent_samples = 0
    while True:
        elapsed_time = local_clock() - start_time
        required_samples = int(srate * elapsed_time) - sent_samples
        for sample_ix in range(required_samples):
            # make a new random n_channels sample; this is converted into a
            # pylsl.vectorf (the data type that is expected by push_sample)
            mysample = [rand()*10 for _ in range(n_channels)]
            # now send it
            outlet.push_sample(mysample)
        sent_samples += required_samples
        # now send it and wait for a bit before trying again.
        time.sleep(0.01)


if __name__ == '__main__':
    main(sys.argv[1:])

Now run the script in your terminal with a command like python LSLExampleOutlet.py. The script will start an LSL stream with stream name ‘Dummy-8Chan’ and stream type ‘EEG’. The stream will generate random data with 8 channels and a sampling rate of 250 Hz. The stream will keep running until you stop the script.

Add the streams to be recorded

1. In the main window, navigate to the stream tab located in the main window. In the Add Stream widget, type in ‘Dummy-8Chan’, the name of the stream we created in the previous step. Press the Add button or press Enter on your keyboard to add the stream.

2. We will add an video stream capturing your computer’s display. Now create a new stream by starting to type ‘monitor 0’. PhysioLabXR uses this name for screen capturing. The current version only supports capturing the main display if multiple displays are in use.

Note

This setup, a physiological stream and a screen capturing stream is a good example of what needs to be recorded in a typical experiment. You can add more streams if you have more data sources.

2. In the same tab, you should see two stream widgets now ‘Dummy-8Chan’ and ‘monitor 0’ with some information about the streams. There’s no start/stop button for the screen capturing because it’s always on. You should see stream_available at the bottom of the ‘Dummy-8Chan’ widget, meaning this stream is available on the network. Press the ico6 button under ‘Dummy-8Chan’ stream to start receive the stream.

Note

If the bubble is red, it means the stream is not available on the network. Make sure the dummy stream is running by checking the steps in the previous section Create a Dummy Stream.

Record the data

3. Now navigate to the recording tab located on the upper left corner in the main window. (Optional) In the recording tab, click the recording options button, you can modify the directory to which you want to store your data and the file format you want to store your data in.

4. Click Start recording button, the app will start recording the streams. At the bottom right corner, you can see the recording duration and file size as they increase.

  1. Click Stop Recording button, the app will stop recording and store the recorded data to the path you specified.

Note

Loading .p, .xdf, and .mat are faster than .dats and .csv files. Recording video as .csv files are not recommended, as it takes a long time and the recorded file can be very large. See Supported File Formats for more details.

  1. Now you can open the recording directory (you can open it from the context menu file/Show Recordings) to see the recorded file.

Using the recorded file

You can use the load functions from PhysioLabXR, first install the pip package pip install PhysioLabXR

And simply import the load function, here is an example

from physiolabxr.utils.user_utils import stream_in

data = stream_in('path/to/dats/file')

Check out the :ref:’stream_in API reference <Stream_in>’ for more details.

Further Reading