2016-10-04 4 views
1

私は自分のつま先をPythonに浸しています。Matplotlibグラフを更新するためにここで助けてくださいました。グラフ付きのPythonデータ表示

TimeStamp, ReadCount, Antenna, Protocol, RSSI, EPC, Sensor 
09/28/2016 17:34:28.967, 5686, 2, GEN2, -25, E036115348A908CB, 23.16,0.00,0.00, (Infinity%), 
09/28/2016 17:34:29.716, 5687, 2, GEN2, -32, E036115348A908CB, (Infinity%), 
09/28/2016 17:34:31.155, 5689, 2, GEN2, -27, E036115348A908CB, 22.74,3.38, (Infinity%), 
09/28/2016 17:34:32.351, 5692, 2, GEN2, -25, E036115348A908CB, 22.95,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:32.895, 5695, 2, GEN2, -23, E036115348A908CB, 22.95,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:33.397, 5698, 2, GEN2, -21, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:33.946, 5699, 2, GEN2, -23, E036115348A908CB, 23.57,0.00,3.38, (Infinity%), 
09/28/2016 17:34:34.912, 5702, 2, GEN2, -27, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:35.394, 5705, 2, GEN2, -25, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:35.988, 5707, 2, GEN2, -23, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:36.489, 5710, 2, GEN2, -21, E036115348A908CB, 23.99,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:37.269, 5712, 2, GEN2, -23, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:37.796, 5715, 2, GEN2, -18, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:38.296, 5718, 2, GEN2, -7, E036115348A908CB, 22.32,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:38.826, 5721, 2, GEN2, -7, E036115348A908CB, 23.57,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:39.320, 5724, 2, GEN2, -30, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%), 
09/28/2016 17:34:39.870, 5727, 2, GEN2, -9, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%), 

は、このデータは、センサーから来ている、と私はプルできるようにしたいと思います/いくつかを表示します。このプログラムは、次のようなデータを動的に成長しているCSVファイルからデータを取得するためのアニメーションを使用していますこのデータがこのグラフと共にディスプレイ上に含む他の値。プロットのためのコードは次のようになります。

import matplotlib 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation 

from datetime import datetime, timedelta 
import collections 
import csv 

offset = 16 
slope = -.2081 

def plot(ax, data, colour, width): 
    if data: 
     last_dt = data[0][0] 
     gap = timedelta(seconds=10) 

     x = [] 
     y = [] 

     # Plot groups of data not more than 60 seconds apart 
     for dt, ten in data: 
      if dt <= last_dt + gap: 
       x.append(dt) 
       y.append(ten) 
      else: 
       ax.plot(matplotlib.dates.date2num(x), y, colour, linewidth=width) 
       x = [dt] 
       y = [ten] 

      last_dt = dt 

     ax.plot(matplotlib.dates.date2num(x), y, colour, linewidth=width) 


def animate(i, fig, ax): 
    # Read in the CSV file 
    data = collections.defaultdict(list) 
    fields = ["TimeStamp", "ReadCount", "Antenna", "Protocol", "RSSI", "EPC", "Temp", "Ten", "Powr", "Unpowr", "Inf"] 

    with open('SensorLogFile.csv') as f_input: 
     csv_input = csv.DictReader(f_input, skipinitialspace=True, fieldnames=fields) 
     header = next(csv_input) 

     # Separate the rows based on the Antenna field 
     for row in csv_input: 
      try: 
       data[row['Antenna']].append(
        [datetime.strptime(row['TimeStamp'], '%m/%d/%Y %H:%M:%S.%f'), 
        int(float(row['Ten']) * float(slope) + float(offset))]) 
      except: 
       pass 

    # Drop any data points more than 1.5 mins older than the last entry 

    latest_dt = data[row['Antenna']][-1][0]  # Last entry 
    not_before = latest_dt - timedelta(minutes=.25) 

    for antenna, entries in data.items(): 
     data[antenna] = [[dt, count] for dt, count in entries if dt >= not_before] 

    # Redraw existing axis 
    ax.clear() 

    ax.spines['bottom'].set_color("#5998ff") 
    ax.spines['top'].set_color("#5998ff") 
    ax.spines['left'].set_color("#5998ff") 
    ax.spines['right'].set_color("#5998ff") 

    hfmt = matplotlib.dates.DateFormatter('%m/%d/%Y\n%I:%M:%S %p') 
    ax.xaxis.set_major_formatter(hfmt) 
    fig.autofmt_xdate() 

    plot(ax, data['1'], 'c', 6)  # Antenna 1 
    plot(ax, data['2'], 'r', 6)  # Antenna 2 
    plot(ax, data['3'], 'y', 6)  # Antenna 3 

    ax.grid(True, color='w') 
    plt.ylabel('Tension (lb)', color='w', fontsize=20) 
    plt.title('Spiral 1 Tension', color='w', fontsize=26) 

    ax.tick_params(axis='y', colors='w') 
    ax.tick_params(axis='x', colors='w') 

