gpt4 book ai didi

matplotlib - Matplotlib/PyPlot 中的快速实时绘图

转载 作者:行者123 更新时间:2023-12-03 08:17:31 25 4
gpt4 key购买 nike

多年来,我一直在努力在 matplotlib 中获得高效的实时绘图,直到今天我仍然不满意。

我想要一个 redraw_figure更新图形“实时”(在代码运行时)的函数,如果我停在断点处,它将显示最新的图。

这是一些演示代码:

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

def live_update_demo():

plt.subplot(2, 1, 1)
h1 = plt.imshow(np.random.randn(30, 30))
redraw_figure()
plt.subplot(2, 1, 2)
h2, = plt.plot(np.random.randn(50))
redraw_figure()

t_start = time.time()
for i in xrange(1000):
h1.set_data(np.random.randn(30, 30))
redraw_figure()
h2.set_ydata(np.random.randn(50))
redraw_figure()
print 'Mean Frame Rate: %.3gFPS' % ((i+1) / (time.time() - t_start))

def redraw_figure():
plt.draw()
plt.pause(0.00001)

live_update_demo()

当代码运行时,绘图应该实时更新,并且在 redraw_figure() 之后的任何断点处停止时我们应该看到最新的数据。 .问题是如何最好地实现 redraw_figure()
在上面的实现( plt.draw(); plt.pause(0.00001) )中,它可以工作,但是非常慢(~3.7FPS)

我可以将其实现为:
def redraw_figure():
plt.gcf().canvas.flush_events()
plt.show(block=False)

它运行得更快(~11FPS),但是当您在断点处停止时,绘图不是最新的(例如,如果我在 t_start = ... 行上放置一个断点,则不会出现第二个绘图)。

奇怪的是,真正起作用的是两次调用该节目:
def redraw_figure():
plt.gcf().canvas.flush_events()
plt.show(block=False)
plt.show(block=False)

如果您在任何一行中断,它可以提供 ~11FPS 并且确实使绘图保持最新数据。

现在我听说它说“block”关键字已被弃用。无论如何,两次调用相同的函数似乎是一种奇怪的,可能是不可移植的黑客攻击。

那么我可以在这个函数中放入什么,以合理的帧速率绘制,不是一个巨大的杂物,并且最好跨后端和系统工作?

