10
12

More than 5 years have passed since last update.

animatplot で matplotlibによる gif アニメーションを簡単に作る

Last updated at Posted at 2018-08-16

本日は

animatplot というライブラリの紹介です。

前置き

可視化ツールとしての matplotlib は静的なグラフの描画だけでなく、パラメータによって変化するグラフの様子をgifなどのアニメーションで表現することができます。数学的な対象物をアニメーションで視覚化するというのは我々を楽しくさせます。

test.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 はこういうアニメーション作成をもっと簡単にさせるインターフェースを提供してくれます。

 導入

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

なんとプログレスバーのようなものを導入できるようです。

sin_curve_with_contol.gif

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 みたいなものを呼び出しているのでしょう。

Slider Demo

ちなみに、上記コードを実行するとプログレスバーに連動してグラフが動くグラフが画面に出力されます。Pauseボタンをクリックすると動作を止めることができ、さらに、青色のバーをドラッグすることでパラメータを変化させることができます。

こういった機能の実装を始めるとイベントの登録やそれに対するイベントハンドラを書かなくちゃいけないので、そういった手間を省けるのはとても嬉しいんじゃないかなと思います。

他には?

ギャラリーが用意されているのでそれらをみると良いです。

animatplotはまだできたばかりのライブラリみたいですが、アニメーションを作る第一歩としては良いライブラリな気がします。
こういったライブラリを使えば気軽にアニメーションを実行できて本質的な所に集中できそうですね。

10
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
12