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

tan*_*rea 8 python matplotlib

在我的代码下面.为什么标题不会每次更新?我读到这个:带blit的Matplotlib动画 - 如何更新剧情标题?但它没用.

#! /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()
Run Code Online (Sandbox Code Playgroud)

编辑 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,
Run Code Online (Sandbox Code Playgroud)

现在文本正常工作,但箭头更新不是"流畅的"(它出现并消失每次更新).

Imp*_*est 11

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

可能的解决方案是

  1. 将标题放在轴内.
  2. 不要使用blitting
  3. 可能使用a ArtistAnimation而不是a FuncAnimation也可以工作.但我没有测试过它.

请注意,plt.draw在更新功能中使用或类似(如在其他答案中所提出的)是没有意义的,因为它破坏了使用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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

请注意,我略微改变了角度设置,因为它的角度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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述