用Matplotlib製作動畫

下面是駐波隨時間的變化。用Matplotlib製作動畫,關鍵要用到animation這個包中的FuncAnimation。下面我們一步一步來看如何實現動畫效果。

https://www.zhihu.com/video/929834002282491904

動畫實現的基本原理

Matplotlib中動畫實現的原理跟其它一樣,就是讓多幅圖連續播放,每一幅圖叫做一幀(frame)。那麼只要我們不斷修改圖中的曲線,讓其連續變化,那麼就得到動畫效果。

所以設計動畫的核心就是如何讓曲線的屬性發生改變。

修改曲線的屬性--面向對象編程

如果要修改曲線或者圖形的屬性,或者任何對象的屬性。大家要對面向對象編程有些了解。在Matplotlib中我們調用的任何函數,都會返回一個對象的實例。這樣我們就可以直接修改相應屬性即可改變曲線。

舉個例子,當我們用plot函數畫圖的時候,其實它會返回一個叫做line類的實例,這裡面包含了很多信息,看如下代碼,我們把一條sin曲線改為直線。注意代碼中plot返回了L1。注意L1具有set_data這個屬性。

from numpy import *from pylab import *x=linspace(0,2*pi,100)y=sin(x)L1,=plot(x,y)L1.set_data((x,x))ylim(0,2*pi)show()

好了,通過上面的程序,大家應該可以看到,我們只要修改實例中屬性,那麼曲線就會發生改變。其實除了plot外,可以說任意函數返回值都會是某種類的實例。比方legend返回的就legend的實例、figure返回的就是figure的實例等等,不一而足。

FuncAnimation函數的介面

FuncAnimation(fig, func, frames=None,fargs=None)

FuncAnimation的參數比較多,這裡只列舉出最重要的四個。

  • fig: 指得是目前曲線所在在的figure。
  • func: 這個函數主要是修改lines的屬性,並返回。
  • frames: 這是func參數中,跟每一幀相關的參數,靠它曲線才會發生變化。
  • fargs: 對應func中其他參數。

這個函數中的其他參數我們放在最後再介紹兩個常用的。

以行波為例說明如何設計介面中的參數

下面我們要畫一個動畫,表示行波,那麼怎麼設定以上參數呢?逐個來看。

fig是我們畫圖時自動產生,或者調用figure或其他函數獲得的,不是重點。重點是如何設計其他參數,特別是func。

如果要畫一列行波,那麼func必須是cos函數的樣子,並且隨時間變化,所以我們首先定義這個函數。如下:

def WW(t,omega,k): x=linspace(0,10,100) return (x,cos(omega*t-k*x))

這樣就產生了一列朝右傳播的行波,注意這還不是func函數。

接著我們要定義func函數,除了調用WW函數外,還要將WW函數產生的數據寫入到圖中的曲線。

def update(t,omega,k): x,y=WW(t,omega,k) line.set_data((x,y)) ax.set_xlim(0,10) ax.set_ylim(-1,1) return line

update函數對應每一幀。第一個參數是某個時刻t,omega和k分別跟WW函數對應,為頻率和波矢。除了調用WW外,還對line的屬性修改,並返回line。

將所有內容整理在一段代碼中結果如下。

import matplotlib.animation as animationfrom pylab import *from numpy import *omega=0.1Lambda=2#omega2=0.07k=2*pi/Lambdadef WW(t,omega,k): x=linspace(0,10,100) return (x,cos(omega*t-k*x))def update(t,omega,k): x,y=WW(t,omega,k) line.set_data((x,y)) ax.set_xlim(0,10) ax.set_ylim(-1,1) return linefig, ax = plt.subplots()line, = ax.plot([], [], lw=2)ani = animation.FuncAnimation(fig, update,frames=800,fargs=(omega,k))show()

注意這裡面FuncAnimation參數。特別是frames,它設定了一共有多少幀,實際上調用arange(frames)產生了這麼多數據,每一次傳遞一個數據給update函數的第一個參數,這樣就相當於時間在變化。那麼fargs是update中後面兩個參數的數據,它不限定參數的數量。

frames可以是整數,列表,甚至其他都可以,具體大家可以參考matplotlib.animation.FuncAnimation - Matplotlib 2.1.1 documentation 和 matplotlib繪製動畫的示例 - CSDN博客。

如何保存動畫

為了保存動畫,利用下面這段代碼就可以了。這裡的意思是,當我們調用FuncAnimation返回的對象為ani,自帶屬性save,那麼一般我們默認把它保存成html5,如果需要制定格式,加後綴即可。我們這裡加了mp4,即保存為mp4。在保存為視頻格式時,會調用ffmpeg,如果沒有安裝的話,可以在anaconda中安裝。

ani.save(Liss.mp4)

把上面的代碼總結在一起得到:

mport matplotlib.animation as animationfrom pylab import *from numpy import *omega=0.1Lambda=2#omega2=0.07k=2*pi/Lambdadef WW(t,omega,k): x=linspace(0,10,100) return (x,cos(omega*t-k*x))def update(i,omega,k): x,y=WW(i,omega,k) line.set_data((x,y)) ax.set_xlim(0,10) ax.set_ylim(-1,1) return linefig, ax = plt.subplots()line, = ax.plot([], [], lw=2)ani = animation.FuncAnimation(fig, update,frames=800,fargs=(omega,k))ani.save(Liss.mp4)

和如下視頻。

https://www.zhihu.com/video/930038032862625792
推薦閱讀:

VLCP協程框架簡介
【20170627】將數據導入到Python中(sql&excel)
第八章 對象引用、可變性
三十歲從電氣轉行 IT 是否可行?

TAG:動畫 | Matplotlib | Python |