使用PyQtGraph读取实时数据而不附加数据

时间:2016-05-06 19:15:25

标签: python serial-port pyqtgraph

我正在尝试使用PyQtgraph绘制实时数据,我开始学习。我在这里阅读了很多帖子,例如:

Fast plotting using pyqtgraph

并在互联网上搜索文档。我遇到的问题是绘制数据时绘图非常慢。这是因为,当数据来自串口时,我将它附加到列表中,然后我从该列表中取出并绘制它。因此,即使关闭了数据来源的设备,该图也会继续绘制。

这是我的代码:

class LivePlot(QtGui.QApplication):
  def __init__(self, *args, **kwargs):
    super(MyApplication, self).__init__(*args, **kwargs)
    self.t = QTime()
    self.t.start()

    self.data = deque()
    self.plot = self.win.addPlot(title='Timed data') 
    self.curve = self.plot.plot()

    print "Opening port"
    self.raw=serial.Serial("com4",115200)
    print "Port is open"

    self.tmr = QTimer()
    self.tmr.timeout.connect(self.update)
    self.tmr.start(100)

    self.cnt = 0

  def update(self):
    line = self.raw.read()
    ardString = map(ord, line)
    for number in ardString:
        numb = float(number/77.57)
        self.cnt += 1
        x = self.cnt/2

        self.data.append({'x': x , 'y': numb})  
        x = [item['x'] for item in self.data]
        y = [item['y'] for item in self.data]
        self.curve.setData(x=x, y=y)

那么,如何在不将其附加到列表的情况下绘制数据呢?我是这个图书馆的新手,所以我很困惑。希望你能帮帮我。

----编辑----

我在代码中尝试了这个修改:

class LivePlot(QtGui.QApplication):
  def __init__(self, *args, **kwargs):
    super(MyApplication, self).__init__(*args, **kwargs)
   self.cnt = 0
 #Added this new lists
   self.xData = []
   self.yData = []

  def update(self):
    line = self.raw.read()
    ardString = map(ord, line)
    for number in ardString:
        numb = float(number/77.57)
        self.cnt += 1
        x = self.cnt/2

        self.data.append({'x': x , 'y': numb}) 
        self.xData.append(x)
        self.yData.append(numb) 

    self.curve.setData(x=self.xData, y=self.yData)

但我遇到了同样的问题。

1 个答案:

答案 0 :(得分:0)

对于您从设备中读取的每个号码,您将从头开始重新创建xy数组。这意味着,如果您有1000个数据点,您将通过1000个元素的列表行走1000次,这相当于一百万步。可以想象,这并不能很好地扩展。您的执行时间会增加n^2因子,其中n是您衡量的点数。 Google '计算复杂性' &#O;大O符号' 并阅读相关内容。

附加到Python列表(或deque)的速度很快,所花费的时间并不取决于列表中元素的数量(请注意,为了附加到Numpy数组,这为True )。如果您创建self.xDataself.yData列表然后将数据附加到这些列表,则可以摆脱内部循环:

def update(self):
    line = self.raw.read()
    ardString = map(ord, line)
    for number in ardString:
        numb = float(number/77.57)
        self.cnt += 1
        x = self.cnt/2

        # Appending goes in constant time 
        self.data.append({'x': x , 'y': numb})  
        self.xData.append(x) # self.xData should be a list or deque
        self.yData.append(x) # self.yData should be a list or deque

    # Drawing the plot is now only performed once per update
    self.curve.setData(x=x, y=y)

此外,重新绘制setData中发生的绘图是一项昂贵的操作,您可以在读取每个数据点后执行此操作。更好的解决方案是每次更新只更新一次。请参阅上面的示例。这仍然是十秒钟(至少,如果您的绘图可以跟上数据)。

作为最后一句话,与硬件的沟通是一个棘手的主题,你的第一次尝试无疑将是不稳定的,充满了错误。如果你这是一个爱好项目,那么这是一个很好的学习机会。如果您在专业环境中这样做,请尝试找一位导师。