# ax.set_ylim([21,28]) 

fig = plt.figure(facecolor='#07000d') 
ax = fig.add_subplot(111, axisbg='#07000d') 

ani = animation.FuncAnimation(fig, animate, fargs=(fig, ax), interval=250) 
plt.show() 

私は置くことができる上に、グラフとグラフの下のオープンエリア(グラフの全幅を)持ってできるようにしたいのですが

  • 「温度」
  • 「タイム」(現在の時刻)
  • (各行の第七CSV、ちょうどFを℃に変換する必要があり):(おそらく、これらのデータのそれぞれのボックスを持っている)は、次の
  • "オーバードライブ"(このデータには何も表示されず、将来的にはプレースホルダが表示されます)
  • 右下の画像に「サイクル」(アンテナ1は、第一微小間隙後に読み出される回数であろう)
  • ボックス - 例えばthis image here

このイメージを言うことができます私はTkinterを使用して見て、sentdexに従うようにしましたvideo here

しかし、それを動作させることができませんでした。

私は時間が掛かっており、これ以上ソロでは苦労することはできません。プロの助けが必要です。誰かが私に探しているもののようなディスプレイを作る方法について、私にある方向性/ガイダンスを教えてもらえますか?

答えて

1

まず、最初に回答する必要がある質問があります。

  1. ライブはどのようにライブですか?それはリアルタイムで更新する必要がありますか?この場合、FuncAnimationの使用はおそらく悪い考えです。 回答:はい、リアルタイム
  2. どのくらいの速さで更新する必要がありますか? 回答:1秒に4回更新する
  3. アップデートのトリガーはありますか?新しいデータがいつ届くのか知っていますか? 回答:実際のトリガーはありませんが、2を参照してください。
  4. どの程度の対話性が必要ですか?それは、それ自身のために開く必要があるか、またはデータの一部を選択できるインタラクティブなボタン/スライダが必要なプロットですか?いくつかの基本的なインタラクティブ性があっても、インタラクティブなバックエンドでmatplotlibに滞在し、tkinterをあまり使わないことをお勧めします。あなたはそれについて何も知らないようで、時間が限られています。 回答:インタラクティブ機能は必要ありません。
  5. データには問題があります。それらの行を見る
    E036115348A908CB, 22.74,3.38, (Infinity%),
    E036115348A908CB, 22.95,0.00,0.00,3.38, (Infinity%),
    データが完全ではない場合がありますか?これは避けられますか?

  6. プロットの時間軸はどうですか?まず、#Drop any data points more than 1.5 mins older than the last entryとし、次に#Plot groups of data not more than 60 seconds apartとし、次に古いデータの場合は、gap = timedelta(seconds=10)を破棄します。 「データのグループ」が意味するものと時間軸の長さを教えてください。

  7. number of cyclesをどのように計算しますか?


結果(今のところ): ここで行く、これはあなたが簡単にmatplotlibのを得ることができるものです。

enter image description here

import matplotlib 
import matplotlib.pyplot as plt 
import matplotlib.image as mpimg 

from datetime import datetime, timedelta 
import collections 
import csv 

