Processing math: 100%

[matplotlib animation] 8. 3Dグラフの軸範囲更新アニメーション

matplotlib Animation

はじめに

matplotlib FuncAnimationによる軸範囲更新アニメーションについて解説する。

コード

%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML
import numpy as np
from matplotlib import cm
fig = plt.figure(figsize=(5,5))
ax = fig.gca(projection='3d')
def update(num):
plot[0].remove()
Z =c[num]* np.sinh(u)
zmin, zmax = ax.get_zlim()
if Z[0,0] <= zmin:
ax.set_zlim(2*zmin, 2*zmax)
plot[0] = ax.plot_surface(X, Y, Z, cmap=cm.viridis)
u = np.linspace(-3,3,100)
v = np.linspace(0, 2 * np.pi, 100)
u,v = np.meshgrid(u,v)
a=1
b=1
c=np.linspace(0,10,100)
X =a* np.cosh(u)*np.cos(v)
Y =b* np.cosh(u)*np.sin(v)
Z =c[0]* np.sinh(u)
ax.set_xlabel('x axis')
ax.set_ylabel('y axis')
ax.set_zlabel('z axis')
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
ax.set_zlim(-10,10)
#ax.set_aspect('equal')
ax.view_init(elev=15, azim=-60)
plot= [ax.plot_surface(X, Y, Z,alpha=0.8, cmap=cm.viridis)]
ani = animation.FuncAnimation(fig, update, 100, interval=100)
HTML(ani.to_html5_video())
#dpi=100
#ani.save('hyperboloid_extend.mp4', writer="ffmpeg",dpi=dpi)

解説

モジュールのインポート

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML
import numpy as np
from matplotlib import cm

軸と軸ラベルの設定

ax.set_xlabel('x axis')
ax.set_ylabel('y axis')
ax.set_zlabel('z axis')
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
ax.set_zlim(-10,10)
#ax.set_aspect('equal')
ax.view_init(elev=15, azim=-60)

視点を変える設定は、ax.view_init(elev=15, azim=-60)。
elevはElevation viewing angle の略で、視点の高さの設定。(default=30)
azimはAzimuthal viewing angleの略で、方位角の設定。(default=-60)[1]

データの生成

u = np.linspace(-3,3,100)
v = np.linspace(0, 2 * np.pi, 100)
u,v = np.meshgrid(u,v)
a=1
b=1
c=np.linspace(0,10,100)
X =a* np.cosh(u)*np.cos(v)
Y =b* np.cosh(u)*np.sin(v)
Z =c[0]* np.sinh(u)

双曲面は媒介変数でデータを生成するので、uとvを先に作成してmeshgridする。
双曲面は媒介変数で以下のようになる。

X = cosh(u)*cos(v)\\ Y = cosh(u)*sin(v)\\ Z = sinh(u)

ここで、cをnp.linspace(0,10,100)として、0〜10まで100stepで変化させていく。

アニメーションの設定

plot= [ax.plot_surface(X, Y, Z,alpha=0.8, cmap=cm.viridis)]

plotに最初に表示するグラフをプロットしておく。[]で囲んでリストにしておく。

def update(num):
plot[0].remove()
Z =c[num]* np.sinh(u)
zmin, zmax = ax.get_zlim()
if Z[0,0] <= zmin:
ax.set_zlim(2*zmin, 2*zmax)
plot[0] = ax.plot_surface(X, Y, Z, cmap=cm.viridis)

アニメーションでは古いプロットを消す必要がある。
3Dグラフの場合、plot[0].remove()で消すことができる。

Zのcのところをc[num]にして、Zを順次大きくしていく。

zmin, zmax = ax.get_zlim()で、今plotしている図のz軸の範囲を得る。
zminは初期設定で-10にしてある。
Z[0,0]には、zの最も小さい値が入っているので、この値がzminを下回ったとき、
ax.set_zlim(2*zmin, 2*zmax)で軸範囲を2倍にしていく。
そして、plot[0]に3Dグラフをプロットする。

アニメーションの表示

ani = animation.FuncAnimation(fig, update, 100, interval=100)
HTML(ani.to_html5_video())

FuncAnimationでanimationの表示。updateのnumを100としているので、frame数は100とする。interval=100なので、100 frames×100 ms = 10000 ms = 10秒のアニメーションとなる。
to_html5_videoでHTMLビデオ化。

コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

参考

Matplotlib > view_init(elev=None, azim=None)のデフォルト値 > elev = 30, azim = -60 - Qiita
GeForce GTX 1070 (8GB)ASRock Z170M Pro4S Ubuntu 16.04 LTS desktop amd64Tensor…
[matplotlib animation] 5. Decay(軸の更新アニメーション)
python, matplotlibのanimationにおける軸の更新について説明する。

コメント