matplotlib.animation
#
Animação #
A maneira mais fácil de fazer uma animação ao vivo no Matplotlib é usar uma das
Animation
classes.
Uma classe base para animações. |
|
Faz uma animação chamando repetidamente uma função func . |
|
Animação usando um conjunto fixo de |
Em ambos os casos, é fundamental manter uma referência ao objeto da instância. A animação é avançada por um cronômetro (normalmente da estrutura da GUI do host) ao qual o Animation
objeto contém a única referência. Se você não mantiver uma referência ao Animation
objeto, ele (e, portanto, os temporizadores) será coletado como lixo, o que interromperá a animação.
Para salvar uma animação, use Animation.save
, Animation.to_html5_video
ou Animation.to_jshtml
.
Consulte as classes auxiliares abaixo para obter detalhes sobre quais formatos de filme são suportados.
FuncAnimation
#
O funcionamento interno de FuncAnimation
é mais ou menos:
for d in frames:
artists = func(d, *fargs)
fig.canvas.draw_idle()
fig.canvas.start_event_loop(interval)
com detalhes para lidar com 'blitting' (para melhorar drasticamente o desempenho ao vivo), não bloquear, não iniciar/parar repetidamente o loop de eventos da GUI, lidar com repetições, vários eixos animados e salvar facilmente a animação em um arquivo de filme.
'Blitting' é uma técnica padrão em computação gráfica. A essência geral é pegar um mapa de bits existente (no nosso caso, uma figura quase toda rasterizada) e então 'blit' mais um artista no topo. Assim, ao gerenciar um bitmap 'limpo' salvo, podemos apenas redesenhar os poucos artistas que estão mudando a cada quadro e possivelmente economizar uma quantidade significativa de tempo. Quando usamos blitting (passando blit=True
), o loop principal de
FuncAnimation
fica um pouco mais complicado:
ax = fig.gca()
def update_blit(artists):
fig.canvas.restore_region(bg_cache)
for a in artists:
a.axes.draw_artist(a)
ax.figure.canvas.blit(ax.bbox)
artists = init_func()
for a in artists:
a.set_animated(True)
fig.canvas.draw()
bg_cache = fig.canvas.copy_from_bbox(ax.bbox)
for f in frames:
artists = func(f, *fargs)
update_blit(artists)
fig.canvas.start_event_loop(interval)
É claro que isso está deixando de fora muitos detalhes (como atualizar o plano de fundo quando a figura é redimensionada ou totalmente redesenhada). No entanto, este exemplo esperançosamente minimalista dá uma noção de como init_func
e func
são usados dentro de FuncAnimation
e a teoria de como 'blitting' funciona.
A assinatura esperada em func
e init_func
é muito simples de manter FuncAnimation
fora de sua contabilidade e lógica de plotagem, mas isso significa que os objetos chamáveis que você passa devem saber em quais artistas eles devem estar trabalhando. Existem várias abordagens para lidar com isso, de complexidade e encapsulamento variados. A abordagem mais simples, que funciona muito bem no caso de um script, é definir o artista em um escopo global e deixar que o Python resolva as coisas. Por exemplo
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = ax.plot([], [], 'ro')
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)
plt.show()
O segundo método é usar functools.partial
para 'vincular' os artistas à função. Um terceiro método é usar encerramentos para criar os artistas e funções necessários. Um quarto método é criar uma classe.
Exemplos #
ArtistAnimation
#
Exemplos #
Aulas de Escritor #
Os escritores fornecidos se enquadram em algumas categorias amplas.
O Pillow Writer depende da biblioteca Pillow para escrever a animação, mantendo todos os dados na memória.
O gravador de HTML gera animações baseadas em JavaScript.
Escritor de filmes HTML baseados em JavaScript. |
Os gravadores baseados em pipe transmitem os quadros capturados por um pipe para um processo externo. As variantes baseadas em tubos tendem a ser mais eficientes, mas podem não funcionar em todos os sistemas.
Gravador ffmpeg baseado em pipe. |
|
GIF animado baseado em tubos. |
Os escritores baseados em arquivo salvam arquivos temporários para cada quadro que são unidos em um único arquivo no final. Embora mais lentos, esses gravadores podem ser mais fáceis de depurar.
Gravador ffmpeg baseado em arquivo. |
|
Escritor de gif animado baseado em arquivo. |
As classes do gravador fornecem uma maneira de obter quadros sequenciais do mesmo arquivo Figure
. Todos eles fornecem três métodos que devem ser chamados em sequência:
setup
prepara o escritor (por exemplo, abrindo um cachimbo). Os escritores baseados em pipe e baseados em arquivo usam argumentos diferentes para arquivossetup()
.grab_frame
pode então ser chamado sempre que necessário para capturar um único quadro de cada vezfinish
finaliza o filme e grava o arquivo de saída no disco.
Exemplo:
moviewriter = MovieWriter(...)
moviewriter.setup(fig, 'my_movie.ext', dpi=100)
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
moviewriter.finish()
Se estiver usando as classes do gravador diretamente (não por meio Animation.save
de ), é altamente recomendável usar o saving
gerenciador de contexto:
with moviewriter.saving(fig, 'myfile.mp4', dpi=100):
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
para garantir que a configuração e a limpeza sejam executadas conforme necessário.
Exemplos #
Classes Auxiliares #
Classes básicas de animação #
Uma classe base para animações. |
|
|
Registro do gravador #
Um registro em nível de módulo é fornecido para mapear entre o nome do gravador e a classe para permitir que uma string seja transmitida em
Animation.save
vez de uma instância do gravador.
Registro de classes de gravador disponíveis por nome legível por humanos. |
Classes básicas do Writer #
Para reduzir classes base de duplicação de código
Classe base abstrata para escrever filmes, fornecendo uma maneira de obter quadros chamando |
|
Classe base para escrever filmes. |
|
|
e mixins
Classe Mixin para saída FFMpeg. |
|
Classe Mixin para saída do ImageMagick. |
são fornecidos.
Consulte o código-fonte para saber como implementar facilmente novas MovieWriter
classes.