重新采样滚动绘图实时数据以仅显示实际可见的点以提高性能(PyQtGraph)

Resample Scrolling Plot Live Data to show only actually visible points to increase performance (PyQtGraph)

我有一个正在阅读的设备。目前它只是实现 GUI 的测试设备 (PyQT/PySide2)。我正在使用 PyQtGraph 来显示绘图。

这是更新函数(为了更好的可读性进行了简化):

def update(self, line):
    self.data_segment[self.ptr] = line[1] # gets new line from a Plot-Manager which updates all plots
    self.ptr += 1 # counts the amount of samples
    self.line_plot.setData(self.data_segment[:self.ptr]) # displays all read samples
    self.line_plot.setPos(-self.ptr, 0) # shifts the plot to the left so it scrolls

我有一个算法可以删除数组的前 x 个值并将它们保存到一个临时文件中。当前可用数据的最大值为 100 k。如果用户放大后只看到一部分剧情,没有问题,没有滞后情节

但是显示的点越多(x 范围越大)它就越滞后,滞后图

特别是当我将滚动图的宽度设置为 < 1 时,它开始滞后得更快。请注意,这只是一个测试图,实际图会更复杂,但峰值也很重要,因此丢失数据至关重要。

我需要一种算法,可以在不丢失信息或几乎不丢失信息的情况下对数据进行重新采样,并且只显示可见点,而不是计算 100k 点,这些点无论如何都不可见并且会浪费性能而没有任何收获。

这对我来说似乎是一个基本问题,但我似乎无法以某种方式找到解决方案...我对信号处理的了解非常有限,这就是为什么我可能无法在网络。我什至可能采取错误的方法来解决这个问题。

编辑 这就是我所说的 "invisible points"

隐形点

作为对您正在做的事情的简单修改,您可以尝试这样的事情:

def update(self, line):

    # Get new data and update the counter
    self.data_segment[self.ptr] = line[1]
    self.ptr += 1

    # Update the graph to show the last 256 samples
    n = min( 256, len(self.data_segment) )
    self.line_plot.setData(self.data_segment[-n:])

对于数据的显式下采样,您可以试试这个

resampled_data = scipy.signal.resample( data, NumberOfPixels )

或对最近的一组 N 个点进行下采样,

n = min( N, len(self.data_segment) )
newdata = scipy.signal.resample( self.data_segment[-n:], NumberOfPixels )
self.line_plot.setData(newdata)

但是,一个好的图形引擎应该会自动为您执行此操作。

重采样或下采样的一个警告是,原始数据不包含在重采样或下采样后对于新比例来说太快的比例的信息或特征。如果是,那么这些特征将 运行 在一起,你会得到看起来像你的第二张图的东西。

关于编码信号采集、处理和显示的一些一般性评论

此时提供一些关于使用和显示信号的一般性评论似乎很有用。

在任何信号采集、处理和显示编码任务中,架构师或编码人员(有时默认)应该了解 (a) 数据所代表的某些物理现象,(b) 如何使用这些信息,以及 (c) 测量、信号处理和显示系统的物理特性(c.f、带宽、采样率、动态范围、噪声特性、混叠、像素化效应等)。

这是一个很大的主题,通常在任何一本教科书中都不会完整描述。似乎需要一些经验才能将它们整合在一起。此外,在我看来,如果您对测量的理解不够深入,无法自己编写代码,那么您也不太了解如何使用或依赖固定例程。换句话说,理解是无可替代的,固定例程应该只是一种方便而不是拐杖。即使对于上面建议的重采样算法,我也鼓励其用户了解它的工作原理以及它如何影响他们的信号。

在这个特定的示例中,我们了解到应用程序是心电图,未指定类型,并且留给编码人员很大的自由度。作为编码员,我们应该尝试了解这些类型的测量(c.f。一般心脏和电、声和超声心动图)以及它们是如何执行和使用的,并尝试找到一些示例。

P/S 对于任何使用数字滤波器的人来说,如果您还没有正式研究过该主题,阅读 Hamming 的书 "Digital Filters" 可能会有用。它作为 Dover 书籍出售,价格实惠。

Pyqtgraph 实现了下采样:

self.line_plot.setDownsampling(auto=True, method='peak')

根据您创建线条的方式,您可能不得不使用

self.line_plot.setDownsampling(auto=True, mode='peak')

还有其他 methods/modes 个可用。

持续移动显示的 XRange 也会减慢绘图速度(以及 UI 的反应性)。在这种情况下,只需每隔 x 毫秒或样本更新位置即可。这也对地块的更新很重要。

我使用 pyqtgraph 绘制来自三个振动传感器的实时数据,采样率为 12800 kSamples/second。对于该图,我查看了每个传感器 10 秒的时间 window(因此总共有 384000 个样本)。显示的时间包括读取数据、绘制数据并定期计算和绘制 FFT、写入数据库等。对于 "no downsampling" 部分,我关闭了三个图中之一的下采样。 它足够快,我没有为多线程或类似的东西而烦恼。