I have been trying to generate animation files (.AVI files) in parallel remotely on a cluster via shell script with Matlab. So far this has been an impossible task. I have all but given up, and have just accepted that I will need to generate the animations on my laptop overnight for 8 hours or so. But I’m hoping that someone out there knows how to fix this, or that I can stop someone from wasting a day of trial and error.
I have generated a large number of two dimensional probability distributions numerically (via Matlab) and I want to plot these surfaces as a function of time. I know that I could probably try to output a bunch of .jpegs to file and use another program such as MEncoder or something, but dammit, this is something Matlab should be able to do.
I have access to a nice cluster with lots of nodes and want to generate animations in parallel via shell script:
/usr/local/MATLAB/R2013b/bin/matlab -nojvm -nodisplay -r “TestFile1”
I know that the switch -nojvm will kill Java, so I omit this:
/usr/local/MATLAB/R2013b/bin/matlab -nodisplay -r “TestFile1”
I will go through the progression of my code below, first running code on my laptop (new MacBook Pro) successfully and then failing when trying to run the same code on the cluster. Hopefully someone with more experience with Matlab will notice my error and set me on the correct path.
First I have had success doing this with movie2avi, a simple example for which is shown below:
%%————————————————————————%%
clear Mov
clear rect
rect = get(gcf,'Position');
rect(1:2) = [0 0];
figure(1)
for ii=1:100
clf;
meshc(((ii+75)/100).*peaks)
grid on
axis([0 50 0 50 -20 20 -10 10])
colorbar
shading interp
Mov(:,ii) = getframe(gcf,rect);
end
movie2avi(Mov, 'test0.avi', 'compression','None','fps',30); % fps = frames per second
%%————————————————————————%%
The problem with this method is that it uses getframe which requires the plots to be generated on the screen.
Second After a lot of trial and error I was able to generate this .AVI file on my laptop without displaying the figure using figure('visible','off') and addframe.
%%————————————————————————%%
aviobj=avifile('test1.avi','compression','None');
hf= figure('visible','off');
for ii=1:100
clf;
meshc(((ii+75)/100).*peaks)
grid on
axis([0 50 0 50 -20 20 -10 10])
colorbar
shading interp
aviobj=addframe(aviobj,hf);
end
aviobj=close(aviobj);
close(hf);
exit
%%————————————————————————%%
As I mentioned above, this works quite nicely on my laptop, but is met with the Matlab message:
Warning: AVIFILE will be removed in a future release. Use VIDEOWRITER instead.
When I try to run this on the cluster the error message is:
Error using avifile/addframe>ValidateFrame (line 287) Frame must be 660 by 520.
So I go back to my laptop and print aviobj for each loop iteration and see that the frame size is always Width: 560, Height: 419. At this point I figure maybe Matlab just doesn’t like AVIFILE so instead I should try to use VIDEOWRITER.
Third I found some examples on the web (via the Matlab website and stackoverflow) that generated animations with VIDEOWRITER, but for the life of me I cannot work out how to use this function without also using getframe, so a figure is always displayed. One example that works on my laptop, showing the figure before the .AVI file is generated is shown below:
%%————————————————————————%%
writerObj = VideoWriter('test2.avi');
open(writerObj);
Z = peaks; surf(Z);
axis tight
set(gca,'nextplot','replacechildren');
set(gcf,'Renderer','zbuffer');
for k = 1:100
surf(sin(2*pi*k/20)*Z,Z)
frame = getframe;
writeVideo(writerObj,frame);
end
close(writerObj);
%%————————————————————————%%
Of course when I run this on the cluster I get the expected error:
getframe requires a valid figure window
I’ve seen plenty of examples on stackoverflow of people attempting to use VIDEOWRITER with im2frame instead of getframe, but none of these work and I beginning to think that VIDEOWRITER is incompatible with im2frame.
Is there anyone out there that has solved a similar issue, and if so can you give me a simple example to try to run remotely?
EDIT:
Thanks nkjt, with your advice I was able to create an .AVI file from a series of figures that were saved to disk. I have put my code below for anyone that might be interested. This worked on both my laptop and the cluster I have access to. Though the cluster had some issues with the size of the figure, something I was not able to resolve. Also, when I used this code to write the figures to disk for the actual case I was interesting in, I got the error:
Segmentation fault (core dumped),
something that seems quite common when generating figures with the -nodisplay switch. So I have given up and have instead generated my animations overnight on my laptop. It may be time to start using python instead of Matlab…
To write the plots to file:
%%————————————————————————%%
[X,Y] = meshgrid(-3:0.1:3);
Z = peaks(X,Y);
set(gcf,'Visible','off');
for ii=1:100
filename1 = [ 'WTest', num2str(ii),'a.jpg' ];
clf;
meshc(X,Y,((ii+75)/100).*Z)
grid on
axis([-3 3 -3 3 -20 20 -10 10])
colorbar
saveas(gcf,filename1,'jpg');
end
%%————————————————————————%%
To take the saved plot files and make an .AVI file:
%%————————————————————————%%
% Take plots to file and make .AVI file
vidObj = VideoWriter('Wtest.avi');
vidObj.Quality = 100; % 0 -- 100
vidObj.FrameRate = 10; % fps
open(vidObj);
set(gcf,'Visible','off');
for ii = 1:100
clf;
filename1 = [ 'WTest', num2str(ii),'a.jpg' ];
img = imread(filename1);
writeVideo(vidObj,img);
end
close(vidObj);
%%————————————————————————%%