Как ускорить внедрение tkinter matplot lib и python

Я знаю, что это не самый pythonic способ делать что-то, поскольку я довольно новичок в python, но, пожалуйста, со мной, у меня есть графический интерфейс, который я использую для отправки данных запроса от arduino. Затем я перешел к графику этих данных без замедления. В настоящее время я замедляюсь с большим количеством чисел, которые я планирую, и у меня была аналогичная проблема, когда я впервые написал этот gui в matlab. Я хотел знать, могу ли я сделать это быстрее, поскольку в конечном итоге хочу иметь возможность графического отображения сразу нескольких окон. Я знаю об анимационной библиотеке из предыдущего предложения, но не увенчался успехом, чтобы заставить ее работать с моим tkinter-объектом из того, что я понимаю, что было бы идеальным способом ускорить графику, кроме того, чтобы рисовать прямо на холсте. Мне нужно всего лишь построить около 200 точек данных за раз. Вот текущий код GUI:

import Tkinter import numpy as np import serial import time from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure from matplotlib import pyplot as plt import matplotlib.animation as animation from math import cos, sin from collections import deque class App: def __init__(self, master): frame = Tkinter.Frame(master) self.Max_press = Tkinter.StringVar() self.Max_press.set("10") self.Min_press = Tkinter.StringVar() self.Min_press.set("0") self.Cycle_per_minute = Tkinter.StringVar() self.Cycle_per_minute.set("12") self.Duration_cycle = Tkinter.StringVar() self.Duration_cycle.set("1") self.respiration = Tkinter.LabelFrame(frame, text="Respiration Testing", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10) self.respiration.grid(row=0, column=0, padx=20, pady=20) self.max_pressure = Tkinter.Label(self.respiration, text="Maximum Pressure (mmHg)") self.max_pressure.grid(row=0, column=0, padx=5, pady=5) self.Max_pressure = Tkinter.Entry(self.respiration,textvariable=self.Max_press) self.Max_pressure.grid(row=1, column=0, padx=5, pady=5) self.min_pressure = Tkinter.Label(self.respiration, text="Minimum Pressure (mmHg)") self.min_pressure.grid(row=2, column=0, padx=5, pady=5) self.Min_pressure = Tkinter.Entry(self.respiration, textvariable=self.Min_press) self.Min_pressure.grid(row=3, column=0, padx=5, pady=5) self.cycles_per_minute = Tkinter.Label(self.respiration, text="Cycles Per Minute") self.cycles_per_minute.grid(row=4, column=0, padx=5, pady=5) self.Cycles_per_minute = Tkinter.Entry(self.respiration,textvariable=self.Cycle_per_minute) self.Cycles_per_minute.grid(row=5, column=0, padx=5, pady=5) self.duration_of_test = Tkinter.Label(self.respiration, text="Duration (minutes)") self.duration_of_test.grid(row=6, column=0, padx=5, pady=5) self.Duration_of_test = Tkinter.Entry(self.respiration, textvariable=self.Duration_cycle) self.Duration_of_test.grid(row=7, column=0, padx=5, pady=5) self.run_respiration = Tkinter.Button(self.respiration, text="RUN RESPIRATION", command=self.getData) self.run_respiration.grid(row=8, column=0, padx=5, pady=5) self.burst = Tkinter.LabelFrame(frame, text="Burst Test", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 ) self.burst.grid(row=0, column=1, padx=20, pady=20) self.burst_pressure = Tkinter.Button(self.burst, text="RUN BURST TEST") self.burst_pressure.grid(row=0, column=0, padx=5, pady=5) self.test_options = Tkinter.LabelFrame(frame, text="Test Options", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 ) self.test_options.grid(row=0, column=2, padx=20, pady=35) self.stop = Tkinter.Button(self.test_options, text="STOP", bd=10, height=5, width=10) self.stop.grid(row=0, column=0, padx=10, pady=25) self.pause = Tkinter.Button(self.test_options, text="PAUSE", bd=10, height=5, width=10) self.pause.grid(row=1, column=0, padx=10, pady=25) self.reset = Tkinter.Button(self.test_options, text="RESET", bd=10, height=5, width=10) self.reset.grid(row=2, column=0, padx=10, pady=25) self.save = Tkinter.Button(self.test_options, text="SAVE", bd=10, height=5, width=10) self.save.grid(row=3, column=0, padx=10, pady=25) self.xdata = deque([0]*200,maxlen=200) self.ydata = deque([0]*200,maxlen=200) self.fig = plt.Figure() self.ax1 = self.fig.add_subplot(111) self.line, = self.ax1.plot(self.xdata, self.ydata, lw=2) self.canvas = FigureCanvasTkAgg(self.fig,master=master) self.canvas.show() self.canvas.get_tk_widget().grid(row=0, column=3, padx=20, pady=20) frame.grid(row=0, column=0, padx=20, pady=20) def getData(self): press_max = float(self.Max_press.get()) press_min = float(self.Min_press.get()) duration = float(self.Duration_cycle.get())*60*20 cycle_time = float(self.Cycles_per_minute.get()) i = 0 x = [] y = [] amp = (press_max - press_min)/2 offset = amp + press_min spb = 60/cycle_time while (i < duration): x.append(i) sine = amp*np.sin((x[i]*(np.pi*4))/(2*spb)) + offset + 1 y.append(sine) i = i + 1 arduinoData = serial.Serial('com5', 115200) arduinoData.flushInput() press = [] t = [] i = 0 start = time.time() while (i < duration + 1): while (arduinoData.inWaiting()==0): pass arduinoString = arduinoData.readline() dataArray = int(arduinoString) i = i + 1 print (dataArray) self.plotData(dataArray,i) end = time.time() print (end - start) def plotData(self, y, x ): self.xdata.append(x) self.ydata.append(y) self.ax1.plot(self.xdata, self.ydata) self.canvas.show() root = Tkinter.Tk() app = App(root) root.mainloop() 

Но самая важная часть здесь:

  self.fig = plt.Figure() self.ax1 = self.fig.add_subplot(111) self.line, = self.ax1.plot(self.xdata, self.ydata, lw=2) self.canvas = FigureCanvasTkAgg(self.fig,master=master) self.canvas.show() self.canvas.get_tk_widget().grid(row=0, column=3, padx=20, pady=20) frame.grid(row=0, column=0, padx=20, pady=20) def getData(self): press_max = float(self.Max_press.get()) press_min = float(self.Min_press.get()) duration = float(self.Duration_cycle.get())*60*20 cycle_time = float(self.Cycles_per_minute.get()) i = 0 x = [] y = [] amp = (press_max - press_min)/2 offset = amp + press_min spb = 60/cycle_time while (i < duration): x.append(i) sine = amp*np.sin((x[i]*(np.pi*4))/(2*spb)) + offset + 1 y.append(sine) i = i + 1 arduinoData = serial.Serial('com5', 115200) arduinoData.flushInput() press = [] t = [] i = 0 start = time.time() while (i < duration + 1): while (arduinoData.inWaiting()==0): pass arduinoString = arduinoData.readline() dataArray = int(arduinoString) i = i + 1 print (dataArray) self.plotData(dataArray,i) end = time.time() print (end - start) def plotData(self, y, x ): self.xdata.append(x) self.ydata.append(y) self.ax1.plot(self.xdata, self.ydata) self.canvas.show() root = Tkinter.Tk() app = App(root) root.mainloop() 

Заранее благодарю вас за любую помощь, которую вы можете мне дать.

    One Solution collect form web for “Как ускорить внедрение tkinter matplot lib и python”

    Для быстрого реагирования вам необходимо использовать возможности анимации matplotlib. Вот пример внутри окна tkinter. Я, очевидно, не могу это проверить, так как у меня нет вашего arduino, поэтому я прокомментировал части arduino и добавил некоторые случайные части.

     import Tkinter as tk import serial from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure from matplotlib import pyplot as plt import matplotlib.animation as animation from collections import deque import random HISTORY_LEN = 200 class App(tk.Frame): def __init__(self, master=None, **kwargs): tk.Frame.__init__(self, master, **kwargs) self.running = False self.ani = None btns = tk.Frame(self) btns.pack() lbl = tk.Label(btns, text="Number of points") lbl.pack(side=tk.LEFT) self.points_ent = tk.Entry(btns, width=5) self.points_ent.insert(0, '500') self.points_ent.pack(side=tk.LEFT) lbl = tk.Label(btns, text="update interval (ms)") lbl.pack(side=tk.LEFT) self.interval = tk.Entry(btns, width=5) self.interval.insert(0, '30') self.interval.pack(side=tk.LEFT) self.btn = tk.Button(btns, text='Start', command=self.on_click) self.btn.pack(side=tk.LEFT) self.fig = plt.Figure() self.ax1 = self.fig.add_subplot(111) self.line, = self.ax1.plot([], [], lw=2) self.canvas = FigureCanvasTkAgg(self.fig,master=master) self.canvas.show() self.canvas.get_tk_widget().pack() def on_click(self): if self.ani is None: return self.start() if self.running: self.ani.event_source.stop() self.btn.config(text='Un-Pause') else: self.ani.event_source.start() self.btn.config(text='Pause') self.running = not self.running def start(self): self.xdata = deque([], maxlen=HISTORY_LEN) self.ydata = deque([], maxlen=HISTORY_LEN) #~ self.arduinoData = serial.Serial('com5', 115200) #~ self.arduinoData.flushInput() self.points = int(self.points_ent.get()) + 1 self.ani = animation.FuncAnimation( self.fig, self.update_graph, frames=self.points, interval=int(self.interval.get()), repeat=False) self.running = True self.btn.config(text='Pause') self.ani._start() def update_graph(self, i): self.xdata.append(i) #~ self.ydata.append(int(self.arduinoData.readline())) self.ydata.append(random.randrange(100)) # DEBUG self.line.set_data(self.xdata, self.ydata) self.ax1.set_ylim(min(self.ydata), max(self.ydata)) self.ax1.set_xlim(min(self.xdata), max(self.xdata)) if i >= self.points - 1: #~ self.arduinoData.close() self.btn.config(text='Start') self.running = False self.ani = None return self.line, def main(): root = tk.Tk() app = App(root) app.pack() root.mainloop() if __name__ == '__main__': main() 

    Для большей скорости вырезайте функции печати. Печать на терминал очень медленная. Кроме того, вы можете захотеть перенести последовательную инициализацию туда, где она вызывается только один раз.

    Для моего компьютера самое быстрое, что я мог сделать, – 25 мс / кадр.

    Python - лучший язык программирования в мире.