HOWTO · Matplotlib

Comment tracer des données en temps réel à l'aide de Matplotlib

Tracez des données changeantes dans une fenêtre Matplotlib avec FuncAnimation(), des redessins manuels du canevas ou un artiste de dispersion qui se met à jour.

Sur cette page

Pour tracer des données qui changent dans une fenêtre Matplotlib, mettez à jour les données des éléments graphiques, puis laissez un backend compatible avec une interface graphique rafraîchir l’affichage. Choisissez FuncAnimation() pour des mises à jour par trames, canvas.draw() et canvas.flush_events() pour contrôler directement une boucle, ou un élément de nuage de points lorsqu’une mise à jour ajoute un point. Ces exemples génèrent les valeurs localement ; remplacez la logique de mise à jour par des valeurs provenant de votre propre source pour les adapter. Ils ne se connectent ni à un capteur ni à un flux réseau.

Animer un graphique avec FuncAnimation()

matplotlib.animation.FuncAnimation appelle une fonction de mise à jour pour chaque trame et planifie les redessins. La fonction de rappel reçoit la valeur de la trame en cours, met à jour la ligne existante et renvoie les éléments graphiques qui ont changé. frames=10 fournit les valeurs de 0 à 9, tandis que interval=50 demande un délai de 50 millisecondes entre les trames ; le rythme réel dépend de la boucle d’événements de l’interface graphique.

Conservez une référence à l’objet d’animation tant que la fenêtre reste ouverte. L’exemple affiche l’animation de manière interactive. Pour l’enregistrer, appelez ani.save("animation.gif", writer="pillow", fps=10) avant plt.show() et installez un moteur d’animation compatible, tel que Pillow. L’enregistrement est une étape de rendu distincte et ne crée pas de flux de données en direct.

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()

Graphique en temps réel animé avec FuncAnimation

Utilisez init_func si l’animation nécessite un état initial distinct, et fargs pour transmettre des paramètres fixes supplémentaires à la fonction de rappel. Si la fenêtre s’ouvre sans que le graphique se mette à jour, vérifiez que le backend Matplotlib sélectionné prend en charge une boucle d’événements graphique et gardez ani en mémoire tant que la fenêtre est affichée.

Mettre à jour une ligne avec canvas.draw() et canvas.flush_events()

Pour contrôler chaque mise à jour dans une boucle, créez une ligne une seule fois et modifiez ses données avec set_ydata(). Ensuite, canvas.draw() redessine la figure mise à jour et canvas.flush_events() permet à l’interface graphique de traiter les événements en attente. Ce sont des méthodes du canevas Matplotlib ; elles n’effacent pas la figure. plt.ion() active le mode interactif, et une courte pause laisse le temps à l’interface graphique de répondre.

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()

Courbe tracée en temps réel avec Matplotlib à l’aide de canvas.draw()

Cette méthode convient lorsque la boucle doit aussi coordonner d’autres tâches. Gardez chaque mise à jour courte afin que la boucle d’événements puisse traiter les entrées et les demandes de redessin. Avec un backend non interactif, ces appels peuvent générer une figure, mais pas afficher une fenêtre réactive ; sélectionnez un backend graphique pour obtenir des mises à jour interactives.

Créer un nuage de points en temps réel

Pour afficher un flux de points, créez un seul élément de nuage de points et remplacez ses décalages à mesure que de nouvelles coordonnées arrivent. La mise à jour du même élément évite d’accumuler un nouvel objet graphique à chaque itération. plt.pause() actualise la boucle d’événements de l’interface graphique entre les trames, et les limites d’axes ci-dessous gardent visibles tous les points générés.

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()

Nuage de points mis à jour en temps réel

Si seul le point le plus récent vous intéresse, conservez une seule paire de coordonnées au lieu de garder tout l’historique. Si vous souhaitez afficher tous les points précédents, élargissez les limites des axes à mesure que le flux augmente. Pour des données à haute fréquence, effectuez les mises à jour moins souvent que l’arrivée des données ou ne conservez qu’une fenêtre récente afin que le dessin ne devienne pas le goulot d’étranglement.