How to animate a time-ordered sequence of matplotlib plots
Question: I want to plot a sequence of .png images in matplotlib. The goal is to plot
them rapidly to simulate the effect of a movie, but I have additional reasons
for wanting to avoid actually creating an .avi file or saving matplotlib
figures and then viewing them in sequence outside of Python.

I'm specifically trying to view the image files in sequence inside a for-loop
in Python. Assuming I have imported matplotlib correctly, and I have my own
functions 'new_image()' and 'new_rect()', here's some example code that fails
to work because of the blocking effect of the show() function's call to the
GUI mainloop:

    
    
     for index in index_list:
         img = new_image(index)
         rect = new_rect(index)
    
         plt.imshow(img)
         plt.gca().add_patch(rect)
         plt.show()
    
         #I also tried pausing briefly and then closing, but this doesn't
         #get executed due to the GUI mainloop from show()
         time.sleep(0.25)
         plt.close()
    

The above code works to show only the first image, but then the program just
hangs and waits for me to manually close the resultant figure window. Once I
do close it, the program then just hangs and doesn't re-plot with the new
image data. What should I be doing? Also note that I have tried replacing the
plt.show() command with a plt.draw() command, and then adding the plt.show()
outside of the for-loop. This doesn't display anything and just hangs.


Answer: Based on
<http://matplotlib.sourceforge.net/examples/animation/simple_anim_tkagg.html>:

    
    
    import time
    import numpy as np
    import matplotlib
    matplotlib.use('TkAgg') # do this before importing pylab
    
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    def animate():
        tstart = time.time()                   # for profiling
        data=np.random.randn(10,10)
        im=plt.imshow(data)
    
        for i in np.arange(1,200):
            data=np.random.randn(10,10)
            im.set_data(data)
            fig.canvas.draw()                         # redraw the canvas
        print 'FPS:' , 200/(time.time()-tstart)
    
    win = fig.canvas.manager.window
    fig.canvas.manager.window.after(100, animate)
    plt.show()
    

* * *

`plt.imshow` can accept a float array, uint8 array, or a PIL image. So if you
have a directory of PNG files, you could open them as PIL images and animate
them like this:

    
    
    import matplotlib
    matplotlib.use('TkAgg') # do this before importing pylab
    import matplotlib.pyplot as plt
    import Image
    import glob
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    def animate():
        filenames=sorted(glob.glob('*.png'))
        im=plt.imshow(Image.open(filenames[0]))
        for filename in filenames[1:]:
            image=Image.open(filename)
            im.set_data(image)
            fig.canvas.draw() 
    
    win = fig.canvas.manager.window
    fig.canvas.manager.window.after(100, animate)
    plt.show()
    

