概要
Pythonのmatplotlib
にはanimation
パッケージがあり、ArtistAnimation
とFuncAnimation
の2つのクラスが準備されている。
ArtistAnimation
は、予め動画に表示する各フレームを生成しておいて、これらを動画として表示するFuncAnimation
は、全結果を保存せず、フレームごとに描画を実行する関数を実行して、動画して表示する
ここでは、ArtistAnimation
による動画の表示方法を整理する(FuncAnimationについてはこちら)。
1つのグラフの表示
流れ
animation
パッケージ又はArtistAnimation
クラスをインポート- フレームの数だけグラフを描画してリストに保存
- フレームリストを渡して
ArtistAnimation
インスタンスを生成 - 表示
処理ステップ
インポート
パッケージをインポートする
1 2 |
from matplotlib.animation import ArtistAnimation # この場合はArtistAnimation(...)と直接コンストラクターを呼ぶ |
または
1 2 |
import matplotlib.animation as animation # この場合はanimation.ArtistAnimation(...)のようにコンストラクターを呼ぶ |
フレームリストの準備
動画の各フレームを保存するリストを準備する。animation
パッケージでは、個々のグラフフレームをartist
と表現している。
1 |
artists = [] |
FigureとAxesオブジェクトを準備
フレームを描画するオブジェクトを準備しておく
1 |
fig, ax = plt.subplots() |
フレーム数を指定して各フレームを保存する
以下ではフレーム数を20として、20回分のグラフを少しずつずらして描画して保存している。
1 2 3 4 5 6 |
frame_count = 20 for i in range(frame_count): x = np.linspace(0, 4 * np.pi) y = np.sin(x - 2 * np.pi / frame_count * i) artist = ax.plot(x, y, color='blue') artists.append(artist) |
ここではグラフを正弦波として、1周期分を20分割して表示させている。
- ここではループごとに
x
を計算しているが、今回は全フレーム共通なので、ループの外で準備してもよい plot
命令のcolor
指定をしないと、描画するごとに違うグラフとして色を変えて描画されてしまう- 描画結果はオブジェクトとして、先に準備した
artist
コレクションに追加している
アニメーション設定して表示させる
ArtistAnimation
クラスのコンストラクターに必要な引数を与えてインスタンスを生成し、表示させる。interval
はフレーム間の待機時間で、ミリ秒で与える。
1 2 3 |
arim = ArtistAnimation(fig, artists, interval=100) plt.show() |
GIF画像として保存する
結果をGIF画像として保存するには、plt.show()
を実行せず、以下のようにimagemagic
でファイルとして書き出す。
1 2 3 |
anim = ArtistAnimation(fig, artists, interval=100) anim.save("test.gif", writer="imagemagick") |
実行結果
以下のような動画が表示される。
コード
全体の実行コードは以下のとおり。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import ArtistAnimation # 各フレームを保存するフレームリスト artists = [] # FigureとAxesインスタンスを取得 fig, ax = plt.subplots() # 1サイクルの動画のフレーム数 frame_count = 20 # 表示する各フレームの生成・保存 for i in range(frame_count): # グラフの描画 x = np.linspace(0, 4 * np.pi) y = np.sin(x - 2 * np.pi / frame_count * i) # グラフの保存 artist = ax.plot(x, y, color='blue') # フレームリストへの追加 artists.append(artist) # フレームリストを渡してArtistAnimationインスタンスを生成 anim = ArtistAnimation(fig, artists, interval=100) # 表示 plt.show() #anim.save("simple.gif", writer="imagemagick") |
複数のグラフの表示
流れ
全体の流れは単一のグラフの場合と同じ。リスト保存時に複数グラフを加算して重ね合わせるところだけが異なる。
animation
パッケージ又はArtistAnimation
クラスをインポート- フレームの数だけグラフを描画して、重ね合わせてリストに保存
- フレームリストを渡して
ArtistAnimation
インスタンスを生成 - 表示
処理ステップ
以下の部分だけが単一グラフの場合と異なる。2つのグラフを描画し、そのオブジェクトを加算して1フレームとした上でartists
に追加している
1 2 3 4 5 6 7 |
for i in range(frame_count): x = np.linspace(0, 4 * np.pi) y1 = np.sin(x - 2 * np.pi / frame_count * i) y2 = np.sin(x - 2 * np.pi / frame_count * i + np.pi / 2) artist1 = ax.plot(x, y1, color='blue') artist2 = ax.plot(x, y2, color='green') artists.append(artist1 + artist2) |
実行結果
以下のように、2つのグラフが同時に表示される。
コード
全体の実行コードは以下のとおり。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import ArtistAnimation # 各フレームを保存するフレームリスト artists = [] # FigureとAxesインスタンスを取得 fig, ax = plt.subplots() # 1サイクルの動画のフレーム数 frame_count = 20 # 表示する各フレームの生成・保存 for i in range(frame_count): # グラフの描画 x = np.linspace(0, 4 * np.pi) y1 = np.sin(x - 2 * np.pi / frame_count * i) y2 = np.sin(x - 2 * np.pi / frame_count * i + np.pi / 2) # グラフの保存 artist1 = ax.plot(x, y1, color='blue') artist2 = ax.plot(x, y2, color='green') # フレームリストへの追加 artists.append(artist1 + artist2) # フレームリストを渡してArtistAnimationインスタンスを生成 anim = ArtistAnimation(fig, artists, interval=100) # 表示 plt.show() #anim.save("multi.gif", writer="imagemagick") |
図形を含むアニメーション
matplotlib.patches
による図形を含んでアニメーション表示するには、少し工夫がいる。その方法はこちら。