2010-08-09 5 views
6

Ich habe stundenlang versucht, dieses einfache Skript zum Laufen zu bringen, aber nichts, was ich tue, scheint mir zu helfen. Es ist eine geringfügige Änderung des grundlegendsten animierten Plot-Beispielcodes von der Matplotlib-Website, die nur ein paar Frames von Rauschen zeigen sollte (ich habe das gleiche Problem mit dem unmodifizierten Code von ihrer Website BTW).Matplotlib-Animation friert entweder nach ein paar Frames ein oder funktioniert einfach nicht

Auf meinem Computer mit dem TkAgg-Backend bekomme ich etwa 20 Frames (von 60), bevor das Plotfenster einfriert. Mit Qt4Agg bekomme ich nur ein eingefrorenes schwarzes Fenster und es werden überhaupt keine Frames geplottet. Ich habe mehrere Kombinationen verschiedener NumPy-, PyQt-, Python- und Matplotlib-Versionen ausprobiert, aber immer das gleiche Ergebnis.

Bitte lassen Sie mich wissen, wenn dies für Sie funktioniert oder wenn etwas schief aussieht. Ich bin mir ziemlich sicher, dass das in der Vergangenheit funktioniert hat, also denke ich, dass es ein Windows-Problem oder etwas sein könnte, das mit ion() zusammenhängt.

FYI Ich benutze Windows 7 (32 Bit) und habe mit Python 2.6/2.7, MPL 1.0.0/0.9.9.8, PyQt 4.6/4.7, Numpy 1.4/1.5b getestet.

import matplotlib 
matplotlib.use('TkAgg') # Qt4Agg gives an empty, black window 
from pylab import * 
import time 

ion() 
hold(False) 

# create initial plot 
z = zeros(10) 
line, = plot(z) 
ylim(-3, 3) 

for i in range(60): 
    print 'frame:', i 

    d = randn(10) 
    line.set_ydata(d) 

    draw() 
    time.sleep(10e-3) 

Diese einfachere Version friert auch nach den ersten paar Frames:

from pylab import * 

ion() 
hold(False) 

for i in range(40): 
    plot(randn(10)) 
    draw() 

show() 

Dank!

EDIT: scheinen Diese Menschen wie mir das gleiche oder ein ähnliches Problem mit zu:

  • mail-archive.com/[email protected]/msg10844.html
  • stackoverflow.com/questions/2604119/matplotlib-pyplot-pylab-not-updating-figure-while-isinteractive-using-ipython
  • mail-archive.com/[email protected]/msg01283.html

