I have 20 figures to display one after another like slide show. Can I do it using Imshow in Matlab? Any sort of help will be appreciated.
Couple options:
Open a figure for each plot
Open and close a figure for each plot
Reuse one figure
Open a figure for each plot
for i=1:20
h = figure;
%plot here
pause
end
Open and close a figure for each plot
for i=1:20
h = figure;
%plot
pause
close gcf
end
Reuse one figure
h=figure
for i=1:20
clf(h);
%plot
pause
end
OR depending on what you are plotting, you can use the refreshdata method.
If you use #Jonas' method, and if you have dual monitors, you have to force the figure to the main monitor for getframe to actually work, as per. You can do this via:
ff=figure;
movegui(ff)
You can use MOVIE to display plots/images one after the other. For this, you create the figures, capture them via GETFRAME, and then you can call movie. See this example from the help for getframe
Z = peaks; surf(Z)
axis tight
set(gca,'NextPlot','replacechildren');
for j = 1:20
surf(sin(2*pi*j/20)*Z,Z)
F(j) = getframe;
end
movie(F,20) % Play the movie twenty times
Related
I am attempting to write some code that will allow me to click on the axes and the ode solution with the clicked point as the initial condition will be plotted. Here is what I have tried thus far:
function myui
clc
close all
xmin=2;
xmax=10;
ymin=-4;
ymax=4;
f=#(t,y) y^2-t
fig=figure;
ax=axes('Units','pixels',...
'XLim',[xmin,xmax],...
'YLim',[ymin,ymax],...
'ButtonDownFcn',#plotode)
function plotode(source,event)
initcond=get(ax,'CurrentPoint');
initcond=initcond(1,1:2)
[t,y]=ode45(f,[initcond(1),xmax],initcond(2));
plot(t,y)
hold on
[t,y]=ode45(f,[initcond(1),xmin],initcond(2));
plot(t,y)
axis([xmin xmax ymin ymax])
hold off
end
end
I have several questions.
I can only click one time. I'd like to click several times and draw several curves.
The curve can shoot to plus or minus infinity quite quickly, so I'd like to halt ode 45 if it leaves my axes window.
I'd appreciate it if someone could share some complete code that works as I could really learn quite a bit.
Thanks.
All,
I've added some steps to my code that performs the task I wished to see.
function myui
% clear command window and close all open figures
clc
close all
% define our function
f=#(t,y) y^2-t;
% axes boundaries
tmin=2;
tmax=10;
ymin=-4;
ymax=4;
% steps for quiver
tstep=20;
ystep=20;
% create a figure window
fig=figure;
% create axes with limits
ax=axes('Units','Normalized',...
'XLim',[tmin,tmax],...
'YLim',[ymin,ymax]);
% create direction field with quiver
[T,Y]=meshgrid(linspace(tmin,tmax,tstep),...
linspace(ymin,ymax,ystep));
S=Y.^2-T;
L=sqrt(1+S.^2);
quiver(T,Y,1./L,S./L,0.5,'r','ButtonDownFcn',#plotode)
axis tight
hold on
% set ButtonDownFcn on axes ax
set(ax,'ButtonDownFcn',#plotode);
% function plots initial conditions and solutions
function plotode(source,event)
warning('off','MATLAB:ode45:IntegrationTolNotMet');
initcond=get(ax,'CurrentPoint');
initcond=initcond(1,1:2);
[t,y]=ode45(f,[initcond(1),tmax],initcond(2));
plot(t,y,'b','linewidth',1)
[t,y]=ode45(f,[initcond(1),tmin],initcond(2));
plot(t,y,'b','linewidth',1)
plot(initcond(1),initcond(2),'ro')
set(ax,'XLim',[tmin,tmax],'YLim',[ymin,ymax],...
'ButtonDownFcn',#plotode);
end
end
It produces this image when I click on the axes with my mouse several times.
I'd still love to listen to some instruction and suggestions.
Thanks.
I'm trying to create an animation file in MATLAB from a figure with 2 subplots using the VideoWriter. However, the avi file that I get includes only one of the subplots.
Here is the code:
clc
clear
vidObj = VideoWriter('randdata');
open(vidObj)
figure (1)
for i = 1:100
clf
subplot(1,2,1)
imagesc(rand(100))
subplot(1,2,2)
imagesc(rand(100))
drawnow
CF = getframe;
writeVideo(vidObj,CF);
end
There must be something simple going wrong here but I don't know what. I would like to capture the entire figure.
The documentation for getframe states in the first line:
F = getframe captures the current axes
So it's capturing the axes, not figure.
You want to use it as also specified in the documentation
F = getframe(fig) captures the figure identified by fig. Specify a figure if you want to capture the entire interior of the figure window, including the axes title, labels, and tick marks. The captured movie frame does not include the figure menu and tool bars.
So your code should be
clc; clear
vidObj = VideoWriter('randdata');
open(vidObj);
figure(1);
for ii = 1:100
clf
subplot(1,2,1)
imagesc(rand(100))
subplot(1,2,2)
imagesc(rand(100))
drawnow;
% The gcf is key. You could have also used 'f = figure' earlier, and getframe(f)
CF = getframe(gcf);
writeVideo(vidObj,CF);
end
For ease, you might want to just get a File Exchange function like the popular (and simple) gif to create an animated gif.
I have a figure in which I plot some disperse points and then a trajectory. I want to switch between different trajectories by plotting them in the same figure as the points, but without creating new figures, i.e., "erasing" the first trajectory and then plotting the new one.
Is there a way of doing this?
Perhaps this little demo will be helpful:
xy = rand(20,2);
figure
% Plot first iteration and output handles to each
h = plot(xy(:,1),xy(:,2),'b.',xy(1:2,1),xy(1:2,2),'r-');
axis([0 1 0 1])
% Update second plot by setting the XData and YData properties of the handle
for i = 2:size(xy,1)-1
set(h(2),{'XData','YData'},{xy(i:i+1,1),xy(i:i+1,2)})
drawnow
pause(0.1);
end
You should read up on handle graphics in Matlab and the get and set functions.
I want to plot two simultaneous plots in two different positions in Matlab, looped animations and both are different animations, one with hold on and another with hold off.
Also, one is 2D and one is 3D
I am doing something like this:
for i=1:some_number
axes('position',...)
plot(...);hold on;
axes('position',...)
clf
plot3(...) (or fill3 but has to do with 3d rendering)
view(...)
set(gca, 'cameraview',...)
set(gca,'projection',...)
mov(i)=getframe(gcf)
end
Q1. Do the set properties effect first axes? if so, how to avoid that?
Q2. In my plot hold on did not work. Both were instantenous. like using hold off. How do I make it work?
Q3. I hope the mov records both axes.
P.S. I hope clf is not a problem. I must use clf or if there are equivalents more suitable in my case do suggest me.
You need to store the return from the axes function and operate specifically on a given axes with subsequent function calls, rather than just the current axes.
% Create axes outside the loop
ax1 = axes('position',...);
ax2 = axes('position',...);
hold(ax1, 'on');
for i=1:some_number
plot(ax1, ...);
cla(ax2); % use cla to clear specific axes inside the loop
plot3(ax2, ...) (or fill3 but has to do with 3d rendering)
view(ax2, ...)
set(ax2, 'cameraview',...)
set(ax2,'projection',...)
mov(i)=getframe(gcf)
end
Here is a snippet from a piece of my code which plots orbits of three celestial bodies which I think will help you:
for i = 1:j, %j is an arbitrary number input by the user
plot(x, y, '*')
plot(x2, y2, 'r')
plot(xa, ya, '+')
grid on
drawnow %drawnow immediately plots the point(s)
hold on %hold on keeps the current plot for future plot additions
%dostuff to x,y,x2,y2,xa,ya
end
The two main functions you want are the drawnow and hold on.
Just to note: x,y,x2,y2,xa, and ya change with each iteration of the loop, I have just omitted that code.
EDIT: I believe the drawnow function will solve your problem with hold on.
I think this may solve your problem.
for i=1:some_number
axes('position',...)
plot(...);
drawnow %also note that you must not put the ; at the end
hold on %see above comment
axes('position',...)
clf
plot3(...) (or fill3 but has to do with 3d rendering)
view(...)
set(gca, 'cameraview',...)
set(gca,'projection',...)
mov(i)=getframe(gcf)
end
I am trying to create a movie from my MATLAB plot. When I call getframe, it "usually" captures the plot image, but sometimes if there is something else active on the screen (which is normal if I continue to use the computer) it captures whatever window is active. Is there another way to grab the image of the active figure?
e.g.
fig = figure;
aviobj = avifile('sample.avi','compression','None');
for i=1:t
clf(fig);
plot(...); % some arbitrary plotting
hold on;
plot(...); % some other arbitrary plotting
axis([0 50 0 50]);
aviobj = addframe(aviobj, getframe(fig));
end
aviobj = close(aviobj);
OK, found the solution; instead of
aviobj = addframe(aviobj, getframe(fig));
sending the figure handle directly to addframe is enough:
aviobj = addframe(aviobj, fig);
The Matlab people are apparently phasing out the avifile and addframe functions in future releases, replacing them with VideoWriter and writeVideo respectively. Unfortunately, this means that the accepted answer will no longer work, since writeVideo doesn't accept the figure handle as the argument.
I've played around with it a bit, and for future reference, the same thing can be accomplished using the undocumented hardcopy function. The following code works perfectly for me, with the added benefit of not even having a plot window pop up, so it does everything completely in the background:
fig = figure('Visible','off');
set(fig,'PaperPositionMode','auto');
writerobj = VideoWriter('sample.avi','Uncompressed AVI');
open(writerobj);
for i=1:t
clf(fig);
plot(...); % some arbitrary plotting
hold on;
plot(...); % some other arbitrary plotting
axis([0 50 0 50]);
figinfo = hardcopy(fig,'-dzbuffer','-r0');
writeVideo(writerobj, im2frame(figinfo));
end
close(writerobj);
You can pass the handle of the desired figure or axis to GETFRAME to ensure that it doesn't capture another window.
I may depend on the renderer you're using. If it's 'painters', then you should be OK, but if it's anything else, such as 'OpenGL', then I think it has to get the frame data from the graphics card, which means that if you have something overlapping the window, then that may end up in the output of getframe.
As someone has already stated you don't have to use getframe, however if you insist on using it you can use
set(fig,'Renderer','zbuffer')
and this should fix your issue.
If you use getframe in many subplots, try to add at the end:
I think the get frame works fine it just the rendering a bit was unpositioned.
clf(fig)
% use 1st frame to get dimensions
[h, w, p] = size(frames(1).cdata);
hf = figure;
% resize figure based on frame's w x h, and place at (150, 150)
set(hf,'Position', [150 150 w h]);
axis off
% Place frames at bottom left
movie(hf,frames,4,30,[0 0 0 0]);
close(gcf)