Python matplotlib中的动画标题

Python matplotlib中的动画标题,python,animation,matplotlib,Python,Animation,Matplotlib,我不知道如何在动画情节(使用blit)上获得动画标题。基于和,我构建了一个动画,但是文本部分不会动画。简化示例: 导入matplotlib.pyplot作为plt 将matplotlib.animation导入为动画 将numpy作为np导入 vls=np.linspace(0,2*2*np.pi,100) 图=plt.图() img,=plt.plot(np.sin(vls)) ax=plt.axs() ax.set_xlim([0,2*2*np.pi]) #ttl=ax.set\u标题(“”

我不知道如何在动画情节(使用blit)上获得动画标题。基于和,我构建了一个动画,但是文本部分不会动画。简化示例:

导入matplotlib.pyplot作为plt
将matplotlib.animation导入为动画
将numpy作为np导入
vls=np.linspace(0,2*2*np.pi,100)
图=plt.图()
img,=plt.plot(np.sin(vls))
ax=plt.axs()
ax.set_xlim([0,2*2*np.pi])
#ttl=ax.set\u标题(“”,动画=True)
ttl=ax.text(.5,1.005',transform=ax.transAxes)
def init():
ttl.set_文本(“”)
img.set_数据([0],[0])
返回img,ttl
def func(n):
ttl.set_文本(str(n))
img.set_数据(vls,np.sin(vls+.02*n*2*np.pi))
返回img,ttl
ani=animation.FuncAnimation(图,func,init_func=init,frames=50,interval=30,blit=True)
plt.show()
如果删除
blit=True
,文本将显示,但速度会减慢。它似乎失败于
plt.title
ax.set\u title
,以及
ax.text

编辑:我发现了第一个链接中的第二个示例为什么有效;文本在
img
部分中。如果你把上面的
1.005
a
.99
,你就会明白我的意思了。也许有一种方法可以通过边界框来实现这一点,不知何故…

您必须调用

plt.draw()
之后


这里有一个非常简单的示例,演示了一个图形“无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()
看到和

因此,问题在于,在实际保存blit背景(的第792行)的
动画中,它获取轴边界框中的内容。当多个轴独立设置动画时,这是有意义的。在您的例子中,您只需要担心一个
,我们希望在轴边界框之外设置动画。通过一点猴子补丁、一点深入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()
请注意,如果您的图形中有多个轴,这可能无法按预期工作。更好的解决方案是展开
轴.bbox
,刚好可以捕获标题+轴刻度标签。我怀疑mpl中有这样做的代码,但我不知道它在哪里。要添加到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()

如果需要修复标题,可以使用以下内容更新标题:

fig.suptitle()

请参见该图。

这确实绘制了它,但它减慢了它的速度,与blit=False的速度相同。我希望只是重新绘制文本。为什么不干脆避免动画,用plt.ion()制作自己的动画呢?有了它,你就有了很多的控制权,而且你肯定每一帧你都在做什么。。。看看fig=plt.figure()img,=plt.plot(np.sin(vls))ax=plt.axs()ax.set\uxlim([0,2*2*np.pi])title=ax.text(.5,1.005',transform=ax.transAxes)plt.ion(),用于范围(100)内的i:img.set\u数据(vls,np.sin(vls+.02*(i%50)*2*np.pi))title.set\utext(str(i%50))plt.draw,它仍然很慢,但我可以手动调用
canvas.blit
。我认为动画是一种较新的/首选的方法(而不是手动构建)。问题是“如何让blit在轴以外的艺术家身上工作”这是一种全速工作的方法!希望它包含在matplotlib中,与monkey patched相比,效果很好@HenrySchreiner您的编辑本应被接受。(我只是重新做了)。如果这解决了您的问题,您是否可以接受答案(左侧的大灰色复选框)。理想情况下,应该使用文本边界框(因为它是从动画函数传递的),但由于某种原因,它没有被使用(尽管我认为它在美术师中)。目前,这是一个合理的修复方法。:)谢谢@HenrySchreiner动画代码的边缘仍然有点粗糙。在主代码中不这样做有很好的理由(请参阅我的注意事项)。若你们想在主线上改进这一点,请这样做。mpl上的开发人员非常友好。如果我在
FuncAnimation
调用中使用
repeat=False
,然后等到动画完成并放大某个地方,绘图就会消失。@bretcj7我想你可以试一试。
fig.suptitle()