本日は
animatplot というライブラリの紹介です。
前置き
可視化ツールとしての matplotlib は静的なグラフの描画だけでなく、パラメータによって変化するグラフの様子をgifなどのアニメーションで表現することができます。数学的な対象物をアニメーションで視覚化するというのは我々を楽しくさせます。
楽しい反面、手間がかかります。例えば、アニメーションを実装するには matplotlib.animation.FuncAnimation
という matplotlib の機能を用いることで実現できます。例えば下記のような実装になります。
import itertools
import logging
logging.basicConfig(level=logging.INFO)
import random
import matplotlib.animation as animation
from matplotlib import pyplot as plt
import numpy as np
def do_somehting(xs, ts):
for t in ts:
yield xs, np.sin(2 * np.pi * (xs + t))
class Visualizer():
def __init__(self, xs, ts):
self.fig, self.ax = plt.subplots()
self.iterator = itertools.cycle(do_somehting(xs, ts))
def init_func(self):
self.step = 0
def update(self, *args):
self.ax.clear()
logging.info("i={}".format(self.step))
xs, ys = self.iterator.__next__()
self.ax.plot(xs, ys)
self.ax.set_title("step={}".format(self.step))
self.step += 1
def main():
xs = np.linspace(0, 1, 50)
ts = np.linspace(0, 1, 20)
visualizer = Visualizer(xs, ts)
ani = animation.FuncAnimation(visualizer.fig,
visualizer.update,
init_func=visualizer.init_func,
frames=100,
interval=100)
ani.save('test.gif', writer="imagemagick")
if __name__ == '__main__':
main()
このコードを実行して test.gif
を開くとアニメーションが見られます。
慣れれば上のようなコードを書くことができるのですが、ここまでたどり着くのに結構な学習コストがかかっていますし(こういうアプリを作るのに毎回作り方をググっている)、やるべき手続きが多い(updateメソッドをいちいち書く必要がある)ことから静的な描画の実装に比べるとかなりの手間がかかります。
そんな私たちに animatplot
animatplot はこういうアニメーション作成をもっと簡単にさせるインターフェースを提供してくれます。
animatplot: A #Python package for creating animated #dataviz. Built on top of matplotlib. #DataSciencehttps://t.co/kexyqDhCLV pic.twitter.com/ogktdMfXCj
— Randy Olson (@randal_olson) 2018年8月7日
導入
pip で入ります。
$ pip install animatplot
Example 1
ドキュメントのチュートリアルから引っ張ってきます。
"""
Introduction to animatplot
https://animatplot.readthedocs.io/en/latest/tutorial/getting_started..html#Basic-Animation
"""
import numpy as np
from matplotlib import pyplot as plt
import animatplot as amp
def main():
xs = np.linspace(0, 1, 50)
ts = np.linspace(0, 1, 20)
Xs = np.asarray([xs] * len(ts))
Ys = [np.sin(2 * np.pi * (xs + t)) for t in ts]
"""
# you can also write
Xs, Ts = np.meshgrid(xs, ts)
Ys = np.sin(2 * np.pi * (Xs + Ts))
"""
block = amp.blocks.Line(Xs, Ys)
anim = amp.Animation([block])
anim.save_gif("sin_curve")
plt.show()
if __name__ == '__main__':
main()
必要な描画データを Xs
, Ys
に突っ込んでおいてそれを amp.blocks.Line(Xs,Ys)
という形で渡すだけでOKです。
上記のコードを実行すると sin_curve.gif
というものが得られます。
Example 2
なんとプログレスバーのようなものを導入できるようです。
import numpy as np
from matplotlib import pyplot as plt
import animatplot as amp
def main():
fig, ax = plt.subplots()
ax.set_title("sin curve animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
xs = np.linspace(0, 1, 50)
ts = np.linspace(0, 1, 20)
Xs, Ts = np.meshgrid(xs, ts)
Ys = np.sin(2 * np.pi * (Xs + Ts))
block = amp.blocks.Line(Xs, Ys, axis=ax)
timeline = amp.Timeline(ts, units='s', fps=20)
anim = amp.Animation([block], timeline)
anim.controls()
anim.save_gif("sin_curve_with_contol")
plt.show()
if __name__ == '__main__':
main()
多分内部では matplotlib.widgets.Slider
みたいなものを呼び出しているのでしょう。
ちなみに、上記コードを実行するとプログレスバーに連動してグラフが動くグラフが画面に出力されます。Pauseボタンをクリックすると動作を止めることができ、さらに、青色のバーをドラッグすることでパラメータを変化させることができます。
こういった機能の実装を始めるとイベントの登録やそれに対するイベントハンドラを書かなくちゃいけないので、そういった手間を省けるのはとても嬉しいんじゃないかなと思います。
他には?
ギャラリーが用意されているのでそれらをみると良いです。
animatplotはまだできたばかりのライブラリみたいですが、アニメーションを作る第一歩としては良いライブラリな気がします。
こういったライブラリを使えば気軽にアニメーションを実行できて本質的な所に集中できそうですね。