Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-使用pyqtgraph(16ms)快速绘图?_Python_Python 2.7_Pyqt_Pyqtgraph - Fatal编程技术网

Python-使用pyqtgraph(16ms)快速绘图?

Python-使用pyqtgraph(16ms)快速绘图?,python,python-2.7,pyqt,pyqtgraph,Python,Python 2.7,Pyqt,Pyqtgraph,我需要使用pyqtgraph绘制一个连续的输入,所以我使用一个循环缓冲区来保存数据。我使用deque和maxlen来完成这项工作。(Python 2.7、numpy 1.9.2、pyqtgraph 0.9.10) 之后,我会这样使用它: import time def update_cbuffer(self): data_points, data = data_feeds() # data get every 16ms as lists start_t = time.time(

我需要使用pyqtgraph绘制一个连续的输入,所以我使用一个循环缓冲区来保存数据。我使用deque和maxlen来完成这项工作。(Python 2.7、numpy 1.9.2、pyqtgraph 0.9.10)

之后,我会这样使用它:

import time
def update_cbuffer(self):
    data_points, data = data_feeds()  # data get every 16ms as lists
    start_t = time.time()
    self.cbuffer[0].extend(data_points) # Thanks to @PadraicCunningham
    # for k in xrange(0, self.number_of_points):
    #     self.cbuffer[0].append(data_points[k])
    self.cbuffer[1].append(data)
    fin_t = time.time() - start_t
将绘图设置为:

self.curve[0] = self.plots[0].plot(self.X_AXIS, 
                [0]*self.BUFFER_LEN*self.number_of_points,
                pen=pg.intColor(color_idx_0),name='plot1')
self.curve[1] = self.plots[1].plot(self.X_AXIS_2, [0]*self.BUFFER_LEN,
                pen=pg.intColor(color_idx_1),name='plot2')
将绘图更新为:

def update_plots(self):
    self.curve[0].setData(self.X_AXIS, self.cbuffer[0])
    self.curve[0].setPos(self.ptr, 0)
    self.curve[1].setData(self.X_AXIS_2, self.cbuffer[1])
    self.curve[1].setPos(self.ptr, 0)
    self.ptr += 0.016
然后我用QTimer调用它:

self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.update_cbuffer)
self.timer.timeout.connect(self.update_plots)
self.timer.start(16)
问题是:

1.当我绘制它时,它似乎比16ms慢得多。有没有加快速度的办法?

2.当我使用time.time()对update_plots()计时并计算其平均运行时间(总运行时间/运行次数)时,它会逐渐增加,我试图理解其背后的原因

有什么建议吗?我是Python新手,我可能会在代码中犯一些错误,请毫不犹豫地指出。提前谢谢你的帮助

p、 我已经尝试了中建议的不同循环缓冲区

但事实证明,它的速度要慢得多

我也尝试过这个:

class CB_list():
    def __init__(self, buffer_len):
        self.__buffer = [0]*buffer_len

    def append(self, data):
        self.__buffer = self.__buffer[1:]
        self.__buffer.append(data)

    def get(self):
        return self.__buffer
它的性能与deque类似,因此我坚持使用deque

编辑: 对不起,我昨天犯了一个错误。我已经在代码中更正了它

data = [0]*buffer_len # buffer_len = 16k  <--- Should be 160k instead

data=[0]*buffer#len#buffer#len=16k我不确定这是一个完整的答案,但信息太长,无法转化为注释,我认为这对您理解问题至关重要

我认为你不太可能让计时器每16毫秒触发一次。首先,如果你的方法
self.update\cbuffer
self.update\u plots
运行时间超过16毫秒,那么
QTimer
将在应该触发的时候跳过触发,并在下一个16毫秒的倍数触发(例如,如果方法运行需要31毫秒,则计时器应在32毫秒后启动。如果方法运行需要33毫秒,则计时器将在上一个方法运行48毫秒后启动)

此外,计时器的准确性取决于平台。在windows上,计时器仅适用于平台。为了证明这一点,我编写了一个脚本在我的windows 8.1机器上进行测试(文章末尾包含代码)。此图显示了与预期超时的偏差,单位为毫秒

在本例中,我的示例大约提前12毫秒触发。请注意,这并不完全正确,因为我认为我的代码没有考虑将错误附加到错误列表所需的时间长度。但是,该时间应该远小于您在我的图中看到的偏移量,也没有考虑到值的大范围扩展。简言之,twindows上的IMER在超时大小上有精确性。这不是一个好的组合

