labstreaminglayer / App-LabRecorder

An application for streaming one or more LSL streams to disk in XDF file format.
MIT License
123 stars 45 forks source link

Initializing multiple LSL streams for multiple cognitive tasks in Lab Recorder #115

Closed Chenot closed 3 months ago

Chenot commented 3 months ago

Hello,

I am currently developing an experiment involving EEG and several cognitive tasks (e.g. Stroop, n-back, category-switch, mental rotation, etc.) I would like to record the marker streams from each of these tasks with LSL/Lab Recorder.

At the moment, I have individual scripts for each task, each generating its own stream. When I run these scripts separately, I can select the corresponding stream and start recording in Lab Recorder without any issues. Here is what I use to create an outlet as an example: info = StreamInfo(name='ReactionTimeMarkers', type='Markers', channel_count=1, channel_format='int32', source_id='reaction_time_stream') outlet = StreamOutlet(info)

However, the streams only appear when the associated task scripts (.py) are launched, meaning that I need to manually start and stop the lab recorder for every task/stream, which is tedious...

Is there a way to initialize all the streams at the start of the experiment without having to run the task scripts first? At the moment, I'm using a “metascript” that launches each task individually one after another, and I'd like to generate the streams at the beginning of this script, but I can't get it right.

Thank you in advance

cboulay commented 3 months ago

There are at least a dozen very different ways to tackle this problem, but since you asked in the LabRecorder issue tracker I'll give you a LabRecorder way.

  1. Make sure all of your task scripts use unique names for their outlets.
  2. Modify LabRecorder.cfg RequiredStreams field and include all of those streams.
  3. Start LabRecorder, you should see the streams listed in red.
  4. Start recording. LabRecorder should warn you of missing required streams. Proceed anyway.

When the required streams become available, they will be added to the XDF. However, LabRecorder's resolver only checks for missing streams every K seconds. To work around this, modify your task scripts so they create the streams as soon as possible and send a quick "task scripted started" (or similar) message. Have the script sleep ~5 seconds before actually starting the task and sending markers you must keep.

cboulay commented 3 months ago

By the way, while this approach works, it's not ideal because your XDF file will have a bunch of different marker streams and this is somewhat atypical. For example, EEGLAB can load XDF files but it only grabs 1 marker stream to parse events.

If it were me, my preferred approach would be to use your "metascript" to create the single Markers outlet that you will use throughout your experiment. Then the individual task scripts will pass events off to the metascript which will then push the event over the outlet.

Note: The task script should record both the event and the time of the event using pylsl.local_clock(), and pass both of those together to the metascript. The metascript should then use this received timestamp when calling push_sample. Make sure the manual timestamp is in LSL time, not time.time()!!

Chenot commented 3 months ago

After some trials and errors, we succeded with your 2nd solution (all events in the same stream). Thank you very much!!