Skip to content

Tutorial 3. Generate your own data streams using MATLAB

Chadwick Boulay edited this page Dec 23, 2019 · 2 revisions

LSL provides the possibility to easily generate your own data and marker streams. Here you can find examples for how to send or receive data for several programming languages including C, C++, Python, MATLAB, Java and C#. This allows you, for example, to send event codes in stimulus presentation programs such as Psychopy (using LSL for Python), PsychToolbox (using LSL for MATLAB). Some commercial software packages support LSL directly. See here for other supported Stimulus presentation software. We will use here some MATLAB examples to convey the general principle.


For this tutorial you need

The LSL App can be downloaded from the ftp as .zip files.


  • 'Unlink' all apps that are currently running.
  • Start LabRecorder.exe
  • Start MATLAB

First, we generate a random stream of data of the type EEG.

  • In MATLAB, change to ./MATLAB viewer/liblsl-Matlab/examples
  • Open the SendData.m script
  • This shows how a stream is created and how data can be sent as LSL stream
  • In this case the stream has the name ‘BioSemi’, the type ‘EEG’, has 8 channels, and streams random data at 100Hz
  • Run the script
  • In the Lab Recorder you should see the ‘BioSemi’ stream
    • While the script is running MATLAB is not responsive
    • You can stop the execution of the script with 'Control-C'
  • Record a short piece of data and load it into MATLAB (see Tutorial 1)

Now we generate a marker stream.

  • Open the SendStringMarker.m script. This shows how an irregular marker stream can be created, e.g. for sending event trigger
  • Run the script
  • In the LabRecorder you should see the stream ‘MyMarkerStream’
  • Record a short piece of data and load it again into MATLAB (see next lines)
    • While the script is running MATLAB is not responsive for anything else
    • You can stop the execution of the script with 'Control-C'

Now we adapt the SendStringMarker script so that we have a small experiment. Send 15 tones (use the sound command) with an increasing ITI (start with 700 msec between the first and the second tone and increase by 100 msec)

  • Send an individual marker (including the trial number) for each tone
  • Use the ‘Input’ function to interrupt the script after it has been started. This allows you to start the LabRecorder after the stream was established and before the actual experiment is started
%%
clear all; close all
% instantiate the library

disp('Loading library...');
lib = lsl_loadlib();

disp('Creating a new marker stream info...');
info = lsl_streaminfo(lib,'MyMarkerStream','Markers',1,0,'cf_string','myuniquesourceid23443');

disp('Opening an outlet...');
outlet = lsl_outlet(info);
%load sound
load splat.mat
% Wait for user input
reply = input('Press key to start' ,'s');

% send markers into the outlet
disp('Now transmitting data...');
markers = {'T1', 'T2', 'T3','T4', 'T5', 'T6','T7', 'T8', 'T9','T10', 'T11', 'T12','T13','T14', 'T15'};


for k=1:numel(markers)
    outlet.push_sample(markers(k));   % note that the string is wrapped into a cell-array
    sound(y) % play sound
    pause(1+.100*(k-1));    
end

display('End of Experiment. Please stop recording.')
  • ‘Link’ the AudioCaptureWin stream again
  • In the LabRecorder you should now see two streams
  • Select both streams
  • Start the recording and continue the experiment script, by pressing enter
  • Analyze the data in MATLAB as before (you might need to change to the ‘MATLAB Import‘ folder)

Visualize data and marker stream. (The order of your streams might be different)

figure;
plot(data{2}.time_stamps, data{2}.time_series)
hold all
plot(data{1}.time_stamps, zeros(size(data{1}.time_stamps)),'o', 'LineWidth',2)


Check for the marker stream whether the time difference between two successive markers is as expected. The timing of this experiment will be rather poor as the pause.m function does not provide accurate timing (You can also epoch your data using EEGlab to visualize the relationship between the marker and sound onset).

  • You expect that the time between the first and the second sound is 1 second, and increases by 100 msec for each sound: expectedTiming=[1:0.1:2.3]

The actual time difference between two markers can be computed by computing the difference between two successive time stamps of the marker stream.

actualTiming=diff(data{1}.time_stamps)

%% explore timing
% the time between two markers should increase by 100 msec
expectedTiming=[1:0.1:2.3] 
% the actual timing might deviate from this
actualTiming=diff(data{1}.time_stamps)
figure
subplot(211)
scatter(expectedTiming,actualTiming, 'LineWidth',2)
hold all
plot(expectedTiming,expectedTiming, 'LineWidth',2)
xlabel('Expected Timing [seconds]');
ylabel('Measured Timing [seconds]');
legend({'Time between two sounds', 'Optimal Timing'})
title('Timing')

subplot(212)
plot(actualTiming-expectedTiming,'-o', 'LineWidth',2)
title('Deviation from expected Timing')
xlabel('Sound order');
ylabel('Deviation from expected presentation [seconds]');

The timing in this setup is not optimal (this was to be expected). The sounds are presented a bit later than expected (upper plot). Especially, the second sound is presented much later (almost 200 msec) than expected. For most applications, a constant delay (if known) can be compensated for. More relevant (e.g. for EEG recordings) is a jitter in the data. In this example, the sounds are delayed (excluding the first one), by about 17 msec and jitter between 5 msec to 25 msec. Whether this imprecision is acceptable depends on the specific application. With dedicated stimulus presentation software you will achive much better results.