sccn / lsl_archived

Multi-modal time-synched data transmission over local network
242 stars 134 forks source link

Visualize xdf with multiple streams from different machines #301

Closed RKCZ closed 5 years ago

RKCZ commented 6 years ago

Hello, we have EEG amplifier connected to Win64 PC and using BrainVision RDA Connector to link it into LSL stream. Then we have raspberry pi which reads EMG data from microcontroller and sends it to the first win64 PC where LabRecorder is running. Problem is that I tried to view recorded data with Sig Viewer (I found reference in #70 ) but signal from EEG is shifted a lot after EMG. In stream footers I found: EEG stream: <?xml version="1.0"?><info><first_timestamp>18723.687831879</first_timestamp><last_timestamp>19279.098382872</last_timestamp>...

EMG stream (sent from RPi): <?xml version="1.0"?><info><first_timestamp>17359.727759835</first_timestamp><last_timestamp>17900.264723587</last_timestamp>...

Clock offsets seems to be OK, so I assume that Sig viewer displays streams without applying offset correction. Am I missing some reason why it is not displayed correctly?

My answer is if there is some other program which I could use to visualize those streams without much effort (best if it would work just out of the box). I need it just to show some results for final submission of the project and deadline is soon. Thanks for advice.

cboulay commented 6 years ago

Maybe we can tag @cbrnr to see if he has any idea if this is an LSL problem, XDF problem, or SigViewer problem.

cbrnr commented 6 years ago

AFAIK we read clock offsets, but we might not process them correctly (maybe @Yida-Lin can confirm). According to the information in the stream footer, your EEG and EMG streams seem to have rather large clock offsets. These should be corrected via clock offset chunks in the file.

Can you try to use the MATLAB XDF reader (also available as an EEGLAB plugin) as a quick workaround?

RKCZ commented 6 years ago

Thank you for quick response. I tried using matlab with eeglab GUI but I can't figure out how to display both datasets at a time. I load import EEG data from xdf into eeglab and then use the same method to import EMG from the same file. Then I have dataset for EEG and dataset for EMG. I can plot EEG data but cannot plot EMG or both datasets together. Probably it is because eeglab takes EMG dataset as EEG. Could you please instruct me how to load data to matlab or eeglab correctly?

cbrnr commented 6 years ago

Hm, I didn't know that EEGLAB can't visualize multiple streams simultaneously. Would you be able to share a dataset with us so that we can try it with SigViewer? I think SigViewer is still our best bet, but let's wait what @Yida-Lin (who integrated XDF support into SigViewer) has to say.

There is also a preliminary Python reader, but I haven't tested it since we don't use XDF in our lab. If you know Python, you could try to build a quick visualization with Matplotlib. Depending on what the reader spits out, this might or might not be a straightforward task. Note that people have already expressed their wish to see XDF integrated into MNE, something I'd love to see too, but currently I don't have the time to do it myself.

cboulay commented 6 years ago

@RKCZ If you are using EEGLAB then that has trouble loading more than 1 stream at a time. If you just use the plain load_xdf.m (not eeg_loadxdf or pop_loadxdf) then that should load all the streams into a cell array, then you can access them at the same time.

RKCZ commented 6 years ago

Here is one of the xdf files. It contains EEG Brainvision RDA stream, Brainvision RDA markers and EMG stream collected from RPi. test_duplicate.zip

Thank you for your help. I will try to look if I am able to make some quick visualization in matlab or python in the meantime.

cbrnr commented 6 years ago

Here's a very quick example that you can tweak (put xdf.py in your working directory):

import matplotlib.pyplot as plt
from xdf import load_xdf

streams, header = load_xdf("test_duplicate.xdf")
fig, ax = plt.subplots()
ax.plot(streams[0]["time_stamps"], streams[0]["time_series"])
ax.plot(streams[2]["time_stamps"], streams[2]["time_series"])
fig.show()

This results in something like this: figure_2

So it seems like at least the import is working and both signal types are correctly displayed.

Yida-Lin commented 6 years ago

Hi @RKCZ @cbrnr , I think the range that SigViewer displays is calculated by looking at the earliest <first_timestamp> and the latest <last_timestamp> across all streams. As an emergence remedy (for your submission), I think you could try manually change these values of the xdf file in a text editor and see if SigViewer displays it correctly

Yida-Lin commented 6 years ago

@RKCZ @cbrnr But when manually updating the values, need to be careful that it needs to be the exact same precision, since SigViewer reads it byte by byte; in other words, changing 35.6800 to 35.68 would fail.

RKCZ commented 6 years ago

Thank you all very much. I decided to go with @cbrnr matplotlib suggestion and I think it will do as a workaround.

cbrnr commented 6 years ago

Thanks @Yida-Lin, this might indeed work as a last resort. I've created an issue for SigViewer: https://github.com/cbrnr/sigviewer/issues/110. If you have time to implement this in libXDF (I guess this is where it should go?), this would be awesome.

Yida-Lin commented 6 years ago

@cbrnr Hi Clemens! Sounds good, I would love to work on it. I will look into this soon.

cboulay commented 5 years ago

I think I can close this issue. Let me know if it needs to be reopened.