[英]python error when trying to a create an animated 3d plot_surface with matplotlib
看起来像这样的文档非常不完整,或者我只是在错误的地方寻找。 以前的问题似乎从未得到解答,或者看起来足够不同,无法在此处应用。 我希望有一个解决方案可以为该过程提供当前不存在的文档。 ( 编辑我错了- 链接的帖子之一或多或少已经存在答案。)
我有数百个nx x ny数组,其中包含PDE在网格上的解决方案迭代。
预期的行为是随时间创建3d曲面图的动画(其中明显是迭代)。 我得到第一个解决方案的表面图,但是此后,我遇到了与qt相关的错误,并且没有动画。
这是该行为的最小工作示例
# matplotlib stuff
from mpl_toolkits.mplot3d import axes3d, Axes3D
import matplotlib.pyplot as plt
from matplotlib import animation
# lots of array indexing will be had
import numpy
# gussy up matplotlib
from matplotlib import cm
def data_generating_function(p, epsilon, it):
# scale values down randomly until epsilon
pn = numpy.empty_like(p)
pt = [p.copy()]
l2norm = 1
while l2norm > epsilon:
pn = p.copy()
p = numpy.random.uniform() * pn
l2norm = numpy.sqrt(numpy.sum((p - pn)**2) / numpy.sum(pn**2))
pt = numpy.append(pt, [p], axis=0)
it += 1
return pt
def update_plot(i, data, plot):
ax.clear()
plot = ax.plot_surface(xv, yv, data[i,:], rstride=1, cstride=1, cmap=cm.plasma, linewidth=0, antialiased=True)
return plot,
##
# main
##
nx = 200
ny = 100
epsilon = 1e-8
it = 0
# initialize
p = numpy.random.rand(ny, nx)
x = numpy.linspace(0, 1, nx)
y = numpy.linspace(0, 1, ny)
xv, yv = numpy.meshgrid(x, y)
# attach 3D axis to the figure
fig = plt.figure()
ax = Axes3D(fig)
# populate data
# data will contain several hundred nx x ny arrays
data = data_generating_function(p.copy(), epsilon, it)
# set the axes properties
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_zlabel('$z$')
ax.view_init(30, 45)
# create the animation object
plot = ax.plot_surface(xv, yv, data[0,:], rstride=1, cstride=1, cmap=cm.plasma, linewidth=0, antialiased=True)
line_ani = animation.FuncAnimation(fig, update_plot, frames=it, fargs=(data, plot), interval=30, blit=False)
plt.show()
这是回溯
Traceback (most recent call last):
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\backends\backend_qt5agg.py", line 197, in __draw_idle_agg
FigureCanvasAgg.draw(self)
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py", line 464, in draw
self.figure.draw(self.renderer)
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
draw(artist, renderer, *args, **kwargs)
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\figure.py", line 1150, in draw
self.canvas.draw_event(renderer)
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\backend_bases.py", line 1815, in draw_event
self.callbacks.process(s, event)
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\cbook.py", line 549, in process
proxy(*args, **kwargs)
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\cbook.py", line 416, in __call__
return mtd(*args, **kwargs)
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\animation.py", line 831, in _start
self._init_draw()
File "C:\Users\Walter\Anaconda3\lib\site-packages\matplotlib\animation.py", line 1490, in _init_draw
self._draw_frame(next(self.new_frame_seq()))
StopIteration
编辑
我应该提一下,我碰巧知道数据中的解是“正确的”(即,我期望的数据以我期望的形式出现),并且我知道这些图应该可以计算出来,因为我可以将任何给定的迭代绘制为表面本身(非动画)。
编辑编辑
包括一个示例data_generating_function,可以将我的代码片段转换为一个最小的工作示例,并阐明了预期的行为(以回应评论)。
编辑#3
我发现我错误地认为变量“ it”是通过引用传递的。 将代码更改为使用“ len(data)”可以解决该问题。 如果有人知道为什么这会导致给出的错误,我很想知道。
如您所知, frames
参数必须是提供frames
的整数,或者是一个列表,或者是可迭代的,并为animation函数提供参数。
在您的情况下,您使用了变量it
( frames=it
)。 如果为零, it = 0
,动画将由零帧组成,因此将立即停止,并抛出上述错误。
重现此错误的最小示例是
import matplotlib.pyplot as plt
import matplotlib.animation
fig,ax = plt.subplots()
l, = ax.plot([],[])
x=[];y=[]
def animate(i):
x.append(i)
y.append(i**2/9.)
l.set_data(x,y)
ax.set_xlim(min(x), max(x)+1.e-5)
ax.set_ylim(min(y), max(y)+1.e-5)
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=0, interval=500)
plt.show()
设置frames = 10
消除错误。
请注意,即使在代码的修改版本中也是如此。 it
一直为零。 在python中,“按引用”或“按值”的概念不直接适用; 而是有可变且不可变的对象。 像整数一样, it
是不可变的,因此在函数定义的封闭范围内对其进行更改不会在外部进行更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.