データの範囲が大きく異なるアニメーションがあります。データの最大値と最小値を追跡するcolorbar
が欲しい(つまり、修正されないようにしたい)。問題は、これをどのように行うかです。
理想的には、colorbar
を独自の軸上に配置したいと思います。
私は次の4つのことを試しました
問題:新しいカラーバーがフレームごとにプロットされます
#!/usr/bin/env python
"""
An animated image
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
ax = fig.add_subplot(111)
def f(x, y):
return np.exp(x) + np.sin(y)
x = np.linspace(0, 1, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
frames = []
for i in range(10):
x += 1
curVals = f(x, y)
vmax = np.max(curVals)
vmin = np.min(curVals)
levels = np.linspace(vmin, vmax, 200, endpoint = True)
frame = ax.contourf(curVals, vmax=vmax, vmin=vmin, levels=levels)
cbar = fig.colorbar(frame)
frames.append(frame.collections)
ani = animation.ArtistAnimation(fig, frames, blit=False)
plt.show()
上記のforループをに変更
initFrame = ax.contourf(f(x,y))
cbar = fig.colorbar(initFrame)
for i in range(10):
x += 1
curVals = f(x, y)
vmax = np.max(curVals)
vmin = np.min(curVals)
levels = np.linspace(vmin, vmax, 200, endpoint = True)
frame = ax.contourf(curVals, vmax=vmax, vmin=vmin, levels=levels)
cbar.set_clim(vmin = vmin, vmax = vmax)
cbar.draw_all()
frames.append(frame.collections + [cbar])
問題:これは発生します
AttributeError: 'Colorbar' object has no attribute 'set_visible'
問題:colorbar
が更新されていません。
#!/usr/bin/env python
"""
An animated image
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
def f(x, y):
return np.exp(x) + np.sin(y)
x = np.linspace(0, 1, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
frames = []
for i in range(10):
x += 1
curVals = f(x, y)
vmax = np.max(curVals)
vmin = np.min(curVals)
levels = np.linspace(vmin, vmax, 200, endpoint = True)
frame = ax1.contourf(curVals, vmax=vmax, vmin=vmin, levels=levels)
cbar = fig.colorbar(frame, cax=ax2) # Colorbar does not update
frames.append(frame.collections)
ani = animation.ArtistAnimation(fig, frames, blit=False)
plt.show()
問題:colorbar
は一定です。
同様の質問が投稿されています ここ ですが、OPは固定のcolorbar
で満足しているようです。
特にArtistAnimation
を使用してこれを行う方法はわかりませんが、FuncAnimation
を使用するのはかなり簡単です。 「ナイーブ」バージョン1に次の変更を加えると、機能します。
修正バージョン1
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig = plt.figure()
ax = fig.add_subplot(111)
# I like to position my colorbars this way, but you don't have to
div = make_axes_locatable(ax)
cax = div.append_axes('right', '5%', '5%')
def f(x, y):
return np.exp(x) + np.sin(y)
x = np.linspace(0, 1, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
frames = []
for i in range(10):
x += 1
curVals = f(x, y)
frames.append(curVals)
cv0 = frames[0]
cf = ax.contourf(cv0, 200)
cb = fig.colorbar(cf, cax=cax)
tx = ax.set_title('Frame 0')
def animate(i):
arr = frames[i]
vmax = np.max(arr)
vmin = np.min(arr)
levels = np.linspace(vmin, vmax, 200, endpoint = True)
cf = ax.contourf(arr, vmax=vmax, vmin=vmin, levels=levels)
cax.cla()
fig.colorbar(cf, cax=cax)
tx.set_text('Frame {0}'.format(i))
ani = animation.FuncAnimation(fig, animate, frames=10)
plt.show()
主な違いは、アーティストのリストを作成する代わりに、関数でレベルの計算と輪郭を作成することです。前のフレームから軸をクリアして、フレームごとにやり直すことができるため、カラーバーは機能します。
contour
またはcontourf
を使用する場合は、データを動的に変更することはできないため、このやり直しを行う必要があります。ただし、非常に多くの等高線レベルをプロットし、結果が滑らかに見えるので、代わりにimshow
を使用する方が良いと思います。つまり、実際には同じアーティストを使用してデータとカラーバーを変更することができます。自動的に更新されます。また、はるかに高速です!
より良いバージョン
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig = plt.figure()
ax = fig.add_subplot(111)
# I like to position my colorbars this way, but you don't have to
div = make_axes_locatable(ax)
cax = div.append_axes('right', '5%', '5%')
def f(x, y):
return np.exp(x) + np.sin(y)
x = np.linspace(0, 1, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
# This is now a list of arrays rather than a list of artists
frames = []
for i in range(10):
x += 1
curVals = f(x, y)
frames.append(curVals)
cv0 = frames[0]
im = ax.imshow(cv0, Origin='lower') # Here make an AxesImage rather than contour
cb = fig.colorbar(im, cax=cax)
tx = ax.set_title('Frame 0')
def animate(i):
arr = frames[i]
vmax = np.max(arr)
vmin = np.min(arr)
im.set_data(arr)
im.set_clim(vmin, vmax)
tx.set_text('Frame {0}'.format(i))
# In this version you don't have to do anything to the colorbar,
# it updates itself when the mappable it watches (im) changes
ani = animation.FuncAnimation(fig, animate, frames=10)
plt.show()