2013-07-09 146 views
6

我無法弄清楚如何在FuncAnimation情節(使用blit)上獲得動畫標題。基於http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/Python/Matplotlib - Quickly Updating Text on Axes,我已經構建了一個動畫,但文本部分不會動畫。簡單的例子:matplotlib中的動畫標題

import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
import numpy as np 

vls = np.linspace(0,2*2*np.pi,100) 

fig=plt.figure() 
img, = plt.plot(np.sin(vls)) 
ax = plt.axes() 
ax.set_xlim([0,2*2*np.pi]) 
#ttl = ax.set_title('',animated=True) 
ttl = ax.text(.5, 1.005, '', transform = ax.transAxes) 

def init(): 
    ttl.set_text('') 
    img.set_data([0],[0]) 
    return img, ttl 
def func(n): 
    ttl.set_text(str(n)) 
    img.set_data(vls,np.sin(vls+.02*n*2*np.pi)) 
    return img, ttl 

ani = animation.FuncAnimation(fig,func,init_func=init,frames=50,interval=30,blit=True) 

plt.show() 

如果blit=True被刪除,文本顯示出來,但它減緩一路下滑。它似乎失敗,plt.title,ax.set_titleax.text

編輯:我發現爲什麼第一個鏈接的第二個例子工作;該文本在img部分。如果你使上述1.005 a .99,你會明白我的意思。有可能是一種方式具有邊框,不知何故做到這一點...

回答

14

Animating matplotlib axes/tickspython matplotlib blit to axes or sides of the figure?

那麼,問題是,在該塊傳輸的背景實際上是保存(行animation.py 792)的animation膽量,它抓住的是在邊界框。當您有多個獨立動畫的軸時,這是有意義的。在你的情況下,你只有一個axes擔心,我們想要動畫的動畫軸邊界框外。帶着幾分猴子修補,公差爲伸進MPL的膽量和周圍有點戳的水平,並接受最快,dirtyest解決方案,我們可以解決你的問題,因爲這樣的:

import matplotlib 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
import numpy as np 

def _blit_draw(self, artists, bg_cache): 
    # Handles blitted drawing, which renders only the artists given instead 
    # of the entire figure. 
    updated_ax = [] 
    for a in artists: 
     # If we haven't cached the background for this axes object, do 
     # so now. This might not always be reliable, but it's an attempt 
     # to automate the process. 
     if a.axes not in bg_cache: 
      # bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox) 
      # change here 
      bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.figure.bbox) 
     a.axes.draw_artist(a) 
     updated_ax.append(a.axes) 

    # After rendering all the needed artists, blit each axes individually. 
    for ax in set(updated_ax): 
     # and here 
     # ax.figure.canvas.blit(ax.bbox) 
     ax.figure.canvas.blit(ax.figure.bbox) 

# MONKEY PATCH!! 
matplotlib.animation.Animation._blit_draw = _blit_draw 

vls = np.linspace(0,2*2*np.pi,100) 

fig=plt.figure() 
img, = plt.plot(np.sin(vls)) 
ax = plt.axes() 
ax.set_xlim([0,2*2*np.pi]) 
#ttl = ax.set_title('',animated=True) 
ttl = ax.text(.5, 1.05, '', transform = ax.transAxes, va='center') 

def init(): 
    ttl.set_text('') 
    img.set_data([0],[0]) 
    return img, ttl 

def func(n): 
    ttl.set_text(str(n)) 
    img.set_data(vls,np.sin(vls+.02*n*2*np.pi)) 
    return img, ttl 

ani = animation.FuncAnimation(fig,func,init_func=init,frames=50,interval=30,blit=True) 

plt.show() 

注意,這如果圖中有多個軸,則可能無法按預期工作。一個更好的解決方案是擴展axes.bbox只需足以捕獲您的標題+軸刻度標籤。我懷疑在mpl中有代碼可以做到這一點,但我不知道它在哪裏。

+0

這工作全速!希望它被包含在matplotlib中,與猴子修補,但效果很好! –

+0

