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.
Comments
-
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(":"); } }