再びmatplotlibの動画の話です。
先日、一枚のfigureの中に複数のグラフを持っている図をアニメーションにしたいことがありました。
これもすぐにできると思ったのですが、方法が理解できるまで結構手間取ったので記録として残しておきます。
ドキュメントの ArtistAnimation のページには明記されてないし、
Examples の Animationの一覧 をみても、
サンプルは全部1枚の図に1つのグラフのもので、2グラフを動かしている例はないんですよね。(※記事執筆時点の情報です)
さて、方法ですが結論としては、次のようなコードで実現できました。
matplotlibでgif動画生成 の記事のコードがグラフ一つの例なので、見比べてみてください。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation
fig = plt.figure(facecolor="w")
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2)
# 0 <=x < 2pi の範囲の点列を作成。
x = np.linspace(0, 2*np.pi, 101)[: -1]
# 各コマの画像を格納する配列
image_list = []
# 1周だと短すぎたので5回繰り返す
for _ in range(5):
for i in range(100):
# ずらしながらsinカーブを描写し、配列に格納
y1 = np.sin(np.roll(x, -i))
y2 = np.cos(np.roll(x, -i))
# 一つ目のグラフを描写する
image1 = ax1.plot(x, y1, c="b")
# 二つ目のグラフを描写する
image2 = ax2.plot(x, y2, c="g")
# 同時に描写したいグラフを連結したものを配列に追加する。
image_list.append(image1+image2)
# アニメーションを作成
ani = ArtistAnimation(fig, image_list, interval=10)
# mp4ファイルに保存
ani.save('animation.mp4', writer='ffmpeg')
# gifファイルに保存する場合
# ani.save('animation.gif', writer='pillow')
ポイントになるのはこの部分です。
作成したグラフの配列を連結して、それをコマの配列に追加していっています。
image_list.append(image1+image2)
image1(とimage2)はそれぞれ、グラフの配列(要素は一個だけ)です。
print(image1)
# [<matplotlib.lines.Line2D object at 0x7fbe7dc4eed0>]
print(image2)
# [<matplotlib.lines.Line2D object at 0x7fbe7db8cf90>]
これを足すことで配列が連結されています。
print(image1+image2)
# [<matplotlib.lines.Line2D object at 0x7fbe7dc4eed0>, <matplotlib.lines.Line2D object at 0x7fbe7db8cf90>]
これ一コマとして、それらの配列を作り、ArtistAnimation メソッドに渡すことで動画にできます。
出来上がったのがこちらです。
最初、順番に更新したらいいかと思ってこういうのを試しましたが、これは2つのグラフが同時には表示されず、
1枚ずつ表示されるので非常にチカチカした見た目になります。
# 失敗例1
image_list.append(image1)
image_list.append(image2)
次に試みたのがこれ。これはこの後の ArtistAnimation でエラーになりました。
(配列の階層が深くなりすぎたようです)
# 失敗例2
image_list.append([image1, image2])