I want to plot real-time data as a file is updated. I have my run
routine as follows (I read the data in the live plot and then attempt to plot it):
def run(self):
os.startfile("TPSLogger.exe")
self.running = True # Now running
self.new_f = self.find_latest_file()
plt.figure()
self.live_plot()
I have abstracted out a lot of the unnecessary code in relation to this question. Then in the live_plot
routine:
def live_plot(self):
file_size = os.path.getsize(self.new_f) # The new file size
if self.running:
if file_size != self.new_pointer:
channels, self.new_pointer = writeToExcel.conversion(self, self.new_f, self.new_pointer)
c_count = 1
for channel in channels:
if len(channel) == 0:
pass # Empty channel
else:
plt.plot(channel[0]) # Plot the data
c_count += 1
self.after(self.timing, self.live_plot) # Redo after a certain time
else:
# We are now longer running
plt.show()
First off, do I need to store plt
as an attribute of the class which it is in? Secondly when I place plt.show()
just outside the for
loop it shows the first graph (pulse) and then doesn't show the rest and freezes. Is there a better way to read the file in periods of x seconds without the plot freezing - the GUI works fine during all of this as by the way.
As it is now it plots all the data once the program is finished. Is there a way for me to plot the data as it comes in?
Here is a MCVE:
import matplotlib.pyplot as plt
import tkinter as tk
import random
class tkinterApp(tk.Tk):
# __init__ function for class tkinterApp
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# creating a container
container = tk.Frame(self)
container.pack(side = "top", fill = "both", expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
frame = MCVE(container, self)
self.frames[MCVE] = frame
frame.grid(row = 0, column = 0, sticky ="nsew")
self.show_frame(MCVE)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class MCVE(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.channel = [1, 2, 3, 4, 2, 1]
runButton = tk.Button(self, text="Run", command=self.run)
runButton.pack()
def run(self):
self.live_plot()
def live_plot(self):
print("iterating.")
if len(self.channel) == 0:
pass # Empty channel
else:
plt.plot(self.channel)
plt.show()
self.channel.append(random.randint(0,10))
self.after(1000, self.live_plot) # Redo after a certain time
app = tkinterApp()
app.mainloop()