J'ai joué avec Numpy et matplotlib ces derniers jours. J'ai des problèmes pour essayer de faire en sorte que matplotlib trace une fonction sans bloquer l'exécution. Je sais qu'il y a déjà beaucoup de discussions ici sur SO posant des questions similaires, et j'ai beaucoup cherché sur Google mais je n'ai pas réussi à faire en sorte que cela fonctionne.
J'ai essayé d'utiliser show (block = False) comme certaines personnes le suggèrent, mais tout ce que je reçois est une fenêtre figée. Si j'appelle simplement show (), le résultat est tracé correctement mais l'exécution est bloquée jusqu'à la fermeture de la fenêtre. D'après d'autres discussions que j'ai lues, je soupçonne que le fonctionnement de show (block = False) dépend du backend. Est-ce correct? Mon dos est Qt4Agg. Pourriez-vous regarder mon code et me dire si vous voyez quelque chose qui ne va pas? Voici mon code. Merci pour toute aide.
from math import *
from matplotlib import pyplot as plt
print plt.get_backend()
def main():
x = range(-50, 51, 1)
for pow in range(1,5): # plot x^1, x^2, ..., x^4
y = [Xi**pow for Xi in x]
print y
plt.plot(x, y)
plt.draw()
#plt.show() #this plots correctly, but blocks execution.
plt.show(block=False) #this creates an empty frozen window.
_ = raw_input("Press [enter] to continue.")
if __== '__main__':
main()
PS J'ai oublié de dire que je voudrais mettre à jour la fenêtre existante chaque fois que je dessine quelque chose au lieu d'en créer une nouvelle.
J'ai passé beaucoup de temps à chercher des solutions et j'ai trouvé cette réponse .
Il semble que pour obtenir ce que vous (et moi) voulons, vous avez besoin de la combinaison de plt.ion()
, plt.show()
(pas avec blocking=False
, c'est déprécié) et, plus important encore, plt.pause(.001)
(ou à l'heure que vous voulez). pause est nécessaire car les événements de l'interface graphique se produisent pendant que le code principal est en veille, y compris le dessin. Il est possible que cela soit mis en œuvre en prenant le temps d'un thread en veille, alors peut-être que les IDE s'en mêlent - je ne sais pas.
Voici une implémentation qui fonctionne pour moi sur python 3.5:
import numpy as np
from matplotlib import pyplot as plt
def main():
plt.axis([-50,50,0,10000])
plt.ion()
plt.show()
x = np.arange(-50, 51)
for pow in range(1,5): # plot x^1, x^2, ..., x^4
y = [Xi**pow for Xi in x]
plt.plot(x, y)
plt.draw()
plt.pause(0.001)
input("Press [enter] to continue.")
if __== '__main__':
main()
n truc simple qui fonctionne pour moi est le suivant:
Exemple:
import matplotlib.pyplot as plt
plt.imshow(add_something)
plt.xlabel("x")
plt.ylabel("y")
plt.show(block=False)
#more code here (e.g. do calculations and use print to see them on the screen
plt.show()
Note: plt.show()
est la dernière ligne de mon script.
Vous pouvez éviter le blocage de l'exécution en écrivant le tracé dans un tableau, puis en affichant le tableau dans un autre thread. Voici un exemple de génération et d’affichage simultané de tracés à l’aide de pf.screen à partir de pyformulas 0.2.8 :
import pyformulas as pf
import matplotlib.pyplot as plt
import numpy as np
import time
fig = plt.figure()
canvas = np.zeros((480,640))
screen = pf.screen(canvas, 'Sinusoid')
start = time.time()
while True:
now = time.time() - start
x = np.linspace(now-2, now, 100)
y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x)
plt.xlim(now-2,now+1)
plt.ylim(-3,3)
plt.plot(x, y, c='black')
# If we haven't already shown or saved the plot, then we need to draw the figure first...
fig.canvas.draw()
image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,))
screen.update(image)
#screen.close()
Résultat:
Disclaimer: Je suis le responsable des pyformulas.
Référence: Matplotlib: sauvegarder le tracé dans un tableau numpy
Beaucoup de ces réponses sont super gonflées et d'après ce que je peux trouver, la réponse n'est pas si difficile à comprendre.
Vous pouvez utiliser plt.ion()
si vous le souhaitez, mais j'ai trouvé que plt.draw()
était tout aussi efficace.
Pour mon projet spécifique, je trace des images, mais vous pouvez utiliser plot()
ou scatter()
ou peu importe au lieu de figimage()
, cela n'a pas d'importance.
plt.figimage(image_to_show)
plt.draw()
plt.pause(0.001)
Ou
fig = plt.figure()
...
fig.figimage(image_to_show)
fig.canvas.draw()
plt.pause(0.001)
Si vous utilisez un chiffre réel.
J'ai utilisé @ krs013 et les réponses de @Default Picture pour comprendre cela.
J'espère que cela évitera à quelqu'un de lancer chaque personnage sur un fil séparé ou d'avoir à lire ces romans juste pour comprendre cela
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 100)
# plt.axis([x[0], x[-1], -1, 1]) # disable autoscaling
for point in x:
plt.plot(point, np.sin(2 * point), '.', color='b')
plt.draw()
plt.pause(0.01)
# plt.clf() # clear the current figure
si la quantité de données est trop importante, vous pouvez réduire le taux de mise à jour avec un simple compteur
cnt += 1
if (cnt == 10): # update plot each 10 points
plt.draw()
plt.pause(0.01)
cnt = 0
C'était mon problème actuel pour lequel je ne pouvais pas trouver de réponse satisfaisante, je voulais un tracé qui ne se ferme pas une fois le script terminé (comme MATLAB),
Si vous y réfléchissez, une fois le script terminé, le programme est terminé et il n’existe aucun moyen logique de conserver le tracé de cette façon. Il existe donc deux options.
ce n'était pas satisfaisant pour moi alors j'ai trouvé une autre solution en dehors de la boîte
Pour cela, l'enregistrement et la visualisation doivent être rapides et le visualiseur ne doit pas verrouiller le fichier et doit mettre à jour le contenu automatiquement
les formats vectoriels sont à la fois petits et rapides
Pour PDF il existe plusieurs bonnes options
Sous Windows, j'utilise SumatraPDF , qui est gratuit, rapide et léger (n'utilise que 1,8 Mo RAM pour mon cas)
Sous Linux, il existe plusieurs options telles que Evince (GNOME) et Ocular (KDE)
Exemple de code pour la sortie d'un tracé dans un fichier
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(2 * x)
plt.plot(x, y)
plt.savefig("fig.pdf")
après la première exécution, ouvrez le fichier de sortie dans l’un des lecteurs mentionnés ci-dessus et profitez-en.
Voici une capture d'écran de VSCode aux côtés de SumatraPDF, le processus est également assez rapide pour obtenir une vitesse de mise à jour semi-directe (je peux obtenir près de 10Hz sur ma configuration, utilisez simplement time.sleep()
entre les intervalles)
La réponse d'Iggy était la plus facile à suivre, mais j'ai l'erreur suivante lors de l'exécution d'une commande ultérieure subplot
qui n'était pas présente alors que je ne faisais que show
:
MatplotlibDeprecationWarning: l'ajout d'un axe utilisant les mêmes arguments qu'un axe précédent réutilise actuellement l'instance précédente. Dans une version ultérieure, une nouvelle instance sera toujours créée et renvoyée. En attendant, cet avertissement peut être supprimé et le comportement futur assuré en transmettant une étiquette unique à chaque instance d'axes.
Afin d'éviter cette erreur, il est utile de fermer (ou effacer ) le tracé après que l'utilisateur ait cliqué sur Entrée.
Voici le code qui a fonctionné pour moi:
def plt_show():
'''Text-blocking version of plt.show()
Use this instead of plt.show()'''
plt.draw()
plt.pause(0.001)
input("Press enter to continue...")
plt.close()
Le package Python drawnow permet de mettre à jour un tracé en temps réel de manière non bloquante.
Il fonctionne également avec une webcam et OpenCV, par exemple, pour tracer des mesures pour chaque image.
Voir le message d'origine .