在Matplotlib动画中更新surface_plot上的z数据 [英] Updating z data on a surface_plot in Matplotlib animation

查看:217
本文介绍了在Matplotlib动画中更新surface_plot上的z数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找在平面图中创建动画的方法.动画具有固定的x和y数据(每个维度为1到64),并通过np数组读取z信息.代码概述如下:

I am looking to create an animation in a surface plot. The animation has fixed x and y data (1 to 64 in each dimension), and reads through an np array for the z information. An outline of the code is like so:

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中更新绘图.但是,这非常慢,我怀疑是由于每个循环都重新绘制了情节.

So the code generates the z data and updates the plot in FuncAnimation. This is very slow however, I suspect it is due to the plot being redrawn every loop.

我尝试了该功能

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

但出现错误

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

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

How can I update the data in only the z direction without redrawing the whole plot? (Or otherwise increase the framerate of the graphing procedure)

推荐答案

调用plot_surface时,表面下发生了很多事情.尝试将新数据设置为Poly3DCollection时,您需要复制所有内容.

There is a lot going on under the surface when calling plot_surface. You would need to replicate all of it when trying to set new data to the Poly3DCollection.

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

This might actually be possible and there might also be a way to do that slightly more efficient than the matplotlib code does it. The idea would then be to calculate all the vertices from the gridpoints and directly supply them to Poly3DCollection._vec.

但是,动画的速度主要取决于执行3D-> 2D投影所需的时间以及绘制实际图的时间.因此,在绘制速度方面,上述方法无济于事.

However, the speed of the animation is mainly determined by the time it takes to perform the 3D->2D projection and the time to draw the actual plot. Hence the above will not help much, when it comes to drawing speed.

最后,您可能只是坚持当前为表面设置动画的方式,即删除先前的图并绘制一个新的图.不过,在表面上使用较少的点将大大​​提高速度.

At the end, you might simply stick to the current way of animating the surface, which is to remove the previous plot and plot a new one. Using less points on the surface will significantly increase speed though.

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()

请注意,动画本身的速度由FuncAnimationinterval参数确定.在上面没有指定,因此默认值为200毫秒.根据数据,您仍然可以在遇到帧滞后问题之前降低此值,例如尝试40毫秒,然后根据需要进行调整.

Note that the speed of the animation itself is determined by the interval argument to FuncAnimation. In the above it is not specified and hence the default of 200 milliseconds. Depending on the data, you can still decrease this value before running into issues of lagging frames, e.g. try 40 milliseconds and adapt it depending on your needs.

animate = animation.FuncAnimation(fig, update_plot, ..., interval=40,  ...)

这篇关于在Matplotlib动画中更新surface_plot上的z数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