Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

matlab - pull_chunk for eeg - timestamps not equidistant #63

Open
marvnmtz opened this issue Oct 8, 2020 · 10 comments
Open

matlab - pull_chunk for eeg - timestamps not equidistant #63

marvnmtz opened this issue Oct 8, 2020 · 10 comments

Comments

@marvnmtz
Copy link

marvnmtz commented Oct 8, 2020

Hey everybody,
I'm working with EEG Data that i want to process while reading it. Therefor i use the pull_chunk function to read the data chunk by chunk. My problem is that the difference between the timestamps is not constant. To break down my problem to this issue i used the example code "ReceiveDataInChunks.m" provided together with liblsl_matlab .

`% instantiate the library
disp('Loading the library...');
lib = lsl_loadlib();

% resolve a stream...
disp('Resolving an EEG stream...');
result = {};
while isempty(result)
result = lsl_resolve_byprop(lib,'type','EEG'); end

% create a new inlet
disp('Opening an inlet...');
inlet = lsl_inlet(result{1});
time = [];
ende = 0;
disp('Now receiving chunked data...');
while true
% get chunk from the inlet
[chunk,stamps] = inlet.pull_chunk();
for s=1:length(stamps)
time(ende+s) = stamps(s);
end
ende = ende + length(stamps);
pause(0.05);
end`

I let it run for some time and then I plot

plot(diff(time))

pull_chunk error

So normally that should be a straigt line at y=0,0004883 (~1/2048Hz)
I stream the EEG data via a BioSemi device, if this is of interest.
Does someone know why i get these discontinuities and how i solve them?
Thanks a lot in advance
Marvin

@cll008
Copy link
Contributor

cll008 commented Oct 8, 2020 via email

@cboulay
Copy link
Collaborator

cboulay commented Oct 8, 2020

Hi @mrvnmtz ,

Can you please let us know which device you're using and how it streams data via LSL (vendor-provided app, community app, custom, etc)?

In order of decreasing importance:

  • If the hardware provides timestamps then the application should be using those timestamps (converted to lsl's clock) when pushing data to the stream and you should use these without postprocessing (other than clock offset adjustment).
  • If the hardware does not provide timestamps but you trust it to have equal sampling interval (as Clement mentioned), then you can dejitter. This happens automatically by both the matlab and python xdf importers, but you can also do it online by calling set_postprocessing on the inlet after it is created. This is the most likely solution.
  • If you don't trust the hardware to have a better sampling interval than the application pushing the data then maybe the provided timestamps are the most accurate, uneven intervals and all.

@chkothe
Copy link
Contributor

chkothe commented Oct 8, 2020

Adding to those comments, to me these stamps actually don't look all that bad, as in, there's a good chance that dejitter will pretty much fix that up for you.

I sometimes use the following rough back of the envelope calculation: it looks like the hardware is natively providing about 15 chunks per sec (the spikes), and if you use online dejitter that'll be smoothed out over a minute-long sliding window (effectively a bit more since it's exponentially weighted, but we're going to conservatively assume a minute). You can get a rough idea of the residual timing error after dejitter by taking the magnitude of those spikes (17ms) and dividing them by the number of spikes that are averaged (that's the effective number of time measurements, which ignores the flat portions, which are not actual timing measurements but filled in based on 1/srate), so that makes ca. 15x60 in total over a minute. So 17ms/(15x60) comes out at 0.018ms (i.e., less than a sample at 2048 Hz). It'll be a bit worse than that in in the first minute after turning on the stream since there's less data.

Now, in case you don't actually need those stamps in real time, but you just want to record them to disk (eg to an XDF file), then that dejitter would instead be done on the whole recording at import time, in which case the timing error due to jitter will be even smaller (miniscule).

@arnodelorme
Copy link
Contributor

arnodelorme commented Oct 8, 2020 via email

@marvnmtz
Copy link
Author

marvnmtz commented Oct 9, 2020

Thanks to all for trying to help me. The device is a BioSemi device, should be this one: https://www.biosemi.com/ad-box_activetwo.htm. I link the device with the software that I think came with it to open the stream.

So far i would have said that it looks quite trustworthy.

@cll008 I normally link my BioSemi device to another PC than the one i run matlab on, but that's just because the lab i arranged like that. But I also tried to run matlab on the same Pc to which i connect the EEG and it seems to make no difference. Where do I find this stream's synchronization field?

@cboulay So far I haven't done any postprocessing. I sometimes used inlet.time_correction();. I also tried to apply inlet.set_postprocessing(); but than i says " Unrecognized function or variable 'lsl_set_postprocessing' "

@chkothe Unfortunatelly I do need the data online and i even have to classify them online. How do I dejitter, when processing the data online not saving them to an xdf-file?

@arnodelorme Eventually i will have a second stream that will be sent by Matlab, but so far i got stuck on this issue

While writing this answers i figured out that, when i put all my chunks together after each other in one matrix, my timeseries looks good, as such that I do not have any missing data.

Thanks again for all your answers but right now it looks like this issue won't be a problem for me any longer.

@cboulay
Copy link
Collaborator

cboulay commented Oct 9, 2020

. I also tried to apply inlet.set_postprocessing(); but than i says " Unrecognized function or variable 'lsl_set_postprocessing' "

That’s something we need to fix. My Matlab license just expired. Any volunteers?

@dmedine
Copy link
Contributor

dmedine commented Oct 11, 2020

Well I just bought a Matlab license so I guess this goes on my todo pile.

I did implement this some time ago (labstreaminglayer/liblsl-Matlab@2ad59f1) but it might not be working on every conceivable combination of Matlab/OS/etc. @mrvnmtz, can you please tell me which version of Matlab and liblsl you are using? It could be that you just need to build liblsl-Matlab on your system.

@marvnmtz
Copy link
Author

@dmedine Sorry for my late response, but if you still want to take a look at it, I'm using Matlab R2020a und i actually just updated liblsl when investigating this problem.
But like I said, i figured out that it actually is not a problem for my results. I still wonder, why LSL or my BioSemi Device behaves like that, but as far as it works for my, I'm fine.

@mrsaeedpour
Copy link

Hello, I have the same issue. When I stream my EEG data (CXG) at 500 Hz, the difference between two consecutive samples is not close to 0.002 (as you can see in the figure below). However, the number of received samples is close to the frame rate. For instance, for a 5-second recording, I get around 2479 samples.
Your feedback is greatly appreciated!

image

@cboulay
Copy link
Collaborator

cboulay commented Jul 7, 2023

@mrsaeedpour , it looks like the Cognionics LSL integration is calling push_sample (instead of push_chunk but the app is receiving samples from the device in chunks, so the first sample in a chunk has some non-zero interval from the end of the previous chunk but the remaining samples in the chunk have a near zero interval. But this is fine!

The uneven sampling intervals are dejittered automatically when loading the file via an xdf importer. And they can be fixed online automatically by LSL's built-in dejittering by setting the postprocessing flags.

However, do you really need the timestamps to be dejittered? LSL's dejittering simply assumes that devices have consistent inter-sample intervals at the source even if their timestamps in the stream don't have consistent intervals. If you simply process the data without paying attention to the timestamps then you are effectively making the same assumption.

If you need to align these jittered data with other streams and your precision requirement is < 10 msec then yes you'll need to dejitter. But this is a very unusual requirement for online analysis. Most online analyses will simply want to run things as fast as possible so you'll align the most recent EEG with the most recent other stream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants