You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Adding subplots to animated gif file
14 views (last 30 days)
Show older comments
Hi all,
I have the following code to create a gif from my data plots and I would like to do this with subplots for other parameters. The code is a bit messy but I am not sure how to work the handles for the subplots to have the playback synchronized for each plot:
DATASET1 = tower_pres_allyrs(1:100,1);
DATASET2 = tower_pres_allyrs(1:100,2);
h = plot(NaN,NaN);
axis([min(DATASET1) max(DATASET1) min(DATASET2) max(DATASET2)]);
for ii = 1:length(DATASET1)
pause(0.1)
set(h, 'XData', DATASET1(1:ii), 'YData', DATASET2(1:ii));
drawnow
frame = getframe(1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,'filename.gif','gif','Loopcount',inf,'DelayTime',0.01);
else
imwrite(imind,cm,'filename.gif','gif','WriteMode','append','DelayTime',0.01);
end
end
Thanks!
Accepted Answer
Geoff Hayes
on 17 Oct 2014
Edited: Geoff Hayes
on 22 Oct 2014
Masao - what do you mean by I would like to do this with subplots for other parameters? As your above code doesn't reference subplots, how are you currently using subplots?
If hSubPlotAxes is the handle to the axes of any subplot, then your above code could become
h = plot(hSubPlotAxes,NaN,NaN);
axis(hSubPlotAxes,[min(DATASET1) max(DATASET1) min(DATASET2) max(DATASET2)]);
for ii = 1:length(DATASET1)
pause(0.1)
set(h, 'XData', DATASET1(1:ii), 'YData', DATASET2(1:ii));
drawnow
frame = getframe(hSubPlotAxes);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,'filename.gif','gif','Loopcount',inf,'DelayTime',0.01);
else
imwrite(imind,cm,'filename.gif','gif','WriteMode','append','DelayTime',0.01);
end
end
So we just use the handle to the subplot axes for whenever we wish to plot, set the axis limits, or getframe. You could the above code in a function and just pass the data, handle, and filename, so as to re-use the same code for each subplot.
EDIT
The line to call getframe has been updated to remove the second parameter.
20 Comments
mashtine
on 21 Oct 2014
Hi Geoff,
Thanks for this! I am a bit confused with your first line, with the hSubPlotAxes part in the plot() function.
What you are saying is that I would repeat this for each subplot I would like on my figure? For instance, I would like a gif that has 4 subplots on it that synchronously plots the data.
Do I make sense?
Geoff Hayes
on 21 Oct 2014
Hi Masao - hSubPlotAxes is the handle to the subplot axes. So if you have two rows of with one column of subplots, then the code may look something like
% create subplot
hSubPlotAxes = subplot(2,1,1);
% do some stuff (like above code)
% create second subplot
hSubPlotAxes = subplot(2,1,2);
% so some stuff
So as you create the subplots, you get the handle to the axes on that subplot. You then use the above code to add whatever data you want to it, then get the frames and write to file.
I'm not quite sure what you mean by I would like a gif that has 4 subplots on it that synchronously plots the data. Are you saying that your figure has 4 subplots, and that you will be updating all four, then grab the figure's frame, save to file, and repeat?
mashtine
on 22 Oct 2014
Hi Geoff,
Thanks again for your time. By 'I would like a gif that has 4 subplots on it that synchronously plots the data' I do mean what you said. I want all of the subplots to update at the same time and then simultaneously plot the next data point after saving the first into a gif.
I adjusted the code like you said but I keep getting and error with the getframe.
DATASET1 = tower_pres_allyrs(1:100,1);
DATASET2 = tower_pres_allyrs(1:100,2);
DATASET3 = tower_temp_allyrs(1:100,1);
DATASET4 = tower_temp_allyrs(1:100,2);
hSubPlotAxes = subplot(2,1,1);
h = plot(hSubPlotAxes,NaN,NaN);
axis(hSubPlotAxes,[min(DATASET1) max(DATASET1) min(DATASET2) max(DATASET2)]);
for ii = 1:length(DATASET1)
pause(0.1)
set(h, 'XData', DATASET1(1:ii), 'YData', DATASET2(1:ii));
drawnow
frame = getframe(hSubPlotAxes,1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,'filename.gif','gif','Loopcount',inf,'DelayTime',0.01);
else
imwrite(imind,cm,'filename.gif','gif','WriteMode','append','DelayTime',0.01);
end
end
hSubPlotAxes = subplot(2,1,2);
h = plot(hSubPlotAxes,NaN,NaN);
axis(hSubPlotAxes,[min(DATASET3) max(DATASET3) min(DATASET4) max(DATASET4)]);
for ii = 1:length(DATASET3)
pause(0.1)
set(h, 'XData', DATASET3(1:ii), 'YData', DATASET4(1:ii));
drawnow
frame = getframe(hSubPlotAxes,1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,'filename.gif','gif','Loopcount',inf,'DelayTime',0.01);
else
imwrite(imind,cm,'filename.gif','gif','WriteMode','append','DelayTime',0.01);
end
end
I am clearly missing something and I am sure the fault is on my end or in my explanation of the problem.
Geoff Hayes
on 22 Oct 2014
Hi Masao - first, what is the error that you are observing? If it is
Index exceeds matrix dimensions.
Error in getframe>Local_getRectanglesOfInterest (line 166)
absoluteRect = [pos(1:2)+offsetRect(1:2) offsetRect(3:4)];
Error in getframe (line 63)
[offsetRect, absoluteRect, figPos, figOuterPos] = ...
Error in gg (line 19)
frame = getframe(hSubPlotAxes,1);
then this is because of the call to getframe which I goofed on (now corrected) in my answer. Please change the line of code from
frame = getframe(hSubPlotAxes,1);
to
frame = getframe(hSubPlotAxes);
I removed the one which is not needed (unless you want to specify a rectangular area from which to copy the image). Try this again.
mashtine
on 22 Oct 2014
Hi Geoff - That works now in terms of getframe but when I run the code, the first subplot is animated and then the second one after the first has finished rather than both starting at the same time. Also, in the final .gif file, only the last subplot is saved (attached)
Geoff Hayes
on 22 Oct 2014
Masao - if you want the two animations to run at the same time, then there can only be one loop. You will have to combine the two blocks of code (that you have shown above) into one loop. Try using arrays to manage the 2 (or 4) different subplots, and create another array for the handles to the plots. For example
hSubPlotAxes = [];
hSubPlotAxes(1) = subplot(2,1,1);
hSubPlotAxes(2) = subplot(2,1,1);
hPlots = [];
hPlots(1) = plot(hSubPlotAxes(1),NaN,NaN);
hPlots(2) = plot(hSubPlotAxes(2),NaN,NaN);
Then use the arrays to set the axis dimensions, update the plots, etc. And within the one loop, you will have only one call to write the figure (of 2 or 4 subplots) to file. Since you are creating a frame of all subplots, then you will have to change the line of code for the getframe back to
frame = getframe(1);
or
frame = getframe(gcf);
Geoff Hayes
on 22 Oct 2014
Edited: Geoff Hayes
on 22 Oct 2014
Is the x data the same for each set of y data? Would you replace both sets of y data on each iteration of the for loop?
Geoff Hayes
on 23 Oct 2014
If you are plotting more than one set of y data, then you will probably end up with two handles for your plot. For example, if
figure;
x=-2*pi:0.0001:2*pi;
h=plot(x,cos(x),x,sin(x));
then h will be a 2x1 vector of handles
h =
350.00830078125
351.0078125
That means you would have to update the y data of each graphics object (plot) separately using each handle. If you are doing this, then you might want to consider storing these handles in a cell array
hPlots = {};
hPlots{1} = plot(x,cos(x),x,sin(x));
etc.
mashtine
on 23 Oct 2014
Thats the part that confused me, so if I have the first subplot with just one y data, I will use this:
hSubPlotAxes(1) = subplot(6,1,1);
hPlots{1} = plot(hSubPlotAxes(1),NaN,NaN);
but I am not too sure of how to then incorporate this with the axis handles and set within the loop. So far I have this (without taking into account what you just mentioned) and I am not too sure how to incorporate your the cell arrays. I only started plotting on the first two subplots:
hSubPlotAxes = [];
hSubPlotAxes(1) = subplot(6,1,1);
hSubPlotAxes(2) = subplot(6,1,2);
hSubPlotAxes(3) = subplot(6,1,3);
hSubPlotAxes(4) = subplot(6,1,4);
hSubPlotAxes(5) = subplot(6,1,5);
hSubPlotAxes(6) = subplot(6,1,6);
hPlots = [];
hPlots(1) = plot(hSubPlotAxes(1),NaN,NaN);
hPlots(2) = plot(hSubPlotAxes(2),NaN,NaN);
hPlots(3) = plot(hSubPlotAxes(3),NaN,NaN);
hPlots(4) = plot(hSubPlotAxes(4),NaN,NaN);
hPlots(5) = plot(hSubPlotAxes(5),NaN,NaN);
hPlots(6) = plot(hSubPlotAxes(6),NaN,NaN);
axis(hSubPlotAxes(1),[min(PRESSTIME) max(PRESSTIME) 0 370]); % WINDDIR
axis(hSubPlotAxes(2),[min(PRESSTIME) max(PRESSTIME) -0.5 0.5]); % LR
axis(hSubPlotAxes(3),[min(PRESSTIME) max(PRESSTIME) 900 1050]);
axis(hSubPlotAxes(4),[min(PRESSTIME) max(PRESSTIME) 270 300]);
axis(hSubPlotAxes(5),[min(PRESSTIME) max(PRESSTIME) 0 25]);
axis(hSubPlotAxes(6),[min(PRESSTIME) max(PRESSTIME) 0 30]);
for ii = 1:length(PRESSTIME)
pause(0.01)
set(hPlots(1), 'XData', PRESSTIME(1:ii), 'YData', WINDDIR(1:ii,3), 'Color', 'r');
% LR
set(hPlots(2), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,2), 'Color', 'k');
hold all
set(hPlots(2), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,3), 'Color', 'k');
set(hPlots(2), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,4), 'Color', 'k');
set(hPlots(2), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,5), 'Color', 'r');
set(hPlots(2), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,6), 'Color', 'r');
set(hPlots(2), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,7), 'Color', 'r');
drawnow
frame = getframe(gcf);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,'Cold_front.gif','gif','Loopcount',inf,'DelayTime',0.001);
else
imwrite(imind,cm,'Cold_front.gif','gif','WriteMode','append','DelayTime',0.001);
end
end
Geoff Hayes
on 23 Oct 2014
So you are plotting six sets of data on the same axes, is that correct? If the above is not working, then please describe the problem. I don't have your data (nor am I am asking for it!) but you have to provide some hints as to what is going on (or wrong). Have you stepped through the code?
I suspect that with each set you are overwriting the data from the previous set. And that makes sense. If you do want to plot six sets of data, then try the following
hPlots = {};
hPlots{1} = plot(gca,NaN,repmat(NaN,6,1));
and note that hPlots{1} is a 6x1 vector of handles to graphics objects. Now just set each one individually, accessing the different handles as
hPlots{1}(1)
hPlots{1}(2)
etc.
mashtine
on 23 Oct 2014
Edited: mashtine
on 23 Oct 2014
Sorry, I thought I mentioned what was going wrong before but yes, the code is overwriting the ydata and only displaying the last plot:
set(hPlots(2), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,7), 'Color', 'r');
However when I try plotting now with the cell array handles I am getting the following error:
Error using handle.handle/set
Invalid or deleted object.
I cannot find anything online that helps explain what is going on. The script works perfectly up to when the first set() is called but when I try to do plots on the second subplot, neither subplot (first nor second) plots on the figure and I get the above error. Here is the updated code:
hSubPlotAxes = [];
hSubPlotAxes(1) = subplot(6,1,1);
hSubPlotAxes(2) = subplot(6,1,2);
hSubPlotAxes(3) = subplot(6,1,3);
hSubPlotAxes(4) = subplot(6,1,4);
hSubPlotAxes(5) = subplot(6,1,5);
hSubPlotAxes(6) = subplot(6,1,6);
hPlots = {};
hPlots{1} = plot(hSubPlotAxes(1),NaN,NaN);
hPlots{2} = plot(gca,NaN,NaN(6,1));
hPlots{3} = plot(hSubPlotAxes(3),NaN,NaN);
hPlots{4} = plot(hSubPlotAxes(4),NaN,NaN);
hPlots{5} = plot(hSubPlotAxes(5),NaN,NaN);
hPlots{6} = plot(hSubPlotAxes(6),NaN,NaN);
axis(hSubPlotAxes(1),[min(PRESSTIME) max(PRESSTIME) 0 370]); % WINDDIR
axis(hSubPlotAxes(2),[min(PRESSTIME) max(PRESSTIME) -0.5 0.5]); % LR
axis(hSubPlotAxes(3),[min(PRESSTIME) max(PRESSTIME) 900 1050]);
axis(hSubPlotAxes(4),[min(PRESSTIME) max(PRESSTIME) 270 300]);
axis(hSubPlotAxes(5),[min(PRESSTIME) max(PRESSTIME) 0 25]);
axis(hSubPlotAxes(6),[min(PRESSTIME) max(PRESSTIME) 0 30]);
for ii = 1:length(PRESSTIME)
pause(0.01)
set(hPlots{1,1}(1,1), 'XData', PRESSTIME(1:ii), 'YData', WINDDIR(1:ii,3), 'Color', 'r');
set(hPlots{1,2}(1,1), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,2), 'Color', 'k');
hold all
set(hPlots{1,2}(2,1), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,3), 'Color', 'k');
set(hPlots{1,2}(3,1), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,4), 'Color', 'k');
set(hPlots{1,2}(4,1), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,5), 'Color', 'r');
set(hPlots{1,2}(5,1), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,6), 'Color', 'r');
set(hPlots{1,2}(6,1), 'XData', PRESSTIME(1:ii), 'YData', LR(1:ii,7), 'Color', 'r');
drawnow
frame = getframe(gcf);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,'Cold_front.gif','gif','Loopcount',inf,'DelayTime',0.001);
else
imwrite(imind,cm,'Cold_front.gif','gif','WriteMode','append','DelayTime',0.001);
end
end
I only tried to plot on the first two subplots to reduce clutter. Geoff I am really sorry for all my painstaking questions! I hope this is the last!Attached is my hPlots array
Geoff Hayes
on 23 Oct 2014
Masao - you didn't say which line generates the error. Is this the first set, the second, third, or...? Which iteration of the for loop?
Try replacing
hPlots{2} = plot(gca,NaN,NaN(6,1));
with
hPlots{2} = plot(hSubPlotAxes(2),NaN,NaN(6,1));
The problem is that you are creating 6 plots on the gca which corresponds to the sixth subplot. These plots are then deleted when you plot (again) on the sixth subplot with
hPlots{6} = plot(hSubPlotAxes(6),NaN,NaN);
and so the error makes sense.
Geoff Hayes
on 24 Oct 2014
Glad it worked out, Masao!
derbruin
on 8 Jul 2015
Hi, Geoff:
just following up on Masao's question. I would like to simultaneously update a curve and a picture side by side. So far, I can update the picture. My question is how can I update the two together?
for idx = 1:numImages
frame = mat2gray(cView(:,:,ind),lungWindow);
[frameIndexed,frameMap] = gray2ind(frame,256);
if idx == 1
imwrite(frameIndexed, frameMap,fullfile(outputFolder,outputFilename),'gif','DelayTime', 0.15, 'LoopCount', inf);
else
imwrite(frameIndexed, frameMap,fullfile(outputFolder,outputFilename),'gif','DelayTime', 0.15, 'WriteMode','append');
end
Any help is appreciated!
Geoff Hayes
on 8 Jul 2015
Derbruin - where is the code to update the curve or even plot the image? Does the curve appear on the same axes as the image or on a different one? Please provide more information. As well, you may just want to post this as a separate question since it is distinct from Masao's question.
More Answers (0)
See Also
Categories
Find more on Graphics Performance in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)