matplotlib.animation#

Animation #

Der einfachste Weg, eine Live-Animation in Matplotlib zu erstellen, ist die Verwendung einer der AnimationKlassen.

Vererbungsdiagramm von matplotlib.animation.FuncAnimation, matplotlib.animation.ArtistAnimation

Animation

Eine Basisklasse für Animationen.

FuncAnimation

Erstellt eine Animation durch wiederholtes Aufrufen einer Funktion func .

ArtistAnimation

Animation mit einem festen Satz von ArtistObjekten.

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 AnimationObjekt die einzige Referenz enthält. Wenn Sie keinen Verweis auf das AnimationObjekt 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 FuncAnimationist 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 FuncAnimationetwas 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 funcinnerhalb von FuncAnimationund der Theorie verwendet werden, wie „Blitting“ funktioniert.

Die erwartete Signatur an funcund init_funcist sehr einfach FuncAnimationaus 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 #

Vererbungsdiagramm von matplotlib.animation.FFMpegFileWriter, matplotlib.animation.FFMpegWriter, matplotlib.animation.ImageMagickFileWriter, matplotlib.animation.ImageMagickWriter, matplotlib.animation.PillowWriter, matplotlib.animation.HTMLWriter

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.

PillowWriter

Der HTML-Writer generiert JavaScript-basierte Animationen.

HTMLWriter

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.

FFMpegWriter

Pipe-basierter ffmpeg-Writer.

ImageMagickWriter

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.

FFMpegFileWriter

Dateibasierter ffmpeg-Writer.

ImageMagickFileWriter

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:

  • setupbereitet den Schreiber vor (z. B. das Öffnen einer Pfeife). Pipe-basierte und dateibasierte Writer verwenden unterschiedliche Argumente für setup().

  • grab_framekann dann so oft wie nötig aufgerufen werden, um jeweils einen einzelnen Frame zu erfassen

  • finishschließ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 savingKontextmanager 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 #

Animation

Eine Basisklasse für Animationen.

TimedAnimation

AnimationUnterklasse für zeitbasierte Animation.

Writer- Registrierungsnummer

Eine Registrierung auf Modulebene wird bereitgestellt, um den Namen des Schreibers und der Klasse zuzuordnen, damit Animation.saveanstelle einer Schreiberinstanz eine Zeichenfolge übergeben werden kann.

MovieWriterRegistry

Registrierung verfügbarer Writer-Klassen nach lesbarem Namen.

Writer-Basisklassen #

Um die Codeduplizierung von Basisklassen zu reduzieren

AbstractMovieWriter

Abstrakte Basisklasse zum Schreiben von Filmen, die eine Möglichkeit bietet, Frames durch Aufrufen von grab_frame.

MovieWriter

Basisklasse zum Schreiben von Filmen.

FileMovieWriter

MovieWriterzum Beschreiben einzelner Dateien und zum Zusammenheften am Ende.

und Mixins

FFMpegBase

Mixin-Klasse für FFMpeg-Ausgabe.

ImageMagickBase

Mixin-Klasse für die ImageMagick-Ausgabe.

sind vorgesehen.

Sehen Sie sich den Quellcode an, um zu erfahren, wie Sie neue MovieWriterKlassen einfach implementieren können.