2017-04-18 10 views
0

これは私がむしろPythonには新しくて、私は裸でおいてください。 arduino。私はその後、減速せずにこのデータをグラフに表示しました。私は現在、私がプロットしている数字が増えて、私が最初にこのGUIをmatlabに書いたときに同様の問題を抱えていました。私は最終的に複数のウィンドウに一度にグラフを描くことができるようにするために、これをもっと速くできるかどうかを知りたかったのです。私は以前の提案からアニメーションライブラリを認識していますが、キャンバスにまっすぐに描画するだけでなくグラフ作成をスピードアップする理想的な方法であると私が理解しているものから、私のtkinterオブジェクトの不具合を取り除くことに失敗しました。私は、一度に約200点のデータをプロットする必要があります。ここでは、現在のGUIコードです:tkinter埋め込みmatplotのlibとpythonをスピードアップするには

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() 

は、あなたが私を与えることができます任意の助けを事前にありがとうございます。

答えて

1

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() 

さらに高速にするには、印刷機能を削除します。端末への印刷は非常に遅いです。また、シリアル初期化を一度だけ呼び出される場所に移動することもできます。

私のコンピュータでは、できるだけ速いのは25ms /フレームでした。

関連する問題