在Matplotlib动画中更新surface_plot上的z数据

时间:2017-08-16 11:16:47

标签: python matplotlib

我希望在曲面图中创建动画。动画固定了x和y数据(每个维度1到64),并通过np数组读取z信息。代码大纲如下:

import numpy as np
import matplotlib.pyplot as plt 
import matplotlib.animation as animation

def update_plot(frame_number, zarray, plot):
    #plot.set_3d_properties(zarray[:,:,frame_number])
    ax.collections.clear()
    plot = ax.plot_surface(x, y, zarray[:,:,frame_number], color='0.75')

fig = plt.figure()
ax = plt.add_subplot(111, projection='3d')

N = 64
x = np.arange(N+1)
y = np.arange(N+1)
x, y = np.meshgrid(x, y)
zarray = np.zeros((N+1, N+1, nmax+1))

for i in range(nmax):
  #Generate the data in array z
  #store data into zarray
  #zarray[:,:,i] = np.copy(z)

plot = ax.plot_surface(x, y, zarray[:,:,0], color='0.75')

animate = animation.FuncAnimation(fig, update_plot, 25, fargs=(zarray, plot))
plt.show()

因此代码生成z数据并更新FuncAnimation中的绘图。这是非常缓慢的,但我怀疑这是由于每个循环重新绘制的情节。

我尝试了这个功能

ax.set_3d_properties(zarray[:,:,frame_number])

但它出现了错误

AttributeError: 'Axes3DSubplot' object has no attribute 'set_3d_properties'

如何在不重绘整个图的情况下仅在z方向更新数据? (或以其他方式增加绘图程序的帧率)

2 个答案:

答案 0 :(得分:6)

调用plot_surface时,表面上有很多事情要发生。在尝试将新数据设置为Poly3DCollection时,您需要复制所有数据。

实际上这可能是可能的,并且可能还有一种方法可以比matplotlib代码更有效。然后,想法是从网格点计算所有顶点并直接将它们提供给Poly3DCollection._vec

然而,动画的速度主要取决于执行3D-> 2D投影所花费的时间和绘制实际绘图的时间。因此,在绘制速度方面,上述内容无济于事。

最后,您可能只是坚持当前的动画表面方式,即删除之前的绘图并绘制一个新绘图。在表面上使用较少的点会显着提高速度。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.animation as animation

def update_plot(frame_number, zarray, plot):
    plot[0].remove()
    plot[0] = ax.plot_surface(x, y, zarray[:,:,frame_number], cmap="magma")

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

N = 14
nmax=20
x = np.linspace(-4,4,N+1)
x, y = np.meshgrid(x, x)
zarray = np.zeros((N+1, N+1, nmax))

f = lambda x,y,sig : 1/np.sqrt(sig)*np.exp(-(x**2+y**2)/sig**2)

for i in range(nmax):
    zarray[:,:,i] = f(x,y,1.5+np.sin(i*2*np.pi/nmax))

plot = [ax.plot_surface(x, y, zarray[:,:,0], color='0.75', rstride=1, cstride=1)]
ax.set_zlim(0,1.5)
animate = animation.FuncAnimation(fig, update_plot, nmax, fargs=(zarray, plot))
plt.show()

请注意,动画本身的速度取决于interval的{​​{1}}参数。在上面没有指定,因此默认值为200毫秒。根据数据的不同,您仍然可以在遇到滞后帧问题之前降低此值,例如:尝试40毫秒并根据您的需要进行调整。

FuncAnimation

答案 1 :(得分:0)

set_3d_properties()Poly3DCollection类的函数,而不是Axes3DSubplot

你应该运行

plot.set_3d_properties(zarray[:,:,frame_number])

正如您在更新功能BTW中所评论的那样,而不是

ax.set_3d_properties(zarray[:,:,frame_number])

我不知道这是否会解决您的问题,但我不确定,因为函数set_3d_properties没有附加文档。我想知道你是否应该更好地尝试plot.set_verts()