简体   繁体   English

Matplotlib中的实时绘图-python

[英]Real-time plot in matplotlib - python

I'm trying to get real-time spectrum analyzer type plot in matplotlib. 我正在尝试在matplotlib中获取实时频谱分析仪类型图。 I've got some code working (with help from other posts on StackOverflow) as follows: 我有一些代码正在工作(在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()

The code works and I'm getting what I want, but there is a serious problem. 代码工作正常,我得到了想要的东西,但是有一个严重的问题。 The plot window would freeze after some time. 一段时间后,绘图窗口将冻结。 I know the program is still running by inspecting the i variable (I'm running the code in Anaconda/Spyder so I can see the variables). 我知道程序通过检查i变量仍在运行(我正在Anaconda / Spyder中运行代码,因此我可以看到变量)。 However the plot window would show "Non responding" and if I terminate the python program in Spyder by ctrl+c, the plot window comes back to life and show the latest plot. 但是,绘图窗口将显示“无响应”,如果我通过ctrl + c终止了Spyder中的python程序,则绘图窗口将恢复工作并显示最新的绘图。

I'm out of wits here as how to further debug the issue. 关于如何进一步调试问题,我不明智。 Anyone to help? 有人帮忙吗?

Thanks 谢谢

I am not sure that adding plt.pause will entirely solve your issue. 我不确定添加plt.pause是否可以完全解决您的问题。 It may just take longer before the application crash. 应用程序崩溃可能需要更长的时间。 The memory used by your application seems to constantly increase over time (even after adding plt.pause ). 您的应用程序使用的内存似乎随着时间不断增加(即使添加了plt.pause )。 Below are two suggestions that may help you with your current issue: 以下是两个可以帮助您解决当前问题的建议:

  1. Instead of removing/recreating the lines artists with each iteration with remove and plot , I would use the same artist throughout the whole animation and simply update its ydata . 与其在每次使用removeplot迭代中都删除/重新创建线条艺术家,我将在整个动画中使用同一艺术家并简单地更新其ydata

  2. I'll use explicit handlers for the axe and figure and call show and draw explicitly on the figure manager and canvas instead of going with implicit calls through pyplot , following the advices given in a post by tcaswell . 我将使用显式处理程序来处理斧头和图形,并在图形managercanvas上显式调用showdraw ,而不要pyplot帖子中给出的建议通过pyplot进行隐式调用。

Following the above, the code would look something like this: 按照上面的内容,代码将如下所示:

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()

I've run the above code for a good 10 minutes and the memory used by the application remained stable the whole time, while the memory used by your current code (without plt.pause ) increased by about 30MiB over the same period. 我已经将上述代码运行了10分钟,并且应用程序使用的内存始终保持稳定,而当前代码(没有plt.pause )使用的内存在同一时期增加了约30MiB。

To answer myself, I solved the issue by adding 为了回答自己,我通过添加解决了该问题

plt.pause(0.01)

after the 之后

plt.draw()

This probably allows the GUI to finish the drawing and clear the buffer somewhere (my guess) before the new data comes in. 这可能允许GUI在输入新数据之前完成绘图并清除缓冲区(我的猜测)。

I know I'm late to answer this question, but for your issue you could look into the "joystick" package. 我知道我来回答这个问题已经很晚了,但是对于您的问题,您可以研究“游戏杆”程序包。 It is based on the line.set_data() and canvas.draw() methods, with optional axes re-scaling, hence most probably faster than removing a line and adding a new one. 它基于line.set_data()和canvas.draw()方法,并具有可选的轴重缩放比例,因此最有可能比删除一条线并添加一条新线更快。 It also allows for interactive text logging or image plotting (in addition to graph plotting). 它还允许交互式文本记录或图像绘图(除了图形绘图外)。 No need to do your own loops in a separate thread, the package takes care of it, just give the update frequency you wish. 无需在单独的线程中执行自己的循环,程序包会照顾它,只需提供您希望的更新频率即可。 Plus the terminal remains available for more monitoring commands while live plotting, which is not possible with a "while True" loop. 另外,终端在实时绘图时仍可用于更多监视命令,而“ while True”循环则无法实现。 See http://www.github.com/ceyzeriat/joystick/ or https://pypi.python.org/pypi/joystick (use pip install joystick to install) 参见http://www.github.com/ceyzeriat/joystick/https://pypi.python.org/pypi/joystick (使用pip install游戏杆进行安装)

try: 尝试:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM