11

I have a NxN grid with some values, which change every time step. I have found a way to plot a single grid configuration of this with matshow function, but I don't know how do I update the status with every time step. Here is a simple example:

from pylab import *
from matplotlib import pyplot

a = arange(25)
a = a.reshape(5,5)
b = 10*rand(5,5)
matshow(a-b, cmap = cm.jet)
colorbar()
show()

This code produces the following picture: enter image description here
Now imagine that the next time step some values change, so should this picture. This is the logic I had in mind:

from pylab import *
from matplotlib import pyplot

a = arange(25)
a = a.reshape(5,5)
time=10
for t in range(time):
    b = 10*rand(5,5)
    print b
    matshow(a-b, cmap=cm.jet)
    colorbar()
show()

This produces 10 pictures. I'd like to animate this instead producing individual pictures, and for example I'd like to choose a time step between changes (that is, frame rate).
Also, I'm open to suggestions for a different functions, if matshow is not the way to go, but please keep it simple, I'm relatively inexperienced.

enedene
  • 3,525
  • 6
  • 34
  • 41

2 Answers2

18

matplotlib 1.1 has an animation module (look at the examples).

Using animation.FuncAnimation you can update your plot like so:

import numpy as np
import matplotlib.pyplot as plt 
import matplotlib.animation as animation

def generate_data():
    a = np.arange(25).reshape(5, 5)
    b = 10 * np.random.rand(5, 5)
    return a - b 

def update(data):
    mat.set_data(data)
    return mat 

def data_gen():
    while True:
        yield generate_data()

fig, ax = plt.subplots()
mat = ax.matshow(generate_data())
plt.colorbar(mat)
ani = animation.FuncAnimation(fig, update, data_gen, interval=500,
                              save_count=50)
plt.show()

You can save the animation using:

ani.save('animation.mp4')

I you save it with

ani.save('animation.mp4', clear_temp=False)

the frames are conserved and you can create an animated gif like the following with

convert *.png animation.gif

enter image description here

bmu
  • 35,119
  • 13
  • 91
  • 108
  • 1
    I should have asked this in the question, but is there a way to put an condition on a-b so that animation stops, and only the last figure stays (as if I did static plot). For example if max(a-b)>22? – enedene May 03 '12 at 14:59
  • 1
    @bmu I took the liberty of adding a few frames of your "movie" as a animated gif - great answer! Looking at the animation, I would suggest that the colorbar has fixed limits so it doesn't change during the animation. – Hooked May 03 '12 at 15:01
  • @Hooked: I tried to upload an animated gif, but something went wrong, so I thought Stackoverflow do not allow it. But it works, nice. – bmu May 03 '12 at 15:11
  • @enedene: You can stop the animation for a certain time with `time.sleep()` if a condition is met. However I think it would be difficult to interact with the user if he wants to continue. – bmu May 03 '12 at 15:46
1

The easiest way is probably to have matplotlib save individual images and then have another program or library stitch together them to an animation. This approach uses a module called write2gif but you can also use mencoder, ffmpeg or any other software capable of producing video:

from images2gif import writeGif
from pylab import *
from matplotlib import pyplot as plt
from PIL import Image

a = arange(25)
a = a.reshape(5,5)
time=10
images = []
for t in range(time):
    fig = plt.figure(figsize = (5, 5))
    ax = fig.add_subplot(111)
    b = 10*rand(5,5)
    cax = ax.matshow(a-b, cmap=cm.jet, vmin = -8, vmax = 24)
    fname = 'tmp%03d.png' % t
    fig.colorbar(cax)
    fig.savefig(fname)
    images.append(Image.open(fname))
writeGif('matanim.gif', images, duration = .2)    

Here is an example on how to do it from within pylab's interface. It doesn't work so well since the continuous rendering runs in the same thread as pylabs gui handlers:

from pylab import arange, cm, draw, rand
from matplotlib import pylab as plt
from time import sleep
plt.ion()
a = arange(25)
a = a.reshape(5,5)
fig = plt.figure(figsize = (5, 5))
for i in range(200):
    ax = fig.add_subplot(111)
    b = 10*rand(5,5)
    cax = ax.matshow(a-b, cmap=cm.jet, vmin = -8, vmax = 24)
    if i == 0:
        fig.colorbar(cax)
    draw()
    sleep(0.2)
Björn Lindqvist
  • 19,221
  • 20
  • 87
  • 122
  • Thank you for your answer. There are examples of animating plots within matplotlib interface, for example: http://www.scipy.org/Cookbook/Matplotlib/Animations Is there no way for my example to be animated within that interface as well? – enedene May 03 '12 at 11:29