A Hands-on Tutorial For Creating Matplotlib Animations | by Shuai Guo | Towards Data Science

Animations are great data visualization tools to convey complicated insights engagingly. In this article, we will walk through the steps of creating an animation with Matplotlib and Celluloid.
This is what we will make: it simulates various projectile motion trajectories and updates the associated histogram of the projectile shooting range.
This tutorial goes as follows. After introducing the animation packages and the employed data, we dive straight into creating the animation. We go from simple to complex: to start, we animate a single trajectory, followed by animating multiple trajectories. Finally, we will add a histogram component and take a close look at how to synchronize the histogram updates with the trajectory data.
If your time is short, the simple example of animating a single trajectory should be sufficient to give you a good grasp of the general workflow. Otherwise, I would encourage you to go through all the steps.
This Jupyter Notebook contains the code for this tutorial. Alternatively, you could run the code on Google Colaboratory.
colab.research.google.com
Without further ado, let’s get to it!
· 1. Packages· 2. Data· 3. Animate A Single Trajectory· 4. Animate Multiple Trajectories· 5. Animate Histogram· 6. Side Notes· About the Author
In this tutorial, we will use theCelluloid module. If you have ever made a plot with Matplotlib, creating animations with Celluloid is no more difficult. The basic idea is to use a “Camera” to take snapshots of individual frames, which are later rolled up into an animation.
To install Celluloid, use
pip install celluloid
Also, to display the created animation within the Jupyter notebook, we need to import HTML from IPython.display.
For this tutorial, we will load the pre-calculated projectile trajectory data: two NumPy 2D arrays that record the x and y coordinates of the projectile trajectories, respectively.
Both NumPy arrays have 1000 rows, corresponding to 1000 different trajectories. Each trajectory is discretized with 20 points, hence the NumPy arrays have 20 columns. One sample trajectory is plotted below.
Now we are ready to create some animations! We start by simulating a single trajectory. Let’s first see the code and the output, and then we elaborate on the steps to get there.
We set up the graph using Matplotlib (line 12–16).We initiate a Camera instance using the created graph (line 19).We create 20 frames, where each frame depicts the current location of the projectile and its trajectory. camera.snap() is used to take a snapshot of the individual frames (line 22–35).We call camera.animate() to roll the captured snapshots up into an animation (line 38).We display the animation with HTML (line 41).
We set up the graph using Matplotlib (line 12–16).
We initiate a Camera instance using the created graph (line 19).
We create 20 frames, where each frame depicts the current location of the projectile and its trajectory. camera.snap() is used to take a snapshot of the individual frames (line 22–35).
We call camera.animate() to roll the captured snapshots up into an animation (line 38).
We display the animation with HTML (line 41).
Under the hood, camera.animate() uses animation.ArtistAnimation() from Matplotlib. We feed three parameters to camera.animate(): the interval, which controls the delay between frames in milliseconds; the repeat, which controls whether the animation should repeat when the sequence of frames is completed; the repeat_delay, which controls the delay in milliseconds before repeating the animation when the animation is set to repeat.
Once we get the hang of simulating a single trajectory, simulating multiple trajectories becomes easy. We simply need to add an extra loop to cycle through all the trajectories.
For demonstration purposes, we will simulate the first 30 trajectories. The steps are the same as the last example. However, in this example, we will create a total of 20×30 frames to capture all 30 trajectories.
Here is the animation we’ve just made.
In this final step, we will add an updating histogram on top of multiple trajectory simulations. This histogram describes the distribution of the shooting range, and it updates when receiving new data, i.e., when a sample trajectory reaches its end.
First, let’s extract the range data and obtain the bins' edges for plotting the histogram.
Then, let’s specify how we want our histogram to behave:
the histogram has its own y-axis;
the histogram only gets updated in the frames when a sample trajectory reaches its end;
in other frames when the projectile is still “flying,” the histogram should stay the same.
To address those requirements, we will
use ax.twin() to create a twin Axes that shares the x-axis while having an independent y-axis. This new twin axis will host our histogram;
maintain a list R, which contains the range values for all sample trajectories. R starts as an empty list and gets appended when a new trajectory reaches its end. The final x coordinate value of this new trajectory (i.e., its shooting range) is appended to R;
plot the histogram using the up-to-date R.
Here are the results.
There you have it! Thanks for going through the entire tutorial😊 Hopefully, the stuff covered in this tutorial could help create your own animations!
The animation we’ve just made is intended to show the audience the uncertainty of the projectile shooting range under various combinations of initial projectile velocity and shooting angle. This type of visualization is also known as the Hypothetical Outcome Plots, a powerful technique that is especially good at delivering intuitive and effective uncertainty visualization. To learn more about hypothetical outcome plots, take a look at this article:
towardsdatascience.com
I’m a Ph.D. researcher working on uncertainty quantification and reliability analysis for aerospace applications. Statistics and data science form the core of my daily work. I love sharing what I’ve learned in the fascinating world of statistics. Check my previous posts to find out more and connect with me on Medium and Linkedin.