Animation

Overview

Animations can be a useful and effective tool to visualize data, especially when that data changes over time. In this notebook, we will explore how to create animations using the matplotlib library.

We will cover the two methods for creating animations in matplotlib, how to set up the elements of both types of animation, how to show the animation in jupyter notebooks, and how to save the animation to a file.

  1. Animation fundamentals with matplotlib

  2. Artist Animation

  3. Function Animation

Prerequisites

Concepts

Importance

Notes

Matplotlib

Necessary

Cartopy

Useful

Not necessary for animations in general, but useful for the examples in this notebook

  • Time to learn: 10 minutes


import cartopy.crs as ccrs
import matplotlib.animation as animation
import xarray as xr
from matplotlib import pyplot as plt
import os
from PIL import Image

import geocat.datafiles as gdf

Animation fundamentals with matplotlib

There are two different methods of creating animations with matplotlib:

  1. Artist animations pulls from a list of pre-made artists to draw in each frame to produce an animation

  2. Function animation iteratively modifies data on a pre-existing figure to produce an animation

Generally, function animation is easier to use, but artist animation can be more flexible for certain applications. We’ll cover both methods in this notebook.

Animating within jupyter notebooks

Before we get into either type of animation, we’re going to alter matplotlib’s runtime configuration settings (or rcParams) to allow us to use matplotlib’s animation functions within jupyter notebooks. This next cell is not necessary if you want to create animations in a script or just want to save the animation to a file.

Here, we’re changing default animation html output setting to "jshtml", which creates a JavaScript animation that can be displayed in a jupyter notebook. The default setting is "none".

plt.rcParams["animation.html"] = "jshtml"

Artist Animation

Artist animation uses pre-made artists to cycle through to produce an animation.

In this example, we’re going to plot images using matplotlib’s imshow function and save the resulting artist object to a list. Then, we’ll use the ArtistAnimation function to create an animation from that list of artists.

Data

Before we get into those steps, let’s get some images to animate. First, we’ll be looking at some GeoColor satellite imagery from GOES-16.

In this repository, there is a script, notebooks/scripts/goes_getter.py, that will download hourly images from the last 24 hours from the GOES-16 archive if you’d like to play around with this yourself. We have already downloaded some images for this example in the notebooks/data/goes16_hr/ directory and will be using those for this part of the notebook.

Get the images into a list

First, we need to ge the images from the directory into a list. We know the only files in this directory are the images we want to plot, so let’s get get a list of all the files ending in .jpg from that path using os.listdir().

We’ll also sort them using the built in sorted function to make sure that our list of images ends up in chronological order.

im_dir = "./data/goes16_hr/"
im_paths = sorted([p for p in os.listdir(im_dir) if p.endswith(".jpg")])

Creating the figure

Now, we need to set up the figure we’ll be plotting our animation on.

Note

Running the next cell will produce a blank figure in the jupyter notebook. This is expected since we’ve only created a blank figure to plot on, but haven’t actually plotted anything yet.

dpi = 100
figsize = tuple(t / dpi for t in Image.open(im_dir + im_paths[0]).size)
fig = plt.figure(figsize=figsize, dpi=dpi)
ax = fig.add_axes([0, 0, 1, 1])  # span the whole figure
ax.set_axis_off()
../_images/36d4e797b8f48851f2cf84c1f810d71e1c88b8d93f95818b4f407638614dad5d.png

First, we set out dpi to be 100. This is technically not necessary at this point in creating the animation, but we’re going to use it to set the size of the figure. Since we’re plotting images, we want to make sure that the figure size is the same size as the images we’re plotting.

Next, we’re going to figure out what our figsize should be based on the dpi and the size of the images we’re about to plot. tuple(t / dpi for t in Image.open(im_dir + im_paths[0]).size) divides each dimension of the size of the image by the intended dpi and then returns the result as a tuple. We then use that tuple to create our figsize.

Next, we create the figure using plt.figure() and the figsize and dpi we just calculated.

Then, we create the axes object using fig.add_axes([0, 0, 1, 1]). This adds axes to our figure that span the entire range of the figure, allowing the images plot on these axes to take up the entire figure space.

Finally, we turn off the axes using ax.axis("off"). This is because we don’t want to see axes on our final image plot.

Tip

Customizing the figure size, dpi, and axes is not necessary for creating an artist animation, but it will make our end result look nicer.

Creating a list of artists

Now that we have a list of the filepaths for all the images we want to plot and axes to plot them on, we can use imshow to plot each image and save the resulting artist object to a list.

ims = [[ax.imshow(Image.open(im_dir + im_path), animated=True)] for im_path in im_paths]

A couple of things to note here:

  • You may notice that we’re using list generation to create our final list, ims. But what might not be obvious is that we’re actually making a list of lists. Each created implot object is put into its own one-item list, and then all of those lists are used to create ims. This is because ArtistAnimation expects a list of lists, where each inner list is a list of artists to be plotted in a single frame.

  • We’re using a kwarg you may not have seen before using imshow: animated=True. This allows the artist to only be drawn when called as part of an animation. This is a kwarg that is common to all artist objects.

Creating the artist animation

Now that we’ve set up our figure and list (of lists) of artists, we can create the animation using ArtistAnimation.

ani = animation.ArtistAnimation(fig, ims, interval=150, repeat_delay=1000)

ArtistAnimation takes two required arguments:

  • the figure to plot on (fig in our case) and

  • the list of pre-created artist objects (ims) to plot.

We’ve also provided a few optional arguments:

  • interval: The time between frames in milliseconds. We’ve set this to 150 milliseconds, or 0.15 seconds.

  • repeat_delay: The time in milliseconds to wait before repeating the animation. We’ve set this to 1000 milliseconds, or 1 second.

And that’s it! We’ve created an animation in matplotlib using artist animation. Let’s take a look at it.

ani