How to animate a plot of raw EEG data?

Hello,
I would like to do a
1) simple plot of time against raw EEG (uV) data, the tricky thing is that
2) I hope to animate it as a moving line, as if it's being read real-time and the line forming.
I tried to look for answers throughout the forum but couldn't find any answer that can resolve this. I tried using this code, that plots a graph without any animation, and it seems to have an error message. Can anyone please help me see what the problem might be?
clear all
clc
a1 = animatedline('Color', [0 .7 .7]);
axis([0 30 0 1000])
t = linspace(0, 20, 180); %what does this mean?
T = readtable('d_museMonitor_2021-01-21--18-36-17.csv');
A = table2array(T(:, 23));
fs=256;
for k = 1:length(t)
tk = [0:length(A)-1]/fs;
y = A; %or can this be y = A(k,:)? but this doesn't seem to work either
addpoints(a1, tk, A);
drawnow limitrate
end
Warning: Number of points exceeds the default maximum number of points of 1000000. To control the number of points in the animated
line, set the MaximumNumPoints property of the AnimatedLine object to the desired value.
> In testing (line 17)
Yet the data I have only has around 50000 points.. So I don't quite understand what the situation is..
3) Also, would it be possible to also show me how to covert the animation into a movie?
Thanks!!

Answers (2)

Hi
I've changed a few things in your code.
Firstly, below is your movie as a .gif file. You can make it smoother if you want (see code below).
For more info on how to make .gif files, check out: https://uk.mathworks.com/matlabcentral/answers/94495-how-can-i-create-animated-gif-images-in-matlab (this is where I took the gif-making code sections from, and modified them a little).
I hope this answers all three questions.
Here is the code:
clear all
clc
close all
h = figure;
a1 = animatedline('Color', [0 .7 .7]);
axis([0 30 0 1000])
T = readtable('d_museMonitor_2021-01-21--18-36-17.csv');
A = table2array(T(:, 23));
t = linspace(0, 20, length(A)); % Q: what does this mean?
% A: this creates a vector of length 47039
% with the first element 0 and
% the final element 20...
fs=256;
filename = 'testAnimated.gif'; % this is for your movie
for k = 1:length(t)
tk = t(k);
yk = A(k);
addpoints(a1, tk, yk); % you need to make sure you are only adding one
% point at a time... that means that
% length of tk = length of yk = 1.
% I think you were giving it 47039 elements every time,
% which may have caused the Warning to appear, but I am not too sure.
drawnow limitrate
% to make a gif:
% Write to the GIF File
if k == 1
% Capture the plot as an image
frame = getframe(h);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
if mod(k,1000) == 0 % NOTE: change this to a smaller number if you want smoother gif
% you have quite a lot of points though, so it's a bit of a tradeoff
% between quality and total time required
% Capture the plot as an image
frame = getframe(h);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
end
end

1 Comment

Cherie Chao
Cherie Chao on 30 Jan 2021
Edited: Cherie Chao on 30 Jan 2021
Thank you so much for spending the time to help resolve my issues and answering my queries, you even processed the data! I'm a newbie and this process of exchange really helps me to learn and understand more about the logics of Matlab, such a powerful tool.
*I wish I could accept both answers because both helped me.

Sign in to comment.

I would modify the plotting code a little.
  • Use fs to set the time
  • Adjust xlim to give the perception of a 30 second scrolling window.
I find it much better to use the variable names to refer to data in a table. It helps you make sure you are plotting what you intended.
a1 = animatedline('Color', [0 .7 .7]);
axis([0 30 0 1000])
opts = detectImportOptions("d_museMonitor_2021-01-21--18-36-17.csv");
opts.VariableNamesLine = 1;
T = readtable('d_museMonitor_2021-01-21--18-36-17.csv',opts);
fs=256;
t = (1:height(T)-1)/fs;
for k = 1:height(T)
addpoints(a1, t(k), T.RAW_AF7(k));
% set the xlims to create a scrolling window
xlim([max(0, t(k)-30) max(30, t(k))])
drawnow limitrate
end

8 Comments

Thank you so much, it does exactly what I wish to achieve, especially for this time frame window of the building line allows for more details to be observed. This function "detectImportOptions" is new to me.
There is an error message that comes from the script:
Index exceeds the number of array elements (47038).
that I think I have corrected with:
t = (0:height(T)-1)/fs;
What could I do to import this animation into a, say mp4, file? Would it be very complicated?
Thanks again!
That is the correct line to fix, but wrong fix. The intent was to besically get the row numbers, subtract 1 so time starts at 0, then divide by fs to turn it into time. However, the '-1' is only being subtracted from height and not the entire vector. That can be fixed by adding parentheses to force the desired order of operations.
t = ((1:height(T))-1)/fs;
Your fix has it now starting at a negative value.
As for creating and mp4, that can be done following this example. Starting at the "Create a video writer object" part, adapt it to your code and just change the video extension in the example from 'avi' to 'mp4'.
Cris LaPierre
Cris LaPierre on 30 Jan 2021
Edited: Cris LaPierre on 30 Jan 2021
One caution. The default framerate of videowriter is 30. Your data is at 256. You can set the FrameRate, but if you save 47039 frames, your mp4 is going to be very large (and take a very long time). Consider creating an mp4 that uses a subset of the frames.
Thank you so much! I finally got a plot with a video output. For now, I don't know how to create the mp4 file yet, I tried setting it as v = VideoWriter('filename.mp4') which outputs to an avi file still, and v = VideoWriter('filename.mp4', 'MPEG-4') doesn't seem to work yet.
Still have so much I hope to do, yet this helps a big chunk of it. Thank you!
For reference, I will post here what I use for now:
set(groot,'defaultfigureposition',[0 0 1000 250])
a1 = animatedline('color',[1 1 1]);
axis([0 3 0 1650])
%appearances settings
title('AF7 EEG', 'color',[.5 .5 .5])
xlabel('Time (s)')
ylabel('Voltage (uV)')
set(gcf,'color',[0 0 0])
set(gca,'color',[0 0 0])
set(gca,'xcolor',[.5 .5 .5])
set(gca,'ycolor',[.5 .5 .5])
opts = detectImportOptions("d_museMonitor_2021-01-21--18-36-17.csv");
opts.VariableNamesLine = 1;
T = readtable('d_museMonitor_2021-01-21--18-36-17.csv',opts);
fs=256;
t = ((1:height(T))-1)/fs;
v = VideoWriter('AF7.avi');
open(v);
for k = 1:height(T)
addpoints(a1, t(k), T.RAW_AF7(k));
frame = getframe(gcf);
writeVideo(v,frame);
% set the xlims to create a scrolling window
xlim([max(0, t(k)-3) max(3, t(k))])
drawnow limitrate
end
close(v);
Thanks again!
Have you looked at the documentation page for videowriter? That will give you the correct syntax and input for an mp4.
Yes, I took a look again today, and input the seemingly same things, I am not very sure what is the difference, yet somehow it works today! Yay!
set(groot,'defaultfigureposition',[0 0 1000 250])
a1 = animatedline('color',[1 1 1]);
axis([0 3 0 1650])
%appearances settings
title('AF7 EEG', 'color',[.5 .5 .5])
xlabel('Time (s)')
ylabel('Voltage (uV)')
set(gcf,'color',[0 0 0])
set(gca,'color',[0 0 0])
set(gca,'xcolor',[.5 .5 .5])
set(gca,'ycolor',[.5 .5 .5])
opts = detectImportOptions("d_museMonitor_2021-01-21--18-36-17.csv");
opts.VariableNamesLine = 1;
T = readtable('d_museMonitor_2021-01-21--18-36-17.csv',opts);
fs=256;
t = ((1:height(T))-1)/fs;
v = VideoWriter('AF7.mp4','MPEG-4');
open(v);
for k = 1:height(T)
addpoints(a1, t(k), T.RAW_AF7(k));
frame = getframe(gcf);
writeVideo(v,frame);
% set the xlims to create a scrolling window
xlim([max(0, t(k)-3) max(3, t(k))])
drawnow limitrate
end
close(v);
Thank you again!
The only difference was variable names and columns. Once you've selected the correct data, the rest of the code remains the same.

Sign in to comment.

Categories

Asked:

on 29 Jan 2021

Commented:

on 4 Feb 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!