2017-03-06 60 views
1

試圖創建一個程序,讀取串行數據,並更新多個圖(1線和2條形圖現在但也可能是更多)。如何使用FuncAnimation使用matplotlib更新和動畫多個數字?

使用到FuncAnimation 3個獨立的電話()的權利,但被證明是很慢這是不好的,因爲我還需要在未來增加更多的動畫人物的選項。

所以,我怎麼能使其成爲一個單一的FuncAnimation(或者類似的東西),更新所有三個(可能更多)的數字?或者,我可以做些什麼來加快它的速度?

#figure for current 
amps = plt.figure(1) 
ax1 = plt.subplot(xlim = (0,100), ylim = (0,500)) 
line, = ax1.plot([],[]) 
ax1.set_ylabel('Current (A)') 

#figure for voltage 
volts = plt.figure(2) 
ax2 = plt.subplot() 
rects1 = ax2.bar(ind1, voltV, width1) 
ax2.grid(True) 
ax2.set_ylim([0,6]) 
ax2.set_xlabel('Cell Number') 
ax2.set_ylabel('Voltage (V)') 
ax2.set_title('Real Time Voltage Data') 
ax2.set_xticks(ind1) 

#figure for temperature 
temp = plt.figure(3) 
ax3 = plt.subplot() 
rects2 = ax3.bar(ind2, tempC, width2) 
ax3.grid(True) 
ax3.set_ylim([0,101]) 
ax3.set_xlabel('Sensor Number') 
ax3.set_ylabel('temperature (C)') 
ax3.set_title('Real Time Temperature Data') 
ax3.set_xticks(ind2) 

def updateAmps(frameNum): 

    try: 
    #error check for bad serial data 
     serialString = serialData.readline() 
     serialLine = [float(val) for val in serialString.split()] 
     print (serialLine) 

     if (len(serialLine) == 5): 
      voltV[int(serialLine[1])] = serialLine[2] 
      tempC[int(serialLine[3])] = serialLine[4] 
      currentA.append(serialLine[0]) 
      if (len(currentA)>100): 
       currentA.popleft() 

     line.set_data(range(100), currentA) 

    except ValueError as e: 
    #graphs not updated for bad serial data 
     print (e) 

    return line, 

#function to update real-time voltage data 
def updateVolts(frameNum): 

    for rects, h in zip(rects1,voltV): 
     rects.set_height(h) 

    return rects1 

#function to update real-time temperature data 
def updateTemp(frameNum): 

    for rects, h in zip(rects2,tempC): 
     rects.set_height(h) 

    return rects2 

電話funcAnimation:

anim1 = animation.FuncAnimation(amps, updateAmps, 
           interval = 20, blit = True) 
anim2 = animation.FuncAnimation(volts, updateVolts, interval = 25, blit = True) 
anim3 = animation.FuncAnimation(temp, updateTemp, interval = 30, blit = True) 
+0

有兩種機制可以在這裏限制速度:(1)讀取串行數據的時間和(2)繪製藝術家到畫布上的時間。它不應該與您擁有的FuncAnimations的數量有關。我建議你分別調查兩件事。如果您使用單個動畫(例如,只有anim1),速度會更快嗎? – ImportanceOfBeingErnest

+0

@ImportanceOfBeingErnest不認爲這是讀取串行數據的時間。擁有一個FuncAnimation似乎可以加快速度。當程序開始變得有點波動時,點擊3個FuncAnimations後會有明顯的不同。 另外,我還需要潛在再添3個實時數據圖表這就是爲什麼我需要找到一種方法,現在來優化它,因爲我不認爲它會去好,如果我按照當前implentation。 – user3458571

+0

因此,下一個測試用例將是將所有三個圖作爲子圖展示給同一個圖,並使用單個FuncAnimation。比較這與三種不同的動畫的情況。它顯着更快嗎?如果是這樣,考慮是否有一個數字實際上可以接受你的情況。 – ImportanceOfBeingErnest

回答

1

呼應@ ImportanceOfBeingErnest的評論,顯而易見的解決辦法是使用3個次要情節,只有一個FuncAnimation()電話。您只需確保您的回調函數返回每次迭代中要更新的所有藝術家列表。

一個缺點是,更新將發生在所有3個副區(與你在你的例子有不同的時機)一個相同的時間間隔。你可以通過使用全局變量來解決這個問題,這些全局變量可以計算函數被調用了多少次,並且例如每隔一段時間只執行一些圖。

#figure 
fig = plt.figure(1) 
# subplot for current 
ax1 = fig.add_subplot(131, xlim = (0,100), ylim = (0,500)) 
line, = ax1.plot([],[]) 
ax1.set_ylabel('Current (A)') 

#subplot for voltage 
ax2 = fig.add_subplot(132) 
rects1 = ax2.bar(ind1, voltV, width1) 
ax2.grid(True) 
ax2.set_ylim([0,6]) 
ax2.set_xlabel('Cell Number') 
ax2.set_ylabel('Voltage (V)') 
ax2.set_title('Real Time Voltage Data') 
ax2.set_xticks(ind1) 

#subplot for temperature 
ax3 = fig.add_subplot(133) 
rects2 = ax3.bar(ind2, tempC, width2) 
ax3.grid(True) 
ax3.set_ylim([0,101]) 
ax3.set_xlabel('Sensor Number') 
ax3.set_ylabel('temperature (C)') 
ax3.set_title('Real Time Temperature Data') 
ax3.set_xticks(ind2) 

def updateAmps(frameNum): 

    try: 
    #error check for bad serial data 
     serialString = serialData.readline() 
     serialLine = [float(val) for val in serialString.split()] 
     print (serialLine) 

     if (len(serialLine) == 5): 
      voltV[int(serialLine[1])] = serialLine[2] 
      tempC[int(serialLine[3])] = serialLine[4] 
      currentA.append(serialLine[0]) 
      if (len(currentA)>100): 
       currentA.popleft() 

     line.set_data(range(100), currentA) 

    except ValueError as e: 
    #graphs not updated for bad serial data 
     print (e) 

    return line, 

#function to update real-time voltage data 
def updateVolts(frameNum): 

    for rects, h in zip(rects1,voltV): 
     rects.set_height(h) 

    return rects1 

#function to update real-time temperature data 
def updateTemp(frameNum): 

    for rects, h in zip(rects2,tempC): 
     rects.set_height(h) 

    return rects2 

def updateALL(frameNum): 
    a = updateAmps(frameNum) 
    b = updateVolts(frameNum) 
    c = updateTemp(frameNum) 
    return a+b+c 

animALL = animation.FuncAnimation(fig, updateALL, 
           interval = 20, blit = True) 
相關問題