12. Animations

[1]:
%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib import animation
from IPython.display import display, Image, HTML
import numpy as np
import pandas as pd
import seaborn as sns

plt.style.use('ggplot')
np.random.seed(37)

12.1. Line animation

[2]:
def init():
    line.set_data([], [])
    return (line,)

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return (line,)

fig, ax = plt.subplots(figsize=(8, 5))
ax.set_xlim(0, 2)
ax.set_ylim(-2, 2)
line, = ax.plot([], [], lw=1)

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=100, interval=20, blit=True)

plt.close(anim._fig)

HTML(anim.to_html5_video())
[2]:

12.2. Line, decay

Example taken from the documentation.

[3]:
def data_gen():
    for cnt in range(1000):
        t = cnt / 10
        yield t, np.sin(2*np.pi*t) * np.exp(-t/10.)

def init():
    ax.set_ylim(-1.1, 1.1)
    ax.set_xlim(0, 10)
    del xdata[:]
    del ydata[:]
    line.set_data(xdata, ydata)
    return line,

fig, ax = plt.subplots(figsize=(8, 5))
line, = ax.plot([], [], lw=2)
ax.grid()
xdata, ydata = [], []


def run(data):
    # update the data
    t, y = data
    xdata.append(t)
    ydata.append(y)
    xmin, xmax = ax.get_xlim()

    if t >= xmax:
        ax.set_xlim(xmin, 2*xmax)
        ax.figure.canvas.draw()
    line.set_data(xdata, ydata)

    return line,

anim = animation.FuncAnimation(fig, run, data_gen, blit=False, interval=10,
                              repeat=True, init_func=init)

plt.close(anim._fig)

HTML(anim.to_html5_video())
[3]:

12.3. Using a class to control animation

Example taken from the documentation.

[4]:
import math

def beta_pdf(x, a, b):
    return (x**(a-1) * (1-x)**(b-1) * math.gamma(a + b)
            / (math.gamma(a) * math.gamma(b)))


class UpdateDist(object):
    def __init__(self, ax, prob=0.5):
        self.success = 0
        self.prob = prob
        self.line, = ax.plot([], [], 'k-')
        self.x = np.linspace(0, 1, 200)
        self.ax = ax

        # Set up plot parameters
        self.ax.set_xlim(0, 1)
        self.ax.set_ylim(0, 15)
        self.ax.grid(True)

        # This vertical line represents the theoretical value, to
        # which the plotted distribution should converge.
        self.ax.axvline(prob, linestyle='--', color='black')

    def init(self):
        self.success = 0
        self.line.set_data([], [])
        return self.line,

    def __call__(self, i):
        # This way the plot can continuously run and we just keep
        # watching new realizations of the process
        if i == 0:
            return self.init()

        # Choose success based on exceed a threshold with a uniform pick
        if np.random.rand(1,) < self.prob:
            self.success += 1
        y = beta_pdf(self.x, self.success + 1, (i - self.success) + 1)
        self.line.set_data(self.x, y)
        return self.line,


fig, ax = plt.subplots(figsize=(8, 5))
ud = UpdateDist(ax, prob=0.7)
anim = animation.FuncAnimation(fig, ud, frames=np.arange(100), init_func=ud.init,
                     interval=100, blit=True, repeat=True)

plt.close(anim._fig)

HTML(anim.to_html5_video())
[4]:

12.4. Animating a bar chart

[5]:
from random import randint, uniform

class RandomBarDist(object):
    def __init__(self, ax):
        self.s = pd.Series([10, 8, 5], index=['a', 'b', 'c'])
        self.ax = ax
        self.colors = ['r', 'g', 'b']

    def __call__(self, i):
        a, b, c = randint(1, 5), randint(1, 5), randint(1, 5)
        y = [a, b, c]
        y = [-1 * v if uniform(0.0, 1.0) < 0.5 else v for v in y]
        y = [v if v > 0 else 0 for v in y]
        y = pd.Series(y, index=['a', 'b', 'c'])

        self.s = self.s + y
        self.ax.clear()
        container = self.ax.bar(self.s.index, self.s.values, width=0.3, color=self.colors)
        return container

fig, ax = plt.subplots(figsize=(8, 5))
dist = RandomBarDist(ax)

anim = animation.FuncAnimation(fig, dist, frames=np.arange(100),
                     interval=100, blit=True, repeat=True)

plt.close(anim._fig)

HTML(anim.to_html5_video())
[5]: