import numpy as np
import scipy as sp
import matplotlib as mpl
import matplotlib.pyplot as plt
print(np.__version__)
print(sp.__version__)
print(mpl.__version__)
1.16.2 1.2.1 3.0.3
# osxの場合
%matplotlib osx
conda install python.app
$ ipython kernel install --user --name pythonw3 --display-name pythonw3
$ jupyter kernelspec list # pythonw3カーネルのパスを確認
$ vim ~/.pyenv/versions/miniconda3-4.3.30/envs/py36/share/jupyter/kernels/pythonw3/kernel.json # kernel.json記載のpathをpythonwに変更
plt.pause(second)
を使って描画を繰り返すplt.plot()
,plt.pause(sec)
, plt.cla()
を繰り返す# 説明上の共通コード
plt.close("all")
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
fig = plt.figure(1)
ax = fig.add_subplot(111)
# アニメーションしないバージョン
for _ in range(100):
ax.plot(xs, np.sin(xs)); xs += dx;
plt.show()
# 説明上の共通コード
plt.close("all")
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
fig = plt.figure(1)
ax = fig.add_subplot(111)
# アニメーションするバージョン
for n in range(100):
ax.plot(xs, np.sin(xs)); xs += dx;
plt.pause(0.1); plt.cla(); # 0.1s待ってclear
plt.show()
# アニメーションするバージョン
for n in range(100):
ax.plot(xs, np.sin(xs)); xs += dx;
plt.pause(0.1); ax.clear(); # ax.clearでも良い
plt.show()
ax.plot
は毎回プロットし直すためコストが大きい# 説明上の共通コード
plt.close("all")
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
fig = plt.figure(1)
ax = fig.add_subplot(111)
lines = ax.plot(xs, np.sin(xs))
for n in range(100):
lines[0].set_data(xs, np.sin(xs)); xs += dx;
ax.set_xlim((np.min(xs), np.max(xs))) # 横軸範囲の再設定
plt.pause(0.1) # clear不要
plt.show()
plt.ion()
, plt.draw()
を使う方法¶plt.ion()
-> plt.show()
ax.plot()
-> plt.draw()
-> plt.cla()
を繰り返すplt.pause
を入れないと動作しないplt.ion()
しておく必要は特にない?print(plt.isinteractive())
True
# 説明上の共通コード
plt.close("all")
dx = np.pi / 10.0; xs = np.arange(-np.pi, np.pi, dx)
fig = plt.figure(1); ax = fig.add_subplot(111)
plt.ion(); plt.show();
for n in range(100):
ax.plot(xs, np.sin(xs)); xs += dx
plt.draw(); plt.pause(0.1); plt.cla();
print(plt.isinteractive())
True
plt.ioff()
print(plt.isinteractive())
False
from IPython.display import Image
Image("./15/animation_class.png")
class matplotlib.animation.ArtistAnimation(fig, artists, *args, **kwargs)
import matplotlib.animation as anim
plt.close("all")
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
interval_ms = 100
images = []
fig = plt.figure(1); ax = fig.add_subplot(111)
for _ in range(100):
images.append(ax.plot(xs , np.sin(xs))); xs += dx;
ani = anim.ArtistAnimation(fig, images, interval=interval_ms, repeat=False)
plt.show()
plt.close("all")
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
interval_ms = 100
images = []
fig = plt.figure(1); ax = fig.add_subplot(111)
for n in range(100):
images.append(ax.plot(xs , np.sin(xs + n*dx)))
ani = anim.ArtistAnimation(fig, images, interval=interval_ms, repeat=False)
plt.show()
class matplotlib.animation.FuncAnimation(fig, func, frames=None, init_func=None, fargs=None, save_count=None, **kwargs)
def func(frame, *fargs) -> iterable_of_artists
def init_func() -> iterable_of_artists
def gen_function() -> obj
を指定itertools.count
を供給import matplotlib.animation as anim
plt.close("all")
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
ys = np.sin(xs)
interval_ms = 100
# 呼び出しごとにデータを生成するジェネレータ
def gen_data():
counter = 0
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
while counter < 100:
ys = np.sin(xs); xs += dx;
counter += 1
yield (xs, ys)
fig = plt.figure(1); ax = fig.add_subplot(111)
gline2d = ax.plot(xs, ys)[0] # これを上書き
def update_data(data):
xs, ys = data
ax.set_xlim((np.min(xs), np.max(xs)))
gline2d.set_data(xs, ys)
return gline2d
ani = anim.FuncAnimation(fig, update_data, gen_data,
interval=interval_ms, repeat=False)
plt.show()
update_data
でx軸レンジを都度再設定できるclass MyAnimation:
def __init__(self):
plt.close("all")
self.fig = plt.figure(1)
self.ax = self.fig.add_subplot(111)
self.dx = np.pi / 10.0
self.xs = np.arange(-np.pi, np.pi, self.dx)
self.ys = np.sin(self.xs)
self.interval_ms = 100
self.line2d = self.ax.plot(self.xs, self.ys)[0]
self.counter = 0
def gen(self):
while self.counter < 100:
self.ys = np.sin(self.xs)
self.xs += self.dx;
self.counter += 1
yield (self.xs, self.ys)
def update_data(self, data):
xs, ys = data
self.ax.set_xlim((np.min(xs), np.max(xs)))
self.line2d.set_data(xs, ys)
return self.line2d
def animate(self):
ani = anim.FuncAnimation(self.fig, self.update_data, self.gen,
interval=self.interval_ms, repeat=False)
plt.show()
MyAnimation().animate()
ArtistAnimation
、FuncAnimation
が継承しているクラスself._draw_frame(self, frame)
self.new_frame_seq(self)
self._init_draw(self)
class MyTimedAnimation(anim.TimedAnimation):
def __init__(self):
plt.close("all")
self.fig = plt.figure(1)
self.ax = self.fig.add_subplot(111)
self.dx = np.pi / 10.0
self.xs = np.arange(-np.pi, np.pi, self.dx)
self.ys = np.sin(self.xs)
self.interval_ms = 100
self.line2d = self.ax.plot(self.xs, self.ys)[0]
self.counter = 0
plt.show()
anim.TimedAnimation.__init__(self, self.fig, self.interval_ms)
def new_frame_seq(self):
while self.counter < 100:
self.ys = np.sin(self.xs)
self.xs += self.dx;
self.counter += 1
yield (self.xs, self.ys)
def _draw_frame(self, data):
xs, ys = data
self.ax.set_xlim((np.min(xs), np.max(xs)))
self.line2d.set_data(xs, ys)
return self.line2d
def _init_draw(self):
pass
MyTimedAnimation()
<__main__.MyTimedAnimation at 0x11bb5dd30>
save
メソッドsave(filename, writer="ffmpeg")
to_html5_video
メソッドsave(filename, writer=None, fps=None, dpi=None, codec=None, bitrate=None, extra_args=None, metadata=None, extra_anim=None, savefig_kwargs=None)
Image("./15/animation_inheritance.png")
plt.close("all")
dx = np.pi / 10.0
xs = np.arange(-np.pi, np.pi, dx)
interval_ms = 100
images = []
fig = plt.figure(1); ax = fig.add_subplot(111)
for _ in range(100):
images.append(ax.plot(xs , np.sin(xs))); xs += dx;
ani = anim.ArtistAnimation(fig, images, interval=interval_ms, repeat=False)
ani.save("./test.gif", "imagemagick")
!ls
animation_class.webp animation_inheritance.webp pydata_osaka_20190323_matplotlib_animation.ipynb test.gif
Image("./15/test.gif")
<IPython.core.display.Image object>
# 要ffmpeg
from IPython.display import HTML
HTML(ani.to_html5_video())