matplotlib 无法使FuncAnimation在类中工作

kse8i1jr  于 2023-02-23  发布在  其他
关注(0)|答案(2)|浏览(184)

我在下面给出的代码中无法使FuncAnimation工作

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
%matplotlib notebook

class Simulator:
    def __init__(self, timesteps = 1000, ):
        self.simulation_time = np.linspace(0, timesteps, 10*(timesteps)+1)
        self._theta = np.arange(0,100, 10*(timesteps)+1)

    def init_plot(self):
        self._p1, = self.axes.plot(self.simulation_time[0], self._theta[0])
        return self.fig,

    def update_plot(self, i):
        self._p1.set_data(self.simulation_time[:i], self._theta[:i])
        return self.fig,

    def start_simulation(self):

        self.fig, self.axes = plt.subplots()
        ani=FuncAnimation(fig=self.fig, func=self.update_plot, init_func=self.init_plot,
                          interval=5, blit=True)
        plt.show()

simHandler = Simulator()
simHandler.start_simulation()

运行完这段代码后,我看到的是一个空白屏幕。。

但是当我在类之外运行类似的代码作为简单的函数时,动画就会运行,有什么办法可以解决这个问题吗?

zynd9foi

zynd9foi1#

您代码有几个问题。
第一个也是最重要的是(as per the documentation):
保持对示例对象的引用是至关重要的。动画由计时器(通常来自主机GUI框架)推进,动画对象持有对该计时器的唯一引用。如果不持有对动画对象的引用,则它(以及计时器)将被垃圾收集,从而停止动画。
这意味着类需要保留/返回对动画的引用,否则动画将立即停止。
第二个问题是,即使这样做,也需要更新xlims和ylim,因为在使用Line2D.set_data()时,它们不会自动缩放。
最后,update_plot()应该返回更新的艺术家列表,而不是对图的引用(尽管只有在使用blit=True时才需要)
更正代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
%matplotlib notebook

class Simulator:
    def __init__(self, timesteps = 1000, ):
        self.simulation_time = np.linspace(0, timesteps, 10*(timesteps)+1)
        self._theta = np.sin(self.simulation_time) # I've changed this so one could see the plot being drawn

    def init_plot(self):
        self._p1, = self.axes.plot(self.simulation_time[0], self._theta[0])
        return self.fig,

    def update_plot(self, i):
        self._p1.set_data(self.simulation_time[:i], self._theta[:i])
        self.axes.set_xlim(right=self.simulation_time[i])
        return self._p1,

    def start_simulation(self):
        self.fig, self.axes = plt.subplots()
        self.ani = FuncAnimation(fig=self.fig, func=self.update_plot, init_func=self.init_plot,
                          interval=5, blit=True)

simHandler = Simulator()
simHandler.start_simulation()
zazmityj

zazmityj2#

为了保持代码按照Diziet Asahi的建议运行,在必要的地方进行一些小的调整:
1.从FuncAnimation-调用中删除init_func
1.在start_simulation程序中初始化绘图
1.对“update_plot”进行微小变更,以调整限值
(and进一步删除%matplotlib notebook语句)
最后的结果(对我来说也是如此)是:

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

class Simulator:
    def __init__(self, timesteps = 1000, ):
        self.simulation_time = np.linspace(0, timesteps, 10*(timesteps)+1)
        self._theta = np.sin(self.simulation_time) # I've changed this so one could see the plot being drawn
    
    def update_plot(self, i):
        self._p1.set_data(self.simulation_time[:i], self._theta[:i])
        self.fig.gca().relim()
        self.fig.gca().autoscale_view() 
        return self._p1,

    def start_simulation(self):
        self.fig, self.axes = plt.subplots()
        self._p1, = self.axes.plot(self.simulation_time[0],self._theta[0])
        self.ani = FuncAnimation(fig=self.fig,func=self.update_plot,interval=5, blit=True)

simHandler = Simulator()
simHandler.start_simulation()

相关问题