Traçage d'une manière non-bloquante avec Matplotlib

J'ai joué avec Numpy et matplotlib ces derniers jours. J'ai du mal à faire de matplotlib plot une fonction sans bloquer l'exécution. Je sais qu'il y a déjà beaucoup de fils ici sur donc en posant des questions similaires, et j'ai cherché sur Google Pas mal de choses mais je n'ai pas réussi à faire ce travail.

j'ai essayé d'utiliser show(block=False) comme certains le suggèrent, mais tout ce que j'obtiens c'est une fenêtre gelée. Si j'appelle show (), le résultat est tracé correctement. mais l'exécution est bloquée jusqu'à ce que la fenêtre est fermée. D'autres threads que j'ai lus, je soupçonne que si show(block=False) fonctionne ou non dépend de l'arrière-plan. Est-ce correct? Mon dos est Qt4Agg. Pouvez-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 __name__ == '__main__':
    main()

PS. J'ai oublié de dire que je voudrais mettre à jour la fenêtre existante chaque fois que je concocte quelque chose, au lieu d'en créer une nouvelle.

63
demandé sur therainmaker 2015-02-02 02:23:00

3 réponses

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) voulez, vous avez besoin de la combinaison de plt.ion() , plt.show() (pas avec blocking=False , qui est déprécié) et, plus important encore, plt.pause(.001) (ou n'importe quel temps que vous voulez). Le pause est nécessaire parce que les événements GUI se produisent pendant que le code principal est endormi, y compris le dessin. Il est possible que ceci est mis en œuvre en récupérant le temps d'un fil endormi, donc peut-être IDEs foutent le bordel avec cela-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 __name__ == '__main__':
    main()
80
répondu krs013 2017-05-23 12:26:10

une astuce simple qui fonctionne pour moi est la suivante:

  1. Utiliser le bloc = False "151990920 argument de" à l'intérieur de spectacle: plt.afficher (bloc = faux)
  2. Utiliser un autre plt.show() à la fin de la .py script.

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() c'est la dernière ligne de mon script.

11
répondu seralouk 2018-09-29 09:40:48

vous pouvez éviter de bloquer l'exécution en écrivant la trame à un tableau, puis en affichant le tableau dans un fil différent. Voici un exemple de création et d'affichage de tracés simultanément en utilisant pf.écran 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:

Sine animation

Avertissement: je suis le responsable pour pyformulas.

Référence: Matplotlib: enregistrer de la parcelle à un tableau numpy

5
répondu Default picture 2018-04-01 16:27:53