Anything that can be plotted with Matplotlib can also be animated. This is especially useful when data changes over time. Animations allow us to see the dynamics in our data, which is nearly impossible with most static plots. Here we will learn how to animate with Matplotlib by producing this traveling wave animation.
This is the code to make the animation. It creates the traveling wave, defines two functions that handle the animation and creates the animation with the
FuncAnimation class. Let’s take it step by step.
import numpy as np from matplotlib.animation import FuncAnimation import matplotlib.pyplot as plt # Create the traveling wave def wave(x, t, wavelength, speed): return np.sin((2*np.pi)*(x-speed*t)/wavelength) x = np.arange(0,4,0.01)[np.newaxis,:] t = np.arange(0,2,0.01)[:,np.newaxis] wavelength = 1 speed = 1 yt = wave(x, t, wavelength, speed) # shape is [t,y] # Create the figure and axes to animate fig, ax = plt.subplots(1) # init_func() is called at the beginning of the animation def init_func(): ax.clear() # update_plot() is called between frames def update_plot(i): ax.clear() ax.plot(x[0,:], yt[i,:], color='k') # Create animation anim = FuncAnimation(fig, update_plot, frames=np.arange(0, len(t[:,0])), init_func=init_func) # Save animation anim.save('traveling_wave.mp4', dpi=150, fps=30, writer='ffmpeg')
On the first three lines we import NumPy, Matplotlib and most importantly the
FuncAnimation class. It will take the center stage in our code as it will create the animation later on by combining all the parts we need. On lines 5-13 we create the traveling wave. I don’t want to go into too much detail, as it is just a toy example for the animation. The important part is that we get the array
yt, which defines the wave at each time point. So yt contains the wave at t0 , yt at t1 and so on. This is important, since we will be iterating over time during the animation. If you want to learn more about the traveling wave, you can change wavelength, speed and play around with the
Now that we have our wave, we can start preparing the animation. We create a the figure and the axes we want to use with
plt.subplots(1). Then we create a the
init_func(). This one will be called whenever the animation starts or repeats. In this particular example it is pretty useless. I include it here because it is a useful feature for more complex animations.
Now we get to
update_plot(), the heart of our animation. This function updates our figure between frames. It determines what we see on each frame. It is the most important function and it is shockingly simple. The parameter
i is an integer that defines what frame we are at. We use that integer as an index into the first dimension of yt. We plot the wave as it looks at
t=i. Importantly, we must clean up our axes with
ax.clear(). If we would forget about clearing, our plot would quickly become all black, filled with waves.
FuncAnimation is where it all comes together. We pass it
init_func. We also pass
frames, those are the values that
i will take on during the animation. Technically, this gets the animation going in your interactive Python console but most of the time we want to save our animation. We do that by calling
anim.save(). We pass it the file name as a string, the resolution in dpi, the frames per second and finally the writer class used for generating the animation. Not all writers work for all file formats. I prefer .mp4 with the ffmpeg writer. If there are issues with saving, the most common problem is that the writer we are trying to use is not installed. If you want to find out if the ffmpeg writer is available on your machine, you can type
matplotlib.animation.FFMpegWriter().isAvailable(). It returns
True if the writer is available and
False otherwise. If you are using Anaconda you can install the codec from here.
This wraps up our tutorial. This particular example is very simple, but anything that can be plotted can also be animated. I hope you are now on your way to create your own animations. I will leave you with a more involved animation I created.