首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用pyqtgraph图绘制大数组

用pyqtgraph图绘制大数组
EN

Stack Overflow用户
提问于 2013-06-14 07:54:38
回答 1查看 17.2K关注 0票数 16

对于电生理学数据分析集,我需要绘制一个大的2D阵列(约20.000 x 120)的点。我过去常常在我的PyQt应用程序中嵌入Matplotlib小部件,但是因为绘图花费了相当长的时间,所以我去寻找其他解决方案。尽管如此,用pyqtgraph绘制数据也比预期的要花费更长的时间,这可能是因为每次使用plot()函数时都会重新绘制小部件。

什么是绘制大数组的最佳实践?

比格图的例子,虽然很广泛,但对我没有多大帮助.

代码语言:javascript
复制
import pyqtgraph as pg
view = pg.GraphicsLayoutWidget()
w1 = view.addPlot()

for n in data:
    w1.plot(n)

代码语言:javascript
复制
w1.plot(data)

最后一条规则生成ValueError:操作数不能与形状(10)一起广播(10,120)

提前谢谢..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-14 12:25:22

参见下面的讨论:https://groups.google.com/forum/?fromgroups#!searchin/pyqtgraph/arraytoqpath/pyqtgraph/CBLmhlKWnfo/jinNoI07OqkJ

Pyqtgraph不会在每次调用plot()之后重新绘制;它将等到控件返回到Qt事件循环后才重新绘制。但是,您的代码可能会通过调用QApplication.processEvents()来强制更频繁地访问事件循环(例如,如果您有进度对话框,这可能是间接发生的)。

通常,提高性能的最重要规则是:分析代码。如果你能直接测量的话,不要假设什么会拖慢你的速度。

由于我没有访问您的代码的权限,所以我只能猜测如何改进它,并向您展示剖析如何帮助您。我将从这里的“慢”例子开始,并通过一些改进。

1.缓慢实现

代码语言:javascript
复制
import pyqtgraph as pg
import numpy as np
app = pg.mkQApp()
data = np.random.normal(size=(120,20000), scale=0.2) + \
       np.arange(120)[:,np.newaxis]
view = pg.GraphicsLayoutWidget()
view.show()
w1 = view.addPlot()
now = pg.ptime.time()
for n in data:
    w1.plot(n)
print "Plot time: %0.2f sec" % (pg.ptime.time()-now)
app.exec_()

这方面的产出如下:

代码语言:javascript
复制
Plot time: 6.10 sec

现在让我们来分析一下:

代码语言:javascript
复制
$ python -m cProfile -s cumulative speed_test.py
. . .
     ncalls  tottime  percall  cumtime  percall filename:lineno(function)
          1    0.001    0.001   11.705   11.705 speed_test.py:1(<module>)
        120    0.002    0.000    8.973    0.075 PlotItem.py:614(plot)
        120    0.011    0.000    8.521    0.071 PlotItem.py:500(addItem) 
    363/362    0.030    0.000    7.982    0.022 ViewBox.py:559(updateAutoRange)
. . .

我们已经看到ViewBox.updateAutoRange花费了很多时间,所以让我们禁用自动测距:

2.更快一点的

代码语言:javascript
复制
import pyqtgraph as pg
import numpy as np
app = pg.mkQApp()
data = np.random.normal(size=(120,20000), scale=0.2) + \
       np.arange(120)[:,np.newaxis]
view = pg.GraphicsLayoutWidget()
view.show()
w1 = view.addPlot()
w1.disableAutoRange()
now = pg.ptime.time()
for n in data:
    w1.plot(n)
w1.autoRange() # only after plots are added
print "Plot time: %0.2f sec" % (pg.ptime.time()-now)
app.exec_()

..and输出是:

代码语言:javascript
复制
Plot time: 0.68 sec

这有点快,但是平移/缩放情节还是很慢的。如果我在拖了一段时间后查看配置文件,它如下所示:

代码语言:javascript
复制
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.034    0.034   16.627   16.627 speed_test.py:1(<module>)
        1    1.575    1.575   11.627   11.627 {built-in method exec_}
       20    0.000    0.000    7.426    0.371 GraphicsView.py:147(paintEvent)
       20    0.124    0.006    7.425    0.371 {paintEvent}
     2145    0.076    0.000    6.996    0.003 PlotCurveItem.py:369(paint)

因此,我们看到了很多对PlotCurveItem.paint()的调用。如果我们将所有120条绘图行放在一个项目中,以减少调用油漆的次数,该怎么办?

3.快速实现

经过几轮的分析,我想出了这个。它基于使用pg.arrayToQPath,如上面的线程中所建议的那样:

代码语言:javascript
复制
import pyqtgraph as pg
import numpy as np
app = pg.mkQApp()

y = np.random.normal(size=(120,20000), scale=0.2) + np.arange(120)[:,np.newaxis]
x = np.empty((120,20000))
x[:] = np.arange(20000)[np.newaxis,:]
view = pg.GraphicsLayoutWidget()
view.show()
w1 = view.addPlot()

class MultiLine(pg.QtGui.QGraphicsPathItem):
    def __init__(self, x, y):
        """x and y are 2D arrays of shape (Nplots, Nsamples)"""
        connect = np.ones(x.shape, dtype=bool)
        connect[:,-1] = 0 # don't draw the segment between each trace
        self.path = pg.arrayToQPath(x.flatten(), y.flatten(), connect.flatten())
        pg.QtGui.QGraphicsPathItem.__init__(self, self.path)
        self.setPen(pg.mkPen('w'))
    def shape(self): # override because QGraphicsPathItem.shape is too expensive.
        return pg.QtGui.QGraphicsItem.shape(self)
    def boundingRect(self):
        return self.path.boundingRect()

now = pg.ptime.time()
lines = MultiLine(x, y)
w1.addItem(lines)
print "Plot time: %0.2f sec" % (pg.ptime.time()-now)

app.exec_()

它快速启动,摇摄/缩放是合理的响应。不过,我要强调的是,这个解决方案是否适用于您,很可能取决于您的程序的细节。

票数 44
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17103698

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档