class Anim(): 
    """ 
    This class provides a "live" plot of the contents of a log file in csv format. 
    The class structure makes it easy to separate the plot generation from the 
     frequent updating of the plot. 
    The code is based on a question at stackoverflow 
     http://stackoverflow.com/questions/39858501/python-data-display-with-graph 
    """ 
    def __init__(self): 

     self.offset = 16. 
     self.slope = -.2081 

     self.i = 0 

     self.axisbg = '#07000d' 

     self.fig = plt.figure(figsize=(15,8), facecolor=self.axisbg) 
     self.ax = self.fig.add_subplot(111, axisbg=self.axisbg) 

     [self.ax.spines[wh].set_color("#5998ff") for wh in ['bottom', 'top', 'left', 'right']] 

     self.hfmt = matplotlib.dates.DateFormatter('%m/%d/%Y\n%I:%M:%S %p') 
     self.ax.xaxis.set_major_formatter(self.hfmt) 
     self.fig.autofmt_xdate() 

     #self.framenumber = plt.figtext(0.9, .9, "0", color='w') 
     self.ax.grid(True, color='w') 
     plt.ylabel('Tension (lb)', color='w', fontsize=20) 
     plt.title('Spiral 1 Tension', color='w', fontsize=26) 

     self.ax.tick_params(axis='y', colors='w') 
     self.ax.tick_params(axis='x', colors='w') 

     initialx = [self.stime("09/28/2016 17:34:28.967"),self.stime("09/28/2016 17:34:29.716") ] 
     initialy = [0,0 ] 

     self.line1, = self.ax.plot(matplotlib.dates.date2num(initialx), initialy, color="c", linewidth=6) 
     self.line2, = self.ax.plot(matplotlib.dates.date2num(initialx), initialy, color="r", linewidth=6) 
     self.line3, = self.ax.plot(matplotlib.dates.date2num(initialx), initialy, color="y", linewidth=6) 

     plt.subplots_adjust(left=0.1, bottom=0.28, right=0.9, top=0.9, wspace=0, hspace=0) 

     self.ax_temp =  plt.axes([0.1, 0.08, 0.2, 0.06], axisbg=self.axisbg) 
     self.ax_time =  plt.axes([0.2, 0.08, 0.2, 0.06], axisbg=self.axisbg) 
     self.ax_overdrive = plt.axes([0.4, 0.08, 0.2, 0.06], axisbg=self.axisbg) 
     self.ax_cycles = plt.axes([0.5, 0.08, 0.2, 0.06], axisbg=self.axisbg) 
     self.ax_image = plt.axes([0.75, 0.03, 0.3, 0.2], axisbg=self.axisbg) 

     self.tx_temp = self.ax_temp.text(0,0, "Temp", color="w", transform=self.ax_temp.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg}) 
     self.tx_time = self.ax_time.text(0,0, "Time", color="w", transform=self.ax_time.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg}) 
     self.tx_overdrive = self.ax_overdrive.text(0,0, "Overdrive", color="w", transform=self.ax_overdrive.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg}) 
     self.tx_cycles = self.ax_cycles.text(0,0, "Cyles", color="w", transform=self.ax_cycles.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg}) 

     self.ax_image.imshow(mpimg.imread('mmbRy.jpg')) 
     self.ax_image.tick_params(axis='x',which='both',bottom='off', top='off',labelbottom='off') 
     self.ax_image.tick_params(axis='y',which='both',left='off', right='off',labelleft='off') 
     [self.ax_image.spines[wh].set_color("#5998ff") for wh in ['bottom', 'top', 'left', 'right']] 

     self.timer = self.fig.canvas.new_timer(interval=250, callbacks=[(self.animate, [], {})]) 
     self.timer.start() 
     plt.show() 


    def plot(self, data, line): 
     if data: 
      last_dt = data[0][0] 
      gap = timedelta(seconds=10) 
      x = [] 
      y = [] 
      # Plot groups of data not more than 60 seconds apart 
      for dt, ten in data: 
       if dt <= last_dt + gap: 
        x.append(dt) 
        y.append(ten) 
       else: 
        line.set_data(matplotlib.dates.date2num(x), y) 
        #ax.plot(, colour, linewidth=width) 
        x = [dt] 
        y = [ten] 
       last_dt = dt 
      line.set_data(matplotlib.dates.date2num(x), y) 


    def animate(self): 
     self.i +=1 #counting the number of frames 
     # Read in the CSV file 
     data = collections.defaultdict(list) 
     fields = ["TimeStamp", "ReadCount", "Antenna", "Protocol", "RSSI", "EPC", "Temp", "Ten", "Powr", "Unpowr", "Inf"] 
     temp = "" 
     # the complete file is read in, which might be a problem once the file gets very large 
     with open('SensorLogFile.csv') as f_input: 
      csv_input = csv.DictReader(f_input, skipinitialspace=True, fieldnames=fields) 
      header = next(csv_input) 
      # Separate the rows based on the Antenna field 
      for row in csv_input: 
       try: 
        data[row['Antenna']].append([self.stime(row['TimeStamp']), self.rten(row['Ten']) ]) 
        temp= row['Temp'] 
       except: 
        pass 

     # Drop any data points more than 1.5 mins older than the last entry 
     latest_dt = data[row['Antenna']][-1][0]  # Last entry 
     not_before = latest_dt - timedelta(minutes=.25) 

     for antenna, entries in data.items(): 
      data[antenna] = [[dt, count] for dt, count in entries if dt >= not_before] 

     self.plot(data['1'], self.line1)  # Antenna 1 
     self.plot(data['2'], self.line2)  # Antenna 2 
     self.plot(data['3'], self.line3)  # Antenna 3 

     #Filling the text boxes 
     self.tx_temp.set_text(u"Temperature\n{temp:.2f} °F".format(temp=self.deg2F(temp))) 
     self.tx_time.set_text("Time\n{time}".format(time=datetime.now().time())) 
     self.tx_overdrive.set_text("Overdrive\nfill later") 
     #Todo: how do you calculate this? 
     self.tx_cycles.set_text("Cyles\n{cyles}".format(cyles=self.i)) 
     #Todo: setting the limits correctly, depending on the user's need 
     self.ax.set_ylim([0,16])  
     self.ax.set_xlim([matplotlib.dates.date2num(not_before), matplotlib.dates.date2num(latest_dt)]) 
     #Update the canvas 
     self.fig.canvas.draw() 


    def deg2F(self,deg): 
     return float(deg) * 9./5. + 32. 

    def stime(self, timestamp): 
     return datetime.strptime(timestamp, '%m/%d/%Y %H:%M:%S.%f') 

    def rten(self, ten): 
     return int(float(ten) * self.slope + self.offset) 


