Skip to main content
 首页 » 编程设计

python之为 maptlotlib FuncAnimation 维护一个颜色条

2025年05月04日22qq78292959

我制作了一个脚本,它使用 matplotlib 的 FuncAnimation 函数来为抛物面函数的一系列等高线图设置动画。我想添加一个颜色条,其范围在整个动画过程中都不会改变。我真的不知道该怎么做。脚本如下所示:

import numpy as np 
import itertools 
import matplotlib.pyplot as plt 
import matplotlib.mlab as ml 
import matplotlib.animation as animation 
 
#Generate some lists 
 
def f(x,y,a): 
    return a*(x**2+y**2) 
 
avals = list(np.linspace(0,1,10)) 
xaxis = list(np.linspace(-2,2,9)) 
yaxis = list(np.linspace(-2,2,9)) 
 
xy = list(itertools.product(xaxis,yaxis)) 
xy = list(map(list,xy)) 
xy = np.array(xy) 
 
x = xy[:,0] 
y = xy[:,1] 
x = list(x) 
y = list(y) 
 
zlist = [] 
 
for a in avals: 
    z = [] 
    for i, xval in enumerate(x): 
        z.append(f(x[i],y[i],a)) 
    zlist.append(z) 
 
xi = np.linspace(min(x),max(x),len(x)) 
yi = np.linspace(min(y), max(y), len(y)) 
 
fig,ax = plt.subplots() 
 
def animate(index): 
    zi = ml.griddata(x, y, zlist[index], xi, yi, interp='linear') 
    ax.clear() 
    contourplot = ax.contourf(xi, yi, zi, cmap=plt.cm.hsv,origin='lower') 
    #cbar = plt.colorbar(contourplot) 
    ax.set_title('%03d'%(index)) 
    return ax 
 
ani = animation.FuncAnimation(fig,animate,np.array([0,1,2,3,4,5,6,7,8,9]),interval=200,blit=False) 
plt.show() 

第 42 行是我尝试包含所述颜色条的尝试。这里的问题是,因为 FuncAnimation 多次调用绘图函数(每帧一次),颜色条被多次绘制,从而弄乱了动画。我也想不出任何方法将 colorbar 实例化移到 animate 函数之外,因为 ax 对象似乎是它的本地对象。

如何为整个动画添加一个颜色条?

请注意以上是完整的工作代码。它应该适用于适当的 python 解释器。

请您参考如下方法:

我想这个想法是在更新函数之外创建一个等高线图并给它一个颜色条。然后等高线图需要定义级别,并且需要定义颜色范围。

ax.contourf(..., levels=levels, vmin=zmin, vmax=zmax) 

其中 zmin 和 zmax 是要显示的最小和最大数据,levels 是要使用的级别列表或数组。

然后,在动画函数中,您只需创建一个具有相同参数的新等高线图,而根本不触及颜色条。

import numpy as np 
import itertools 
import matplotlib.pyplot as plt 
import matplotlib.mlab as ml 
import matplotlib.animation as animation 
 
def f(x,y,a): 
    return a*(x**2+y**2) 
 
avals = list(np.linspace(0,1,10)) 
xaxis = list(np.linspace(-2,2,9)) 
yaxis = list(np.linspace(-2,2,9)) 
 
xy = list(itertools.product(xaxis,yaxis)) 
xy = np.array(list(map(list,xy))) 
 
x = xy[:,0] 
y = xy[:,1] 
 
zlist = [] 
 
for a in avals: 
    z = [] 
    for i, xval in enumerate(x): 
        z.append(f(x[i],y[i],a)) 
    zlist.append(z) 
 
xi = np.linspace(min(x),max(x),len(x)) 
yi = np.linspace(min(y), max(y), len(y)) 
 
zmin = min([min(zl) for zl in zlist]) 
zmax = max([max(zl) for zl in zlist]) 
levels = np.linspace(zmin, zmax,41) 
kw = dict(levels=levels, cmap=plt.cm.hsv, vmin=zmin, vmax=zmax, origin='lower') 
 
fig,ax = plt.subplots() 
zi = ml.griddata(x, y, zlist[0], xi, yi, interp='linear') 
contourplot = ax.contourf(xi, yi, zi, **kw) 
cbar = plt.colorbar(contourplot) 
 
def animate(index): 
    zi = ml.griddata(x, y, zlist[index], xi, yi, interp='linear') 
    ax.clear() 
    ax.contourf(xi, yi, zi, **kw) 
    ax.set_title('%03d'%(index)) 
 
 
ani = animation.FuncAnimation(fig,animate,10,interval=200,blit=False) 
plt.show()