【问题标题】:Recursive animation matplotlib递归动画matplotlib
【发布时间】:2019-12-23 11:47:41
【问题描述】:

我想对波函数的一些时间传播进行动画处理。但我不想每次都计算所有时间步长,因为它需要大量时间,而是将波函数的先前值作为初始值。我不知道如何用animation.FuncAnimation 实现这一点。 我就是这么想的:

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

wavefunction_0 = some array 

def next_wavefunction(wavefunction_init): 
    wavefunction = time_propagation(Psi = wavefunction_init)
    return wavefunction

def animate(framenumber, wavefunction, surf):
    if framenumber == 0:
        wavefunction = wavefunction_0
    else: 
        wavefunction = next_wavefunction(wavefunction)
    ax.clear()
    surf = ax.plot_surface(X, Y, np.reshape(np.abs(wavefunction), (space_shape)), rstride=1, cstride=1, linewidth=0,  antialiased=False, cmap='jet', edgecolor='none')
    return surf, wavefunction

anim = animation.FuncAnimation(fig, animate, fargs=(wavefunction, surf),
                              interval=200, blit=False)

目前它从fargs = wavefunction 开始不起作用,但波函数是animate(...) 的返回值。是否可以将animate的返回值作为fargs传递?

【问题讨论】:

  • 您有没有机会尝试我的答案中的任何一种解决方案?
  • @WilliamMiller 我会在下周之前查看它!
  • 你有时间看这个吗?

标签: python matplotlib animation plot physics


【解决方案1】:

Matplotlib 期望传递给 matplotlib.animation.FuncAnimationanimate 函数返回 artists 的列表,因此(至少在我的理解中)不可能返回像这样的非艺术家

return surf, wavefunction

因此,即使您将wavefunction 传递给animate,您也无法返回变异数组。除非您可以将代码重构为无需前一帧的信息即可计算当前帧的数组的方式,否则您不能使用这种方法。

有两种方法可以解决这个问题,一种是使用全局变量来存储波函数数组并根据需要对其进行变异,这样函数中所做的更改会在函数结束后持续存在。为了演示,这里是这个实现的一个例子,它比 3 维变化的波函数稍微简单一些,

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

n = 100
wf = np.zeros((n,2))

def next_wf():
    global wf
    offset = wf[0,0] + 0.1
    wf[:,0] = np.linspace(offset, np.pi*4+offset, wf.shape[0])
    wf[:,1] = np.sin(wf[:,0])

def animate(frame):
    next_wf()
    plt.cla()
    plot, = plt.plot(wf[:,0], wf[:,1])
    return plot,

next_wf()
fig, ax = plt.subplots(1)
anim = animation.FuncAnimation(fig, animate, interval=25)

这将创建一个如下所示的动画

但是,应该注意的是,文档的Variables and Scope 页面明确建议不要使用全局变量,

请注意,从函数内部访问全局变量通常是非常糟糕的做法,修改它们更糟糕。这使得我们很难将我们的程序安排成逻辑封装的部分,这些部分不会以意想不到的方式相互影响。如果一个函数需要访问一些外部值,我们应该将该值作为参数传递给函数。 [...]

在一个简单的、自包含的脚本中,它不太可能造成伤害,但在更复杂的代码中,它可能是有害的。更“正确”的方法是将整个内容包装在 class 中,即

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

class waveanim:
    def __init__(self):
        n = 100
        self.wf = np.zeros((n,2))
        self.next_wf()
        fig, ax = plt.subplots(1)
        anim = animation.FuncAnimation(fig, self.animate, interval=25, blit=True)

        anim.save('./animation.gif', writer='imagemagick')

    def next_wf(self):
        offset = self.wf[0,0] + 0.1
        self.wf[:,0] = np.linspace(offset, np.pi*4+offset, self.wf.shape[0])
        self.wf[:,1] = np.sin(self.wf[:,0])

    def animate(self, frame):
        self.next_wf()
        plt.cla()
        plot, = plt.plot(self.wf[:,0], self.wf[:,1])
        return plot,

waveanim()

结果与上述相同。

【讨论】:

    猜你喜欢
    • 2013-11-20
    • 2015-11-22
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 2012-11-11
    • 2021-02-01
    • 2012-05-07
    • 2021-01-09
    相关资源
    最近更新 更多