11

我不知道如何在 FuncAnimation 情节(使用 blit)上获得动画标题。基于http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/Python/Matplotlib - Quickly Updating Text on Axes,我构建了一个动画,但文本部分刚刚获胜没有动画。简化示例:

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_title和 而失败ax.text

编辑:我发现了为什么第一个链接中的第二个示例有效;文字在img零件内。如果你把上面1.005的 a .99,你会明白我的意思。可能有一种方法可以用边界框来做到这一点,不知何故......

4

3 回答 3

20

请参阅动画 matplotlib 轴/刻度python matplotlib blit 到图形的轴或边?

所以,问题在于,在animation实际保存 blit 背景的地方(animation.py的第 792 行),它抓取了边界框中的内容。当您有多个轴被独立动画时,这是有道理的。在您的情况下,您只需要axes担心一个,我们希望在轴边界框之外设置动画。通过一些猴子补丁,对进入 mpl 的内部并稍微戳一下的容忍度,并接受最快和最肮脏的解决方案,我们可以这样解决您的问题:

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 中有代码可以做到这一点,但我不知道它在哪里。

于 2013-07-10T05:03:03.773 回答
9

要添加到 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()
于 2015-06-16T06:13:59.223 回答
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()
于 2013-07-09T22:33:17.433 回答