02 September 2019

Realtime plotting in Python

If you intend to create plots/graphs with Python, your first choice may be Matplotlib. Don't use it unless your plots are extremely simple and isn't expected to grow more demanding with time. I used Matplotlib for realtime graph plotting for a really tiny graph and it was disappointingly slow.

Then I came across PyQtGraph, and was impressed by the super-fast plotting speed and the mind-blowingly impressive variety of graphing functionality. Really. You gotta see this.

Install it using: pip install pyqtgraph
Run the examples with: python3 -m pyqtgraph.examples
And prepare to be impressed!!!

I've come to understand that the rendering is quick because the underlying code is in C/C++ and the Python bindings are merely meant for invoking that code.

Still, even though the graphs are very impressive, the non-linearity of the code examples and the lack of code comments make it really hard for a newbie to understand how to get a basic graph running.

Here's where I help. After spending an extraordinarily long time figuring it out on my own, I've created a simple, basic example with which you can create a realtime graph. Hope it helps...

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

class Graph:
    def __init__(self, ):
        self.dat = deque()
        self.maxLen = 50#max number of data points to show on graph
        self.app = QtGui.QApplication([])
        self.win = pg.GraphicsWindow()
        self.p1 = self.win.addPlot(colspan=2)
        self.p2 = self.win.addPlot(colspan=2)
        self.p3 = self.win.addPlot(colspan=2)
        self.curve1 = self.p1.plot()
        self.curve2 = self.p2.plot()
        self.curve3 = self.p3.plot()
        graphUpdateSpeedMs = 50
        timer = QtCore.QTimer()#to create a thread that calls a function at intervals
        timer.timeout.connect(self.update)#the update function keeps getting called at intervals
    def update(self):
        if len(self.dat) > self.maxLen:
            self.dat.popleft() #remove oldest


if __name__ == '__main__':
    g = Graph()