一些注意事项:
  • 我在 OSX 上,使用 TkAgg后端,但欢迎任何后端/系统上的解决方案
  • 交互模式“开”将不起作用,因为它不会实时更新。当解释器等待用户输入时,它只会在 Python 控制台中更新。
  • 一个 blog建议实现:

    def redraw_figure():
    无花果 = plt.gcf()
    fig.canvas.draw()
    fig.canvas.flush_events()

  • 但至少在我的系统上,这根本不会重绘绘图。

    所以,如果有人有答案,你会直接让我和其他成千上万的人非常高兴。他们的幸福可能会渗透到他们的 friend 和亲戚、他们的 friend 和亲戚等等,这样你就有可能改善数十亿人的生活。

    结论

    ImportanceOfBeingErnest 展示了如何使用 blit 进行更快的绘图,但这并不像在 redraw_figure 中放入一些不同的东西那么简单。函数(您需要跟踪要重绘的内容)。

    最佳答案

    首先,问题中发布的代码在我的机器上以 7 fps 运行,QT4Agg 作为后端。

    现在,正如许多帖子中所建议的那样,例如 herehere , 使用 blit可能是一个选择。虽然 this article提到 blit 会导致强烈的内存泄漏,我无法观察到。

    我稍微修改了您的代码,并比较了使用和不使用 blit 的帧速率。下面的代码给出

  • 无 blit 运行时为 28 fps
  • 175 fps 与 blit

  • 代码:
    import time
    from matplotlib import pyplot as plt
    import numpy as np


    def live_update_demo(blit = False):
    x = np.linspace(0,50., num=100)
    X,Y = np.meshgrid(x,x)
    fig = plt.figure()
    ax1 = fig.add_subplot(2, 1, 1)
    ax2 = fig.add_subplot(2, 1, 2)

    img = ax1.imshow(X, vmin=-1, vmax=1, interpolation="None", cmap="RdBu")


    line, = ax2.plot([], lw=3)
    text = ax2.text(0.8,0.5, "")

    ax2.set_xlim(x.min(), x.max())
    ax2.set_ylim([-1.1, 1.1])

    fig.canvas.draw() # note that the first draw comes before setting data


    if blit:
    # cache the background
    axbackground = fig.canvas.copy_from_bbox(ax1.bbox)
    ax2background = fig.canvas.copy_from_bbox(ax2.bbox)

    plt.show(block=False)


    t_start = time.time()
    k=0.

    for i in np.arange(1000):
    img.set_data(np.sin(X/3.+k)*np.cos(Y/3.+k))
    line.set_data(x, np.sin(x/3.+k))
    tx = 'Mean Frame Rate:\n {fps:.3f}FPS'.format(fps= ((i+1) / (time.time() - t_start)) )
    text.set_text(tx)
    #print tx
    k+=0.11
    if blit:
    # restore background
    fig.canvas.restore_region(axbackground)
    fig.canvas.restore_region(ax2background)

    # redraw just the points
    ax1.draw_artist(img)
    ax2.draw_artist(line)
    ax2.draw_artist(text)

    # fill in the axes rectangle
    fig.canvas.blit(ax1.bbox)
    fig.canvas.blit(ax2.bbox)

    # in this post http://bastibe.de/2013-05-30-speeding-up-matplotlib.html
    # it is mentionned that blit causes strong memory leakage.
    # however, I did not observe that.

    else:
    # redraw everything
    fig.canvas.draw()

    fig.canvas.flush_events()
    #alternatively you could use
    #plt.pause(0.000000000001)
    # however plt.pause calls canvas.draw(), as can be read here:
    #http://bastibe.de/2013-05-30-speeding-up-matplotlib.html


    live_update_demo(True) # 175 fps
    #live_update_demo(False) # 28 fps

    更新:
    为了更快地绘图,可以考虑使用 pyqtgraph .
    pyqtgraph documentation说:“对于绘图,pyqtgraph 不像 matplotlib 那样完整/成熟,但运行速度要快得多。”

    我将上面的例子移植到 pyqtgraph。虽然它看起来有点难看,但它在我的机器上以 250 fps 的速度运行。

    总结一下,
  • matplotlib(无 blitting):28 fps
  • matplotlib(带 blitting):175 fps
  • pyqtgraph: 250 帧/秒

  • pyqtgraph 代码:
    import sys
    import time
    from pyqtgraph.Qt import QtCore, QtGui
    import numpy as np
    import pyqtgraph as pg


    class App(QtGui.QMainWindow):
    def __init__(self, parent=None):
    super(App, self).__init__(parent)

    #### Create Gui Elements ###########
    self.mainbox = QtGui.QWidget()
    self.setCentralWidget(self.mainbox)
    self.mainbox.setLayout(QtGui.QVBoxLayout())

    self.canvas = pg.GraphicsLayoutWidget()
    self.mainbox.layout().addWidget(self.canvas)

    self.label = QtGui.QLabel()
    self.mainbox.layout().addWidget(self.label)

    self.view = self.canvas.addViewBox()
    self.view.setAspectLocked(True)
    self.view.setRange(QtCore.QRectF(0,0, 100, 100))

    # image plot
    self.img = pg.ImageItem(border='w')
    self.view.addItem(self.img)

    self.canvas.nextRow()
    # line plot
    self.otherplot = self.canvas.addPlot()
    self.h2 = self.otherplot.plot(pen='y')


    #### Set Data #####################

    self.x = np.linspace(0,50., num=100)
    self.X,self.Y = np.meshgrid(self.x,self.x)

    self.counter = 0
    self.fps = 0.
    self.lastupdate = time.time()

    #### Start #####################
    self._update()

    def _update(self):

    self.data = np.sin(self.X/3.+self.counter/9.)*np.cos(self.Y/3.+self.counter/9.)
    self.ydata = np.sin(self.x/3.+ self.counter/9.)

    self.img.setImage(self.data)
    self.h2.setData(self.ydata)

    now = time.time()
    dt = (now-self.lastupdate)
    if dt <= 0:
    dt = 0.000000000001
    fps2 = 1.0 / dt
    self.lastupdate = now
    self.fps = self.fps * 0.9 + fps2 * 0.1
    tx = 'Mean Frame Rate: {fps:.3f} FPS'.format(fps=self.fps )
    self.label.setText(tx)
    QtCore.QTimer.singleShot(1, self._update)
    self.counter += 1


    if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    thisapp = App()
    thisapp.show()
    sys.exit(app.exec_())

    关于matplotlib - Matplotlib/PyPlot 中的快速实时绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40126176/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com