Animationen mit Matplotlib#

Basierend auf seiner Plot-Funktionalität bietet Matplotlib auch eine Schnittstelle zur Erstellung von Animationen über das Modul animation. Eine Animation ist eine Abfolge von Bildern, wobei jedes Bild einem Plot auf einer Figure entspricht. Dieses Tutorial behandelt eine allgemeine Anleitung zur Erstellung solcher Animationen und die verschiedenen verfügbaren Optionen. Weitere Informationen finden Sie in der API-Beschreibung: animation

import matplotlib.pyplot as plt
import numpy as np

import matplotlib.animation as animation

Animationsklassen#

Der Animationsprozess in Matplotlib kann auf 2 verschiedene Arten betrachtet werden:

  • FuncAnimation: Generiert Daten für das erste Bild und modifiziert dann diese Daten für jedes Bild, um einen animierten Plot zu erstellen.

  • ArtistAnimation: Generiert eine Liste (iterierbar) von Künstlern, die in jedem Bild der Animation gezeichnet werden.

FuncAnimation ist in Bezug auf Geschwindigkeit und Speicher effizienter, da es einen Künstler einmal zeichnet und dann modifiziert. ArtistAnimation hingegen ist flexibel, da es jedes iterierbare Objekt von Künstlern in einer Sequenz animieren kann.

FuncAnimation#

Die Klasse FuncAnimation ermöglicht uns, eine Animation zu erstellen, indem wir eine Funktion übergeben, die die Daten eines Plots iterativ modifiziert. Dies geschieht durch die Verwendung der *Setter*-Methoden verschiedener Artist (Beispiele: Line2D, PathCollection usw.). Ein übliches FuncAnimation-Objekt nimmt eine Figure, die wir animieren möchten, und eine Funktion *func*, die die auf der Abbildung geplotteten Daten modifiziert. Es verwendet den Parameter *frames*, um die Länge der Animation zu bestimmen. Der Parameter *interval* wird verwendet, um die Zeit in Millisekunden zwischen dem Zeichnen zweier Bilder zu bestimmen. Animationen mit FuncAnimation erfordert typischerweise diese Schritte:

  1. Plottet die Anfangsabbildung wie bei einem statischen Plot. Speichert alle erstellten Künstler, die von den Plotfunktionen zurückgegeben werden, in Variablen, sodass Sie in der Animationsfunktion später darauf zugreifen und sie modifizieren können.

  2. Erstellt eine Animationsfunktion, die die Künstler für ein gegebenes Bild aktualisiert. Typischerweise ruft dies die set_*-Methoden der Künstler auf.

  3. Erstellt eine FuncAnimation, wobei die Figure und die Animationsfunktion übergeben werden.

  4. Speichert oder zeigt die Animation mit einer der folgenden Methoden an:

Die folgende Tabelle zeigt einige Plot-Methoden, die zurückgegebenen Künstler und einige häufig verwendete set_*-Methoden, die die zugrunde liegenden Daten aktualisieren. Während die Aktualisierung von Daten die häufigste Operation bei Animationen ist, können Sie auch andere Aspekte wie Farbe oder Textposition aktualisieren.

Die Abdeckung der Set-Methoden für alle Arten von Künstlern sprengt den Rahmen dieses Tutorials, kann aber in den jeweiligen Dokumentationen gefunden werden. Ein Beispiel für solche Aktualisierungsmethoden für Axes.scatter und Axes.plot ist wie folgt:

fig, ax = plt.subplots()
t = np.linspace(0, 3, 40)
g = -9.81
v0 = 12
z = g * t**2 / 2 + v0 * t

v02 = 5
z2 = g * t**2 / 2 + v02 * t

scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s')
line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0]
ax.set(xlim=[0, 3], ylim=[-4, 10], xlabel='Time [s]', ylabel='Z [m]')
ax.legend()


def update(frame):
    # for each frame, update the data stored on each artist.
    x = t[:frame]
    y = z[:frame]
    # update the scatter plot:
    data = np.stack([x, y]).T
    scat.set_offsets(data)
    # update the line plot:
    line2.set_xdata(t[:frame])
    line2.set_ydata(z2[:frame])
    return (scat, line2)


ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=30)
plt.show()

ArtistAnimation#

ArtistAnimation kann verwendet werden, um Animationen zu erstellen, wenn Daten auf verschiedenen Künstlern gespeichert sind. Diese Liste von Künstlern wird dann bildweise in eine Animation umgewandelt. Wenn wir beispielsweise Axes.barh verwenden, um ein Balkendiagramm zu erstellen, werden für jeden Balken und die Fehlerbalken mehrere Künstler erstellt. Um den Plot zu aktualisieren, müsste jeder Balken aus dem Container einzeln aktualisiert und neu gezeichnet werden. Stattdessen kann animation.ArtistAnimation verwendet werden, um jedes Bild einzeln zu plotten und dann zu einer Animation zusammenzufügen. Ein "Barchart Race" ist ein einfaches Beispiel dafür.

