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]: