Updating a real time plot using Matplotlib - python

I'm trying to generate a real time plot using Matplotlib, with real time gathered data from an Arduino MKR1000.
Code:
import serial
import matplotlib.pyplot as plt
import numpy as np
ser = serial.Serial('COM7', 9600)
plt.close('all')
plt.figure(figsize=[10,8])
plt.ion()
data = np.array([])
while True:
a = ser.readline()
a = a.decode()
b = float(a[0:4])
data = np.append(data, b)
plt.plot(data)
plt.pause(0.1)
The output is a new plot created every 0.1 seconds, but I want to update the same real-time plot.
Anyone can help?
I'm using Python 3 on a Windows 10 system

Related

How to draw live-data with time passed in milliseconds on x-axes?

I am new to programing and I am currently trying to visualize force data per second.
The Data is "given me" in realtime through a simulation.
I tried using time.time() for the x-axes, but plt.plot won't show anything with that command, only plt.scatter(), but since I want a line plot I can not just use plt.scatter.
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from win32com.client import Dispatch
import time
Application = Dispatch('Program I am using')
myPlatform = Application.ActiveExperiment.Platforms[0]
while (True):
if(myPlatform.ActiveVariableDescription.Variables["Platform():]")
soll_kraft = myPlatform.ActiveVariableDescription.Variables["Platform():]")
ist_kraft = myPlatform.ActiveVariableDescription.Variables["Platform():]")
ts = time.time()
plt.scatter(ts, soll_kraft, color='red')
plt.scatter(ts, ist_kraft, color='green')
plt.plot(ts, soll_kraft, color='red')
plt.plot(ts, ist_kraft, color='green')
plt.pause(0.005)
plt.draw()
else:
plt.close()
I expect scatter points connected via line, but instead I just get points.

Simple matplotlib.animation graph geting slower very fast and than stoping

I've started to learn about matplotlib functions because i wanted to visualize data i was receiving via websocket. For that i made a dummy program that mimics the behaviour of my main program but has added the functionality of mathplotlib. what i noticed is the program takes more and more time to finish each loop and eventually 'freezes'. i managed to extend it life by changing the interval in animation.FuncAnimation from 1000 to 10000. But that just the program to plot sometimes up to 9s for 1 new peace of data. I believe the problem lays in a inappropriate way of cleaning old plots. But i don't know where exactly i did the mistake
import time
import datetime
import timeit
import queue
import os
import random
import copy
import matplotlib.pyplot as plt
import matplotlib.animation as animation
q = queue.Queue()
beta=[0,]
b=False
czas=[]
produkty=["primo"]
cena=[[] for _ in range(len(produkty))]
fig=plt.figure()
#ax1=fig.add_subplot(1,1,1)
#ax2=fig.add_subplot(1,1,1)
ax1=plt.subplot(1,1,1)
ax2=plt.subplot(1,1,1)
def animate(i):
ax1.clear()
ax2.clear()
ax1.plot(czas,cena[0])
ax2.plot(czas,beta)
while True:
time.sleep(1)
alpfa=time.time()
#input('press enter')
rand_produkt=random.choice(produkty)
rand_price=random.randint(1,10)
rand_czas=time.ctime()
alfa={'type':'ticker','price':rand_price,'product_id':rand_produkt,'time':rand_czas}
q.put(alfa)
if q.not_empty:
dane=q.get()
typ=dane.get('type',None)
if typ=='ticker':
price=dane.get('price', None)
pair=dane.get('product_id',None)
t=dane.get('time', None)
b=True
if b==True:
b=False
produkt_id=produkty.index(pair)
cena[produkt_id].append(float(price))
czas.append(t)
plt.ion()
ani=animation.FuncAnimation(fig,animate,interval=1000)#, blit=True)repeat=True)
plt.show()
plt.pause(0.001)
#fig.clf()
beta.append(time.time()-alpfa)
print(beta[-1])
The problem with your code is that you call a new animation in you while loop. Hence this will cause slow down down the line. It is better to initiate your plot ones. One trick may be to update the object data directly as such:
from matplotlib.pyplot import subplots, pause, show
from numpy import sin, pi
fig, ax = subplots()
x = [0]
y = [sin(2 * pi * x[-1])]
p1, = ax.plot(x, y)
show(block = False)
while True:
# update data
x.append(x[-1] + .1)
y.append(sin(2 * pi * x[-1]))
p1.set_data(x, y) # update data
ax.relim() # rescale axis
ax.autoscale_view()# update view
pause(1e-3)

speed up mplotlib when plotting live serial data

I am using an Arduino to create a 3d lidar scan of the area around it, and sending x,y,z coordinates over serial to a python script to visualize the data live. The issue I've run into is that mplotlib is much too slow to keep up with the stream. I have a feeling this is due to completely redrawing the plot, but I have not found a solution. I write s1000 over serial to start the lidar scan, and sending a x,y,z coordinate once per second.
import serial
import numpy
import matplotlib.pyplot as plt #import matplotlib library
from mpl_toolkits.mplot3d import Axes3D
from drawnow import *
from matplotlib import animation
import time
ser = serial.Serial('COM7',9600,timeout=5)
ser.flushInput()
time.sleep(5)
ser.write(bytes(b's1000'))
plt.ion()
fig = plt.figure(figsize=(16,12))
ax = fig.add_subplot(111, projection="3d")
ax.set_xlim3d(-255, 255)
ax.set_ylim3d(-255, 255)
ax.set_zlim3d(-255, 255)
x=list()
y=list()
z=list()
while True:
try:
ser_bytes = ser.readline()
data = str(ser_bytes[0:len(ser_bytes)-2].decode("utf-8"))
xyz = data.split(", ")
dx = float(xyz[0])
dy = float(xyz[1])
dz = float(xyz[2].replace(";",""))
x.append(dx);
y.append(dy);
z.append(dz);
ax.scatter(x,y,z, c='r',marker='o')
plt.draw()
plt.pause(0.0001)
except:
print("Keyboard Interrupt")
ser.close()
break

Erratic data stream from python sketch

I am trying to output time, pitch, roll and yaw from a quadrotor and create graphs using python. I have two XBee modules sending data from the quadrotor to the computer. The values I receive from the python sketch are very erratic, there seem to be a large number of errors, this seems to be caused by unwanted numbers randomly appearing in the data stream. I cannot seem to solve this, does anyone have any ideas??? Below I've attached a copy of the code.
import serial # import Serial Library
import numpy as np # Import numpy
import matplotlib.pyplot as plt #import matplotlib library
from drawnow import *
time=[]
d0k0=[]
d0k1=[]
d0k2=[]
arduinoData = serial.Serial('COM4', 9600) #Creating our serial object named arduinoData
plt.ion() #Tell matplotlib you want interactive mode to plot live data
cnt=0
ydata = [0] * 50
#ax1 = plt.axes()
#line, = plt.plot(ydata)
def makeFig(): #Create a function that makes our desired plot
plt.ylim(180,-180) #Set y min and max values
plt.title('Stability') #Plot the title
plt.grid(True) #Turn the grid on
plt.ylabel('Kalman estimated angles') #Set ylabels
line.set_xdata(time)
line.set_ydata(d0k0)
#plt.plot(t, d2)
#plt.plot(t, d3)
plt.legend(['roll','pitch','yaw'], loc='upper left')
plt.draw()
while True: # While loop that loops forever
while (arduinoData.inWaiting()==0): #Wait here until there is data
pass #do nothing
data = arduinoData.readline()
data = data.decode("ascii", "ignore")
data = ''.join([c for c in data if c in '1234567890.,'])
data = data.strip()
data = data.split(",")
if len(data) == 4:
print(data)
t = float( data[0])
#print (t)
d1 = float( data[1])
d2 = float( data[2])
d3 = float( data[3])
time.append(t)
d0k0.append(d1)
#d0k1.append(d2)
#d0k2.append(d3)
#drawnow(makeFig)
#plt.pause(0.01)

Graph plots are slow than the real time values that are received

I am trying to get data from arduino and trying to then show the data in real time in python using subplot. The values that are coming from arduino uno board are fast and are displayed in the python console also at the same rate but when I am trying to plot the real time data in the graph it is very slowly plotted. It needs to as fast as the rate of values that are coming from the uno board.
Please help. Here is my code:
import serial
import numpy
import matplotlib.pyplot as plt
from drawnow import *
x = []
y = []
z = []
magnitude = []
arduinoData = serial.Serial('com4', 9600)
plt.ion()
count=0
fig = plt.figure()
def makeFig():
ax1 = fig.add_subplot(4,1,1)
ax1.plot(x, 'ro-', label='X axis')
ax2 = fig.add_subplot(4,1,2)
ax2.plot(y, 'b^-', label='Y axis')
ax3 = fig.add_subplot(4,1,3)
ax3.plot(z, 'gp-', label='Y axis')
ax4 = fig.add_subplot(4,1,4)
ax4.plot(magnitude, 'yo-', label='X axis')
while True:
while (arduinoData.inWaiting()==0):
pass
arduinoString = arduinoData.readline()
dataArray = arduinoString.split(',')
xaxis = float( dataArray[0])
yaxis = float( dataArray[1])
zaxis = float( dataArray[2])
mag =float( dataArray[3])
x.append(xaxis)
y.append(yaxis)
z.append(zaxis)
magnitude.append(mag)
drawnow(makeFig)
count = count + 1
nowThere are some things you must understand before you can find a good solution. How fast does the data arrive from arduino? How fast is the drawnow function? These timings are not under your control, so if the data arrives faster than the plotting routine can execute then the task as you have defined it is impossible. All Python versions have a time module, and the function time.time() returns the current time in seconds. This can be used to measure the speed of the drawnow function. You may need to cache a chunk of data before updating the plot. Updating the plot a few times a second will give the illusion of real time, and that may be good enough.
To see how fast the graph plots, use:
t = time.time()
drawnow()
print(time.time()-t) # time in seconds

Categories

Resources