Scrolling Plots - Real Time Plot Updates How To?

811 views
Skip to first unread message

Kaisar Khatak

unread,
May 17, 2018, 2:39:43 AM5/17/18
to pyqtgraph
I have a real time application that uses a camera to measure eye aspect ratio. The ratio will be an integer value and will fluctuate between 1-10 (example).

What is the easiest way to capture that value and display a scrolling plot (best approach?) real time? Do I need threading? Just looking for simplest solution to start off with...

I have read the scrollingPlots.py examples...

I have installled pyqtgraph and am running python 2/3 on ubuntu 16.


Thanks.

----------------------------------------------------------------------------
# -*- coding: utf-8 -*-
"""
Various methods of drawing scrolling plots.
"""
import initExample ## Add path to library (just for examples; you do not need this)

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np

win = pg.GraphicsLayoutWidget(show=True)
win.setWindowTitle('pyqtgraph example: Scrolling Plots')


# 1) Simplest approach -- update data in the array such that plot appears to scroll
#    In these examples, the array size is fixed.
p1 = win.addPlot()
p2 = win.addPlot()
data1 = np.random.normal(size=300)
curve1 = p1.plot(data1)
curve2 = p2.plot(data1)
ptr1 = 0
def update1():
    global data1, ptr1
    data1[:-1] = data1[1:]  # shift data in the array one sample left
                            # (see also: np.roll)
    data1[-1] = np.random.normal()
    curve1.setData(data1)
    
    ptr1 += 1
    curve2.setData(data1)
    curve2.setPos(ptr1, 0)
    

# 2) Allow data to accumulate. In these examples, the array doubles in length
#    whenever it is full. 
win.nextRow()
p3 = win.addPlot()
p4 = win.addPlot()
# Use automatic downsampling and clipping to reduce the drawing load
p3.setDownsampling(mode='peak')
p4.setDownsampling(mode='peak')
p3.setClipToView(True)
p4.setClipToView(True)
p3.setRange(xRange=[-100, 0])
p3.setLimits(xMax=0)
curve3 = p3.plot()
curve4 = p4.plot()

data3 = np.empty(100)
ptr3 = 0

def update2():
    global data3, ptr3
    data3[ptr3] = np.random.normal()
    ptr3 += 1
    if ptr3 >= data3.shape[0]:
        tmp = data3
        data3 = np.empty(data3.shape[0] * 2)
        data3[:tmp.shape[0]] = tmp
    curve3.setData(data3[:ptr3])
    curve3.setPos(-ptr3, 0)
    curve4.setData(data3[:ptr3])


# 3) Plot in chunks, adding one new plot curve for every 100 samples
chunkSize = 100
# Remove chunks after we have 10
maxChunks = 10
startTime = pg.ptime.time()
win.nextRow()
p5 = win.addPlot(colspan=2)
p5.setLabel('bottom', 'Time', 's')
p5.setXRange(-10, 0)
curves = []
data5 = np.empty((chunkSize+1,2))
ptr5 = 0

def update3():
    global p5, data5, ptr5, curves
    now = pg.ptime.time()
    for c in curves:
        c.setPos(-(now-startTime), 0)
    
    i = ptr5 % chunkSize
    if i == 0:
        curve = p5.plot()
        curves.append(curve)
        last = data5[-1]
        data5 = np.empty((chunkSize+1,2))        
        data5[0] = last
        while len(curves) > maxChunks:
            c = curves.pop(0)
            p5.removeItem(c)
    else:
        curve = curves[-1]
    data5[i+1,0] = now - startTime
    data5[i+1,1] = np.random.normal()
    curve.setData(x=data5[:i+2, 0], y=data5[:i+2, 1])
    ptr5 += 1


# update all plots
def update():
    update1()
    update2()
    update3()
timer = pg.QtCore.QTimer()
timer.timeout.connect(update)
timer.start(50)



## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

Robert Budzyński

unread,
May 17, 2018, 7:25:48 AM5/17/18
to pyqtgraph
I think threading would complicate things a lot. What is the rate of data acquisition (values per second)? I am able to simulate a few hundred particles bouncing around on a region of the plane at 25 fps, with no threading. So if you don't need to do any complicated processing on your data, threading would probably be superfluous.

Luke Campagnola

unread,
May 17, 2018, 12:52:11 PM5/17/18
to pyqt...@googlegroups.com
My suggestion would have been to look at the scrolling plot examples, but you have already done that. Have you tried using any of those? If so, why didn't they work for you?

--
You received this message because you are subscribed to the Google Groups "pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/2ca21aaa-92a5-48eb-a3c9-7c5490032a24%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kaisar Khatak

unread,
May 17, 2018, 6:08:14 PM5/17/18
to pyqtgraph
Thank you for responding. The capture rate will match the frame rate and processing. So, I expect there to be 25-30 (frame rate) values per second. Its a very simple python app. I do not think I even need to date/time variable on the second (x) axis - maybe a nice to have. I just want to show eye aspect ratio (fluctuations) on the y axis over time (e.g. 60 second demo). I can do this in matplotlib, but the graphs don't look as cool as pyqtgraph.

Kaisar Khatak

unread,
May 17, 2018, 6:33:19 PM5/17/18
to pyqtgraph
Thank you for responding. I am a noob to pyqtgraph.

The capture rate will match the frame rate and processing. So, I expect there to be 25-30 (frame rate) values per second. Its a very simple python app. I do not think I even need  date/time variable on the second (x) axis - maybe a nice to have. I just want to show eye aspect ratio (fluctuations) on the y axis over time (e.g. 60 second demo). I can do this in matplotlib, but the graphs don't look as cool as pyqtgraph. 

I have attached a similar style script which captures yawns (e.g. lip_distance). So, in this case, I want to store lip_distance into an array and while program writes/appends/extends to this lip_distance [] array, I want the plot to show the new values as they are captured. Has anyone built something similar? I saw a few posts in this group around scrolling plots.

So, is scrolling plots the recommended route?  Or is there another python visualization tool that can solve this?
yawn-counter.py

Patrick

unread,
May 17, 2018, 10:14:41 PM5/17/18
to pyqtgraph
Hi,

If you already have your camera/processing etc working as a standalone module with its own acquisition thread, then it might be easy enough just to use one of the scrolling plot examples above. Get your acquisition thread to store the data (say, in a circular buffer or expanding array). On the QTimer update from the scrolling plot examples, reach into the buffer to and curve.setData(). Just ensure you make it threadsafe, for example by surrounding any reads or writes to the buffer with locks.

Patrick
Reply all
Reply to author
Forward
0 new messages