希望这至少能解释为什么代码没有达到您期望的效果。但是,如果没有一个最小的工作示例,或者没有自己对代码进行全面的分析,就很难知道速度瓶颈在哪里

顺便说一句,pyqtgraph似乎在我下面的代码超时很小的时候停止了更新我的直方图。不知道为什么

生成上图的代码

from PyQt4 import QtGui, QtCore
import sys
import time
import pyqtgraph as pg
import numpy as np

start_time = time.time()

timeout = 0.16 # this is in SECONDS. Change to vary how often the QTimer fires
time_list = []

def method():
    global start_time
    time_list.append((timeout-(time.time()-start_time))*1000)
    start_time = time.time()

def update_plot():
    y,x = np.histogram(time_list, bins=np.linspace(-15, 15, 40))
    plt1.plot(x, y, stepMode=True, fillLevel=0, brush=(0,0,255,150))

app = QtGui.QApplication(sys.argv)

win = pg.GraphicsWindow()
win.resize(800,350)
win.setWindowTitle('Histogram')
plt1 = win.addPlot()
y,x = np.histogram(time_list, bins=np.linspace(-15, 15, 40))
plt1.plot(x, y, stepMode=True, fillLevel=0, brush=(0,0,255,150))
win.show()

timer = QtCore.QTimer()
timer.timeout.connect(method)
timer.timeout.connect(update_plot)
timer.start(timeout*1000)

sys.exit(app.exec_())

使用xrange而不是range,range会生成一个列表。如果要追加所有
数据
,只需使用
self.cbuffer[0]。扩展(数据)
。如果要追加切片,请使用
self.cbuffer[0]。扩展(itertools.islice(数据,无,self.number of_points))PadraicCunningham,谢谢,我会考虑的。D@PadraicCunningham更新图怎么样方法?这能更有效吗?你能给完整的代码添加一个链接吗?@PadraicCunningham谢谢你的帮助,但我恐怕不能把它们全部链接起来,因为它是在一个专有的代码框架中。我想所有相关的部分都在这里。其他任何东西都不会影响绘图速度。谢谢你对QTimers的解释。在我定时更新之后e_cbuffer()和update_plots(),我发现update_cbuffer()的运行时间不到1ms,而update_plots()则是另一回事。update_plots()的运行时间一直在增加,从13ms开始。因此我认为self.curve[0].setData()可能存在一些问题,尤其是在数据量较大(我的例子是160k)的情况下我怎样才能知道这个问题是从哪里来的?还有其他更快的方法吗?@ CyyZZ你的意思是160K点吗?这是相当多的。考虑到你在屏幕上的分辨率有限,你可以先考虑以保留特征的方式先进行采样(不确定这一定会节省你的时间)。。否则,您可以深入研究PyQtGraph代码,找出花费时间最长的代码(或使用某种分析工具)但我怀疑最慢的部分实际上是在屏幕上绘制所有你无法加速的数据。谢谢你指出,我现在正在做下采样,希望它能加速绘图。@cityzz注意,我不知道如何进行下采样的细节,但根据我的经验,最快的方法是acPython在下采样时通常很慢,如果速度是一个问题,那么你应该把东西放在C代码中(从Python调用)必要时。这当然需要学习C扩展,从C扩展中使用numpy以及如何编译它们,以及实际编写C代码。目前我正在使用numpy数组对其进行下采样,速度似乎很快。_data=_data.reforme(-1,R).mean(axis=1)
data = [0]*buffer_len # buffer_len = 16k  <--- Should be 160k instead
from PyQt4 import QtGui, QtCore
import sys
import time
import pyqtgraph as pg
import numpy as np

start_time = time.time()

timeout = 0.16 # this is in SECONDS. Change to vary how often the QTimer fires
time_list = []

def method():
    global start_time
    time_list.append((timeout-(time.time()-start_time))*1000)
    start_time = time.time()

def update_plot():
    y,x = np.histogram(time_list, bins=np.linspace(-15, 15, 40))
    plt1.plot(x, y, stepMode=True, fillLevel=0, brush=(0,0,255,150))

app = QtGui.QApplication(sys.argv)

win = pg.GraphicsWindow()
win.resize(800,350)
win.setWindowTitle('Histogram')
plt1 = win.addPlot()
y,x = np.histogram(time_list, bins=np.linspace(-15, 15, 40))
plt1.plot(x, y, stepMode=True, fillLevel=0, brush=(0,0,255,150))
win.show()

timer = QtCore.QTimer()
timer.timeout.connect(method)
timer.timeout.connect(update_plot)
timer.start(timeout*1000)

sys.exit(app.exec_())