2011-03-01 20 views
6

que tienen un bucle como esteespectáculo pyplot Matplotlib() no funciona, una vez cerrada

#!/usr/bin/env python 
import matplotlib.pyplot as p 

for i in xrange(N): 
    # Create my_image here 

    # Display this image 
    p.figure() 
    p.imshow(my_image) 
    p.show() 
    p.close() 

Esto funciona bien cuando i = 0. Para que el programa continúe, necesito cerrar la nueva figura creada por pyplot. Para todas las demás iteraciones de bucle (i> 0), no se crea otra figura nueva, no se presenta una gráfica y el programa simplemente se mueve. ¿Por qué cerrar una figura que hace que pyplot no pueda abrir una nueva (como MATLAB)?

El comportamiento que espero es:

  1. ejecución se detiene en p.show()
  2. Al cerrar la figura, la ejecución continúa
  3. Cuando p.show() se encuentra de nuevo, el se muestra una nueva imagen.
  4. Repita el paso 2 hasta que no más terreno para mostrar
+0

yo soy capaz de crear parcelas secuenciales para N> = 2. ¿Qué IDE estás usando (si estás usando uno)? Tengo que cerrar manualmente el gráfico antes de obtener el siguiente, por lo que en este ejemplo 'p.close()' no tiene sentido. – Paul

+0

Uso PyCharm para escribir el script y ejecutarlo. Noto que este problema parece ocurrir solo cuando se ejecuta como un script en lugar de en ipython -pylab –

Respuesta

3

Puede ser por un error en versiones anteriores de matplotlib. Estaba teniendo un problema similar cuando emití comandos secuenciales de show(); solo el primero mostraba (y permanecía); pero, cuando actualicé matplotlib a 1.0.1, el problema desapareció.

+0

Actualicé a Matplotlib SVN y el problema desaparece. Supongo que es un error. –

+2

esto era 'lo nuevo' para la versión 1.0.1: Una solicitud de larga duración es para admitir llamadas múltiples a show(). Esto ha sido difícil porque es difícil obtener un comportamiento consistente a través de los sistemas operativos, los kits de herramientas de interfaz de usuario y las versiones. Eric Firing ha trabajado mucho para racionalizar el show en backends, con el comportamiento deseado para hacer que Show muestre todas las figuras recién creadas y bloquee la ejecución hasta que se cierren. Las llamadas repetidas para mostrar deben levantar figuras recién creadas desde la última llamada ... – wim

5

Puede haber una mejor manera de animar imshow de, pero esto debería funcionar en caso de apuro. Es una versión ligeramente modificada de animation example from the docs.

# For detailed comments on animation and the techniqes used here, see 
# the wiki entry http://www.scipy.org/Cookbook/Matplotlib/Animations 

import matplotlib 
matplotlib.use('TkAgg') 

import matplotlib.pyplot as plt 
import matplotlib.mlab as mlab 
import matplotlib.cm as cm 

import sys 
import numpy as np 
import time 

ax = plt.subplot(111) 
canvas = ax.figure.canvas 

delta=0.025 
x=y= np.arange(-3.0, 3.0, delta) 
x,y=np.meshgrid(x, y) 
z1=mlab.bivariate_normal(x, y, 1.0, 1.0, 0.0, 0.0) 
z2=mlab.bivariate_normal(x, y, 1.5, 0.5, 1, 1) 
z=z2-z1 # difference of Gaussians 

def run(z): 
    fig=plt.gcf() 
    for i in range(10): 
     plt.imshow(z, interpolation='bilinear', cmap=cm.gray, 
        origin='lower', extent=[-3,3,-3,3]) 
     canvas.draw() 
     plt.clf() 
     z**=2 

manager = plt.get_current_fig_manager() 
manager.window.after(100, run, z) 
plt.show() 
+1

Su solución es ideal para la animación. Pero lo que quiero no es animación, solo quiero un comportamiento simple similar a MATLAB donde pueda ver cierta imagen/matriz a medida que se ejecuta mi algoritmo. –

+0

@Dat Chu: No conozco el comportamiento de MATLAB. – unutbu

+0

@Dat Chu: ¿Necesita que la ejecución del código se detenga mientras se visualiza el trazado? – Paul

0

Después de jugar con el ejemplo de unutbu, encontré un comportamiento que normalmente podría solucionar y depurar con PyDev, donde pude ver progresivamente las tramas.

import time, threading 
import numpy 
from matplotlib.pyplot import * 

x = numpy.linspace(0, 10) 
y = x**2 

def main(): 
    plot(x, x) 
    draw() 
    time.sleep(2) 
    plot(x, y) 
    draw() 

thread = threading.Thread() 
thread.run = main 

manager = get_current_fig_manager() 
manager.window.after(100, thread.start) 
figure(1) 
show() 
+0

Tenga en cuenta que si tiene varias cifras, le sugiero que las "asigne previamente" antes de mostrar() las ventanas de la figura. De lo contrario, cualquier nueva ventana de figura parece estar limitada a la cadena de llamada. – eacousineau

+0

No importa, eso parece arrojar un error de 'no en el bucle principal' ... – eacousineau

0

Durante mucho tiempo he estado buscando en este problema y es posible que tenga una solución aunque no he probado a fondo todavía.

La clave está en escribir código más como MatLab, nombre sus figuras y luego llámelos para mostrar().

por ejemplo.

from matplotlib import pyplot as plt 

fig1 = plt.figure() 
fig2 = plt.figure() 

fig1.show() 
fig2.show() 

Esto podría funcionar para las animaciones y el trazado en diferentes etapas

Cuestiones relacionadas