Fast plotting data in python

12,934

Solution 1

The pyqtgraph module is a great solution. It is very fast and easy.

Here is new code:

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

app = QtGui.QApplication([])

p = pg.plot()
p.setWindowTitle('live plot from serial')
curve = p.plot()

data = [0]
raw=serial.Serial('COM9', 115200)


def update():
    global curve, data
    line = raw.readline()
    if ("hand" in line):
       line=line.split(":")
       if len(line)==8:
            data.append(float(line[4]))
            xdata = np.array(data, dtype='float64')
            curve.setData(xdata)
            app.processEvents()

timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)

if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

Solution 2

Plotting real-time in Matplotlib? There's price to pay for all the power you are buying. Autoscaling, autoaxis, etc... It all costs time!

A much faster solution is using a toolkit such as Gtk, and doing the plotting yourself, with a canvas such as GooCanvas.

Still, there are a few things that you can do to speed up your plotting.

  • Why the Pause statement?
  • Split the communication to another thread and make the plot take the following sample when it's ready (skipping values from the input queue)
  • You are appending, which makes the plot rescale frequently. Remove the first sample after N samples have been acquired.
  • I believe it is possible to plot in the background with MatPlotLib (not sure) and then copy to the screen less frequently.
Share:
12,934
acs
Author by

acs

Electronics Engineer. PHD student.

Updated on June 04, 2022

Comments

  • acs
    acs almost 2 years

    I'm trying to plot data from mpu6050 imu with arduino. MPU6050 sends data faster than plot. Arduino code gives 6 data which are yaw, pitch, roll, ax,ay and az from serial port. I need suggestions for fast plot .

    Python Code:

    import serial
    import matplotlib.pyplot as plt #import matplotlib library
    from drawnow import * 
    
    ser = serial.Serial('COM9', 115200)
    yaw = 0.0
    pitch =0.0
    roll =0.0
    ax =0.0
    ay =0.0
    az =0.0
    o_yaw= [0]
    o_pitch= [0]
    o_roll= [0]
    o_ax= [0]
    o_ay= [0]
    o_az= [0]
    plt.ion()
    cnt=0
    def makeFig(): 
        plt.ylim(-1000,1000)                                 
        plt.grid(True)
        plt.ylabel('Magnitude')  
        plt.plot(olculen_ax, 'ro-', label='ax') 
        plt.plot(olculen_ay, 'bo-', label='ay')  
        plt.plot(olculen_az, 'go-', label='az')                               
        plt.legend()                    
    while True:
        incoming=ser.readline()
        if ("hand" in incoming):
            incoming=incoming.split(":")
            if len(incoming)==8:
                yaw = float(incoming[1])
                pitch = float(incoming[2])
                roll = float(incoming[3])
                ax = float(incoming[4])
                ay = float(incoming[5])
                az = float(incoming[6])
                print "Split works"
        else:
            print incoming
        o_ax.append(ax)                    
        o_ay.append(ay)    
        o_az.append(az)
        o_yaw.append(yaw)
        o_pitch.append(pitch)
        o_roll.append(roll)              
    
        drawnow(makeFig)                       
        plt.pause(.00001)                     
        cnt=cnt+1
        if(cnt>50):                            
            o_ax.pop(0)
            o_ay.pop(0)                     
            o_az.pop(0)
    

    Arduino Code (I just add loop. code derived from this):

    void loop() {
        if (!dmpReady) return;
        while (!mpuInterrupt && fifoCount < packetSize) {
        }
    
        mpuInterrupt = false;
        mpuIntStatus = mpu.getIntStatus();
    
        fifoCount = mpu.getFIFOCount();
    
         if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        mpu.resetFIFO();
        //Serial.println(F("FIFO overflow!"));
    } else if (mpuIntStatus & 0x02) {
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        fifoCount -= packetSize;
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetAccel(&aa, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
        mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
        Serial.print("hand:");
        Serial.print(ypr[0] * 180/M_PI);
        Serial.print(":");
        Serial.print(ypr[1] * 180/M_PI);
        Serial.print(":");
        Serial.print(ypr[2] * 180/M_PI);
        Serial.print(":");
        Serial.print(aaWorld.x);
        Serial.print(":");
        Serial.print(aaWorld.y);
        Serial.print(":");
        Serial.print(aaWorld.z);
        Serial.println(":");
    }
    
    }