python中plot實作即時資料動态顯示方法
本人同類型部落格(新鮮的哦!)
matplotlib animation 繪制動畫:
資料收集(産生)完成後,再生成動态顯示。一般用于成果展示。生成各種格式的視訊,gif動态圖等。
本篇方法的特點:用于
實時
監測系統,
實時
資料可視化,一般用于系統調試過程。是以,matplotlib animation 繪制動畫不能完全取代本篇部落格。
在Matlab使用Plot函數實作資料動态顯示方法總結中介紹了兩種實作即時資料動态顯示的方法。考慮到使用python的人群日益增多,再加上本人最近想使用python動态顯示即時的資料,網上方法很少,故總結于此。本人主要在jupyter notebook作為互動式的python運作環境,但考慮不使用jupyter notebook的情況。是以下面主要分成針對jupyter notebook環境的增量式資料動态顯示方法,與通用的(jupyter notebook 與非juypter notebook都适用)方法兩大類。先介紹通用的方法,後介紹針對jupyter notebook的方法。接着給出一個更加實用的簡單例子,希望可以給大家更多的啟發。最後對博友運作本程式時遇到的問題做一個總結,并給出解決方法。
文章目錄
- python中plot實作即時資料動态顯示方法
-
- 1. 通用的方法
-
- 1.1 需要儲存曆史資料
- 1.2 無需儲存資料
- 1.3 無需儲存資料(進階版)
- 2. Jupyter notebook版本
-
- 2.1 需要儲存曆史資料
- 2.2 無需儲存曆史資料
- 2.3 無需儲存曆史資料(進階版)
- 3. 一個較為實際的應用示例——簡單的機器人仿真環境
- 4. 問題與解決
1. 通用的方法
1.1 需要儲存曆史資料
示例代碼1-1
import matplotlib.pyplot as plt
import numpy as np
import time
from math import *
plt.ion() #開啟interactive mode 成功的關鍵函數
plt.figure(1)
t = [0]
t_now = 0
m = [sin(t_now)]
for i in range(2000):
plt.clf() #清空畫布上的所有内容
t_now = i*0.1
t.append(t_now)#模拟資料增量流入,儲存曆史資料
m.append(sin(t_now))#模拟資料增量流入,儲存曆史資料
plt.plot(t,m,'-r')
plt.draw()#注意此函數需要調用
time.sleep(0.01)
備注:此代碼經過很多人測試發現不能呈現動态效果(我原本在ubuntu系統上是可以的,經驗證在windows上也不行),特在此說明,如果出不了動态效果,就将
plt.draw()
time.sleep(0.01)
替換為:
1.2 無需儲存資料
示例代碼1-2
import matplotlib.pyplot as plt
import numpy as np
import time
from math import *
plt.ion() #開啟interactive mode 成功的關鍵函數
plt.figure(1)
t = [0]
t_now = 0
m = [sin(t_now)]
for i in range(2000):
# plt.clf() # 清空畫布上的所有内容。此處不能調用此函數,不然之前畫出的點,将會被清空。
t_now = i*0.1
"""
由于第次隻畫一個點,是以此處有兩種方式,第一種plot函數中的樣式選
為點'.'、'o'、'*'都可以,就是不能為線段'-'。因為一條線段需要兩
個點才能确定。第二種方法是scatter函數,也即畫點。
"""
plt.plot(t_now,sin(t_now),'.') # 第次對畫布添加一個點,覆寫式的。
# plt.scatter(t_now, sin(t_now))
plt.draw()#注意此函數需要調用
time.sleep(0.01)
1.3 無需儲存資料(進階版)
以上是動态的顯示一個函數,也即直覺上一條軌迹不斷的延伸。這是一種應用,另一種應用是在一張畫布上增量式的畫多條軌迹(函數)。
示例代碼1-3
import matplotlib.pyplot as plt
import numpy as np
import time
from math import *
plt.ion() #開啟interactive mode 成功的關鍵函數
plt.figure(1)
t = np.linspace(0, 20, 100)
for i in range(20):
# plt.clf() # 清空畫布上的所有内容。此處不能調用此函數,不然之前畫出的軌迹,将會被清空。
y = np.sin(t*i/10.0)
plt.plot(t, y) # 一條軌迹
plt.draw()#注意此函數需要調用
time.sleep(1)
2. Jupyter notebook版本
也對應三種應用:需要儲存曆史資料,無需儲存曆史資料,無需儲存曆史資料進階版。
注意:在Jupyter notebook中顯示python的畫圖程式時,需要添加
%matplotlib inline
,但是身邊有人運作本部落格中的程式時會出現無法正常顯示動态圖檔的情況,并且本人在自己電腦windows 10環境下(python 3.6)運作本文中動态顯示圖檔的程式時,也會出現上述情況。出現該情況,隻需要将程式中出現的所有
inline
改為
qt5
,例如
%matplotlib inline
改為
%matplotlib qt5
,以及
is_ipython = 'inline' in matplotlib.get_backend()
改為
is_ipython = 'qt5' in matplotlib.get_backend()
即可。基于QT的圖形顯示界面會跳出jupyter notebook顯示動态圖,而且會多出許多可選的按鈕。大家可以自行探索。建議大家,先運作本文的程式,如果不成功,再做此改變。因為,原本
inline
成功的,改為
qt5
後,可能反而不成功。
2.1 需要儲存曆史資料
示例代碼2-1
上面的方式,可以在跳出的畫圖面闆内動态顯示,但是如果想在jupyter notebook中直接動态顯示,上面的方法将無效。是以,補上在jupyter notebook中可行的動态顯示示例程式。以供舉一反三之用。
import math
import random
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
# set up matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
from IPython import display
plt.ion()
def plot_durations(y):
plt.figure(2)
plt.clf()
plt.subplot(211)
plt.plot(y[:,0])
plt.subplot(212)
plt.plot(y[:,1])
plt.pause(0.001) # pause a bit so that plots are updated
if is_ipython:
display.clear_output(wait=True)
display.display(plt.gcf())
x = np.linspace(-10,10,500)
y = []
for i in range(len(x)):
y1 = np.cos(i/(3*3.14))
y2 = np.sin(i/(3*3.14))
y.append(np.array([y1,y2])) #儲存曆史資料
plot_durations(np.array(y))
2.2 無需儲存曆史資料
示例代碼2-2
import math
import random
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
# set up matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
from IPython import display
plt.ion()
def plot_durations(i, y1, y2):
plt.figure(2)
# plt.clf() 此時不能調用此函數,不然之前的點将被清空。
plt.subplot(211)
plt.plot(i, y1, '.')
plt.subplot(212)
plt.plot(i, y2, '.')
plt.pause(0.001) # pause a bit so that plots are updated
if is_ipython:
display.clear_output(wait=True)
display.display(plt.gcf())
x = np.linspace(-10,10,500)
y = []
for i in range(len(x)):
y1 = np.cos(i/(3*3.14))
y2 = np.sin(i/(3*3.14))
# y.append(np.array([y1,y2])) #儲存曆史資料
plot_durations(i, y1, y2)
2.3 無需儲存曆史資料(進階版)
示例代碼2-3
import math
import random
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
# set up matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
from IPython import display
plt.ion()
def plot_durations(y1, y2):
plt.figure(2)
# plt.clf()
plt.subplot(211)
plt.plot(x, y1)
plt.subplot(212)
plt.plot(x, y2)
plt.pause(0.001) # pause a bit so that plots are updated
if is_ipython:
display.clear_output(wait=True)
display.display(plt.gcf())
x = np.linspace(-10,10,500)
for i in range(100):
y1 = np.cos(x*i/(3*3.14))
y2 = np.sin(x*i/(3*3.14))
plot_durations(y1, y2)
3. 一個較為實際的應用示例——簡單的機器人仿真環境
視訊是由一系例圖檔按時間順序排列組成的。即然能夠基于以上程式實作簡單的動态顯示,進一步的,我們可以利用本文的代碼片段建構自己的簡易仿真環境,用于初步驗證算法。下面的gif圖就是利用本文的代碼片驗證了一個簡單的機器人全局——局部兩層路徑規劃算法。相信大家能夠根據自己的應用背景,得到不同的有意思的動态顯示結果。
其中,藍色圓圈為機器人,黑色為障礙物(有動态與靜态兩種),紅圏表示機器人要到達的目标點,綠色三角形表示機器人目前局部的目标點(由算法根據目前環境與機器人的狀态計算得到),最終的運作軌迹會以紅線顯示。
4. 問題與解決
為了節省大家的時間,這部分主要收集大家運作以上程式時遇到的問題,并給出解決方案。
如果運作以上程式發現運作異常,按以下兩步修改
- 将
替換為plt.draw() time.sleep(0.01)
運作,看是否正常。plt.pause(0.01)
- 如果還不行,就把
也注釋掉再運作。plt.pause(0.01)
部落格中的示例程式都是本人在某些系統上運作成功的,如果某一行代碼導緻程式在你的系統上運作失敗,并不是說這一行代碼完全是多餘的。經過我測試,示例程式2-1如果注釋了,以及
plt.pause(0.01)
(有時我們不小心用了這個程式,又想讓動态圖單獨跳出一個視窗運作),我在ubuntu 14.04上的測試結果是顯示不了圖。但是,我重新用上暫停函數
%matplotlib inline
,程式就能正常在跳出的視窗顯示動态圖了。建議先直接運作示例程式,如果錯誤再按要求修改,沒有錯誤就不用修改。
plt.pause(0.01)