I'm very new to MATLAB and I was trying to display a real time plot of some calculations. I have an N sized vector and I work with m values at a time (say m = N/4), so I want to plot the first m values and then as soon as the second m values are calculated have them replace the first plot.
My approach was as follows:
for i=1:N,
...
//compute m
...
plot(m);
end;
but it fails to update the plot in every loop and waits for all the loops to finish to plot the data. My question is: Should I use another function instead of plot or could I add some delay in each loop?
I think there must be a way I'm not aware of for updating the plot instead of re-plotting it every time.
As Edric mentioned, you'll definitely want to include a drawnow command after the call to plot to force an update of the graphics. However, there is a much more efficient and smoother method to animate plots that doesn't involve recreating the entire plot each time. You can simply initialize your plot, capture a handle to the plot object, then modify the properties of that object in your loop using the set command. Here's an example:
hLine = plot(nan); % Initialize a plot line (which isn't displayed yet
% because the values are NaN)
for i = 1:N % Loop N times
...
% Compute m here
...
set(hLine, 'YData', m); % Update the y data of the line
drawnow % Force the graphics to update immediately
end
In addition, before your loop and after the call to plot you can set a number of axes properties, like the axes limits, etc., if you want the axes to stay fixed and not change their appearance with each new vector m that is plotted.
You can add a call to DRAWNOW to force the plot to update. See the reference page. Note that DRAWNOW causes the graphics event queue to be flushed, which may cause callbacks etc. to be executed.
Related
I'm trying to plot a straight line from a point in x to different values of t, thereby making a line in a for loop. But I see no lines generated in my figure in MATLAB
Following is my code:
t=linspace(0,8,11)
xs=(1.+t).^0.5
x0=xs./(1.+t)
m=size(t)
n=max(m)
hold on
for k=1:n
plot(x0(k),t(1:k),'-')
hold on
end
Thanks
You do not need the loop to perform the plot.
plot(x0,t,'-')
Will work just fine! Unless you were attempting to plot points...use scatter() for that:
scatter(x0,t)
plot() and scatter() (and most of Matlab's functions) are meant to be used with vectors, which can take some time to get used to if you are used to traditional programming languages. Just as you didn't need a loop to create the vector x0, you don't need a loop to use plot().
You are adding one point in Y axis along a line in X Axis use this code
t=linspace(0,8,11)
xs=(1.+t).^0.5
x0=xs./(1.+t)
m=size(t)
n=max(m)
hold on
for k=1:n
plot(x0(1:k),t(1:k),'-')
hold on
end
for more fun and see exactly how for is performed use this for loop
for k=1:n
pause('on')
plot(x0(1:k),t(1:k),'-')
hold on
pause(2)
end
I have a plot in which there are a few noise components. I am planning to select data from that plot preferably above a threshold in my case I am planning to keep it at 2.009 on the Y axis. And plot the lines going only above it. And if anything is below that i would want to plot it as 0.
as we can see in the figure
t1=t(1:length(t)/5);
t2=t(length(t)/5+1:2*length(t)/5);
t3=t(2*length(t)/5+1:3*length(t)/5);
t4=t(3*length(t)/5+1:4*length(t)/5);
t5=t(4*length(t)/5+1:end);
X=(length(prcdata(:,4))/5);
a = U(1 : X);
b = U(X+1: 2*X);
c = U(2*X+1 : 3*X);
d = U(3*X+1 : 4*X);
e = U(4*X+1 : 5*X);
figure;
subplot (3,2,2)
plot(t1,a);
subplot (3,2,3)
plot(t2,b);
subplot(3,2,4)
plot(t3,c);
subplot(3,2,5)
plot(t4,d);
subplot(3,2,6)
plot(t5,e);
subplot(3,2,1)
plot(t,prcdata(:,5));
figure;
A=a(a>2.009,:);
plot (t1,A);
This code splits the data (in the image into 5 every 2.8 seconds, I am planning to use the thresholding in first 2.8 seconds. Also I had another code but I am just not sure if it works as it took a long time to be analysed
figure;
A=a(a>2.009,:);
plot (t1,A);
for k=1:length(a)
if a(k)>2.009
plot(t1,a(k)), hold on
else
plot(t1,0), hold on
end
end
hold off
The problem is that you are trying to plot potentially several thousand times and adding thousands of points onto a plot which causes severe memory and graphical issues on your computer. One thing you can do is pre process all of the information and then plot it all at once which will take significantly less time.
figure
threshold = 2.009;
A=a>threshold; %Finds all locations where the vector is above your threshold
plot_vals = a.*A; %multiplies by logical vector, this sets invalid values to 0 and leaves valid values untouched
plot(t1,plot_vals)
Because MATLAB is a highly vectorized language, this format will not only be faster to compute due to a lack of for loops, it is also much less intensive on your computer as the graphics engine does not need to process thousands of points individually.
The way MATLAB handles plots is with handles to each line. When you plot a vector, MATLAB is able to simply store the vector in one address and call it once when plotting. However, when each point is called individually, MATLAB has to store each point in a separate location in memory and call all of them individually and graphically handle each point completely separately.
Per request here is the edit
plot(t1(A),plot_vals(A))
Inside a while loop, I have some function that creates all the neccesary y-values for the plot I want to make. After all the y-values are done I want my program to plot the dat(while still inside the loop), but the plot can't be made because the data won't come out until the end of the loop.
Is there anyway to do this?
Basically my code is(and I'm just going to for the first case here)
while c~=3
c=menu('a','b','c')
switch c
case 1
for
%function that creates y-values
end
plot(x,y)
end
end
As I said; I get out all the data at the end of the loop, which is stored in the workspace. Meaning that when I run it a second time, it works fine.
But I want to know how to make it work the first time.
for Continuous line plot you can use drawnow and here it is explained how to do this (remember to use pause(.) if you want to visualize the changes "real-time".
for retain current plot when adding new plots use hold on as it is explained here
if you want to open different windows for every different plot you can use something like:
ii=1;
while ...
...
figure(ii)
plot(x,y)
ii=ii+1;
...
end
but be careful with the last one: if you have a big number of plots you can have some problem
This question already has answers here:
Matlab update plot with multiple data lines/curves
(2 answers)
Closed 6 years ago.
I have animated the motion of N points in 1D. The problem is that I cannot find a way to get rid of the previous plots and remove the tracks created in the motion.
function sol=Draw(N)
%N is the number of points
PointsPos=1:N
for s=1:1000
for i=1:N
PointsPos(i)=PointsPos(i)+ rand(1,1)
%The position of the point is increased.
end
for i=1:N
%loop to draw the points after changing their positions
hold on
plot(PointsPos,1,'.')
end
pause(0.005)
%here I want to delete the plots of the previous frame s
end
end
A general guideline for MATLAB procedural animation is:
Avoid creating or deleting graphical objects as much as possible in the animation loop.
Therefore, if you invoke plot image surf or delete in the animation loop, then most likely you are not doing it optimally.
Here, the best practice is to create the plot BEFORE the animation loop, then use set(plot_handle, 'XData', ...) to update the x coordinates of the plot points.
Also you should add a rand(1, N) to PointsPos, as opposed to adding rand(1, 1) N times.
So you code should look somewhat similar to the following:
function sol=Draw(N)
PointsPos=1:N
h = plot(PointsPos, ones(1, N), '.');
for s=1:1000
PointsPos=PointsPos+ rand(1,N)
set(h, 'XData', PointsPos);
pause(0.005)
end
end
If I understood your goal, then this should do what you want:
function sol = Draw(N)
steps = 1000;
% N is the number of points
PointsPos = cumsum([1:N; rand(steps-1,N)],1);
p = scatter(PointsPos(1,:),ones(N,1),[],(1:N).');
colormap lines
for s = 2:steps
p.XData = PointsPos(s,:);
drawnow
end
end
Note that:
There is no need to compute anything inside the loop, use vectorization and cumsum to calculate all the positions of the points (i.e. all the PointsPos matrix) at once.
For plotting unrelated circles, scatter would be a better choice.
Instead of using pause with some arbitrary time you can use drawnow to update your plot.
This is about how MATLAB can take very different times to plot the same thing — and why.
I generate 10000 points in 3D space:
X = rand(10000, 1);
Y = rand(10000, 1);
Z = rand(10000, 1);
I then used one of four different methods to plot this, to create a plot like so:
I closed all figures and cleared the workspace between each run to try to ensure fairness.
Bulk plotting using scatter3:
>> tic; scatter3(X, Y, Z); drawnow; toc
Elapsed time is 0.815450 seconds.
Individual plotting using scatter3:
>> tic; hold on;
for i = 1:10000
scatter3(X(i), Y(i), Z(i), 'b');
end
hold off; drawnow; toc
Elapsed time is 51.469547 seconds.
Bulk plotting using plot3:
>> tic; plot3(X, Y, Z, 'o'); drawnow; toc
Elapsed time is 0.153480 seconds.
Individual plotting using plot3:
>> tic; hold on
for i = 1:10000
plot3(X(i), Y(i), Z(i), 'o');
end
drawnow; toc
Elapsed time is 5.854662 seconds.
What is it that MATLAB does behind the scenes in the 'longer' routines to take so long? What are the advantages and disadvantages of using each method?
Edit:
Thanks to advice from Ben Voigt (see answers), I have included drawnow commands in the timing — but this has made little difference to the times.
The main difference between the time required to run scatter3 and plot3 comes from the fact that plot3 is compiled, while scatter3 is interpreted (as you'll see when you edit the functions). If scatter3 was compiled as well, the speed difference would be small.
The main difference between the time required to plot in a loop versus plotting in one go is that you add the handle to the plot as a child to the axes (have a look at the output of get(gca,'Children')), and you're thus growing a complicated array inside a loop, which we all know to be slow. Furthermore, you're calling several functions often instead of just once and incur thus calls from the function overhead.
Recalculation of axes limits aren't an issue here. If you run
for i = 1:10000
plot3(X(i), Y(i), Z(i), 'o');
drawnow;
end
which forces Matlab to update the figure at every iteration (and which is A LOT slower), you'll see that the axes limits don't change at all (since the default axes limits are 0 and 1). However, even if the axes limits started out differently, it wouldn't take many iterations for them to converge with these data. Compare with omitting the hold on, which makes plotting take longer, because axes are recalculated at every step.
Why have these different functions? scatter3 allows you to plot points with different marker sizes, and colors under a single handle, while you'd need a loop and get a handle for each point using plot3, which is not only costly in terms of speed, but also in terms of memory. However, if you need to interact with different points (or groups of points) individually - maybe you want to add a separate legend entry for each, maybe you want to be able to turn them on and off separately etc - using plot3 in a loop may be the best (though slow) solution.
For a faster approach, consider this third option (directly uses the low-level function LINE):
line([X,X], [Y,Y], [Z,Z], 'LineStyle','none', 'Marker','o', 'Color','b')
view(3)
Here are some articles discussing plotting performance issues:
Performance: scatter vs. line
Plot performance
Well, if you wanted control over the color of each point, bulk scatter would be faster, because you'd need to call plot separately.
Also, I'm not sure your timing information is accurate because you haven't called drawnow, so the actual drawing could take place after toc.
In summary:
plot3 is fastest because it draws the same marker at many different locations
scatter3 draws many different markers, since size and color of the marker (are allowed to) vary with each point
calling in a loop is really slow, because argument parsing and so forth have to take place repeatedly, in addition as points are added to the plot the axes have to be recalculated