モモノキ&ナノネと一緒にMatplotlibで複数のグラフでアニメーションを実行してみよう
Matplotlibで円を正弦波をプロット、円の中の動径線をくるくる回してみよう
今回はMatplotlibで、グラフを複数使ってアニメーションを実行してみよう。
グラフをたくさん描いてアニメーション?
複数とはいってもグラフは2個だけど、3個以上でも原理は一緒だよ。ちょっと動作が重くなるけどグラフの要素はいくつか動かしてみるよ。
どんなグラフにするの?
位相の説明で、前置きによくでてくる定番グラフだよ。
円と正弦波が並んだグラフで、動径がくるくる回るヤツ?
うん。地味だけど作図の練習にやってみよう。
アニメーション自体は簡単なんだけど...........。
グラフの配置にちょっと苦戦かも、Matplotlib手強し。
Matplotlibは作図の自由度高いけど、パラメータの設定がけっこう複雑で覚えきれない。
たしかに。すぐ忘れちゃうから毎回グーグル先生に質問してる。
グラフ設定に調べ疲れた。。。。。。。。。。。。。。。。。。。。。
ナノネ、下のコードで一応動いたから、好きなように変更加えて試してみて。
グラフ配置のポイントは、add_subplot()でAxesを横に2個並べる。サイズの異なるグラフを描画するのにgridspec.GridSpecを利用して右左のグラフの横幅を変えているよ。あとy軸はオプション引数shareyを使ってスケールを一致させているくらいかな。
アニーメーションのポイントは前の練習とほぼ一緒。動かしたいグラフオブジェクトを変数でストックしておいて、描画更新用関数の中でグラフデータを書き換える処理を定義する。データの書き換えはset_○○○系メソッドを利用。あとはanimation.FuncAnimation()を呼びだせばOKだよ。
# Jupyter Notebook上でインタラクティブに表示
%matplotlib nbagg
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation
# グラフ枠作成
fig = plt.figure(figsize=(6,2))
fig.patch.set_alpha(1.0) # figure不透明
# 動径円グラフ(左側=ax1)
gs = gridspec.GridSpec(1, 5)
ax1 = fig.add_subplot(gs[:,:2])
ax1.add_patch(plt.Circle(xy=(0, 0), radius=1.0, ec='gray', fill=False)) # 円
line_radius, = ax1.plot([0, 1], [0, 0], c='orange') # 動径
marker_radius, = ax1.plot(1, 0, marker='o', c='r') # 動径マーカー
ax1.set_xlim(-1.2, 1.2)
ax1.set_ylim(-1.2, 1.2)
ax1.set_aspect('equal')
# 正弦波グラフ(右側=ax2)
ax2 = fig.add_subplot(gs[:, 2:], sharey=ax1)
ax2_x = np.arange(0, 2*np.pi, 0.01)
ax2_y = np.sin(ax2_x)
ax2.plot(ax2_x, ax2_y) # 正弦波
marker_sin, = ax2.plot(0, 0, marker='o', c='r') # 正弦波マーカー
plt.tight_layout()
def init():
# initialize :nothing
return fig,
# 描画更新用関数
def animate(i):
rx = np.cos(2 * np.pi * (i / frames))
ry = np.sin(2 * np.pi * (i / frames))
line_radius.set_data((0, rx), (0, ry)) # 動径更新
marker_radius.set_data(rx, ry) # 動径マーカー更新
marker_sin.set_data(2 * np.pi * (i / frames), ry) # 正弦波マーカー更新
return fig,
frames = 36 # フレーム数
# アニメーション実行
ani1 = animation.FuncAnimation(fig, animate, init_func=init,
frames=frames, interval=500, blit=True)
# plt.show()
# gifファイルに出力
ani1.save("radius-sin.gif", writer='imagemagick') # gifファイル出力にImageMagickを利用
保存したgif画像は、こんな感じて動くよ。
動径くるくる回せたね。
少しコードを追加して、正弦波もナゾルように動かしてみる。
# Jupyter Notebook上でインタラクティブに表示
%matplotlib nbagg
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation
# グラフ枠作成
fig = plt.figure(figsize=(6,2))
fig.patch.set_alpha(1.0) # figure不透明
# 動径円グラフ(左側=ax1)
gs = gridspec.GridSpec(1, 5)
ax1 = fig.add_subplot(gs[:,:2])
ax1.add_patch(plt.Circle(xy=(0, 0), radius=1.0, ec='gray', fill=False)) # 円
line_radius, = ax1.plot([0, 1], [0, 0], c='orange') # 動径
marker_radius, = ax1.plot(1, 0, marker='o', c='r') # 動径マーカー
ax1.set_xlim(-1.2, 1.2)
ax1.set_ylim(-1.2, 1.2)
ax1.set_aspect('equal')
# 正弦波グラフ(右側=ax2)
ax2 = fig.add_subplot(gs[:, 2:], sharey=ax1)
ax2.set_xlim(0, 2*np.pi )
ax2.set_xticks(np.arange(0, 2.1*np.pi, 0.5*np.pi))
ax2.set_xticklabels(['0', '1/2$\pi$','$\pi$', '3/2$\pi$', '2$\pi$']) # πtex表記
ax2_x = np.arange(0, 2*np.pi, 0.01)
ax2_y = np.sin(ax2_x)
ax2.plot(ax2_x, ax2_y, c='gray', alpha=0.5) # # 正弦波(ガイド)
line_sin, = ax2.plot(ax2_x[:0], ax2_y[:0], c='g') # 正弦波(動線)
marker_sin, = ax2.plot(0, 0, marker='o', c='r') # 正弦波マーカー
plt.tight_layout()
def init():
# initialize :nothing
return fig,
def animate(i):
rx = np.cos(2 * np.pi * (i / frames))
ry = np.sin(2 * np.pi * (i / frames))
line_radius.set_data((0, rx), (0, ry)) # 動径更新
marker_radius.set_data(rx, ry) # 動径マーカー更新
marker_sin.set_data(2 * np.pi * (i / frames), ry) # 正弦波マーカー更新
idx_end = int(len(ax2_x) * (i / frames))
line_sin.set_data( ax2_x[:idx_end], ax2_y[:idx_end]) # 正弦波更新
return fig,
frames = 36 # フレーム数
# アニメーション実行
ani2 = animation.FuncAnimation(fig, animate, init_func=init,
frames=frames, interval=500, blit=True)
# plt.show()
# gifファイルに出力
ani2.save("radius-sin_move.gif", writer='imagemagick') # gifファイル出力にImageMagickを利用
gif画像はこんな感じ。うまく動いた。
いいね。前に練習した正弦波スクロールなども、簡単に組み込めそうだね。
あとで、他のパターンも試してみるよ。
またね!
0 件のコメント :
コメントを投稿