pyqtgraph

时间:2017-09-13 20:27:12

标签: python performance pyqt pyqtgraph

我试图将一些代码从使用matplotlib转换为pyqtgraph,因为它应该更高效,并且它提供了更多的交互功能。我已经将代码转换为大部分,但我遇到的问题是它运行缓慢。一些代码重现了这一点:

import numpy as np
import qtpy.QtWidgets as qt
import pyqtgraph as pg


class GraphWidget(qt.QWidget):
    """A widget for simplifying graphing tasks

    :param qt.QWidget parent:
    :param Dict[str, dict] layout: A mapping from title to row/col/rowspan/colspan kwargs
    """
    def __init__(self, parent, layout_spec):
        super(GraphWidget, self).__init__(parent=parent)

        self.axes = {}
        glw = pg.GraphicsLayoutWidget(parent=self)
        for name, layout in layout_spec.items():
            self.axes[name] = pg.PlotItem(name=name, title=name)
            glw.addItem(self.axes[name], **layout)
        box_layout = qt.QVBoxLayout()
        box_layout.addWidget(glw, 1)
        self.setLayout(box_layout)

    @property
    def normal_pen(self):
        return pg.mkPen(color='w', width=2)

    @property
    def good_pen(self):
        return pg.mkPen(color='g', width=2)

    @property
    def bad_pen(self):
        return pg.mkPen(color='r', width=2)

    def plot(self, mode, x, y, axis):
        if mode == 'normal':
            pen = self.normal_pen
        elif mode == 'good':
            pen = self.good_pen
        elif mode == 'bad':
            pen = self.bad_pen

        plot_item = pg.PlotCurveItem(x, y, pen=pen)
        self.axes[axis].addItem(plot_item)


if __name__ == '__main__':
    import random
    import time

    # qt.QApplication.setGraphicsSystem('opengl')

    app = qt.QApplication([])
    window = qt.QWidget(parent=None)
    layout = qt.QVBoxLayout()

    gw = GraphWidget(
        window,
        {
            'A': dict(row=1, col=1, rowspan=2),
            'B': dict(row=1, col=2),
            'C': dict(row=2, col=2),
            'D': dict(row=1, col=3),
            'E': dict(row=2, col=3),
            'F': dict(row=1, col=4),
            'G': dict(row=2, col=4),
        }
    )
    layout.addWidget(gw, 1)

    def plot():
        start = time.time()
        for axis in 'ABCDEFG':
            gw.plot(
                random.choice(['normal', 'good', 'bad']),
                np.arange(2000),
                np.random.rand(2000),
                axis,
            )
        # necessary because without it, the "plotting" completes in ms, 
        # but the UI doesn't update for a while still
        app.processEvents()
        print('Plotting time: {}'.format(time.time() - start))

    button = qt.QPushButton(parent=window, text='Plot')
    button.pressed.connect(plot)
    layout.addWidget(button)

    window.setLayout(layout)
    window.showMaximized()
    app.exec_()

选择绘图的数量和布局以及点数来反映我的实际用例。如果我按原样运行并单击两次绘图按钮,我会看到

Plotting time: 3.61599993706
Plotting time: 7.04699993134

我此时停止了,因为一般来说应用程序突然非常缓慢,需要几秒才能关闭。如果我取消注释一行以启用opengl渲染,我可以轻松地运行它多次看起来像

Plotting time: 0.0520000457764
Plotting time: 0.328999996185
Plotting time: 0.453000068665
Plotting time: 0.55999994278
Plotting time: 0.674000024796
Plotting time: 1.21900010109
Plotting time: 0.936000108719
Plotting time: 1.06100010872
Plotting time: 1.19899988174
Plotting time: 1.35100007057

此时我还可以说这里报告的时间并不准确,UI需要比这些时间更长的时间来实际反映更新。

这是一个相当典型的图表,我能够处理,这个应用程序可以在大约20秒内轻松看到16组图表(每轴额外一行)。如果我的用户界面逐渐变慢,那就不够快了。

下采样似乎不适用于PlotCurveItem(与PlotDataItem不同),但我确实发现在做

plot_item = pg.PlotCurveItem(x, y, pen=pen, connect='pairs')

导致更快的时间:

Plotting time: 0.0520000457764
Plotting time: 0.0900001525879
Plotting time: 0.138000011444
Plotting time: 0.108000040054
Plotting time: 0.117000102997
Plotting time: 0.12299990654
Plotting time: 0.143000125885
Plotting time: 0.15499997139

这对我来说似乎仍然很慢,我想知道是否有任何可以做的事情来加速它。如果我没有将它设置为opengl,它仍然非常慢(每个绘图大约几秒)。我真的在寻找尽可能快的策划方式。我的目标是每个地块<100毫秒。

很难说实际上减速的位置,分析这段代码似乎很困难,因为有些内容发生在OpenGL级别,有些深入Qt代码,有些则出现在pyqtgraph本身。 / p>

还有其他方法可以进一步加快此代码吗?

注意:我目前正在使用Python 2.7 64bit,PyQt 4.10.4和pyqtgraph 0.10.0通过conda安装,虽然这段代码需要在Python 3.5 +上同样运行。

0 个答案:

没有答案