Real time matplotlib plot is not working while still in a loop
Here is the solution add this plt.pause(0.0001)
in your loop as below:
import matplotlib.pyplot as plt
import time
import random
from collections import deque
import numpy as np
# simulates input from serial port
def random_gen():
while True:
val = random.randint(1,10)
yield val
time.sleep(0.1)
a1 = deque([0]*100)
ax = plt.axes(xlim=(0, 20), ylim=(0, 10))
d = random_gen()
line, = plt.plot(a1)
plt.ion()
plt.ylim([0,10])
plt.show()
for i in range(0,20):
a1.appendleft(next(d))
datatoplot = a1.pop()
line.set_ydata(a1)
plt.draw()
print a1[0]
i += 1
time.sleep(0.1)
plt.pause(0.0001) #add this it will be OK.
update plot in while loop
I would recommend using a single Axes object for all of your plots. Something like this:
fig, ax = plt.subplots()
while cap.isOpened():
# generate data here
ax.scatter(df['x'], df['y'])
Python realtime plotting
The lightest solution you may have is to replace the X and Y values of an existing plot. (Or the Y value only, if your X data does not change. A simple example:
import matplotlib.pyplot as plt
import numpy as np
import time
fig = plt.figure()
ax = fig.add_subplot(111)
# some X and Y data
x = np.arange(10000)
y = np.random.randn(10000)
li, = ax.plot(x, y)
# draw and show it
ax.relim()
ax.autoscale_view(True,True,True)
fig.canvas.draw()
plt.show(block=False)
# loop to update the data
while True:
try:
y[:-10] = y[10:]
y[-10:] = np.random.randn(10)
# set the new data
li.set_ydata(y)
fig.canvas.draw()
time.sleep(0.01)
except KeyboardInterrupt:
break
This solution is quite fast, as well. The maximum speed of the above code is 100 redraws per second (limited by the time.sleep
), I get around 70-80, which means that one redraw takes around 4 ms. But YMMV depending on the backend, etc.
How to plot data real time data from a txt file in a matplotlib line graph
First of all, make sure that the code that ultrasonic uses to write data to file is not buffering writes and writes to file instantly by forcing it to flush after every write output.flush()
, I edited your code to do that and also changed it to append to file instead of removing all old data with each write also I made it to save time
with each write to use it in the graph.
start_time = time.time()
while True:
output = open("front sensor distance.txt", "a")
output.write(str(round(time.time()-start_time))+","+str(round(get_distance()))+"\n")
time.sleep(2)
output.flush()
then you can use this code sample which reads data from the file every 1 second and updates the graph in real-time.
I tried to write it as close to your description as possible where the data file contains time,distance
in each line separated by a comma.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
def animate(i):
file_data = open("front sensor distance.txt","r").read()
dataArray = file_data.split('\n')
time = []
distance = []
for eachLine in dataArray:
if len(eachLine)>1:
x,y = eachLine.split(',')
time.append(float(x))
distance.append(float(y))
ax.clear()
ax.plot(time,distance)
def Main():
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
print("done")
Main()
I don't have the hardware you have to test with so I made distance
function return random numbers on my machine to simulate your experience.
and running both files will result in the following real-time graph
Real time data plotting from a high throughput source
You could try to have two separate processes:
- one for acquiring and storing the data
- one for plotting the data
Below there are two basic scripts to get the idea.
You first run gen.py
which starts to generate numbers and save them in a file.
Then, in the same directory, you can run plot.py
which will read the last part of the file and will update the a Matplotlib plot.
Here is the gen.py
script to generate data:
#!/usr/bin/env python3
import time
import random
LIMIT_TIME = 100 # s
DATA_FILENAME = "data.txt"
def gen_data(filename, limit_time):
start_time = time.time()
elapsed_time = time.time() - start_time
with open(filename, "w") as f:
while elapsed_time < limit_time:
f.write(f"{time.time():30.12f} {random.random():30.12f}\n") # produces 64 bytes
f.flush()
elapsed = time.time() - start_time
gen_data(DATA_FILENAME, LIMIT_TIME)
and here is the plot.py
script to plot the data (reworked from this one):
#!/usr/bin/env python3
import io
import time
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.animation
BUFFER_LEN = 64
DATA_FILENAME = "data.txt"
PLOT_LIMIT = 20
ANIM_FILENAME = "video.gif"
fig, ax = plt.subplots(1, 1, figsize=(10,8))
ax.set_title("Plot of random numbers from `gen.py`")
ax.set_xlabel("time / s")
ax.set_ylabel("random number / #")
ax.set_ylim([0, 1])
def get_data(filename, buffer_len, delay=0.0):
with open(filename, "r") as f:
f.seek(0, io.SEEK_END)
data = f.read(buffer_len)
if delay:
time.sleep(delay)
return data
def animate(i, xs, ys, limit=PLOT_LIMIT, verbose=False):
# grab the data
try:
data = get_data(DATA_FILENAME, BUFFER_LEN)
if verbose:
print(data)
x, y = map(float, data.split())
if x > xs[-1]:
# Add x and y to lists
xs.append(x)
ys.append(y)
# Limit x and y lists to 10 items
xs = xs[-limit:]
ys = ys[-limit:]
else:
print(f"W: {time.time()} :: STALE!")
except ValueError:
print(f"W: {time.time()} :: EXCEPTION!")
else:
# Draw x and y lists
ax.clear()
ax.set_ylim([0, 1])
ax.plot(xs, ys)
# save video (only to attach here)
#anim = mpl.animation.FuncAnimation(fig, animate, fargs=([time.time()], [None]), interval=1, frames=3 * PLOT_LIMIT, repeat=False)
#anim.save(ANIM_FILENAME, writer='imagemagick', fps=10)
#print(f"I: Saved to `{ANIM_FILENAME}`")
# show interactively
anim = mpl.animation.FuncAnimation(fig, animate, fargs=([time.time()], [None]), interval=1)
plt.show()
plt.close()
Note that I have also included and commented out the portion of code that I used to generate the animated GIF above.
I believe this should be enough to get you going.
Related Topics
Windowserror: [Error 126] the Specified Module Could Not Be Found
How to Properly Setup Pipenv in Pycharm
Importerror: No Module Named Psycopg2 After Install
Collecting and Reporting Pytest Results
List Append Is Overwriting My Previous Values
Pandas Fill in Missing Date Within Each Group With Information in the Previous Row
Numpy Distance Calculations of Different Shaped Arrays
Print a List of Space-Separated Elements
Django: Get Current User in Model Save
How to Tell If Tensorflow Is Using Gpu Acceleration from Inside Python Shell
How to Clean \Xc2\Xa0 \Xc2\Xa0..... in Text Data
Sqlalchemy - Select for Update Example
How to Find Factors of a Number Using the Simplest Python Method
How to Insert a Word into a List in Python
Airflow:Passing a Dynamic Value to Sub Dag Operator
How to Update/Delete Rows in Bigquery from the Python API
Fill With Nan When Length of Values Does Not Match Length of Index