【问题标题】:Matplotlib's FuncAnimation calls init_func more than onceMatplotlib 的 FuncAnimation 不止一次调用 init_func
【发布时间】:2018-09-02 05:36:13
【问题描述】:

matplotlib.animation.FuncAnimation 的文档说:

init_func : [...] 此函数将在第一帧之前调用一次。

但每当我使用FuncAnimation 时,init_func 就会被多次调用。 您可以通过在basic example from Matplotlib's website 中添加打印语句来看到这一点:

"""
A simple example of an animated plot
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))


def animate(i):
    line.set_ydata(np.sin(x + i/10.0))  # update the data
    return line,


# Init only required for blitting to give a clean slate.
def init():

    # ---> Adding a print statement here <---
    print('Initializing')  

    line.set_ydata(np.ma.array(x, mask=True))
    return line,

ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init,
                              interval=25, blit=True)
plt.show()    

除了产生可爱的情节,它立即给出标准输出:

Initializing
Initializing

如果我让动画继续运行,init_func 实际上会被一遍又一遍地调用! 这是错误还是功能?我该怎么办?


一点背景:我使用init_func初始化多个绘图as described here,只在一个类内:

class MyAnimation:
    def __init__(self, n):
        self.fig, self.ax = plt.subplots()
        self.n = n
        self.lines = []

    def run_animation(self):
        def init():
            for i in range(self.n):
                line = ax.plot([], [])[0]
                self.lines.append(line)     
            return self.lines

        def animate(i):
            ... # Update lines
            return self.lines

        animation = FuncAnimation(self.fig, animate, init_func=init, blit=True)
        plt.show()       

当然,如果init() 被多次调用,这是没有意义的,因为额外的行将附加到self.lines。 我的方法不是很好的做法吗? 我应该在init() 函数中设置self.lines = [] 吗?

【问题讨论】:

    标签: python animation matplotlib


    【解决方案1】:

    首先应该提到“这个函数将在第一帧之前被调用一次”。意味着它在每个动画的第一帧之前被调用一次。所以因为FuncAnimationrepeat参数默认是True,所以每次动画重复,init_func都会被再次调用。

    接下来你是对的,这个函数实际上被调用了两次。第一个调用是设置动画。这一步显然是内部需要的。因此,应该考虑到这一点,并确保 init 函数不会在图中产生任何不可逆的东西。
    另请注意,如果您未提供任何 init_func,则第一帧将用于内部设置过程。

    因此,我认为您在init_func 中重置lines 属性是完全正确的。可能您甚至可能想要清除轴 (self.ax.clear()) 以摆脱以前绘制的元素。

    【讨论】:

    • 哎呀,我希望我以后可以做类似ani = MyAnimation() 的事情,然后更改布局,例如在我打电话给ani.run_animation() 之前,用ani.fig.set_facecolor('blue')。当我清除 init_func 中的轴时,这是不可能的...
    • 正确。在这种情况下,您可以遍历这些行并删除它们,例如for line in self.lines: line.remove()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 1970-01-01
    相关资源
    最近更新 更多