I have been trying to animate a series of surface plots that I created for a 2D heat flow problem using finite element method. At each time step, I saved a plot instead of the whole matrix, in order to be more efficient.
I had trouble with the FuncAnimation
in the matplotlib.animation library, so I decided to render a surface plot at each time, save the surface plot as a .png file, and then read that image using pyplot.imread
. From there, I want to store each image into a list so that I can use the ArtistAnimation ( example). However it is not making the animation, instead I get two separate blank plots and then my surface plot .pngs when I print imgplot
to the screen.
Additionally, when I try to save the animation, I get the following error message:
AttributeError: 'module' object has no attribute 'save'.
Any help with reading in a set of .pngs from the current directory, saving them in a list, and then using ArtistAnimation to "animate" those .pngs would be greatly appreciated. I do not need anything fancy.
(Note - I have to make the code automated, so unfortunately I cannot use an outside source to animate my images like iMovie or ffmpeg.)
Below is my code:
from numpy import *
from pylab import *
import matplotlib.pyplot as plt
import matplotlib.image as mgimg
from matplotlib import animation
## Read in graphs
p = 0
myimages = []
for k in range(1, len(params.t)):
fname = "heatflow%03d.png" %p
# read in pictures
img = mgimg.imread(fname)
imgplot = plt.imshow(img)
myimages.append([imgplot])
p += 1
## Make animation
fig = plt.figure()
animation.ArtistAnimation(fig, myimages, interval=20, blit=True, repeat_delay=1000)
animation.save("animation.mp4", fps = 30)
plt.show()
Issue 1: Images are not displayed
You need to store your animation object in a variable:
This requirement is specific for
animation
and is not consistent with other plotting function inmatplotlib
, where you can usually usemy_plot=plt.plot()
orplt.plot()
indifferently.This question is further discussed here.
Issue 2: Save does not work
Without any
animation
instance, it will not be possible to save a figure either. This is because thesave
method belongs to theArtistAnimation
class. What you did was callingsave
from theanimation
module, this is what raised the error.Issue 3: Two windows
The last issue is that you get two figures popping up. The reason is that when you call
plt.imshow()
, it displays an image on the current figure, but since no figure has been created yet,pyplot
implicitly creates one for you. When python later interprets thefig = plt.figure()
statement, it creates a new figure (another window) and labels it "Figure 2". Moving this statement to the beginning of your code, solves that problem.Here is the modified code:
(To run the code above, just add 3 images into your working folder with name "heatflow001.png" through "heatflow003.png".)
Alternative approach using
FuncAnimation
You were probably right when you first tried to use
FuncAnimation
, since gathering images in a list is costly in terms of memory. I tested the code below against the one above, by comparing memory usage on the system monitor. It appears that theFuncAnimation
approach is more efficient. I believe the difference will grow even bigger as you use more images.Here is the second code: