Ich habe in den letzten Tagen mit Numpy und Matplotlib gespielt. Ich habe Probleme beim Versuch, matplotlib plot zu einer Funktion zu machen, ohne die Ausführung zu blockieren. Ich weiß, dass es bereits viele Threads hier auf SO gibt, die ähnliche Fragen stellen, und ich habe ziemlich viel gegoogelt, aber es ist mir nicht gelungen, dies zum Laufen zu bringen.
Ich habe versucht, show (block = False) zu verwenden, wie es einige Leute vorschlagen, aber alles, was ich bekomme, ist ein eingefrorenes Fenster. Wenn ich einfach show () aufrufe, wird das Ergebnis korrekt dargestellt, aber die Ausführung wird blockiert, bis das Fenster geschlossen wird. Von anderen Threads, die ich gelesen habe, vermute ich, dass es vom Backend abhängt, ob show (block = False) funktioniert oder nicht. Ist das richtig? Mein Backend ist Qt4Agg. Könnten Sie sich meinen Code ansehen und mir mitteilen, ob etwas nicht stimmt? Hier ist mein Code. Vielen Dank für jede Hilfe.
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. Ich habe vergessen zu sagen, dass ich das vorhandene Fenster jedes Mal aktualisieren möchte, wenn ich etwas plotte, anstatt ein neues zu erstellen.
Ich habe lange nach Lösungen gesucht und diese Antwort gefunden.
Es sieht so aus, als ob Sie die Kombination von plt.ion()
, plt.show()
(nicht mit blocking=False
, Das ist veraltet) und benötigen, um zu bekommen, was Sie (und ich) wollen vor allem plt.pause(.001)
(oder wann immer Sie wollen). Das Pause wird benötigt, da die GUI-Ereignisse auftreten, während der Hauptcode im Ruhezustand ist, einschließlich Zeichnen. Es ist möglich, dass dies implementiert wird, indem die Zeit von einem schlafenden Thread abgeholt wird. IDEs können sich also damit herumschlagen - ich weiß nicht.
Hier ist eine Implementierung, die für mich auf python 3.5 funktioniert:
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()
Ein einfacher Trick, der bei mir funktioniert, ist der folgende:
Beispiel:
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()
Anmerkung: plt.show()
ist die letzte Zeile meines Skripts.
Sie können verhindern, dass die Ausführung blockiert wird, indem Sie den Plot in ein Array schreiben und das Array dann in einem anderen Thread anzeigen. Hier ist ein Beispiel für das gleichzeitige Erzeugen und Anzeigen von Plots mit pf.screen aus 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()
Ergebnis:
Haftungsausschluss: Ich bin der Maintainer für Pyformeln.
Viele dieser Antworten sind sehr überladen und nach allem, was ich finden kann, ist die Antwort gar nicht so schwer zu verstehen.
Sie können plt.ion()
verwenden, wenn Sie möchten, aber ich fand es genauso effektiv, plt.draw()
zu verwenden
Für mein spezielles Projekt zeichne ich Bilder, aber Sie können plot()
oder scatter()
oder was auch immer anstelle von figimage()
verwenden, es spielt keine Rolle.
plt.figimage(image_to_show)
plt.draw()
plt.pause(0.001)
Oder
fig = plt.figure()
...
fig.figimage(image_to_show)
fig.canvas.draw()
plt.pause(0.001)
Wenn Sie eine tatsächliche Figur verwenden.
Ich habe @ krs013 und @ Default Picture's Antworten verwendet, um dies herauszufinden
Hoffentlich erspart dies jemandem, jede einzelne Figur in einem separaten Thread zu veröffentlichen oder diese Romane nur lesen zu müssen, um dies herauszufinden
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
wenn die Datenmenge zu groß ist, können Sie die Aktualisierungsrate mit einem einfachen Zähler senken
cnt += 1
if (cnt == 10): # update plot each 10 points
plt.draw()
plt.pause(0.01)
cnt = 0
Dies war mein eigentliches Problem, für das ich keine zufriedenstellende Antwort finden konnte. Ich wollte ein Diagramm, das nach dem Beenden des Skripts nicht geschlossen wurde (wie MATLAB).
Wenn Sie darüber nachdenken, wird das Programm nach Beendigung des Skripts beendet, und es gibt keine logische Möglichkeit, den Plot auf diese Weise zu halten. Es gibt also zwei Möglichkeiten
das war für mich nicht zufriedenstellend, deshalb habe ich eine andere Lösung außerhalb des Rahmens gefunden
Aus diesem Grund sollte das Speichern und Anzeigen sowohl schnell als auch der Betrachter die Datei nicht sperren und den Inhalt automatisch aktualisieren
vektorbasierte Formate sind klein und schnell
Für [~ # ~] pdf [~ # ~] gibt es mehrere gute Optionen
Unter Windows verwende ich SumatraPDF , das kostenlos, schnell und leicht ist (verwendet nur 1,8 MB RAM für meinen Fall)
Unter Linux gibt es verschiedene Optionen wie Evince (GNOME) und Ocular (KDE)
Beispielcode für die Ausgabe eines Plots in eine Datei
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")
öffnen Sie nach dem ersten Start die Ausgabedatei in einem der oben genannten Viewer und genießen Sie.
Hier ist ein Screenshot von VSCode neben SumatraPDF, auch der Prozess ist schnell genug, um die Semi-Live-Aktualisierungsrate zu erhalten (ich kann bei meinem Setup fast 10 Hz erreichen, benutze einfach time.sleep()
zwischen den Intervallen)
Iggys Antwort war für mich am einfachsten zu befolgen, aber bei der Ausführung eines nachfolgenden Befehls subplot
, der nicht vorhanden war, als ich gerade show
ausgeführt habe, wurde folgende Fehlermeldung ausgegeben:
MatplotlibDeprecationWarning: Beim Hinzufügen einer Achse mit denselben Argumenten wie bei einer vorherigen Achse wird derzeit die frühere Instanz wiederverwendet. In einer zukünftigen Version wird immer eine neue Instanz erstellt und zurückgegeben. In der Zwischenzeit kann diese Warnung unterdrückt und das zukünftige Verhalten sichergestellt werden, indem jeder Achseninstanz eine eindeutige Bezeichnung übergeben wird.
Um diesen Fehler zu vermeiden, ist es hilfreich, den Plot zu schließen (oder clear ), nachdem der Benutzer die Eingabetaste gedrückt hat.
Hier ist der Code, der für mich funktioniert hat:
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()
Das Python -Paketdrawow ermöglicht es, einen Plot in Echtzeit nicht blockierend zu aktualisieren.
Es funktioniert auch mit einer Webcam und OpenCV, um beispielsweise Maße für jeden Frame zu zeichnen.
Siehe Originalbeitrag .