Embedding GIF animations in IPython notebook

TL;DR
IPython NBViewer: http://nbviewer.ipython.org/gist/zehsilva/18c28992796d9be99e16
Gist: https://gist.github.com/zehsilva/18c28992796d9be99e16

A couple of days ago I was thinking about the possibility of generating GIF animations using matplotlib and visualizing this animations directly in IPython notebooks. So I did a quick search to find possible solutions, and found one solution to embed videos, and other to convert matplotlib animations to gif, so I combined both solution in a third solution converting the animation to GIF using imagemagick (you will need to have it installed in your computer), enconding the resulting file in a base64 string and embedding this in a img tag. Using IPython.display HTML class this resulting string will be displayed in the notebook (and saved with the notebook).

I will briefly explain the elements of my solution.

First, import HTML class from IPython.display module. This will enable results which are valid html string to be interpreted and displayed by the notebook. We will return a string with an inline image using DataUri

from IPython.display import HTML
IMG_TAG = """<img src="data:image/gif;base64,{0}" alt="some_text">"""

The other important piece of the script is the function that takes a matplotlib animation object, convert and save the GIF to a temporary file using imagemagick, and finally read the file and convert to a base64 string to be inserted in the inline image string.

def anim_to_gif(anim):
    data="0"
    with NamedTemporaryFile(suffix='.gif') as f:
        anim.save(f.name, writer='imagemagick', fps=10);
        data = open(f.name, "rb").read()
        data = data.encode("base64")
    return IMG_TAG.format(data)

def display_animation(anim):
    plt.close(anim._fig)
    return HTML(anim_to_gif(anim))

After that you just need to generate a matplotlib animation and pass it to the display_animation function. This method could be generalize to other libraries, as long as it has some away to convert animations to GIF. Once the conversion is completed that file can be loaded, converted to inline image and displayed in a IPython notebook.

Full code:

from tempfile import NamedTemporaryFile
import matplotlib.pyplot as plt
from matplotlib import animation
from IPython.display import HTML
import numpy as np

IMG_TAG = """<img src="data:image/gif;base64,{0}" alt="some_text">"""

def anim_to_gif(anim):
    data="0"
    with NamedTemporaryFile(suffix='.gif') as f:
        anim.save(f.name, writer='imagemagick', fps=10);
        data = open(f.name, "rb").read()
        data = data.encode("base64")
    return IMG_TAG.format(data)

def display_animation(anim):
    plt.close(anim._fig)
    return HTML(anim_to_gif(anim))

fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(7, 6.5)

ax = plt.axes(xlim=(0, 10), ylim=(0, 10))
patch = plt.Circle((5, -5), 0.75, fc='y')
patch2 = plt.Circle((5, -5), 0.1, fc='b')
c= np.array([5,5])

def init():
    patch.center = (5, 5)
    ax.add_patch(patch)
    ax.add_patch(patch2)
    return patch,

def animate(i):
    x = 5 + 3 * np.sin(np.radians(i))
    y = 5 + 3 * np.cos(np.radians(i))
    patch.center = (x, y)
    patch2.center = (x-0.6*np.sin(np.radians(5*i)),y+0.6*np.cos(np.radians(5*i)))
    return patch2,

anim = animation.FuncAnimation(fig, animate,
                               init_func=init, frames=[5.8*x for x in range(62)], interval=1, blit=True)
display_animation(anim) 

And the resulting GIF
animate

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s