Adding subplots to animated gif file
14 次查看(过去 30 天)
显示 更早的评论
mashtine
2014-10-16
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!
采纳的回答
Geoff Hayes
2014-10-17
编辑:Geoff Hayes
2014-10-22
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 个评论
mashtine
2014-10-21
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
2014-10-21
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
2014-10-22
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
2014-10-22
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
2014-10-22
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
2014-10-22
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);
mashtine
2014-10-22
Perfect! Sorry for the back and forth. I figured they had to be in the same loop but I did not know how to change the getframe.
Thanks Geoff!
mashtine
2014-10-22
Geoff - quick question, if I need to plot more than one YDATA on a sub plot, how would I go about doing this? I know that I would need more handling of the handles but I am not too sure how to go about this.
Geoff Hayes
2014-10-22
编辑:Geoff Hayes
2014-10-22
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?
mashtine
2014-10-23
The x data is the same yes, just time. And yes, I would like each Y data set to animate and thus have them within the loop.
Geoff Hayes
2014-10-23
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
2014-10-23
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
2014-10-23
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
2014-10-23
编辑:mashtine
2014-10-23
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
2014-10-23
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.
mashtine
2014-10-24
And case closed! Geoff, you did not have to do all of this help so thank you sincerely!
derbruin
2015-7-8
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
2015-7-8
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.
derbruin
2015-7-8
hi Geoff,
thanks for looking into this for me. I posted my question using this title "create .gif animation with mixed subplots of grayscale and color figures". Appreciate your help!
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Graphics Performance 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- 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)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)