This web content provides a comprehensive tutorial on creating animations with Matplotlib and Celluloid in a Jupyter Notebook environment, focusing on visualizing projectile motion trajectories and associated histograms.
Abstract
The article serves as a hands-on guide for data visualization enthusiasts interested in animating scientific concepts, particularly projectile motion. It begins by introducing the necessary packages, such as Celluloid, and proceeds to demonstrate the process of animating a single trajectory, gradually advancing to multiple trajectories. The tutorial culminates in the creation of an animation that includes a histogram that dynamically updates to reflect the distribution of projectile shooting ranges. The author emphasizes the importance of such animations in conveying complex insights, such as uncertainty in projectile motion, and positions them as a powerful tool for uncertainty visualization. The tutorial is accompanied by sample code, images, and GIFs to facilitate understanding, and it encourages readers to engage with the material by running the code in Jupyter Notebooks or Google Colaboratory.
Opinions
The author believes that animations are an effective method for data visualization, especially for conveying complex and dynamic insights like projectile motion trajectories.
They suggest that the Celluloid module simplifies the process of creating animations for those already familiar with Matplotlib plotting.
The tutorial is designed to be step-by-step, ensuring that even readers with limited experience in animations can follow along and build their skills progressively.
The author values the practical application of the tutorial, providing a real-world example of uncertainty visualization through the concept of Hypothetical Outcome Plots.
By offering the tutorial both as a Jupyter Notebook and on Google Colaboratory, the author demonstrates a commitment to accessibility and interactivity in learning.
The inclusion of Gfycat animations and author-generated images is intended to enhance the reader's comprehension and engagement with the content.
The author expresses enthusiasm for sharing knowledge in the field of statistics and data science, inviting readers to connect on Medium and LinkedIn for further learning opportunities.
Hands-on Tutorials
A Hands-on Tutorial For Creating Matplotlib Animations
A step-by-step guide to sharpening your skills in creating and displaying animations in Jupyter Notebook.
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.
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.
2. Data
For this tutorial, we will load the pre-calculated projectile trajectory data: two NumPy 2D arrays that record the 𝑥 and 𝑦 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.
A sample trajectory. (Image by Author)
3. Animate A Single Trajectory
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).
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.
4. Animate Multiple Trajectories
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.
5. Animate Histogram
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!
6. Side Notes
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:
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.