今天把 MATPLOTLIB的動態散點圖程式碼 讀懂了
程式碼如下:
心得後附。
import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np class AnimatedScatter(object): """An animated scatter plot using matplotlib.animations.FuncAnimation.""" def __init__(self, numpoints=50): self.numpoints = numpoints self.stream = self.data_stream() # Setup the figure and axes... self.fig, self.ax = plt.subplots() # Then setup FuncAnimation. self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, init_func=self.setup_plot, blit=True) def setup_plot(self): """Initial drawing of the scatter plot.""" x, y, s, c = next(self.stream) self.scat = self.ax.scatter(x, y, c=c, s=s, animated=True) self.ax.axis([-10, 10, -10, 10]) # For FuncAnimation's sake, we need to return the artist we'll be using # Note that it expects a sequence of artists, thus the trailing comma. return self.scat, def data_stream(self): """Generate a random walk (brownian motion). Data is scaled to produce a soft "flickering" effect.""" data = np.random.random((4, self.numpoints)) xy = data[:2, :] s, c = data[2:, :] xy -= 0.5 xy *= 10 while True: xy += 0.03 * (np.random.random((2, self.numpoints)) - 0.5) s += 0.05 * (np.random.random(self.numpoints) - 0.5) c += 0.02 * (np.random.random(self.numpoints) - 0.5) yield data def update(self, i): """Update the scatter plot.""" data = next(self.stream) # Set x and y data... self.scat.set_offsets(data[:2, :]) # Set sizes... self.scat._sizes = 300 * abs(data[2])**1.5 + 100 # Set colors.. self.scat.set_array(data[3]) # We need to return the updated artist for FuncAnimation to draw.. # Note that it expects a sequence of artists, thus the trailing comma. return self.scat, def show(self): plt.show() if __name__ == '__main__': a = AnimatedScatter() a.show()
簡單解釋一下程式,我的理解
1. 程式定義了一個動態散點類
然後在主程式中例項化了這個類並呼叫了類的show()函式
class AnimatedScatter(object):
...
if __name__ == '__main__':
a = AnimatedScatter()
a.show()
2. 下面看看這個類都實現的功能
class AnimatedScatter(object):
def __init__(self, numpoints=50):
def setup_plot(self):
def data_stream(self):
def update(self, i):
def show(self):
上述函式,其實都是為了這句服務的:self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, init_func=self.setup_plot, blit=True)
3. 下面對程式進行註釋
import matplotlib.pyplot as plt #引入pyplot繪圖函式
import matplotlib.animation as animation #引入動畫函式
import numpy as np
class AnimatedScatter(object): #定義類
def __init__(self, numpoints=50): #定義類初始函式 請與 繪圖的初始化函式區分開
self.numpoints = numpoints #散點數為50
self.stream = self.data_stream() #呼叫類的資料流函式,此函式提供了無盡的資料流,給50個散點的X,Y座標,s是直徑,c是顏色這4個值進行賦值。相當於每次迭代提供(4,50)的一個數據塊。
self.fig, self.ax = plt.subplots() #設定繪圖畫布及繪圖區域
self.ani = animation.FuncAnimation(self.fig, self.update, interval=5,
init_func=self.setup_plot, blit=True) #進入此句後,程式進入迭代狀態,直到退出。此FuncAnimation()函式先呼叫init_func對畫面初始化,然後以5ms一幀的速率用update函式進行迭代。blit是指動態圖進行位塊輸送的優化。
def setup_plot(self): #設定繪畫,相當於繪圖的初始化函式
x, y, s, c = next(self.stream) #迭代,用stream對x,y,s,c進行一次賦值,注意stream指向data_stream()
self.scat = self.ax.scatter(x, y, c=c, s=s, animated=True) # 利用上述值繪製散點圖
self.ax.axis([-10, 10, -10, 10]) #設立X,Y座標軸的起始與終止點
return self.scat, # 初始化函式返回散點圖的控制代碼
def data_stream(self): #資料流函式,注意此函式在繪圖的初始化函式和迭代函式中均被呼叫
data = np.random.random((4, self.numpoints))#初始化一個(4,50)陣列,陣列中數為【0,1)的隨機數
xy = data[:2, :] #取陣列的前2行,為50個點 的XY座標賦值,注意xy是指向data陣列前兩行的指標
s, c = data[2:, :] #取陣列的後兩行,分別為50個點的S和C賦值,同上,S和C指向data陣列後兩行
xy -= 0.5 #對XY的值做調整
xy *= 10 #對XY的值做調整,以便匹配-10:10的座標
while True: #進入迭代,每次上個函式setup_pl
xy += 0.03 * (np.random.random((2, self.numpoints)) - 0.5) #迭代直接修改了data的值
s += 0.05 * (np.random.random(self.numpoints) - 0.5)
c += 0.02 * (np.random.random(self.numpoints) - 0.5)
yield data #返回data值,注意data是個(4,50)的陣列
def update(self, i): #此函式每次迭代都會被呼叫,此函式在繪製動態圖中已經被定義為迭代函式,此迭代函式的作用是利用data的值,給散點函式的50個點重新賦值,此i有何作用還請大牛指點。
data = next(self.stream) #更新data值
self.scat.set_offsets(data[:2, :]) #設定散點的XY
self.scat._sizes = 300 * abs(data[2])**1.5 + 100#設定散點直徑
self.scat.set_array(data[3]) #設定散點顏色
# We need to return the updated artist for FuncAnimation to draw..
# Note that it expects a sequence of artists, thus the trailing comma.
return self.scat, #為何返回散點繪圖函式控制代碼,不明白?是因為動畫函式需要麼?
def show(self): #開始繪製函式
plt.show()
if __name__ == '__main__': #主函式
a = AnimatedScatter() #定義類,注意定義類會呼叫類的初始化函式,從而啟動整個流程
a.show() # 開始繪製,這步只是將上一步的繪製顯示到螢幕上,具體為什麼能從上面的迭代過程跳出來開始繪製動畫,這個我也不懂啥機制。