이 토론을 참조하십시오 : 모든 호출이 음모 후 https://groups.google.com/forum/?fromgroups#!searchin/pyqtgraph/arraytoqpath/pyqtgraph/CBLmhlKWnfo/jinNoI07OqkJ
Pyqtgraph이 (다시 그리기하지 않습니다) 다시 그리기 전에 컨트롤이 Qt 이벤트 루프로 반환 될 때까지 기다립니다. 그러나 QApplication.processEvents()를 호출하여 코드가 이벤트 루프를 더 자주 방문하도록 할 수 있습니다 (예 : 진행 대화 상자가있는 경우 등 간접적으로 발생할 수 있음).
일반적으로 성능 향상에 대한 가장 중요한 규칙은 프로필 코드입니다. 직접 측정 할 수있는 경우 무엇이 당신을 둔화 시킬지에 대한 가정을하지 마십시오.
코드에 액세스 할 수 없기 때문에이를 개선하고 프로파일 링이 어떻게 도움이되는지 보여줄 수 있습니다. 여기서 '느린'예제로 시작하여 몇 가지 개선을 통해 작업하겠습니다.
1. 느린 구현
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_()
이의 출력은 다음과 같습니다
Plot time: 6.10 sec
지금의이 프로필 보자
$ 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)
. . .
이미 우리가 뷰 박스 것을 볼 수 있습니다. updateAutoRange는 많은 시간을 필요로하므로 자동 범위 지정을 비활성화하십시오.
2. 비트 빠른
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_()
.. 그리고 출력은 다음과 같습니다
Plot time: 0.68 sec
은 그래서 조금 더 빨리,하지만 패닝/플롯을 확장하는 것은 여전히 매우 느립니다.나는 잠시 동안 플롯을 드래그 한 후 프로파일을 보면, 그것은 다음과 같습니다
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를 사용하여 기반으로 :
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_()
그것은 빨리 시작하고 패닝/스케일링 합리적으로 반응한다. 하지만이 솔루션이 당신에게 효과가 있는지 여부는 프로그램의 세부 사항에 달려 있다고 강조 할 것입니다.
"꽤 오래"이라고 생각하십니까? 저는 쉽게 초당 20.000 x 120 포인트를 그립니다. 문제가되지 않는 스냅 샷의 경우. 예를 들어 128 리드 라이브 ECG를 보여주고 싶다면 충분하지 않습니다. – Micke
데이터를 200x120 포인트로 축소해도 6 초가 소요됩니다. 같은 코드를 사용합니까? –
정확히 '데이터'가 어떤 것인지 정확히 알려주지 않았다면 확실하지 않습니다. numpy.empty ([120, 20000], dtype = numpy.int16) 배열을 사용했습니다. 오늘 밤에 코드를 게시 할 수 있습니다. – Micke