I am working with a device that sends 100 readings per second and I want my GUI to have a plot of this data showing the last 300 points collected. However, I have found that:
appending a new data point to the y-axis queue
clearing the plot that exists already
plotting the new data list
redrawing the canvas
after each point takes nearly 0.2 - 0.4 seconds, which is incredibly slow.
This is the code I am using currently. A while loop keeps checking a queue, and once a new element is pushed to it, it calls update
with the element as a parameter. Would anyone be able to suggest some improvements to the efficiency or alternatives to matplotlib?
class GraphFrame:
def __init__(self,root,channel,index):
self.root=root
self.frame=tk.Frame(self.root)
self.frame.pack(side=tk.LEFT)
self.y = Queue(maxsize = 300)
self.fig, self.axes = plt.subplots(1,1)
self.axes.plot(list(self.y.queue))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, padx=5, pady=5)
def update(self, new_point):
if self.y.full():
self.y.get()
self.y.put(new_point)
self.fig.axes[0].clear()
self.fig.axes[0].plot(list(self.y.queue))
self.canvas.draw()
Edit: managed to solve the issue using blitting for matplotlib and replacing the Tkinter canvas with a label with the image of the Graph. Will try to upload code on github and link it.
Instead of rebuilding your figure for each new point, I would modify the LineArtist you already have.
class GraphFrame:
def __init__(self,root,channel,index):
self.root=root
self.frame=tk.Frame(self.root)
self.frame.pack(side=tk.LEFT)
self.y = Queue(maxsize = 300)
self.fig, self.axes = plt.subplots(1,1)
# capture the artist
self.line, = self.axes.plot(list(self.y.queue))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, padx=5, pady=5)
def update(self, new_point):
if self.y.full():
self.y.get()
self.y.put(new_point)
# update the artist
self.line.set_xdata(list(range(len(self.y))))
self.line.set_ydata(list(self.y.queue))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With