簡體   English   中英

嘗試使用matplotlib創建動畫3d plot_surface時發生python錯誤

[英]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函數提供參數。

在您的情況下,您使用了變量itframes=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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM