Python - Fast ploting using pyqtgraph (16ms)?

后端 未结 1 653
不知归路
不知归路 2021-01-22 18:58

I need to plot an continuous input using pyqtgraph, so I use a circular buffer to hold the data. I use deque with maxlen to do the job. (Python 2.7, numpy 1.9.2, pyqtgraph 0.9.1

1条回答
  •  迷失自我
    2021-01-22 19:33

    I'm not sure this is a complete answer, but the information is too long to turn into a comment, and I think it is critical for your understanding of the problem.

    I think it is very unlikely you will get your timer to fire every 16 ms. Firstly, if your methods self.update_cbuffer and self.update_plots take longer than 16 ms to run, then the QTimer will skip firing when it should, and fire on the next multiple of 16 ms (eg if the methods take 31 ms to run, your timer should fire after 32 ms. If the methods then take 33 ms to run, the timer will next fire 48 ms after the previous one)

    Furthermore, the accuracy of the timer is platform dependent. On windows, timers are only accurate to around 15 ms. As proof of this, I wrote a script to test on my windows 8.1 machine (code included at the end of the post). This graph shows the deviation from the expected timeout in ms.error in timeout trigger

    In this case, my example was firing around 12ms early. Note that this isn't quite correct, as I don't think my code takes into account the length of time it takes to append the error to the list of errors. However, that time should be much less than the offset you see in my figure, nor does it account for the large spread of values. In short, timers on windows have an accuracy around the size of your timeout. Not a good combination.

    Hopefully this at least explains why the code isn't doing what you expect. Without a minimilistic working example though, or comprehensive profiling of the code by yourself, it is difficult to know where the bottleneck in speed is.

    As a small aside, pyqtgraph seemed to stop updating my histogram after a while when the timeout in my code below was very small. Not sure why that was.

    Code to produce the above figure

    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_())
    

    0 讨论(0)
提交回复
热议问题