【问题标题】:FuncAnimation doesn't show outside of functionFuncAnimation 不在函数之外显示
【发布时间】:2018-01-10 13:32:40
【问题描述】:

我在 thread 上给出了答案,谈论 matplotlib 上的褪色点。我对 ImportanceOfBeingErnest 的回答感到好奇。所以我试着玩弄他的代码。

首先,这是我的代码。

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

def get_new_vals():
    x = 0
    y = 0
    while True:
        if x >= .9:
            x = 0
            y = 0
        x += .1
        y += .1
        yield x, y

def update(t, x_vals, y_vals, intensity, scatter, gen):
    #   Get intermediate points
    new_xvals, new_yvals = gen.next()
    x_vals.extend([new_xvals])
    y_vals.extend([new_yvals])

    #   Put new values in your plot
    scatter.set_offsets(np.c_[x_vals, y_vals])

    #   Calculate new color values
    for index in range(len(intensity)):
        if intensity[index] < .1:
            intensity[index] = 0
        intensity[index] *= .6
    intensity.extend(1 for _ in xrange(len([new_xvals])))

    intens_dup = np.array(intensity)

    """
    intensity = np.concatenate((np.array(intensity) * .6, np.ones(len(new_xvals))))
    """
    scatter.set_array(intens_dup)

    # Set title
    axis.set_title('Time: %0.3f' % t)

def anim_random_points(fig, axis):
    x_vals = []
    y_vals = []
    intensity = []
    iterations = 100

    colors = [ [0, 0, 1, 0], [0, 0, 1, 0.5], [0, 0.2, 0.4, 1] ]
    cmap = LinearSegmentedColormap.from_list("", colors)
    scatter = axis.scatter(x_vals, y_vals, c=[], cmap=cmap, vmin=0, vmax=1)

    gen_values = get_new_vals()

    ani = matplotlib.animation.FuncAnimation(fig, update, frames=iterations,
        interval=50, fargs=(x_vals, y_vals, intensity, scatter, gen_values),
        repeat=False)

    #   Position 1 for plt.show()
    plt.show()

if __name__ == '__main__':

    fig, axis = plt.subplots()
    axis.set_xlabel('X Axis', size = 12)
    axis.set_ylabel('Y Axis', size = 12)
    axis.axis([0,1,0,1])

    anim_random_points(fig, axis)

    #   Position 2 for plt.show()
    # plt.show()

然后,我注意到一件奇怪的事情。至少对我来说。注意Position 1Position 2(在代码末尾)。位置 1 放在 animation 函数之后,另一个放在 之后 代码方面,因为函数在位置 1 之后结束,因此转到位置 2。

由于FuncAnimation 需要figure 来运行动画,我想知道为什么plt.show() 在位置1 上有效,而在位置2 上无效。

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    matplotlib documentation 声明了 FuncAnimation

    保持对实例对象的引用至关重要。动画由 Animation 对象唯一引用的计时器(通常来自主机 GUI 框架)推进。如果您没有对 Animation 对象的引用,它(以及计时器)将被垃圾收集,这将停止动画。

    如果您将plt.show() 放在anim_random_points 函数之外,则保存对动画的引用的变量ani 将被垃圾回收,并且将不再显示动画。

    这种情况的解决方案是从该函数返回动画

    def anim_random_points(fig, axis):
        # ...
        ani = matplotlib.animation.FuncAnimation(...)
        return ani
    
    if __name__ == '__main__':
        # ...
        ani = anim_random_points(...)
        plt.show()
    

    【讨论】:

    • 我不明白第二个问题。在一个可以单独理解的新问题中可能会更好(因为它甚至似乎根本与 matplotlib 无关)。
    • 当问题之间的计时器关闭时,我会问一个不同的问题。非常感谢您的回答。 :)
    【解决方案2】:

    你真的应该问两个不同的问题。

    我可以回答第一个。这两个位置之间的差异是由于ani 是函数anim_random_points() 的局部变量。当执行到函数结束时它会被自动删除。因此位置 2 中的plt.show() 没有可显示的内容。

    如果你想在位置 2 使用plt.show(),你需要从你的函数中返回 ani 对象,并在你的代码的主要部分保留对它的引用。

    def anim_random_points(fig, axis):
        (...)
        ani = matplotlib.animation.FuncAnimation(...)
        return ani
    
    
    if __name__ == '__main__':
        (...)
        ani = anim_random_points(fig, axis)
    
        #   Position 2 for plt.show()
        plt.show()
    

    【讨论】:

    • 你说得对,我应该只问一个问题。感谢您的输入。但是,我将验证 ImportanceOfBeingErnest 的答案,因为他提供的文档更具体地说明了局部变量的事情。但你赢得了我的赞成票!谢谢回答。 :)
    猜你喜欢
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2013-06-04
    相关资源
    最近更新 更多