Updating graphs at different intervals; PyQtGraph only updates as fast as the slowest update

1,409 views
Skip to first unread message

Isai Olvera

unread,
Jul 24, 2015, 7:50:44 PM7/24/15
to pyqtgraph
Hi,

I have 2 different graphs updating, and I'm trying to have them update at different speeds, but they seem to only update as fast as the slowest.

In the following example, I have 2 functions which spit data to individual data queues, and then the GUI update functions (called from timers) pull data from the queue and plot.

If I comment out line 43, they both update really quickly.

If I leave in line 43 which puts a sleep function in one of the data generation functions, the graphs update in sync, as opposed to one updating quickly and the other updating every 1s.

Any ideas?

Thanks!









import time


from pyqtgraph.Qt import QtGui, QtCore


import pyqtgraph as pg


from Queue import Queue


from random import randint


from threading import Thread






app = QtGui.QApplication([])  # GUI application load


x_axis_min_range = 0


x_axis_max_range = 6




y_axis_min_range = 0


y_axis_max_range = 100






win2 = pg.GraphicsWindow(title="Test Plots")


win2.resize(1024, 768)


pg.setConfigOptions(antialias=True)




p1 = win2.addPlot(title="Plot 1")


p1curve = p1.plot(pen=(255, 0, 0))


p1.showGrid(x=True, y=True)


p1.setYRange(y_axis_min_range, y_axis_max_range)


p1.setXRange(x_axis_min_range, x_axis_max_range)




p2 = win2.addPlot(title="Plot 2")


p2curve = p2.plot(pen=(0, 255, 0))


p2.showGrid(x=True, y=True)


p2.setYRange(y_axis_min_range, y_axis_max_range)


p2.setXRange(x_axis_min_range, x_axis_max_range)




q1 = Queue(maxsize=0)


q2 = Queue(maxsize=0)




def fxn1():


        global q1


        while True:


                y = []


                for loop in range(0, 5):


                        temp = randint(0, 100)


                        y.append(temp)


        # time.sleep(1)


                q1.put(y)




def fxn2():


        global q2


        while True:


                y = []


                for loop in range(0, 5):


                        temp = randint(0, 100)


                        y.append(temp)


                q2.put(y)






def update_gui():


        global p1curve, q1


        x = [1,2,3,4,5]


        y = q1.get()


        p1curve.setData(x, y)


        # q1.task_done()  # this is important for q


        app.processEvents()




def update_gui1():


        global p2curve, q2


        x = [1,2,3,4,5]


        y = q2.get()


        p2curve.setData(x, y)


        # q2.task_done()


        app.processEvents()




worker1 = Thread(target=fxn1, args=())


worker1.setDaemon(True)


worker1.start()






worker2 = Thread(target=fxn2, args=())


worker2.setDaemon(True)


worker2.start()






timer = QtCore.QTimer()


timer.timeout.connect(update_gui)


timer.start(1)




timer1 = QtCore.QTimer()


timer1.timeout.connect(update_gui1)


timer1.start(1)




# For GUI/thread joining


app.exec_()




# Needed for PyQT graphing/active GUI


if __name__ == '__main__':


        import sys


        if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):


                QtGui.QApplication.instance().exec_()



Scratch_Code.py

Mike

unread,
Jul 25, 2015, 6:26:38 AM7/25/15
to pyqtgraph
Hi Isai,

I am not an expert on this, but I would have suggested using QThreads rather than the Python threading module. Python threads do not run concurrently (because of the GIL), but QThreads do. You can then connect these threads to the main GUI thread using signals and slots, which will update your graph more often if one thread gets data quicker than the other.

Cheers
Michael

Mike

unread,
Jul 26, 2015, 6:20:26 AM7/26/15
to pyqtgraph, mrol...@gmail.com
Hi Isai,

Here is some code using QThreads to do what you are trying to do. It is based on code from another post and doesn't use queues, but it does update one plot faster than the other. It is not perfect, but I hope that it helps.

import time
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
from random import randint

def update_plot1(y):
    global p1curve,x1   
    p1curve.setData(x1,y)
    
def update_plot2(y):
    global p2curve,x2   
    p2curve.setData(x2,y)

class UpdatePlotThread(QtCore.QThread):

    newData = pg.QtCore.Signal(object)
    
    def __init__(self,sizey=100,rangey=[0,100],delay=1.0):
        QtCore.QThread.__init__(self)
        self.sizey  = sizey
        self.rangey = rangey
        self.delay  = delay
        self.y = [0 for i in range(sizey)]
        
    def __del__(self):
        self.wait()
        
    def run(self):
        while True:
            for i in range(self.sizey):
                self.y[i] = randint(*self.rangey)
            self.newData.emit(self.y)
            time.sleep(self.delay)     
    
app = QtGui.QApplication([])
x_axis_min_range = 0
x_axis_max_range = 100

y_axis_min_range = 0
y_axis_max_range = 100

win2 = pg.GraphicsWindow(title="Test Plots")
win2.resize(640, 480)
pg.setConfigOptions(antialias=True)

p1 = win2.addPlot(title="Plot 1")
p1curve = p1.plot(pen=(255, 0, 0))
p1.showGrid(x=True, y=True)
p1.setYRange(y_axis_min_range, y_axis_max_range)
p1.setXRange(x_axis_min_range, x_axis_max_range)

p2 = win2.addPlot(title="Plot 2")
p2curve = p2.plot(pen=(0, 255, 0))
p2.showGrid(x=True, y=True)
p2.setYRange(y_axis_min_range, y_axis_max_range)
p2.setXRange(x_axis_min_range, x_axis_max_range)

x1 = range(1,101)
thread1 = UpdatePlotThread(len(x1),[0,100],1.0)
thread1.newData.connect(update_plot1)
thread1.start()

x2 = range(1,101)
thread2 = UpdatePlotThread(len(x2),[0,100],0.01)
thread2.newData.connect(update_plot2)
thread2.start()

# Needed for PyQT graphing/active GUI
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

Cheers,
Michael

Chris O'Halloran

unread,
Jul 26, 2015, 7:51:18 PM7/26/15
to pyqtgraph, michael.chri...@gmail.com
If you are going to use QThreads, can I suggest reading the following.

https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Subclassing QThread is not, in some peoples opinions, is not actually the correct way to go.

The 'correct' way is to create a worker object. Create a thread, and move the worker object to the thread, start the thread and then using signals and slots let the worker emit a signal when it is finished and then return the result.





Michael Hogg

unread,
Jul 26, 2015, 8:04:20 PM7/26/15
to Chris O'Halloran, pyqtgraph
Chris,

Yes, I have read these posts and many other reports on the best way to use QThreads. There are so many conflicting views that I am not sure who is actually correct.

Michael

Chris O'Halloran

unread,
Jul 26, 2015, 8:17:09 PM7/26/15
to Michael Hogg, pyqtgraph
That's cool. Just thought I'd mention it in case it was helpful.

Cheers

Chris
Reply all
Reply to author
Forward
0 new messages