matplotlib.animation
#
Animation #
Der einfachste Weg, eine Live-Animation in Matplotlib zu erstellen, ist die Verwendung einer der
Animation
Klassen.
Eine Basisklasse für Animationen. |
|
Erstellt eine Animation durch wiederholtes Aufrufen einer Funktion func . |
|
Animation mit einem festen Satz von |
In beiden Fällen ist es wichtig, eine Referenz auf das Instanzobjekt beizubehalten. Die Animation wird durch einen Timer (typischerweise aus dem Host-GUI-Framework) vorangetrieben, auf den das Animation
Objekt die einzige Referenz enthält. Wenn Sie keinen Verweis auf das Animation
Objekt haben, wird es (und damit die Timer) von der Garbage Collection erfasst, wodurch die Animation gestoppt wird.
Um eine Animation zu speichern, verwenden Sie Animation.save
, Animation.to_html5_video
, oder Animation.to_jshtml
.
Einzelheiten zu den unterstützten Filmformaten finden Sie unten unter Hilfsklassen .
FuncAnimation
#
Das Innenleben von FuncAnimation
ist mehr oder weniger:
for d in frames:
artists = func(d, *fargs)
fig.canvas.draw_idle()
fig.canvas.start_event_loop(interval)
mit Details zur Behandlung von "Blitting" (um die Live-Performance dramatisch zu verbessern), nicht zu blockieren, die GUI-Ereignisschleife nicht wiederholt zu starten / zu stoppen, Wiederholungen zu behandeln, mehrere animierte Achsen und die Animation einfach in einer Filmdatei zu speichern.
'Blitting' ist eine Standardtechnik in der Computergrafik. Das allgemeine Prinzip besteht darin, eine vorhandene Bitmap (in unserem Fall eine meist gerasterte Figur) zu nehmen und dann einen weiteren Künstler darüber zu „blitten“. Durch die Verwaltung einer gespeicherten „sauberen“ Bitmap können wir also nur die wenigen Künstler neu zeichnen, die sich bei jedem Frame ändern, und möglicherweise erhebliche Mengen an Zeit sparen. Wenn wir blitten (durch Übergeben blit=True
) verwenden, wird die Kernschleife von
FuncAnimation
etwas komplizierter:
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)
Dabei werden natürlich viele Details ausgelassen (z. B. das Aktualisieren des Hintergrunds, wenn die Größe der Figur geändert oder vollständig neu gezeichnet wird). Dieses hoffentlich minimalistische Beispiel gibt jedoch einen Eindruck davon, wie init_func
und func
innerhalb von FuncAnimation
und der Theorie verwendet werden, wie „Blitting“ funktioniert.
Die erwartete Signatur an func
und init_func
ist sehr einfach FuncAnimation
aus Ihrer Buchhaltungs- und Plotlogik herauszuhalten, aber das bedeutet, dass die von Ihnen übergebenen aufrufbaren Objekte wissen müssen, an welchen Künstlern sie arbeiten sollen. Es gibt mehrere Ansätze, um dies zu handhaben, von unterschiedlicher Komplexität und Kapselung. Der einfachste Ansatz, der im Fall eines Skripts recht gut funktioniert, besteht darin, den Künstler auf globaler Ebene zu definieren und Python die Dinge regeln zu lassen. Zum Beispiel
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()
Die zweite Methode besteht darin functools.partial
, Künstler an ihre Funktion zu „binden“. Eine dritte Methode besteht darin, Closures zu verwenden, um die erforderlichen Künstler und Funktionen aufzubauen. Eine vierte Methode besteht darin, eine Klasse zu erstellen.
Beispiele #
ArtistAnimation
#
Beispiele #
Autorenklassen #
Die bereitgestellten Autoren fallen in einige große Kategorien.
Der Pillow-Writer verlässt sich auf die Pillow-Bibliothek, um die Animation zu schreiben, wobei alle Daten im Speicher bleiben.
Der HTML-Writer generiert JavaScript-basierte Animationen.
Writer für JavaScript-basierte HTML-Filme. |
Die Pipe-basierten Writer streamen die erfassten Frames über eine Pipe zu einem externen Prozess. Die Pipe-basierten Varianten sind in der Regel performanter, funktionieren aber möglicherweise nicht auf allen Systemen.
Pipe-basierter ffmpeg-Writer. |
|
Pipe-basiertes animiertes GIF. |
Die dateibasierten Schreiber speichern temporäre Dateien für jedes Bild, die am Ende zu einer einzigen Datei zusammengefügt werden. Diese Writer sind zwar langsamer, können aber einfacher zu debuggen sein.
Dateibasierter ffmpeg-Writer. |
|
Dateibasierter animierter GIF-Writer. |
Die Writer-Klassen bieten eine Möglichkeit, aufeinanderfolgende Frames von demselben zugrunde liegenden Figure
. Sie alle bieten drei Methoden, die nacheinander aufgerufen werden müssen:
setup
bereitet den Schreiber vor (z. B. das Öffnen einer Pfeife). Pipe-basierte und dateibasierte Writer verwenden unterschiedliche Argumente fürsetup()
.grab_frame
kann dann so oft wie nötig aufgerufen werden, um jeweils einen einzelnen Frame zu erfassenfinish
schließt den Film ab und schreibt die Ausgabedatei auf die Festplatte.
Beispiel:
moviewriter = MovieWriter(...)
moviewriter.setup(fig, 'my_movie.ext', dpi=100)
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
moviewriter.finish()
Wenn Sie die Writer-Klassen direkt verwenden (nicht über Animation.save
), wird dringend empfohlen, den saving
Kontextmanager zu verwenden:
with moviewriter.saving(fig, 'myfile.mp4', dpi=100):
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
um sicherzustellen, dass Setup und Bereinigung nach Bedarf durchgeführt werden.
Beispiele #
Helferklassen #
Animationsbasisklassen #
Eine Basisklasse für Animationen. |
|
|
Writer- Registrierungsnummer
Eine Registrierung auf Modulebene wird bereitgestellt, um den Namen des Schreibers und der Klasse zuzuordnen, damit
Animation.save
anstelle einer Schreiberinstanz eine Zeichenfolge übergeben werden kann.
Registrierung verfügbarer Writer-Klassen nach lesbarem Namen. |
Writer-Basisklassen #
Um die Codeduplizierung von Basisklassen zu reduzieren
Abstrakte Basisklasse zum Schreiben von Filmen, die eine Möglichkeit bietet, Frames durch Aufrufen von |
|
Basisklasse zum Schreiben von Filmen. |
|
|
und Mixins
Mixin-Klasse für FFMpeg-Ausgabe. |
|
Mixin-Klasse für die ImageMagick-Ausgabe. |
sind vorgesehen.
Sehen Sie sich den Quellcode an, um zu erfahren, wie Sie neue MovieWriter
Klassen einfach implementieren können.