MATLAB's drawnow doesn't flush - matlab

Is there any reason that MATLAB's drawnow wouldn't flush?
This is my code:
j=1;
for k = 1:length(P)
for i = 1:n
plot(P(k,j),P(k,j+1),'.');
j = j+2;
end
axis equal
axis([-L L -L L]);
j=1;
drawnow
end
(rungekutta4 is my own function I wrote, and it works OK, so the problem isn't there.)
The particles just stay drawn on the plot and don't get overwritten every time the loop executes.
How could I fix this problem?

The proper and efficient way to do this is with handle graphics. You should also vectorize your plot commands.
% Example data to make runnable
L = 1;
n = 10; % Number of points
P = 2*rand(1e2,n+1)-1;
% Initialize plot, first iteration
h = plot(P(1,1:n),P(1,2:n+1),'.'); % Plot first set of points and return handle
axis equal;
axis([-L L -L L]);
hold on; % Ensure axis properties are fixed
drawnow;
% Animate
for k = 2:size(P,1) % size is safer in this case
% Use handle to update the positions of the previously plotted points
set(h,{'XData','YData'},{P(k,1:n),P(k,2:n+1)});
drawnow;
pause(0.1); % Slow down animation a bit to make visible
end
Calling clf and/or plot on each iteration of an animation causes many things already in memory to be unnecessarily deleted and reallocated, resulting much slower code. It may also result in flickering in some cases.
See also this very similar question and answer.

When you want to animate something, you want to, of course, force draw. Thats what the command drawnow is there for. But there are other things to consider!
One of them is that you need to make sure that everything is drawn in each frame. For that, use the hold on function just before you start drawing (plot).
However, you also need to make sure that you clear the image before drawing, else the plots will stack forever. Use the clf "clear figurecommand before the previously mentionedhold on` and that will do the job.
remember that if the animation is too fast you can always add a pause(0.2) line after drawnow to slow it.

Related

Matlab Plot that changes with time

I am trying to plot a figure that changes with time (think of it as plotting the shape of a pole as the wind passes through it, so I want to plot the shape at every second).
To avoid the x axis limit changing frequently I want to fix it to the limits (max and min that I calculate before plotting). Here is a sample of my code:
for i=1:1:numberofrows
momentvaluesatinstant = momentvalues(i,:);
figure(1)
plot(momentvaluesatinstant,momentheader)
drawnow
title(sprintf('Moment profile along pile at time 0.2%f',time(i)'))
xlabel('Moment (kN.m)')
xlim([momentvalues(rowminmoment) momentvalues(rowmaxmoment)])
ylabel('Length of pile (m)')
delay(1);
end
Although I am specifying the limits of the x axis to be fixed to the values I specify, the plot keeps changing the limits depending on the data being plotted? Is there something I am missing?
Figured it, need to add xlim manual
I'm not sure why you needed xlim manual, but here is a more compact and correct way to animate your data:
% use 'figure', `plot` and all the constant parts of the figure only once, before the loop.
figure(1)
m = plot(momentvalues(1,:),momentheader); % plotting only step 1
xlim([momentvalues(rowminmoment) momentvalues(rowmaxmoment)])
xlabel('Moment (kN.m)')
ylabel('Length of pile (m)')
% loop from step 2 ahead
for k = 2:length(momentvalues)
pause(1); % use pause to set the delay between shots
% use 'set' to change the x values
set(m,'Xdata',momentvalues(k,:));
drawnow
title(sprintf('Moment profile along pile at time 0.2%f',k))
end

Change the color of a pixel in an imagesc plot without repainting everything in Matlab/Octave

I have a for-loop where I would like to paint at every step a new pixel in an imagesc plot. I am currently repainting the whole figure but the figure is blinkering and I know it is not the proper way to do so. Can anyone help to find the appropriate function to do this task?
You can address the data in each pixel with the CData property of the image without having to close and redraw the figure, axes, or axes object over and over. Ends up being about 1.5x - 2x faster than trying to generate a new image object or just calling imagesc() over and over.
In these loops don't forget the drawnow call or MATLAB will try to skip the figure drawing until the looping completes.
Example code:
data = rand(200, 200); % Data to display
figure(1) % Make a figure
imgHand = imagesc(data); % Display data in it
% Naive way - call imagesc() each time.
% Slow. Don't do it this way.
for k = 1:numel(data);
data(k) = data(k) + 10*rand(1,1); % Update data
imagesc(data) % Redraw it by calling imagesc()
drawnow; % Display updated figure
end
% Faster way - address CData of image object directly
% 1.5-2x faster than above method
for k = 1:numel(data);
data(k) = data(k) + 10*rand(1,1); % Update data
set(imgHand, 'CData', data); % Change CData property of object
drawnow; % Display updated figure
end
You don't have a choice but to paint everything at each iteration if you want to draw every frame that has an update. However, you can minimize the flickering (or perhaps even remove it) by perhaps placing a pause at the end of your loop before the next iteration. This way, it'll give the frame buffer a chance to draw to the screen completely before you draw the next frame.
Something like:
for idx = 1 : total_frames
%// Do stuff
drawnow; %// Draw frame
pause(0.1); %// Pause
end
total_frames would be the total number of times you are refreshing the plot, and inside the loop you would do the work necessary, you then draw the figure, then pause for 0.1 ms. Adjust the time to whatever works for you.

Matlab continue graph for second loop

%free fall of a ball
clc
clear all
close all
v0=5; % initial velocity up
g=9.8; %free fall acceleration
v1=(0.7/0.9)*v0
% time of fly
tup=v0/9;
nsteps=10; %number of frames
dt=tup/nsteps; %time step
Hmax=v0*tup+(-g)*tup*tup/2; % maximum altitude
altitude(1:nsteps+1)=0; %define array for position Y
time=0:dt:tup;% define time array
%initilaise plot
figure(1)
axis([0,2*tup,0,2*Hmax]);
hold on
% loop
for i=1:nsteps
altitude(i)=v0*time(i)+(-g)*time(i)*time(i);
plot(time(i),altitude(i), 'ro')
grid on;
M(i)=getframe;
end
%loop bouncing
for i=1:nsteps
altitude(i)=v1*time(i)+(-g)*time(i)*time(i);
plot(time(i),altitude(i), 'ro')
grid on;
M(i)=getframe;
end
%make movie
movie(M);
movie2avi(M, 'C:\Users\Mehmet\Desktop\avi\mm','compression','none');
%extra plots
figure(2)
plot(time(1:nsteps),altitude(1:nsteps))
figure(3)
plot(time(1:nsteps),altitude(1:nsteps),'ro')
We have this ball bouncing simulation. What we want to do is, to continue loop 2 after loop 1 in graph.So, it will be continious bouncing simulation.2 bouncings are shown from 1:10 steps but we want second loop to be shown after 10 steps.
There are a couple of approaches, depending upon what effect you're going for. The simplest is to simply add hold on as a separate command after each of your plot commands. This will keep accumulating new lines/dots without erasing the old ones. To stop this effect, add a hold off command. The next plot command will then erase everything and plot on a clean graph.
Alternatively, if you only want to show a fixed number of the previous steps (and not all of them, as the hold on will do), you'll have to explicitly hold onto the previous values. Something like this:
% loop
max_history = 10; %plot this many symbols
for i=1:nsteps
altitude(i)=v0*time(i)+(-g)*time(i)*time(i);
%get the historical and current data points to plot
start_ind = i-max_history+1; %here's the oldest point that you'd like
start_ind = max([start_ind, 1]) %but you can't plot negative indices
inds = [start_ind:i]; %here are the ones to plot
%update the plot
plot(time(inds),altitude(inds), 'ro');
grid on;
%you might need a "drawnow" here
M(i)=getframe;
end
Copy this same idea into your other for loops and you should be good-to-go!

plot hold for plot3 matlab

There is a similar question, to which the answer was given. My question is the same as this one, except, I have 2 loops instead of one as showed there. Still, the solution does't seem to work for me.
The question : How to hold a plot when using plot3 in matlab?
Here, there is a single loop ad the solution seems to work fine. The following is my code :
figure(1)
for i = 1:n
for j = 1:m
if(condition)
%some calculations to get X
x = X(1,:);
y = X(2,:);
z = X(3,:);
plot3(x,y,z,'.');
view(3);
hold on;
end
end
hold on;
end
Here, after all iterations of the inner loop using 'j', am getting a proper plot, but once it goes to the outer loop, the plot refreshes and starts again. How can I maintain the plot3 for both the loops? I have used hold on again in the outer loop, but it still doesn't seem to work. Can anyone tell me how I can maintain the plot for 2 loops.? Thanks in advance.
I think that your code should work as is. However, a few changes I would make, which should help whatever problem that you are having:
hold on only needs to be called once.
view(3) also only needs to be called once (actually is not needed at all to get the data plotted, just helps with the visualization).
When I'm performing complex plotting, I usually need to specify the axis to plot on explicitly. Otherwise the plot goes to the "current" axis, which can be changed by some operations. (Depends what you are doing in your calculations.)
A common problem when it looks like data is not being added to a plot is axis scaling. You can use axis tight for a decent first guess at scaling the axis limits.
Putting this together, try this, and see what happens:
%Set up figure to catch plots
figure(1);
hAxis = gca; %This will create an axis in the figure, and return its handle
hold on; %You can also use hold(hAxis,'on') if you are really paranoid about which axis is catching your commands
%Perform plots
for i = 1:n
for j = 1:m
if (condition)
%some calculations to get X
x = X(1,:);
y = X(2,:);
z = X(3,:);
plot3(hAxis,x,y,z,'.');
end
end
end
%Adjust view etc (experiment here after the data is plotted)
view(3)
axis tight

Matlab change a single point in a plot without replotting

So I have a plot of N points in the 2D plane (N can be very large). I am writing a script that is to show the workings of an algorithm. So I have for loops. At each step in the for loop I'd like to change the color of the current point (actually probably make a stem plot with just this point).
However, at the end of the step I'd like to remove the coloring of the current point so that I can color the next one. Currently I have to redraw the whole plot (incl. the 2D points). I'm not sure whether Matlab detects such things in the plotting commands but is there a way to do this without redrawing the whole plot?
For example:
plot(x,y, '*');
for j = 1:N-1
for i = j:N
hold on;
%Do stuff
plot(x,y, '*');
hold on;
stem(x(1), y(1), 'g*');
end
end
A quick example:
%# plot some data
x = 1:100;
y = cumsum(rand(size(x))-0.5);
plot(x,y,'*-')
%# animate by going through each point
hold on
h = stem(x(1),y(1),'g');
hold off
for i=1:numel(x)
%# update the stem x/y data
set(h, 'XData',x(i), 'YData',y(i));
%# slow down a bit, drawnow was too fast!
pause(.1)
end
Take a look at the documentation of handle graphics objects.
I'd recommend plotting the whole set of points as one object. Then, for each iteration, plot the point of interest. Save a handle to it (as in, h = plot(...);). When you're ready for the next iteration, delete the object using that handle (delete(h)), and create the next one in the same manner.
%# outside the for loop (do this once)
plot(x,y,'*');
for...
h = stem(x(i),y(i),'g*');
...
%# next iteration... i has been incremented
delete(h);
h = stem(x(i),y(i),'g*');
end