Sieht nicht aus wie jeder von ihnen konnte es auch reparieren :(

+0

ich die Codes versucht, oben in Windows (64-Bit) mit Python 2.6.5, Numpy 1.5.0b1 und Matplotlib 1.0.0 ohne Probleme mit der cmd-Zeile. Ich habe sie auch in IDLE ausprobiert und der erste Code hängt und stürzt am Ende ab, aber der zweite funktionierte gut, was mich überraschte. Ich weiß nicht, ob das überhaupt hilft, aber da hast du es. Ich habe keine QT-Sachen installiert, also war das alles mit Tk. –

+0

Vielen Dank Justin. Sind Sie sicher, dass alle Frames angezeigt wurden? Ich bekomme ein paar, bevor die Dinge mich einfrieren. – Roger

+0

Denke, dass die QTAgg-Probleme damit zusammenhängen [github-Problem] (https://github.com/matplotlib/matplotlib/issues/1646), wobei pause() mit pylab anstelle von draw() funktioniert, auch show() sollte nicht t benötigt werden. – seumas

Antwort

1

Wenn Sie sagen, friert nach den ersten paar Frames meinst du 2 oder 3, oder sagen, 40 oder 60, wie diese sind Obergrenze Ihrer Schleife?

Wenn Sie die Animation auf unbestimmte Zeit fortsetzen wollen, müssen Sie so etwas wie

while True: 
    d = randn(10) 
    line.set_ydata(d) 
    draw() 
    time.sleep(10e-3) 

Aber Sie werden zwingen, müssen Sie Ihr Programm beenden.

+0

Normalerweise friert es nach etwa 20 Frames ein und das Plot-Fenster sagt "nicht reagiert", obwohl das Skript läuft und die Frame-Nummern druckt. – Roger

+0

Funktioniert dieses Beispiel? http://matplotlib.sourceforge.net/examples/animation/simple_anim_gtk.html –

+0

Ich habe keine PyGTK, aber http: //matplotlib.sourceforge.net/examples/animation/simple_anim_tkagg.py gibt das gleiche Problem - es funktioniert für eine Weile, dann friert es ein. – Roger

4

In der Regel müssen GUI-Frameworks die Hauptschleife des Programms "besitzen". Wenn Sie in einer engen Schleife mit "Sleep" sitzen, um Iterationen zu verzögern, "brechen" Sie normalerweise GUI-Anwendungen (Ihre Problembeschreibung stimmt mit typischen Brüchen in diesen Zeilen überein). Es ist möglich, dass die Matplotlib-Entwickler eine Logik hinter den Kulissen implementiert haben, um diese Abriegelungen für bestimmte Toolkits zu verhindern, aber eine leichte Umstrukturierung des Programms sollte jegliche Chance auf Mainloop-Besitz beseitigen (was sehr wahrscheinlich ist). Die matplotlib animation wiki schlägt auch native Ereignisschleifen für alles nicht triviale (wahrscheinlich aus diesem Grund)

Anstatt in einer Schleife mit Schlaf sitzt, schlage ich vor, dass Sie stattdessen das GUI-Toolkit verwenden, um einen Funktionsaufruf nach einem bestimmten zu planen verzögern.

def update_function(): 
    # do frame calculation here 

refresh_timer = QtCore.QTimer() 
QtCore.QObject.connect(refresh_timer, QtCore.SIGNAL('timeout()'), update_function) 
refresh_timer.start(1.0/30) # have update_function called at 30Hz 

an der matplotlib Dokumentation vermuten lässt, dass es möglich sein kann, ihre API nativ zu verwenden, aber ich konnte nicht nur eine schnelle Suche mit jeder gute Beispiele.

+0

Ich muss das wohl tun, wenn mein Skript mehr involviert wird, aber ich würde nicht erwarten, dass mein einfaches (trivial fast) Beispiel etwas komplizierteres braucht, besonders seit ich mich daran erinnere, dass das in der Vergangenheit funktioniert hat. – Roger

+2

Dass es in der Vergangenheit funktioniert hat, war vielleicht eher ein Unfall als alles andere. Alle gängigen GUI-Toolkits sind von Natur aus asynchron und der Versuch, sie synchron zu verwenden, ist ein eindeutiger Konstruktionsfehler. Die asynchrone Verwendung kann immer noch sehr einfach gehalten werden, aber es sieht einfach nicht so aus, als ob die Entwickler von matplotlib viel Mühe darauf verwendet hätten ... wahrscheinlich weil die Animation ein viel kleinerer Anwendungsfall ist als die statische Bilderzeugung. Wie auch immer, viel Glück mit Ihrer App :) – Rakis

+0

'root.after (100, somefunc)', und 'gobject.timeout_add (100, somefunc)' sind nicht so schrecklich kompliziert. Qt ist ein bisschen mehr beteiligt ... –

1

Im Allgemeinen können Sie show() und draw() nicht so verwenden. Wie die Posts andeuten, benötigen Sie eine kleine GUI-Schleife, schauen Sie sich einfach die Animations-Beispiele auf der Matplotlib-Seite an.

1

Nach vielen Stunden mit dem gleichen Problem zu kämpfen Ich denke, dass ich die Antwort gefunden habe: diese einfachen Animationen mit dem tun matplotlib Sie können nur den GTKAgg Backend verwenden. Dies wird als eine vorübergehende Bemerkung in der scipy cookbook angegeben, aber ich denke, es sollte deutlicher betont werden. Wenn ich es verwende, kann ich Ihre Animationen bis zum Ende ohne Freezes oder andere Probleme ausführen.

Beachten Sie, dass Sie PyGTK installieren müssen, um dieses Backend zu verwenden. Ich weiß nicht, was du sonst noch unter Windows brauchst (weil ich Linux benutze), aber das scheint das Minimum zu sein. Übrigens, wenn Sie es standardmäßig verwenden möchten, müssen Sie die folgende Zeile in matplotlibrc hinzuzufügen (unter Linux auf ~ platziert/.matplotlib/matplotlibrc):

backend  : GTKAgg 

Um die anderen Backends verwenden Sie die offizielle folgen müssen matplotlib examples, aber das bedeutet, dass Sie eine Mini-GUI-Anwendung erstellen müssen, nur um eine einfache Animation auszuführen, und ich finde das ziemlich schrecklich!

0

Ich hatte eine ganze Weile mit dem gleichen Problem zu kämpfen. Ich würde empfehlen, ein Blick auf dieses Beispiel zu werfen: http://matplotlib.sourceforge.net/examples/animation/strip_chart_demo.html

Ich dachte, ich folgte diesem Beispiel genau, aber es hat nicht funktioniert. Es würde nur einmal die "update" -Funktion ausführen. Es stellte sich heraus, der einzige Unterschied in meinem Code war, dass die animation.FuncAnimation() wurde nicht zu einer Variablen zugewiesen. Sobald ich den Rückgabewert von animation.FuncAnimation() einem Wert zugewiesen habe, hat alles funktioniert.

1

Ich hatte (glaube ich) die gleichen Probleme, wo das Fenster einfrieren würde, wenn ich den Fokus davon ablenkte oder versuchte, es herumzuziehen, Python 2.7 unter Windows 7 mit Matplotlib 1.3 und TKAgg Backend. Ich hatte einen Anruf bei time.sleep (1) in meiner while while-Schleife, und als ich das durch plt.pause (1) ersetzte, behob sich das Problem. Also, versuchen Sie, die Pause-Funktion von Matplotlib anstelle von Zeitmodul-Schlaffunktion zu verwenden, es hat für mich funktioniert.

1

Aufruf time.sleep() oder plt.pause() bewirkt, dass Flimmern auf dem Fenster Graph wenn Blitten, aber ich habe gute Ergebnisse, indem einfach die Ereignisschleife Aufruf ausdrücklich:

fig.canvas.blit() # or draw() 
fig.canvas.start_event_loop(0.001) #1 ms seems enough 
Verwandte Themen