Es gibt zwei Möglichkeiten, Animationen mit matplotlib zu erstellen: matplotlib.animation.ArtistAnimation
und matplotlib.animation.FuncAnimation
. ArtistAnimation
ist einfacher und Sie können es nach Ihren Wünschen erstellen. Es gab jedoch ein Problem, dass es schwer war, weil alle Elemente im Voraus erstellt und im Speicher gespeichert wurden. FuncAnimation
scheint leichter zu sein, weil es nacheinander generiert wird, aber ich verstehe das Verhalten nicht gut und es ist immer problematisch Ich habe die Seriennummernbilder ausgeschrieben und sie später in mp4 konvertiert. Deshalb habe ich mit viel Mühe studiert, um sie zu verstehen und zu verwenden. Dies ist eine Zusammenfassung.
Wenn Sie die zum Erstellen einer Animation erforderlichen Informationen an matplotlib.animation.FuncAnimation
übergeben, wird die Animation erstellt. Sie müssen also die Argumente und das Verhalten dieser Funktion verstehen.
Die ersten beiden Argumente sind erforderlich, und Sie werden normalerweise zusätzlich die Argumente "Frames" und "Intervall" festlegen.
FuncAnimation
Die Idee von "FuncAnimation" wird im folgenden Codebeispiel zusammengefasst. (Zitiert aus API doc)
for d in frames:
artists = func(d, *fargs)
fig.canvas.draw_idle()
fig.canvas.start_event_loop(interval)
Das heißt, drehen Sie den Iterator "Frames", übergeben Sie jeden "Frame-Namen" "d" an die Funktion "func" und zeichnen Sie den zurückgegebenen "Künstler". Nach dieser Zeit "Intervall" endet "Frames". Wiederholen, bis Sie es tun. Das war's.
Machen wir es jetzt. Erstellen wir eine Animation des Punktes P, der 0, 1, 2, ... auf der x-Achse bewegt. Wird es sein?
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
ax = fig.add_subplot(111)
def update(frame):
ax.plot(frame, 0, "o")
anim = FuncAnimation(fig, update, frames=range(8), interval=1000)
anim.save("c01.gif", writer="imagemagick") #Wenn Sie es auf dem Bildschirm anzeigen möchten, plt.show()Ist gut
plt.close()
Klicken Sie hier für die Ergebnisse.
Es ist nicht das, was ich beabsichtigt habe. Was anders ist, ist, dass die vergangene Position des im vorherigen Frame gezeichneten Punktes P immer noch gezeichnet wird. Um dies zu beheben, update
Es scheint, dass alle in Achsen geschriebenen Elemente zu Beginn der Funktion gelöscht werden sollten.
Hier ist also der geänderte Code und die Ausführungsergebnisse.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
ax = fig.add_subplot(111)
def update(frame):
ax.cla() #Klare Axt
ax.plot(frame, 0, "o")
anim = FuncAnimation(fig, update, frames=range(8), interval=1000)
anim.save("c02.gif", writer="imagemagick")
plt.close()
Die Animation wurde wie vorgesehen durchgeführt.
Beachten Sie, dass beim Aufrufen von "ax.cla ()" auch die Achsenbezeichnung "ax.set_xlabel ()", die Gitterlinie "ax.grid ()" und der Zeichenbereich "ax.set_xlim ()" gelöscht werden. Sie müssen neu konfigurieren, nachdem Sie "ax.cla ()" gelesen haben.
Im obigen Beispiel wurden alle Zeichnungsinhalte an jedem Frame gelöscht, aber ich denke, dass Sie häufig nur einige Künstler löschen möchten. Das folgende Beispiel ist beispielsweise ein Punkt, der sich auf dem Einheitskreis P bewegt Obwohl es sich um eine Animation von handelt, scheint sie nutzlos zu sein, da ich jedes Mal ein Gitter und einen Einheitskreis zeichne.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
ax = fig.add_subplot(111, aspect=1)
theta = np.linspace(0, 2*np.pi, 128)
def update(f):
ax.cla() #Klare Axt
ax.grid()
ax.plot(np.cos(theta), np.sin(theta), c="gray")
ax.plot(np.cos(f), np.sin(f), "o", c="red")
anim = FuncAnimation(fig, update, frames=np.pi*np.arange(0,2,0.25), interval=200)
anim.save("c03.gif", writer="imagemagick")
plt.close()
In diesem Fall können Sie Ihr Ziel erreichen, anstatt alles zu löschen, indem Sie den Künstler, den Sie löschen möchten, explizit entfernen.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
ax = fig.add_subplot(111, aspect=1)
theta = np.linspace(0, 2*np.pi, 128)
p = []
ax.grid()
ax.plot(np.cos(theta), np.sin(theta), c="gray")
def update(f):
if len(p) > 0:
item = p.pop(0)
ax.lines.remove(item)
p.append( ax.plot([np.cos(f)], [np.sin(f)], "o", c="red")[0] )
anim = FuncAnimation(fig, update, frames=np.pi*np.arange(0,2,0.25), interval=200)
anim.save("c03.gif", writer="imagemagick")
plt.close()
Ich bin mir jedoch nicht sicher, welches dieser beiden Beispiele hinsichtlich der Zeichengeschwindigkeit besser ist, obwohl es besser erscheint, es mit "blit = True" im FuncAnimation-Argument zu verwenden.
Wenn Sie "plt.cla ()" verwenden, um den Zeichnungsinhalt zu löschen, hat dies dieselbe Bedeutung wie "ax.cla ()" ("ax" sind die Achsen, die Sie unmittelbar zuvor berührt haben), also mehrere Unterzeichnungen Animationen mit haben einige Unterzeichnungen, die nicht löschen, was angezeigt wird. Lassen Sie uns für alle Achsen "ax.cla ()".
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
axs = [
fig.add_subplot(121),
fig.add_subplot(122, aspect=1),
]
theta = np.linspace(0, 4*np.pi, 128)
def update(f):
for ax in axs:
ax.cla() #Klare Axt
ax.grid()
axs[0].set_xlim([0, 4*np.pi])
axs[0].plot(theta, np.cos(theta - f), c="blue")
axs[0].plot(0, np.cos(f), "o", c="blue")
axs[1].plot(np.cos(theta), np.sin(theta), c="gray")
axs[1].plot(np.cos(f), np.sin(f), "o", c="blue")
axs[1].plot(np.cos(f), 0 , "o", c="blue")
axs[1].plot([np.cos(f), np.cos(f)], [0, np.sin(f)], c="blue")
anim = FuncAnimation(fig, update, frames=np.pi*np.arange(0,2,0.1), interval=200)
anim.save("c04.gif", writer="imagemagick")
plt.close()
Recommended Posts