if __name__ == "__main__": 
    Anim() 
+0

1)理想的には、はい、本当の時間がいいだろう。リアルタイムにかなり近いことがわかっている瞬間、これは250 msごとに実行されています。 2)データがcsvに書き込まれているとき(すべてではない)、250msごとに新しい値が到着します。 3)このために対話性は必要ありません。上にグラフが表示されているディスプレイ、下に表示されているライブデータを表示して写真を表示するセルです。ああ、私はMatplotlibだけでそのすべてを行うことができますか?プロット作成コードは、データ(すなわち、temp)をプルし、式を実行してセルにライブ出力番号を表示するためにどのように見えるでしょうか? – Jeffrey

+0

"Temp" "Time" "Overdrive" "Cycles"をグラフではなく数値形式にしますか? Matplotlibは言うまでもなく 'ax.text(x_coord、y_coord、" E036115348A908CB ")を使って簡単なテキストを表示することができます。プロットはすべて問題ではありません。問題は250msごとにファイルを読み取ることです。 – ImportanceOfBeingErnest

+0

これは私が探しているものに非常に近いです!私はそれをテストしたし、x軸が前のようなデータの最後の '.25'分を表示していないように見えるが、今は固まって新しいデータを実際に表示していないようだ。温度は素晴らしいですが、時間の表示からは時間のデータを引っ張ってはいけませんが、コンピュータの時計などを使用してください(それ以外の場合は、センサーが範囲外になると時間が凍ります)。 – Jeffrey

関連する問題