Several Tricks to display a gif in a Jupyter Notebook

If you want to show the impact on Y by changing X, an animation is often a good choice. There are many considerations to creating a good animation, but since this is a quick overview, it will not exhaustively go through them. One notion is to have smooth acceleration between a starting and stopping point in the automation. I show an example of how to do that below.

There are a number of tricks required to get a gif to display in a Notebook. I've found mixed success, but first try the following code in a markdown cell:

<img src="animated.gif">

If that doesn't embed an animated gif (it should be a moving image but appears static), then copy the .gif to a .png extension. Not to actually change the file, just rename it with another extension. I'm not sure why it works, or even where I learned it, but it's worked a number of times for me. Then all you need to do is to embed it with:

<img src="animated_gif.png">

in a markdown cell.

Finally, once you display an image, your browser may cache the result. This means that if you are iterating on an animation, you may have to refresh the browser. Remember to save the notebook (you won't have to restart the kernel, just refresh the page).


In [1]:
%matplotlib inline
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_context('poster', font_scale=1.3)

In [2]:
n_frames = 120
# start with 10000 so that the filename glob gets the images in the
# correct order.
starting_frame = 10000

In [3]:
def altered_variable(min_val, max_val, fraction):
    """Helper function for getting the fractional part of a variable that you are changing."""
    return min_val + (max_val - min_val) * fraction

def smooth_fraction(n_frames):
    """Taking acceleration into account, return a variable-spaced fractional amount."""
    return 0.5 * (np.cos(np.linspace(0, 2.0 * np.pi, num=n_frames)) + 1.0)
        
def create_gif(n_frames=n_frames, starting_frame=starting_frame, min_val=50.0, max_val=85.0):
    """Create an image per frame."""
    for index, fraction in enumerate(smooth_fraction(n_frames)):
        new_height = altered_variable(min_val=min_val, max_val=max_val, fraction=fraction)
        create_plot(height=new_height, frame_number=starting_frame + index, save_fig=True)
    return

def create_plot(height=0.0, frame_number=0, save_fig=False):
    """Create a plot with a variable height and optionally save to a file."""
    x1 = 0
    x2 = 1
    y1 = 85.0
    y2 = height
    fig, ax = plt.subplots(figsize=(12, 8))
    ax.bar(x1, y1)
    ax.bar(x2, y2)
    ax.set_xlabel("X label")
    ax.set_ylabel("Y label")
    fig.tight_layout()
    if save_fig:
        fig.savefig("temp_gif/" + str(frame_number) + ".png")
        plt.close()
    return

In [4]:
%%bash
rm -rf temp_gif
mkdir -p temp_gif

In [5]:
create_gif()

In [6]:
%%bash
# brew install imagemagick
convert -delay 10 -layers Optimize -loop 0 temp_gif/*.png temp_gif/final.gif

# You may have to copy the gif to a png to display in a Notebook
cp temp_gif/final.gif temp_gif/final.png

The gif version:

The png version:


In [ ]:


In [ ]:


In [ ]:


In [ ]: