Animating pngs in matplotlib using ArtistAnimation

Issue 1: Images are not displayed

You need to store your animation object in a variable:

my_anim = animation.ArtistAnimation(fig, myimages, interval=100)

This requirement is specific for animation and is not consistent with other plotting function in matplotlib, where you can usually use my_plot=plt.plot() or plt.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 the save method belongs to the ArtistAnimation class. What you did was calling save from the animation 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 the fig = 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:

import matplotlib.pyplot as plt 
import matplotlib.image as mgimg
from matplotlib import animation

fig = plt.figure()

# initiate an empty  list of "plotted" images 
myimages = []

#loops through available png:s
for p in range(1, 4):

    ## Read in picture
    fname = "heatflow%03d.png" %p 
    img = mgimg.imread(fname)
    imgplot = plt.imshow(img)

    # append AxesImage object to the list
    myimages.append([imgplot])

## create an instance of animation
my_anim = animation.ArtistAnimation(fig, myimages, interval=1000, blit=True, repeat_delay=1000)

## NB: The 'save' method here belongs to the object you created above
#my_anim.save("animation.mp4")

## Showtime!
plt.show()

(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 the FuncAnimation approach is more efficient. I believe the difference will grow even bigger as you use more images.

Here is the second code:

from matplotlib import pyplot as plt  
from matplotlib import animation  
import matplotlib.image as mgimg
import numpy as np

#set up the figure
fig = plt.figure()
ax = plt.gca()

#initialization of animation, plot array of zeros 
def init():
    imobj.set_data(np.zeros((100, 100)))

    return  imobj,

def animate(i):
    ## Read in picture
    fname = "heatflow%03d.png" % i 

    ## here I use [-1::-1], to invert the array
    # IOtherwise it plots up-side down
    img = mgimg.imread(fname)[-1::-1]
    imobj.set_data(img)

    return  imobj,


## create an AxesImage object
imobj = ax.imshow( np.zeros((100, 100)), origin='lower', alpha=1.0, zorder=1, aspect=1 )


anim = animation.FuncAnimation(fig, animate, init_func=init, repeat = True,
                               frames=range(1,4), interval=200, blit=True, repeat_delay=1000)

plt.show()