2010-08-09 14 views
6

He intentado durante horas hacer funcionar este sencillo script, pero nada de lo que hago parece ayudar. Es una ligera modificación del código de muestra de la trama animado más básico del sitio web de Matplotlib, que solo debe mostrar unos pocos cuadros de ruido (tengo el mismo problema con el código no modificado de su sitio web por cierto).La animación de Matplotlib se congela después de algunos fotogramas o simplemente no funciona

En mi computadora con el backend TkAgg obtengo unos 20 fotogramas (de un total de 60) antes de que la ventana de la trama se congele. Con Qt4Agg obtengo una ventana negra congelada y no se trazan cuadros en absoluto. Probé varias combinaciones de diferentes versiones de NumPy, PyQt, Python y Matplotlib, pero siempre obtengo el mismo resultado.

Háganme saber si esto le sirve o si algo anda mal. Estoy bastante seguro de que esto funcionó en el pasado, así que estoy pensando que puede tratarse de un problema de Windows o algo relacionado con ion().

FYI Estoy usando Windows 7 (32 bit) y lo he probado con Python 2.6/2.7, MPL 1.0.0/0.9.9.8, PyQt 4.6/4.7, Numpy 1.4/1.5b.

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) 

Esta versión más simple queda como también después de los primeros marcos par:

from pylab import * 

ion() 
hold(False) 

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

show() 

Gracias!

EDITAR: Estas personas parecen tener el mismo o un problema similar que yo:

  • 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

No parece que ninguno de ellos haya podido repararlo tampoco :(

+0

Probé los códigos anteriormente en Windows (64 bits) con Python 2.6.5, Numpy 1.5.0b1 y Matplotlib 1.0.0 sin ningún problema con la línea cmd. También los probé en IDLE y el primer código se bloquea y se bloquea al final, pero el segundo funcionó bien, lo que me sorprendió. No sé si eso ayuda en absoluto, pero ahí lo tienes. No tengo ningún material QT instalado, así que esto fue todo con Tk. –

+0

Muchas gracias Justin. ¿Estás seguro de que se mostraron todos los marcos? Tengo un par antes de que las cosas se congelen. – Roger

+0

Creo que los problemas de QTAgg están relacionados con este [problema de github] (https://github.com/matplotlib/matplotlib/issues/1646), usando pause() con pylab en lugar de draw() funciona, también muestra() shouldn ' ser necesario – seumas

Respuesta

1

Cuando dices "congelaciones" después de los primeros dos cuadros, ¿te refieres a 2 o 3, digamos 40 o 60, ya que esos son los los límites superiores de tu ciclo?

Si desea que la animación para continuar indefinidamente necesita algo así como

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

Pero usted tendrá que forzar la salida de su programa.

+0

Normalmente se congela después de aproximadamente 20 fotogramas y la ventana de la trama dice "no responde", aunque la secuencia de comandos sigue ejecutándose e imprimiendo los números de fotograma. – Roger

+0

¿Funciona este ejemplo? http://matplotlib.sourceforge.net/examples/animation/simple_anim_gtk.html –

+0

No tengo PyGTK, pero http: //matplotlib.sourceforge.net/examples/animation/simple_anim_tkagg.py da el mismo problema: funciona por un tiempo, luego se congela. – Roger

4

Por lo general, los marcos de GUI deben 'ser propietarios' del ciclo principal del programa. Sentarse en un circuito cerrado con capacidad para retrasar las iteraciones generalmente 'romperá' las aplicaciones GUI (la descripción de su problema es consistente con la rotura típica a lo largo de estas líneas). Es posible que los desarrolladores de matplotlib hayan implementado una lógica detrás de escena para evitar que estos bloqueos sucedan para ciertos kits de herramientas, pero la reestructuración de su programa debería eliminar cualquier posibilidad de que el problema sea la propiedad de mainloop (que es muy). El matplotlib animation wiki también sugiere el uso de bucles de eventos nativos para cualquier cosa no trivial (probablemente por este motivo)

En lugar de estar sentado en un bucle con duerme, sugiero que use el juego de herramientas GUI para programar una llamada de función después de un cierto retrasar.

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 

En cuanto a la documentación matplotlib sugiere que puede ser posible utilizar la API de forma nativa, pero no pude encontrar ningún buenos ejemplos usando sólo una búsqueda rápida.

+0

Es posible que deba hacer eso cuando mi script se involucre más, pero no esperaría que mi ejemplo simple (trivial casi) necesite algo más complicado, sobre todo porque recuerdo que esto funcionaba en el pasado. – Roger

+2

Que funcionó en el pasado puede haber sido más un accidente que cualquier otra cosa. Todos los kits de herramientas GUI comunes son inherentemente asincrónicos y el intento de utilizarlos de forma sincrónica es un defecto de diseño definitivo. Usarlos de forma asincrónica todavía puede mantenerse realmente simple, pero simplemente no parece que los desarrolladores de matplotlib hayan puesto mucho esfuerzo en ello ... probablemente debido a que la animación es un caso de uso mucho más pequeño que la generación de imágenes estáticas. De todos modos, buena suerte con tu aplicación :) – Rakis

+0

'root.after (100, somefunc)', y 'gobject.timeout_add (100, somefunc)' no son terriblemente complicados. Qt está un poco más involucrado ... –

1

Generalmente no puede usar show() y draw() de esta manera. Tal como lo sugieren las Publicaciones, necesita un pequeño bucle GUI, solo mire los ejemplos de Animaciones en la página Matplotlib.

1

Después de muchas horas de lucha con este mismo problema creo que he encontrado la respuesta: Para hacer estas animaciones sencillas con matplotlib puede única utilizar el backend GTKAgg. Esto se establece como una observación pasajera en el scipy cookbook, pero creo que debe destacarse más claramente. Cuando lo uso, puedo ejecutar tus animaciones hasta el final sin congelaciones ni ningún otro problema.

Tenga en cuenta que para usar este backend necesita instalar PyGTK. No sé qué más necesitas en Windows (porque estoy en Linux) pero parece el mínimo. Además, si desea utilizar por defecto hay que añadir esta línea a su matplotlibrc (en Linux colocado en ~/.matplotlib/matplotlibrc):

backend  : GTKAgg 

para usar el otro backends es necesario seguir el funcionario matplotlib examples, pero eso significa que tienes que crear una aplicación mini-gui solo para ejecutar una animación simple, ¡y eso me parece horrible!

0

Estuve luchando con este mismo problema desde hace bastante tiempo. Yo recomendaría echar un vistazo a este ejemplo: http://matplotlib.sourceforge.net/examples/animation/strip_chart_demo.html

pensé que estaba siguiendo este ejemplo exactamente, pero que no estaba funcionando. Solo ejecutaría la función "actualizar" una vez. Resulta que la única diferencia en mi código era que el animation.FuncAnimation() no estaba asignado a una variable. Tan pronto como asigné el valor de retorno de animation.FuncAnimation() a un valor, todo funcionó.

1

Estaba teniendo (creo) el mismo problema, donde la ventana se congelaría si desviaba la atención o intentaba arrastrarla, usando Python 2.7 en Windows 7 con Matplotlib 1.3 y TKAgg back-end. Tuve una llamada a time.sleep (1) en mi ciclo while principal, y cuando reemplacé eso con plt.pause (1), eso solucionó el problema. Por lo tanto, intente utilizar la función de pausa de matplotlib en lugar de la función de reposo del módulo de tiempo, funcionó para mí.

1

time.sleep llamando al() o plt.pause() hace que el parpadeo en la ventana gráfica cuando se utiliza blitting, pero me dio buenos resultados, simplemente llamando al bucle de eventos explícitamente:

fig.canvas.blit() # or draw() 
fig.canvas.start_event_loop(0.001) #1 ms seems enough 
Cuestiones relacionadas