matplotlib中的实时绘图 - python

时间:2015-08-25 20:14:08

标签: python matplotlib

我试图在matplotlib中获得实时频谱分析仪类型图。我已经得到了一些代码(在StackOverflow上的其他帖子的帮助下),如下所示:

import time
import numpy as np
import matplotlib.pyplot as plt

plt.axis([0, 1000, 0, 1])
plt.ion()
plt.show()

i=0
np.zeros([1,500],'float')
lines=plt.plot(y[0])

while 1:
    i=i+1
    lines.pop(0).remove()
    y = np.random.rand(1,100)
    lines=plt.plot(y[0])
    plt.draw()

代码有效,我得到了我想要的东西,但是有一个严重的问题。一段时间后,情节窗口会冻结。我知道程序仍在运行,检查 i 变量(我在Anaconda / Spyder中运行代码,因此我可以看到变量)。然而,情节窗口将显示"无响应"如果我通过ctrl + c终止Spyder中的python程序,那么绘图窗口将恢复生命并显示最新的情节。

我在这里是如何进一步调试问题的。有人帮忙吗?

由于

3 个答案:

答案 0 :(得分:1)

我不确定添加plt.pause是否能完全解决您的问题。应用程序崩溃可能需要更长时间。应用程序使用的内存似乎会随着时间的推移不断增加(即使在添加plt.pause之后)。以下两条建议可以帮助您解决当前问题:

  1. 我不会在removeplot的每次迭代中移除/重新创建线条艺术家,而是在整个动画中使用相同的艺术家,只需更新其ydata

  2. 我会使用显式处理程序来获取斧头和数字,并在图showdraw上明确调用managercanvas而不是去通过pyplot进行隐式调用,遵循post by tcaswell中提供的建议。

  3. 按照上面的说法,代码看起来像这样:

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots()
    ax.axis([0, 100, 0, 1])
    
    y = np.random.rand(100)
    lines = ax.plot(y)
    
    fig.canvas.manager.show() 
    
    i=0
    while 1:
        i=i+1
        y = np.random.rand(100)
        lines[0].set_ydata(y)
        fig.canvas.draw()
        fig.canvas.flush_events()
    

    我运行上面的代码大约10分钟,应用程序使用的内存一直保持稳定,而当前代码使用的内存(没有plt.pause)增加了大约30MiB在同一时期。

答案 1 :(得分:0)

为了回答自己,我通过添加

解决了这个问题
plt.pause(0.01)

之后

plt.draw()

这可能允许GUI在新数据进入之前完成绘图并在某处清除缓冲区(我的猜测)。

答案 2 :(得分:0)

我知道我迟到了回答这个问题,但对于你的问题,你可以查看"操纵杆"包。它基于line.set_data()和canvas.draw()方法,可选轴重新缩放,因此最有可能比删除行和添加新行更快。它还允许交互式文本记录或图像绘图(除了图形绘图)。 无需在单独的线程中执行您自己的循环,包就可以处理它,只需提供您希望的更新频率。此外,终端在实时绘图时仍然可用于更多监控命令,这是使用"而真正的"环。 请参阅http://www.github.com/ceyzeriat/joystick/https://pypi.python.org/pypi/joystick(使用pip install操纵杆进行安装)

尝试:

import joystick as jk
import numpy as np
import time

class test(jk.Joystick):
    # initialize the infinite loop decorator
    _infinite_loop = jk.deco_infinite_loop()

    def _init(self, *args, **kwargs):
        """
        Function called at initialization, see the doc
        """
        self._t0 = time.time()  # initialize time
        self.xdata = np.array([self._t0])  # time x-axis
        self.ydata = np.array([0.0])  # fake data y-axis
        # create a graph frame
        self.mygraph = self.add_frame(jk.Graph(name="test", size=(500, 500), pos=(50, 50), fmt="go-", xnpts=100, xnptsmax=1000, xylim=(None, None, 0, 1)))

    @_infinite_loop(wait_time=0.2)
    def _generate_data(self):  # function looped every 0.2 second to read or produce data
        """
        Loop starting with the simulation start, getting data and
    pushing it to the graph every 0.2 seconds
        """
        # concatenate data on the time x-axis
        self.xdata = jk.core.add_datapoint(self.xdata, time.time(), xnptsmax=self.mygraph.xnptsmax)
        # concatenate data on the fake data y-axis
        self.ydata = jk.core.add_datapoint(self.ydata, np.random.random(), xnptsmax=self.mygraph.xnptsmax)
        self.mygraph.set_xydata(t, self.ydata)

t = test()
t.start()
t.stop()