HOWTO · Matplotlib
Wie man mit Matplotlib Daten in Echtzeit plotten kann
Stellen Sie veränderliche Daten in einem Matplotlib-Fenster mit FuncAnimation(), manuellem Neuzeichnen der Zeichenfläche oder einem sich aktualisierenden Scatter-Artist dar.
Auf dieser Seite
Um veränderliche Daten in einem Matplotlib-Fenster darzustellen, aktualisieren Sie die Daten der gezeichneten Artists und lassen Sie ein GUI-fähiges Backend die Anzeige auffrischen. Verwenden Sie FuncAnimation() für Aktualisierungen in einzelnen Frames, canvas.draw() und canvas.flush_events() für direkte Kontrolle in einer Schleife oder einen Scatter-Artist, wenn bei jeder Aktualisierung ein Punkt hinzukommt. Diese Beispiele erzeugen die Werte lokal. Ersetzen Sie beim Anpassen die Aktualisierungslogik durch Werte aus Ihrer eigenen Datenquelle. Eine Verbindung zu einem Sensor oder Netzwerkdatenstrom stellen sie nicht her.
Ein Diagramm mit FuncAnimation() animieren
matplotlib.animation.FuncAnimation ruft für jeden Frame eine Aktualisierungsfunktion auf und plant Neuzeichnungen. Der Callback erhält den aktuellen Frame-Wert, aktualisiert die vorhandene Linie und gibt die geänderten Artists zurück. frames=10 liefert Werte von 0 bis 9, während interval=50 eine Verzögerung von 50 Millisekunden zwischen den Frames anfordert. Das tatsächliche Timing hängt von der GUI-Ereignisschleife ab.
Behalten Sie eine Referenz auf das Animationsobjekt, solange das Fenster geöffnet ist. Das Beispiel zeigt die Animation interaktiv an. Um sie zu speichern, rufen Sie ani.save("animation.gif", writer="pillow", fps=10) vor plt.show() auf und installieren Sie einen kompatiblen Writer wie Pillow. Das Speichern ist ein separater Rendering-Schritt und erzeugt keinen Live-Datenstrom.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
figure, ax = plt.subplots()
line, = ax.plot([], [])
ax.set(xlim=(0, 2 * np.pi), ylim=(-1, 1), xlabel="x", ylabel="sin(x)")
def update(frame):
x = np.linspace(0, 2 * np.pi, 200)
y = np.sin(x - frame / 5)
line.set_data(x, y)
return (line,)
ani = FuncAnimation(figure, update, frames=40, interval=50, blit=True)
plt.show()
Verwenden Sie init_func, wenn die Animation einen eigenen Anfangszustand benötigt, und fargs, um dem Callback zusätzliche feste Eingaben zu übergeben. Wenn sich das geöffnete Fenster nicht aktualisiert, prüfen Sie, ob das ausgewählte Matplotlib-Backend eine GUI-Ereignisschleife unterstützt, und lassen Sie ani bestehen, solange das Fenster angezeigt wird.
Eine Linie mit canvas.draw() und canvas.flush_events() aktualisieren
Wenn eine Schleife jede Aktualisierung steuert, erstellen Sie die Linie einmal und ändern ihre Daten mit set_ydata(). Anschließend zeichnet canvas.draw() die aktualisierte Abbildung, und canvas.flush_events() lässt die GUI ausstehende Ereignisse verarbeiten. Dies sind Methoden des Matplotlib-Canvas; sie löschen die Abbildung nicht. plt.ion() aktiviert den interaktiven Modus, und eine kurze Pause gibt der GUI Zeit zu reagieren.
import time
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 200)
figure, ax = plt.subplots()
line, = ax.plot(x, np.sin(x))
ax.set(xlim=(0, 2 * np.pi), ylim=(-1, 1), xlabel="x", ylabel="sin(x)")
plt.ion()
for frame in range(40):
line.set_ydata(np.sin(x - frame / 5))
figure.canvas.draw()
figure.canvas.flush_events()
time.sleep(0.05)
plt.ioff()
plt.show()
Dieser Ansatz eignet sich, wenn die Schleife zusätzlich andere Aufgaben koordinieren muss. Halten Sie jede Aktualisierung kurz, damit die Ereignisschleife Eingaben und Neuzeichnungsanforderungen verarbeiten kann. Auf einem nicht interaktiven Backend können die Aufrufe zwar eine Abbildung rendern, aber kein reaktionsfähiges Fenster bereitstellen. Wählen Sie für interaktive Aktualisierungen ein GUI-Backend.
Ein Echtzeit-Streudiagramm erstellen
Für einen Strom von Punkten erstellen Sie einen Scatter-Artist und ersetzen dessen Offsets, sobald neue Koordinaten eintreffen. Wenn Sie denselben Artist aktualisieren, sammeln sich nicht bei jeder Schleifeniteration weitere gezeichnete Objekte an. plt.pause() aktualisiert zwischen den Frames die GUI-Ereignisschleife, und die Achsengrenzen im folgenden Beispiel halten alle erzeugten Punkte sichtbar.
import numpy as np
import matplotlib.pyplot as plt
figure, ax = plt.subplots()
points = ax.scatter([], [])
ax.set(xlim=(0, 4), ylim=(-1.1, 1.1), xlabel="x", ylabel="sin(x)")
x_values = []
y_values = []
for frame in range(100):
x = frame * 0.04
x_values.append(x)
y_values.append(np.sin(x))
points.set_offsets(np.column_stack((x_values, y_values)))
plt.pause(0.05)
plt.show()
Wenn nur der neueste Punkt wichtig ist, speichern Sie ein einzelnes Koordinatenpaar statt des gesamten Verlaufs. Sollen alle bisherigen Punkte sichtbar bleiben, erweitern Sie die Achsengrenzen, während der Datenstrom wächst. Bei Daten mit hoher Rate können Sie die Anzeige seltener aktualisieren, als neue Daten eintreffen, oder nur ein aktuelles Zeitfenster behalten, damit das Zeichnen nicht zum Engpass wird.