@HenrySchreiner您的編輯應該已被接受。 (我剛剛重新做到了)。如果這解決了你的問題,你可以接受答案(左邊的大灰色複選框)。 – tacaswell

+0

理想情況下,應該使用文本邊界框(因爲它是從動畫函數傳遞的),但由於某種原因它沒有被使用(即使我認爲它是在藝術家中)。這是現在修復它的一個合理的竅門。 :) 謝謝! –

1

必須調用

plt.draw() 

ttl.set_text(str(n)) 

在這裏有一個很簡單的例子沒有FuncAnimation()「的圖形內的文本動畫」。嘗試一下,你會看到它是否對你有用。

import matplotlib.pyplot as plt 
import numpy as np 
titles = np.arange(100) 
plt.ion() 
fig = plt.figure() 
for text in titles: 
    plt.clf() 
    fig.text(0.5,0.5,str(text)) 
    plt.draw() 
+1

這確實會繪製它,但它會減慢相同的量blit = False。我希望只是重新繪製文本。 –

+0

爲什麼不簡單地避免動畫,並用plt.ion()製作自己的動畫?有了它,你有很多的控制,你確定你在做什麼每一幀...看看http://stackoverflow.com/questions/17444655/dynamically-updating-a-graphed-line-in- python/17480397#17480397 – Pablo

+0

fig = plt.figure() img,= plt.plot(np.sin(vls)) ax = plt.axes() ax.set_xlim([0,2 * 2 * np。 π) 標題= ax.text(0.5,1.005, '',變換= ax.transAxes) plt.ion() 爲i的範圍(100): img.set_data(VLS,np.sin (vls + .02 *(i%50)* 2 * np.pi)) title.set_text(str(i%50)) plt.draw() –

2

要添加到tcaswell的「猴子修補」解決方案,以下是如何將動畫添加到軸刻度標籤。具體來說,要動畫x軸,請設置ax.xaxis.set_animated(True)並從動畫函數返回ax.xaxis

import matplotlib 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
import numpy as np 

def _blit_draw(self, artists, bg_cache): 
    # Handles blitted drawing, which renders only the artists given instead 
    # of the entire figure. 
    updated_ax = [] 
    for a in artists: 
     # If we haven't cached the background for this axes object, do 
     # so now. This might not always be reliable, but it's an attempt 
     # to automate the process. 
     if a.axes not in bg_cache: 
      # bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox) 
      # change here 
      bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.figure.bbox) 
     a.axes.draw_artist(a) 
     updated_ax.append(a.axes) 

    # After rendering all the needed artists, blit each axes individually. 
    for ax in set(updated_ax): 
     # and here 
     # ax.figure.canvas.blit(ax.bbox) 
     ax.figure.canvas.blit(ax.figure.bbox) 

# MONKEY PATCH!! 
matplotlib.animation.Animation._blit_draw = _blit_draw 

vls = np.linspace(0,2*2*np.pi,100) 

fig=plt.figure() 
img, = plt.plot(np.sin(vls)) 
ax = plt.axes() 
ax.set_xlim([0,2*2*np.pi]) 
#ttl = ax.set_title('',animated=True) 
ttl = ax.text(.5, 1.05, '', transform = ax.transAxes, va='center') 

ax.xaxis.set_animated(True) 

def init(): 
    ttl.set_text('') 
    img.set_data([0],[0]) 
    return img, ttl, ax.xaxis 

def func(n): 
    ttl.set_text(str(n)) 
    vls = np.linspace(0.2*n,0.2*n+2*2*np.pi,100) 
    img.set_data(vls,np.sin(vls)) 
    ax.set_xlim(vls[0],vls[-1]) 
    return img, ttl, ax.xaxis 

ani = animation.FuncAnimation(fig,func,init_func=init,frames=60,interval=200,blit=True) 

plt.show() 
1

如果您需要修復的標題,你可以只更新標題:

fig.suptitle() 

參見圖API document

+0

如果你打開了blitting,這個工作嗎? – bretcj7

+0

@ bretcj7我認爲你可以試一試。 – shane