Xem thảo luận này: https://groups.google.com/forum/?fromgroups#!searchin/pyqtgraph/arraytoqpath/pyqtgraph/CBLmhlKWnfo/jinNoI07OqkJ
Pyqtgraph không vẽ lại sau mỗi cuộc gọi để vẽ(); nó sẽ đợi cho đến khi điều khiển trở lại vòng lặp sự kiện Qt trước khi vẽ lại. Tuy nhiên, có thể mã của bạn buộc vòng lặp sự kiện phải được truy cập thường xuyên hơn bằng cách gọi QApplication.processEvents() (điều này có thể xảy ra gián tiếp, ví dụ: nếu bạn có hộp thoại tiến trình).
Nói chung, quy tắc quan trọng nhất về cải thiện hiệu suất là: cấu hình mã của bạn. Đừng đưa ra giả định về những gì có thể làm chậm bạn nếu bạn có thể đo trực tiếp điều đó.
Vì tôi không có quyền truy cập vào mã của bạn, tôi chỉ có thể đoán cách cải thiện mã và hiển thị cho bạn cách hồ sơ có thể trợ giúp. Tôi sẽ bắt đầu với ví dụ 'chậm' ở đây và làm việc thông qua một vài cải tiến.
1. Việc thực hiện chậm
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_()
Kết quả của việc này là:
Plot time: 6.10 sec
Bây giờ chúng ta hãy cấu hình nó:
$ 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)
. . .
Đã chúng ta có thể thấy rằng ViewBox. updateAutoRange mất nhiều thời gian, vì vậy hãy tắt tính năng tự động:
2. Một chút nhanh hơn
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_()
..và đầu ra là:
Plot time: 0.68 sec
Vì vậy, đó là nhanh hơn một chút, nhưng panning/rộng cốt truyện vẫn còn khá chậm.Nếu tôi xem hồ sơ sau khi kéo ô trong một thời gian, có vẻ như sau:
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)
Vì vậy, chúng tôi thấy nhiều cuộc gọi tới PlotCurveItem.paint(). Điều gì sẽ xảy ra nếu chúng ta đặt tất cả 120 dòng âm mưu vào một mục duy nhất để giảm số lượng cuộc gọi sơn?
3. Việc thực hiện nhanh
Sau một vài vòng hồ sơ, tôi đã đưa ra với điều này. Nó dựa trên việc sử dụng pg.arrayToQPath, như được đề xuất trong chuỗi ở trên:
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_()
Bắt đầu nhanh và mở rộng/thu nhỏ được đáp ứng hợp lý. Tuy nhiên, tôi sẽ nhấn mạnh rằng liệu giải pháp này có hiệu quả cho bạn hay không, bạn sẽ phụ thuộc vào các chi tiết của chương trình của bạn.
Bạn nghĩ thời gian "khá dài" trong bao lâu? Tôi dễ dàng vẽ 20.000 x 120 điểm trong một giây. Đối với một ảnh chụp đó không phải là một vấn đề. Ví dụ, tôi muốn hiển thị một ECG sống 128-dẫn, nó là không đủ. – Micke
Ngay cả khi tôi giảm dữ liệu xuống 200x120 điểm, nó mất 6 giây. Bạn có sử dụng cùng một mã không? –
Cho rằng bạn đã không nói với tôi chính xác những gì 'dữ liệu' có vẻ như tôi không chắc chắn. Tôi đã sử dụng mảng numpy.empty ([120, 20000], dtype = numpy.int16). Có thể đăng mã tối nay. – Micke