Closed ChadChen68 closed 9 months ago
You cannot use StreamOutlet to receive data. You must be mistaken there.
If you want 2 streams to arrive with their timestamps synchronized to the same base, then you must enable timestamp post-processing on your inlet. https://github.com/labstreaminglayer/pylsl/blob/master/pylsl/pylsl.py#L698-L701
As for whether or not you provide manual timestamps to the push_sample
or push_chunk
calls, I highly recommend you do not and you let LSL stamp them automatically, unless you know the true offset between the event and when you make the push_
call, in which case the timestamp should be pylsl.local_clock() - offset
.
I'm sorry for being so late in replying
I have read the file you recommended. So I did some practice and tried to synchronize 2 streams on the same PC.
At first, I use "SendData" and "SendStringMarkers" examples to generate an event and signal. And based on the liblsl example "ReceiveData" and "ReceiveStringMarkers".
To me, it looks like they are not synchronized
By the way, after I use outlet to push data and events, I just need to run my inlet script and it should synchronize my 2 streams, right?
Here is my inlet
And here is the result With proc Without proc
The mistake here is that the pull_sample calls are blocking, waiting for data to become available, but they are only pulling one sample at a time. Your EEG stream is accumulating data because you're only pulling a single sample then waiting for a marker, then pulling a single sample of EEG again and waiting for a marker again.
You have a couple options. You can either call pull_sample
with timeout=0.0
and skip over the case when nothing is returned, or you can call pull_chunk
to get all samples in the buffer and then only look at the most recent timestamp.
Try this instead:
import pylsl
def main():
# first resolve an EEG stream on the lab network
print("looking for an EEG stream...")
eeg_streams = pylsl.resolve_stream('type', 'EEG')
marker_streams = pylsl.resolve_stream('type', 'Markers')
# create a new inlet to read from the stream
eeg_inlet = pylsl.StreamInlet(eeg_streams[0], processing_flags=pylsl.proc_ALL)
marker_inlet = pylsl.StreamInlet(marker_streams[0], processing_flags=pylsl.proc_ALL)
while True:
# Wait until a marker is received...
marker, marker_ts = marker_inlet.pull_sample()
# And get whatever eeg has accumulated since the laste marker.
eeg_chunk, eeg_ts = eeg_inlet.pull_chunk(timeout=0.0)
# Print output
print(f"Marker: {marker}\t\tMarkerTS:\t{marker_ts:3f}")
if len(eeg_ts):
print(f"EEG most recent ts: \t\t{eeg_ts[-1]:.3f}\tDelta: {eeg_ts[-1] - marker_ts:.3f}")
if __name__ == '__main__':
main()
I get this output:
Marker: ['Testtest'] MarkerTS: 425804.079366
EEG most recent ts: 425804.082 Delta: 0.003
Marker: ['Marker'] MarkerTS: 425806.760775
EEG most recent ts: 425806.762 Delta: 0.001
Marker: ['Testtest'] MarkerTS: 425808.099470
EEG most recent ts: 425808.092 Delta: -0.007
Marker: ['Testtest'] MarkerTS: 425808.507533
EEG most recent ts: 425808.502 Delta: -0.006
I'm so grateful for your help @cboulay, before your help I thought I was just like a headless fly.
I changed a little bit because my event is not continuous, so I added timeout=0.0,
to avoid my inlet waiting for my event stream even if that time should be no events.
# create a new inlet to read from the stream
eeg_inlet = pylsl.StreamInlet(eeg_streams[0], processing_flags=pylsl.proc_ALL)
marker_inlet = pylsl.StreamInlet(marker_streams[0], processing_flags=pylsl.proc_ALL)
while True:
# Wait until a marker is received...
marker, marker_ts = marker_inlet.pull_sample(timeout=0.0)
# And get whatever eeg has accumulated since the laste marker.
eeg_chunk, eeg_ts = eeg_inlet.pull_sample(timeout=0.0)
# Print output
if marker_ts :
print(f"Marker: {marker}\t\tMarkerTS:\t{marker_ts:3f}")
print(f"Marker: {EEG}\t\eeg_ts:\t{eeg_chunk:3f}")
I believe the clocks are synchronized, and I don't know mine offset, so I will keep let timestamp catch automatically. but there's still one thing I can't figure out. The red box is where my event should be, and the yellow box is where my event actually occurred after I load xdf from xdfimport plugin. It was lag 0.0479891017312184 second.
In this video https://www.youtube.com/watch?v=tDDkrmv3ZKE have mention that It might cause lagging because of network, router, load of network, load of PC. I also set both stream sample rate to 250Hz.
Do you have any clue that might cause 0.048 second lagging? I will try to change my 2.4G router to 5G router and see it will get better or not.
Are you using more than 1 computer? Are they connected over wi-fi? If so that will cause poor synchronization. Briefly, the synchronization algorithm relies on the roundtrip time between the receiver and the sender being symmetrical -- same time to send and receive. This breaks down in wi-fi if packets are dropped and have to be re-sent. If synchronization is important then please run all applications on the same computer or use a wired LAN. If you absolutely need to use a wireless setup then there are some settings you can change.
The red box is where my event should be, and the yellow box is where my event actually occurred after I load xdf from xdfimport plugin.
I don't know what this means.
A couple comments about your new code:
pull_sample
for your EEG. Imagine if the print
statement took 1.001 msec but your EEG sample rate was 1 kHz. You would never be able to catch up! Please use pull_chunk for anything faster than 10 Hz so you have ~95 msec to process between chunks.timeout=0.0
but you don't check if eeg_ts is empty before printing it. This only works because you're too far behind and never catching up! If you were caught up then at least some of the pull_sample calls would not get any data and you would be printing blank data.
Hi All I'm trying to build LSL for EEG in Python (data stream) and MATLAB (Event stream). It's not easy for me to understand LSL documents and other examples.
I already have a device that can receive data and events and then output both in 1 stream from "computer A" (I call it "local data"), and use labrecorder to receive stream in "computer B" (I call it "LSL data"). After loading xdf data to EEGLAB and analysis in MATLAB, "local data" and "LSL data" are alike.
But here is my problem, I tried to build 2 streams, one is a data stream (from "computer A") and an event stream (from "computer C"), but I still don't understand how to use local_time to synchronize 2 streams. I added local_time into my script but still not helpful.
By the way, if I add time stamps should I use push_chunk or keep using push_sample, cause there seems no difference in my data? And do I need StreamInlet cause I only use Streamoutlet to push my stream but receive it and still work.
Sincerely Ming-Chuan