Animations with FuncAnimation

Matplotlib · Advanced · 14 min

Animations explain processes that unfold over time, such as simulations and training curves, better than static frames.

matplotlib.animation.FuncAnimation(fig, update, frames=..., interval=...) repeatedly calls your update(frame) function and redraws the figure. The efficient pattern is to create artists once and only change their data in update:

line, = ax.plot([], [])
def update(i):
    line.set_data(x[:i], y[:i])
    return (line,)

Setting data on existing artists is much faster than clearing the Axes and plotting again. Because empty initial artists do not set limits, fix them yourself with set_xlim and set_ylim.

  • frames can be an integer (passes 0..n-1), any iterable, or a generator function.
  • interval is the delay between frames in milliseconds for on-screen playback.
  • blit=True redraws only the artists update returns, a big speedup on interactive backends; then update must return an iterable of artists.

Keep a reference to the animation object (anim = FuncAnimation(...)). If it is garbage collected, the animation silently stops.

To export, call anim.save("out.gif", writer="pillow", fps=20) (needs Pillow only) or anim.save("out.mp4", writer="ffmpeg") (needs the ffmpeg program). In Jupyter, HTML(anim.to_jshtml()) embeds a player without any external tool.

For a handful of precomputed images, ArtistAnimation takes a list of artist lists, one per frame, instead of a function.

Example

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

x = np.linspace(0, 2 * np.pi, 120)
fig, ax = plt.subplots(figsize=(4, 3))
ax.set_xlim(0, 2 * np.pi)
ax.set_ylim(-1.1, 1.1)
line, = ax.plot([], [], lw=2)
calls = []

def update(i):
    calls.append(i)
    line.set_data(x[:i], np.sin(x[:i]))   # change data, don't replot
    return (line,)

anim = FuncAnimation(fig, update, frames=len(x), interval=30, blit=True)
anim.save("wave.gif", writer="pillow", fps=30)
print(calls[-1])                      # 119: last frame index
print(len(line.get_xdata()))          # 119

Remember

  • Create artists once; update their data in the frame function
  • Fix axis limits yourself, and return the changed artists when blit=True
  • Keep a reference to the animation; save with the pillow (GIF) or ffmpeg (MP4) writer

Watch out for

  • Not storing the FuncAnimation in a variable, so it is garbage collected and nothing animates.

Check yourself

  1. Why is `line.set_data(...)` preferred over `ax.clear(); ax.plot(...)` inside the update function?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: matplotlib.org/stable/api/_as_gen/matplotlib.animation.FuncAnimation.html