如何使用动画更新matplotlib的情节标题?

时间:2017-06-16 17:25:36

标签: python matplotlib

在我的代码下面。为什么每个滴答都没有标题更新?我读到了这个:Matplotlib animation with blit -- how to update plot title?但它没有用。

#! /usr/bin/python3
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
import random as rr

plt.rc('grid', color='#397939', linewidth=1, linestyle='-')
plt.rc('xtick', labelsize=10)
plt.rc('ytick', labelsize=5)

width, height = matplotlib.rcParams['figure.figsize']
size = min(width, height)
fig = plt.figure(figsize=(size, size))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True, facecolor='#cfd98c')

ax.set_rmax(20.0)
plt.grid(True)
plt.title("")
def data_gen(t=0):
    tw = 0
    phase = 0
    ctn = 0
    while True:
        ctn += 1
        if ctn == 1000:
            phase=round(rr.uniform(0,180),0)
            tw = round(rr.uniform(0,20),0)
            ctn = 0
            yield tw, phase
def update(data):
    tw, phase = data
    print(data)
    ax.set_title("|TW| = {}, Angle: {}°".format(tw, phase)) 
    arr1 = plt.arrow(phase, 0, 0, tw, alpha = 0.5, width = 0.080,
             edgecolor = 'red', facecolor = 'red', lw = 2, zorder = 5)
    return arr1,

ani = animation.FuncAnimation(fig, update, data_gen, interval=100, blit=True, repeat=False)
plt.show()

编辑n。 1 在@eyllanesc回答之后,我编辑了这段代码:

def data_gen(t=0):
    tw = 10
    phase = 0
    ctn = 0
    while True:
        if phase < 2*180:
            phase += 1
        else:
            phase=0
        yield tw, phase

def update(data):
    tw, phase = data
    angolo = phase /180 * np.pi
    print("|TW| = {}, Angle = {}°".format(tw,phase))
    ax.set_title("|TW| = {}, Angle: {}°".format(tw, phase)) 
    arr1 = plt.arrow(angolo, 0, 0, tw, alpha = 0.5, width = 0.080, edgecolor = 'red', facecolor = 'red', lw = 2, zorder = 5)
    plt.draw()
    return arr1,

现在文字工作正常,但箭头更新不是&#34;流畅&#34; (它出现并消失每次更新)。

1 个答案:

答案 0 :(得分:9)

blit=True中使用FuncAnimation时出现问题。这将存储背景并仅更新由更新功能返回的艺术家。但是,恢复后的背景将覆盖标题,因为它位于轴外。

可能的解决方案是:

  1. 将标题放在轴内。
  2. 不要使用blitting
  3. 可能使用ArtistAnimation代替FuncAnimation也可以。但我还没有测试过它。
  4. 请注意,在更新功能中使用plt.draw或类似内容(如在其他答案中所提议的)是没有意义的,因为它破坏了使用blitting的所有优点并且使动画甚至比不使用blitting时更慢使用blitting。

    1。将标题放在轴(blit=True

    您可以在轴内使用title = ax.text(..),而不是轴外的标题。可以为每次迭代title.set_text("..")更新此文本,然后必须由更新函数(return arr1, title,)返回。

    import matplotlib
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    
    plt.rc('grid', color='#397939', linewidth=1, linestyle='-')
    plt.rc('xtick', labelsize=10)
    plt.rc('ytick', labelsize=5)
    
    width, height = matplotlib.rcParams['figure.figsize']
    size = min(width, height)
    fig = plt.figure(figsize=(size, size))
    ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True, facecolor='#cfd98c')
    
    ax.set_rmax(20.0)
    plt.grid(True)
    
    title = ax.text(0.5,0.85, "", bbox={'facecolor':'w', 'alpha':0.5, 'pad':5},
                    transform=ax.transAxes, ha="center")
    
    def data_gen(t=0):
        tw = 10
        phase = 0
        while True:
            if phase < 2*180:
                phase += 2
            else:
                phase=0
            yield tw, phase
    
    def update(data):
        tw, phase = data
        title.set_text(u"|TW| = {}, Angle: {}°".format(tw, phase))
        arr1 = ax.arrow(np.deg2rad(phase), 0, 0, tw, alpha = 0.5, width = 0.080,
                 edgecolor = 'red', facecolor = 'red', lw = 2, zorder = 5)
        return arr1,title,
    
    ani = animation.FuncAnimation(fig, update, data_gen, interval=100, blit=True, repeat=False)
    
    plt.show()
    

    enter image description here

    请注意,我稍微改变了角度设置,因为arrow的角度必须是辐射而不是度。

    2。不使用blitting(blit=False

    你可能决定不使用blitting,这对动画速度的要求不那么高是有意义的。不使用blitting允许使用轴外的普通标题。但是,在这种情况下,您需要为每次迭代删除艺术家(否则最终会在图中出现很多箭头)。

    import matplotlib
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    
    plt.rc('grid', color='#397939', linewidth=1, linestyle='-')
    plt.rc('xtick', labelsize=10)
    plt.rc('ytick', labelsize=5)
    
    width, height = matplotlib.rcParams['figure.figsize']
    size = min(width, height)
    fig = plt.figure(figsize=(size, size))
    ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True, facecolor='#cfd98c')
    
    ax.set_rmax(20.0)
    plt.grid(True)
    
    def data_gen(t=0):
        tw = 10
        phase = 0
        while True:
            if phase < 2*180:
                phase += 2
            else:
                phase=0
            yield tw, phase
    
    arr1 = [None]
    def update(data):
        tw, phase = data
        ax.set_title(u"|TW| = {}, Angle: {}°".format(tw, phase))
        if arr1[0]: arr1[0].remove()
        arr1[0] = ax.arrow(np.deg2rad(phase), 0, 0, tw, alpha = 0.5, width = 0.080,
                 edgecolor = 'red', facecolor = 'red', lw = 2, zorder = 5)
    
    ani = animation.FuncAnimation(fig, update, data_gen, interval=100, blit=False, repeat=False)
    
    plt.show()
    

    enter image description here