matplotlib.animation
#
Animazione #
Il modo più semplice per creare un'animazione dal vivo in Matplotlib è utilizzare una delle
Animation
classi.
Una classe base per le animazioni. |
|
Crea un'animazione chiamando ripetutamente una funzione func . |
|
Animazione utilizzando un insieme fisso di |
In entrambi i casi è fondamentale mantenere un riferimento all'oggetto istanza. L'animazione è avanzata da un timer (in genere dal framework della GUI host) a cui l' Animation
oggetto contiene l'unico riferimento. Se non si tiene un riferimento Animation
all'oggetto, esso (e quindi i timer) verrà sottoposto a raccolta dei rifiuti che interromperà l'animazione.
Per salvare un'animazione utilizzare Animation.save
, Animation.to_html5_video
o Animation.to_jshtml
.
Vedi Classi di supporto di seguito per i dettagli su quali formati di film sono supportati.
FuncAnimation
#
Il funzionamento interno di FuncAnimation
è più o meno:
for d in frames:
artists = func(d, *fargs)
fig.canvas.draw_idle()
fig.canvas.start_event_loop(interval)
con dettagli per gestire il "blitting" (per migliorare notevolmente le prestazioni dal vivo), per non bloccare, non avviare/arrestare ripetutamente il ciclo di eventi della GUI, gestire le ripetizioni, più assi animati e salvare facilmente l'animazione in un file di filmato.
Il "Blitting" è una tecnica standard nella computer grafica. L'essenza generale è prendere una mappa di bit esistente (nel nostro caso una figura per lo più rasterizzata) e poi "blittare" un altro artista sopra. Pertanto, gestendo una bitmap "pulita" salvata, possiamo solo ridisegnare i pochi artisti che cambiano ad ogni fotogramma e possibilmente risparmiare notevoli quantità di tempo. Quando usiamo blitting (passando blit=True
), il ciclo principale di
FuncAnimation
diventa un po' più complicato:
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)
Questo ovviamente tralascia molti dettagli (come l'aggiornamento dello sfondo quando la figura viene ridimensionata o completamente ridisegnata). Tuttavia, questo esempio, si spera minimalista, dà un'idea di come init_func
e func
sono usati all'interno FuncAnimation
e della teoria di come funziona il "blitting".
La firma prevista su func
ed init_func
è molto semplice da tenere FuncAnimation
fuori dalla tua logica di contabilità e trama, ma questo significa che gli oggetti richiamabili che passi devono sapere su quali artisti dovrebbero lavorare. Esistono diversi approcci per gestirlo, di varia complessità e incapsulamento. L'approccio più semplice, che funziona abbastanza bene nel caso di una sceneggiatura, è definire l'artista a livello globale e lasciare che Python risolva le cose. Per esempio
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()
Il secondo metodo consiste nell'usare functools.partial
per 'legare' gli artisti alla funzione. Un terzo metodo consiste nell'usare le chiusure per costruire gli artisti e le funzioni richieste. Un quarto metodo consiste nel creare una classe.
Esempi #
ArtistAnimation
#
Esempi #
Corsi di scrittura #
Gli scrittori forniti rientrano in alcune grandi categorie.
L'autore di Pillow si affida alla libreria Pillow per scrivere l'animazione, mantenendo tutti i dati in memoria.
Il writer HTML genera animazioni basate su JavaScript.
Scrittore per filmati HTML basati su JavaScript. |
I writer basati su pipe trasmettono i frame acquisiti tramite una pipe a un processo esterno. Le varianti basate su pipe tendono ad essere più performanti, ma potrebbero non funzionare su tutti i sistemi.
Scrittore ffmpeg basato su pipe. |
|
Gif animata basata su pipe. |
I writer basati su file salvano file temporanei per ogni fotogramma che vengono uniti in un unico file alla fine. Sebbene più lenti, questi scrittori possono essere più facili da eseguire il debug.
Scrittore ffmpeg basato su file. |
|
Scrittore di gif animate basato su file. |
Le classi writer forniscono un modo per acquisire frame sequenziali dallo stesso file Figure
. Tutti forniscono tre metodi che devono essere chiamati in sequenza:
setup
prepara lo scrittore (es. aprendo una pipa). Gli scrittori basati su pipe e file accettano argomenti diversi persetup()
.grab_frame
può quindi essere chiamato tutte le volte che è necessario per acquisire un singolo fotogramma alla voltafinish
finalizza il filmato e scrive il file di output su disco.
Esempio:
moviewriter = MovieWriter(...)
moviewriter.setup(fig, 'my_movie.ext', dpi=100)
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
moviewriter.finish()
Se si utilizzano direttamente le classi writer (non tramite Animation.save
), si consiglia vivamente di utilizzare il saving
gestore di contesto:
with moviewriter.saving(fig, 'myfile.mp4', dpi=100):
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
per garantire che la configurazione e la pulizia vengano eseguite come necessario.
Esempi #
Classi di supporto #
Classi base di animazione #
Una classe base per le animazioni. |
|
|
Registro degli scrittori n.
Viene fornito un registro a livello di modulo per eseguire il mapping tra il nome del writer e la classe per consentire il passaggio di una stringa
Animation.save
anziché di un'istanza del writer.
Registro delle classi di scrittori disponibili per nome leggibile dall'uomo. |
Classi di base per scrittori #
Per ridurre le classi base di duplicazione del codice
Classe base astratta per la scrittura di filmati, che fornisce un modo per catturare i fotogrammi chiamando |
|
Classe base per la scrittura di film. |
|
|
e mixin
Classe Mixin per l'output di FFMpeg. |
|
Classe Mixin per l'output di ImageMagick. |
sono forniti.
Vedere il codice sorgente per come implementare facilmente nuove MovieWriter
classi.