fig, ax = plt.subplots()
rng = np.random.default_rng(19680801)
data = np.array([20, 20, 20, 20])
x = np.array([1, 2, 3, 4])

artists = []
colors = ['tab:blue', 'tab:red', 'tab:green', 'tab:purple']
for i in range(20):
    data += rng.integers(low=0, high=10, size=data.shape)
    container = ax.barh(x, data, color=colors)
    artists.append(container)


ani = animation.ArtistAnimation(fig=fig, artists=artists, interval=400)
plt.show()

Animations-Writer#

Animations-Objekte können mit verschiedenen Multimedia-Writern auf Festplatte gespeichert werden (z. B. Pillow, ffmpeg, imagemagick). Nicht alle Videoformate werden von allen Writern unterstützt. Es gibt 4 Haupttypen von Writern:

  • PillowWriter - Verwendet die Pillow-Bibliothek zur Erstellung der Animation.

  • HTMLWriter - Wird zur Erstellung von JavaScript-basierten Animationen verwendet.

  • Pipe-basierte Writer - FFMpegWriter und ImageMagickWriter sind Pipe-basierte Writer. Diese Writer leiten jedes Bild an das Dienstprogramm (ffmpeg / imagemagick) weiter, das dann alle zusammenfügt, um die Animation zu erstellen.

  • Datei-basierte Writer - FFMpegFileWriter und ImageMagickFileWriter sind Beispiele für dateibasierte Writer. Diese Writer sind langsamer als ihre Pipe-basierten Alternativen, aber nützlicher für das Debugging, da sie jedes Bild vor dem Zusammenfügen zu einer Animation in einer Datei speichern.

Speichern von Animationen#

Writer

Unterstützte Formate

PillowWriter

.gif, .apng, .webp

HTMLWriter

.htm, .html, .png

Alle von ffmpeg unterstützten Formate: ffmpeg -formats

Alle von imagemagick unterstützten Formate: magick -list format

Um Animationen mit einem der Writer zu speichern, können wir die Methode animation.Animation.save verwenden. Sie nimmt den *filename*, unter dem wir die Animation speichern möchten, und den *writer*, der entweder ein String oder ein Writer-Objekt ist. Sie nimmt auch ein *fps*-Argument. Dieses Argument unterscheidet sich vom *interval*-Argument, das FuncAnimation oder ArtistAnimation verwenden. *fps* bestimmt die Bildrate, die die **gespeicherte** Animation verwendet, während *interval* die Bildrate bestimmt, die die **angezeigte** Animation verwendet.

Im Folgenden finden Sie einige Beispiele, die zeigen, wie eine Animation mit verschiedenen Writern gespeichert wird.

Pillow-Writer

ani.save(filename="/tmp/pillow_example.gif", writer="pillow")
ani.save(filename="/tmp/pillow_example.apng", writer="pillow")

HTML-Writer

ani.save(filename="/tmp/html_example.html", writer="html")
ani.save(filename="/tmp/html_example.htm", writer="html")
ani.save(filename="/tmp/html_example.png", writer="html")

FFMpegWriter

ani.save(filename="/tmp/ffmpeg_example.mkv", writer="ffmpeg")
ani.save(filename="/tmp/ffmpeg_example.mp4", writer="ffmpeg")
ani.save(filename="/tmp/ffmpeg_example.mjpeg", writer="ffmpeg")

Imagemagick-Writer

ani.save(filename="/tmp/imagemagick_example.gif", writer="imagemagick")
ani.save(filename="/tmp/imagemagick_example.webp", writer="imagemagick")
ani.save(filename="apng:/tmp/imagemagick_example.apng",
         writer="imagemagick", extra_args=["-quality", "100"])

(Die extra_args für *apng* sind notwendig, um die Dateigröße um ca. das 10-fache zu reduzieren)

Beachten Sie, dass ffmpeg und imagemagick separat installiert werden müssen. Eine plattformübergreifende Methode zur Beschaffung von ffmpeg ist die Installation des imageio_ffmpeg PyPI-Pakets und anschließend das Setzen von rcParams["animation.ffmpeg_path"] = imageio_ffmpeg.get_ffmpeg_exe().

Gesamtlaufzeit des Skripts: (0 Minuten 6,098 Sekunden)

Galerie generiert von Sphinx-Gallery