Comment puis-je tracer en temps réel dans une boucle while l'aide de matplotlib?
Je suis en train de tracer certaines données provenant d'une caméra en temps réel à l'aide d'OpenCV. Cependant, le tracé en temps réel (à l'aide de matplotlib) ne semble pas fonctionner.
J'ai isolé le problème dans cet exemple simple:
fig = plt.figure()
plt.axis([0, 1000, 0, 1])
i = 0
x = list()
y = list()
while i < 1000:
temp_y = np.random.random()
x.append(i)
y.append(temp_y)
plt.scatter(i, temp_y)
i += 1
plt.show()
Je m'attends à ce que cet exemple parcelle de 1000 points individuellement. Ce qui se passe réellement est que la fenêtre pop-up s'ouvre avec le premier point marquant (ok avec ça), puis attend la boucle se termine avant qu'il remplit le reste du graphe.
Pensées, pourquoi je ne suis pas le voir points peuplée à la fois?
Vous devez vous connecter pour publier un commentaire.
Voici la version de travail du code en question (nécessite au moins la version Matplotlib 1.1.0 de 2011-11-14):
Noter certains changements:
plt.pause(0.05)
pour dessiner les nouvelles données et qu'il exécute la GUI boucle d'évènements (permettant l'interaction de la souris).plt.pause()
vsplt.draw()
ettime.sleep(0.05)
: dessiner/sommeil attire toujours de la parcelle, mais à l'aide de tirage/le sommeil empêche choses comme la souris redimensionner la fenêtre, de la souris zoom, bouton d'événements, toute l'interaction de la souris, etc.plt.axis()
mais au lieu de créer deux listes x et y et appelezplt.plot(x,y)
2. dans votre boucle, ajouter les nouvelles valeurs des données pour les deux listes 3. appelplt.gca().lines[0].set_xdata(x); plt.gca().lines[0].set_ydata(y); plt.gca().relim(); plt.gca().autoscale_view(); plt.pause(0.05);
plt.pause()
n'est pas un choix judicieux, car il déclenche une pleinedraw()
. Utilisationtime.sleep()
aveccanvas.flush_events()
est beaucoup mieux.while True: plt.pause(0.5)
, avecplt.ioff(); plt.show()
.Si vous êtes intéressé en temps réel complot, je vous recommande de regarder dans matplotlib d'animation de l'API. En particulier, en utilisant
blit
pour éviter de redessiner l'arrière-plan sur chaque image peut vous donner de substantiels gains de vitesse (~10x):De sortie:
plt.show()
etplt.draw()
. J'ai ajouté ces modifications dans le code ci-dessus.blit()
semble très bien être "améliorer le tracé en temps réel"? Si vous avez un matplotlib développeur/blog discuter le pourquoi/but/intention/la motivation, ce qui serait formidable. (on dirait que cette nouvelle blit opération serait de convertir Matplotlib à partir de seulement utiliser en mode hors connexion ou très lentement de la modification des données à maintenant, vous pouvez utiliser Matplotlib avec une très rapide mise à jour des données... presque comme un oscilloscope).show
est probablement pas le meilleur choix pour ce. Ce que je voudrais faire est d'utiliserpyplot.draw()
à la place. Vous pouvez également inclure un petit temps de retard (par exemple,time.sleep(0.05)
) dans la boucle de sorte que vous pouvez voir les parcelles qui se passe. Si je fais ces changements à votre exemple, il fonctionne pour moi et je vois chaque point figurant à la fois.Aucune des méthodes qui ont fonctionné pour moi.
Mais j'ai trouvé que c'
Temps réel matplotlib intrigue n'est pas de travail tout en restant dans une boucle
Tous vous avez besoin est d'ajouter
et que vous avez pu voir de la nouvelle parcelle.
De sorte que votre code devrait ressembler à ceci, et il va travailler
Je sais que je suis un peu en retard pour répondre à cette question. Néanmoins, j'ai fait un peu de code il y a un moment pour tracer des graphiques en direct, que j'aimerais partager:
Il suffit de l'essayer. Copiez-collez ce code dans un nouveau python-fichier et exécutez-le. Vous devriez obtenir un beau, fluide en mouvement graphique:
dataSendLoop
fil restent en cours d'exécution en arrière-plan lorsque vous fermez la fenêtre. J'ai donc ajouté ledaemon = True
mot-clé pour résoudre ce problème.conda install pyqt=4
a fait le tour.PyQt4
ne fonctionne que sur Windows.Le haut (et beaucoup d'autres) les réponses ont été construits sur
plt.pause()
, mais c'était une vieille façon de l'animation de l'intrigue dans matplotlib. Il est non seulement lente, mais aussi les causes de se concentrer à être saisi à chaque mise à jour (j'ai eu un temps d'arrêt dur le tracé python processus).TL;DR: vous souhaiterez peut-être utiliser
matplotlib.animation
(comme mentionné dans la documentation).Après avoir creusé autour de diverses réponses et des morceaux de code, c'est en fait avéré être un bon moyen d'attirer les données entrantes à l'infini pour moi.
Voici mon code pour un démarrage rapide. Il marque heure actuelle avec un nombre au hasard dans [0, 100) toutes les 200ms à l'infini, tout en également la manipulation automatique de mise à l'échelle de la vue:
Vous pouvez aussi explorer
blit
pour de meilleures performances, même comme dans FuncAnimation documentation.Un exemple de la
blit
documentation:for i in range(1000): x,y = some func_func()
. Icisome_func()
génère en lignex,y
les paires de données, dont je voudrais parcelle une fois qu'ils sont disponibles. Est-il possible de faire cela avecFuncAnimation
. Mon objectif est de construire la courbe définie par les données, étape par étape, à chaque itération.pyploy.show()
devrait bloquer. Si vous souhaitez ajouter des données, de les récupérer et de mettre à jour leupdate
fonction.pyplot.show
dans une boucle, la boucle sera bloqué par le présent appel et ne va pas continuer. Si vous souhaitez ajouter des données à la courbe, étape par étape, mettez votre logique àupdate
, qui sera appelée à chaqueinterval
donc c'est aussi une étape-par-étape.Je sais que cette question est ancienne, mais maintenant il y en a un paquet appelé drawnow sur GitHub comme "python-drawnow". Cela fournit une interface similaire à MATLAB drawnow -- vous pouvez facilement mise à jour d'une figure.
Un exemple pour votre cas d'utilisation:
python-drawnow est une fine enveloppe
plt.draw
mais offre la possibilité de confirmer (ou debug) après la figure d'affichage.Le problème semble être que vous attendez
plt.show()
pour afficher la fenêtre, puis de revenir. Il ne le fait pas. Le programme s'arrête à ce point et ne reprendra qu'une fois que vous fermez la fenêtre. Vous devriez être capable de test: Si vous fermez la fenêtre, puis une autre fenêtre devrait apparaître.Pour résoudre le problème viens de l'appeler
plt.show()
une fois après votre boucle. Alors vous procurer l'intégralité de la parcelle. (Mais pas un "tracé en temps réel')Vous pouvez essayer le réglage de la clé argument
block
comme ceci:plt.show(block=False)
une fois au début et ensuite utiliser.draw()
de mise à jour.Voici une version que j'ai eu à travailler sur mon système.
La drawnow(makeFig) ligne peut être remplacé par un makeFig(); plt.draw() de la séquence et il fonctionne toujours OK.
Si vous voulez tirer et de ne pas geler votre fil que d'autres point sont établis, vous devez utiliser plt.pause() pas de temps.sleep()
im en utilisant le code suivant à l'intrigue d'une série de coordonnées xy.