I am imitating getting stream of data where not each "message" line has the information I want to plot in live mode. Since each line will still be read, how can I skip one iteration (frame) and therefore skip plot update for 1 frame until next iteration that returns data comes along. My code has the following structure:
fig, ax = plt.subplots()
line, = ax.plot([], [])
lap_stat = []
file = open(path + 'file.log', 'r')
def update(lap_stat):
#Plot lap number on x-axis, lap time on y-axis from lap_stat list that
#contains a tuple
line.set_data(lap_stat[0], lap_stat[1])
return line,
def data_gen():
while True:
line = file.readline()
#Get data from line
#Apply conditions, if line doesn't contain relevant information nothing happens
#If data is present in line, save data as tuple [lap, lap_time] to lap_stat
yield lap_stat
ani = FuncAnimation(fig, update, data_gen, interval=100, blit=True)
plt.show()
Not each line has the relevant information, so if at current frame no information was appended the input list at update(lap_stat) function is empty, nothing gets plotted and the process dies. How can I modify my code to only plot information when it is returned? Plotting 0's also not an option, if I plot lap times from lap 0-10 and the then next data point is lap 15, I want the point from lap 10 to be connected to point 15. Hope it makes, thank you!
you made me sweat, I dont think this is the right way to approach the problem, but given your layout, here what I got working:
input file file.log
:
1 10
2 20
3 10
4 50
5 80
6 10
7 70
8
9
10 55
11 40
12 66
my code:
import matplotlib.animation as animation #to save animation
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.set_xlim([0,12])
ax.set_ylim([0,100])
line, = ax.plot([],[], marker="o", markersize=10,markeredgecolor="red", markerfacecolor="green")
path = ''
file = open(path + 'file.log', 'r')
def zero():
line = ax.plot(0,0)
return line
def update(lap_stat):
#Plot lap number on x-axis, lap time on y-axis from lap_stat list that
#contains a tuple
line.set_data(lap_stat[0], lap_stat[1])
return line,
def data_gen():
line = 'pippo'
while line:
line = file.readline()
print('line : ', line)
try:
lap_stat = (int(line.split()[0]),int( line.split()[1]))
print('lap_stat : ', lap_stat)
#Get data from line
#Apply conditions, if line doesn't contain relevant information nothing happens
#If data is present in line, save data as tuple [lap, lap_time] to lap_stat
yield lap_stat
except:
continue
ani = FuncAnimation(fig, update, data_gen(), init_func=zero , interval=2000, blit=True)
# ani = FuncAnimation(fig, update, data_gen(), interval=1000) # need first frame, doesnt clear previous points
# ani.save('animation.gif' , writer=animation.PillowWriter(fps=1)) #save animation
plt.show()
output :
as per OP, modified code on same input to get animation below:
import matplotlib.animation as animation #to save animation
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.set_xlim([0,1])
ax.set_ylim([0,1])
line, = ax.plot([],[], marker="o", markersize=10,markeredgecolor="red", markerfacecolor="green")
path = ''
file = open(path + 'file.log', 'r')
def zero():
line = ax.plot(0,0)
return line
x_points = [0]
y_points = [0]
def update(lap_stat):
#Plot lap number on x-axis, lap time on y-axis from lap_stat list that
#contains a tuple
x_points.append(lap_stat[0])
y_points.append(lap_stat[1])
ax.set_xlim([0,max(x_points)])
ax.set_ylim([0,max(y_points)])
# line.set_data(lap_stat[0], lap_stat[1])
line.set_data(x_points, y_points)
print(x_points, y_points)
return line,
def data_gen():
line = 'pippo'
while line:
line = file.readline()
print('line : ', line)
try:
lap_stat = (int(line.split()[0]),int( line.split()[1]))
print('lap_stat : ', lap_stat)
#Get data from line
#Apply conditions, if line doesn't contain relevant information nothing happens
#If data is present in line, save data as tuple [lap, lap_time] to lap_stat
yield lap_stat
except:
continue
# ani = FuncAnimation(fig, update, data_gen(), init_func=zero , interval=2000, blit=True)
ani = FuncAnimation(fig, update, data_gen(), init_func=zero , interval=2000, blit=False, repeat = False)
# ani = FuncAnimation(fig, update, data_gen(), interval=1000) # need first frame, doesnt clear previous points
# ani.save('animation_line.gif' , writer=animation.PillowWriter(fps=1)) #save animation
plt.show()
print(x_points, y_points)
output: