How can I make an animation with contourf()?
Asked Answered
A

4

15

I'm trying to animate the wigner function of the spatial coordinates of some time-dependent data. The wigner function is 2 dimensional, so I'm using contourf() to plot it. I have the data stored in a HDF5 file and can make Wigner distributions on the fly, but I can't figure out how to animate it. All of the animation tutorials and examples I've been able to find (for example this one and this one) are strictly for line plots. Specifically, their animate(i) function uses line.set_data(), and I can't seem to find an equivalent for contourf().

How can I animate images made with contourf()?

What's the contourf() equivalent of set_data()?

Amy answered 14/4, 2014 at 21:0 Comment(2)
possible duplicate of Using matplotlib.animate to animate a contour plot in pythonAmy
What I have done is to create a new contour plot each time, and to hide the old one I do cont.set_alpha(0). Hacky. There ought to be a set_data method.Stob
S
13

There's a simple way to do it with FuncAnimation: You must have a function that clears the axis and plot a new contour based on frame number. Don't forget to set blit as False.

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

DATA = np.random.randn(800).reshape(10,10,8)


fig,ax = plt.subplots()

def animate(i):
       ax.clear()
       ax.contourf(DATA[:,:,i])
       ax.set_title('%03d'%(i)) 

interval = 2#in seconds     
ani = animation.FuncAnimation(fig,animate,5,interval=interval*1e+3,blit=False)

plt.show()
Stele answered 15/7, 2016 at 17:10 Comment(1)
Works, but clearing and replotting the contour plot is very slow.Postman
L
7

I am plotting geographical data and therefore need Basemap. Based on the answer by captain_M and a discussion/bug report on https://github.com/matplotlib/matplotlib/issues/6139 I post a response inspired by tacaswell that allows you to use contourf in an animation of 2 dimensional data and save it as mp4 if you have ffmpeg:

from matplotlib import animation
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.basemap import Basemap


fig, ax = plt.subplots()

# set up map projection
m = Basemap(projection='nsper',lon_0=-0,lat_0=90)
m.drawcoastlines()
m.drawparallels(np.arange(0.,180.,30.))
m.drawmeridians(np.arange(0.,360.,60.))

# some 2D geo arrays to plot (time,lat,lon)
data = np.random.random_sample((20,90,360))
lat = np.arange(len(data[0,:,0]))
lon = np.arange(len(data[0,0,:]))
lons,lats = np.meshgrid(lon,lat)

# ims is a list of lists, each row is a list of artists to draw in the
# current frame; here we are animating three artists, the contour and 2 
# annotatons (title), in each frame
ims = []
for i in range(len(data[:,0,0])):
    im = m.contourf(lons,lats,data[i,:,:],latlon=True)
    add_arts = im.collections
    text = 'title={0!r}'.format(i)
    te = ax.text(90, 90, text)
    an = ax.annotate(text, xy=(0.45, 1.05), xycoords='axes fraction')
    ims.append(add_arts + [te,an])

ani = animation.ArtistAnimation(fig, ims)
## If you have ffmpeg you can save the animation by uncommenting 
## the following 2 lines
# FFwriter = animation.FFMpegWriter()
# ani.save('basic_animation.mp4', writer = FFwriter)
plt.show()
Lora answered 10/3, 2016 at 16:42 Comment(1)
I got missing set_visible and set_animated errors and this one worked for me.Antitrust
S
6

Here is what I use to animate 2d contour plots, it was adapted from http://matplotlib.org/examples/animation/dynamic_image2.html

import pylab as pl
import numpy as np
import matplotlib.animation as animation
import types


fig = pl.figure()
# Some 2D arrays to plot (time,x,y)
data = np.random.random_sample((20,10,10))

# ims is a list of lists, each row is a list of artists to draw in the
# current frame; here we are just animating one artist, the image, in
# each frame
ims = []
for i in range(len(data[:,0,0])):
    t_step = int(i)
    im = pl.contourf(data[i,:,:])

    #################################################################
    ## Bug fix for Quad Contour set not having attribute 'set_visible'
    def setvisible(self,vis):
        for c in self.collections: c.set_visible(vis)
    im.set_visible = types.MethodType(setvisible,im)
    im.axes = pl.gca()
    im.figure=fig
    ####################################################################

    ims.append([im])

ani = animation.ArtistAnimation(fig, ims, interval=70, blit=False,repeat_delay=1000)

pl.show()
Schmo answered 1/5, 2014 at 1:35 Comment(0)
M
1

If you are like me and the matplotlib.animation doesn't work. Here is something else you can try. If you want to continuously update the colorbar and everything else in the figure, use plt.ion() at the very beginning to enable interactive plotting and use a combo of plt.draw() and plt.clf() to continuously update the plot. Here is example code:

import matplotlib.pyplot as plt
import numpy as np

plt.ion(); plt.figure(1);
for k in range(10):
    plt.clf(); plt.subplot(121);
    plt.contourf(np.random.randn(10,10)); plt.colorbar();
    plt.subplot(122,polar=True)
    plt.contourf(np.random.randn(10,10)); plt.colorbar();
    plt.draw();

Note that this works with figures containing different subplots and various types of plots (i.e. polar or cartesian)

Meraz answered 5/7, 2015 at 4:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.