python - ejemplos - ¿Hay una manera de separar los gráficos de matplotlib para que el cálculo pueda continuar?
django (18)
Aquí hay una actualización (python 3.6.5 en Windows 10).
Intenté todo tipo de combinaciones: lo más simple que he encontrado es usar pause(0.01)
después de cada gráfico, no es necesario un show()
para los gráficos intermedios, luego un solo show()
al final asegura que puedas mirar en la parcela final antes de la terminación.
A modo de ejemplo, aquí hay un poco de código que utilizo para verificar la velocidad de varios tamaños de matriz: los valores trazados más altos son velocidades más altas ... hay 10 gráficos superpuestos ...
from pylab import *
import matplotlib.pyplot as plt
from time import *
ttot=clock();
mmax=6;npts=20;nplts=10;
x=[int(a+0.5) for a in 10**linspace(0,mmax,npts)]
for nrun in range(nplts):
j=0;aa=1;bb=1;b=1;
tim=zeros(npts)
for n in x:
aa=rand(n);bb=aa;b=aa;
if n<100:m=10000
elif n<5000:m=1000
elif n<20000:m=100
else:m=100
tt=clock()
for ii in range(1,m+1):
b=aa*bb+aa
tt1=clock()-tt
tim[j]=tt1/n/m
j=j+1
print(n,2/(tt1/n/m)/1e6);
plt.semilogx(x,2/tim/1e6)
pause(0.01)
print(clock()-ttot)
show()
Después de estas instrucciones en el intérprete de Python, se abre una ventana con un gráfico:
from matplotlib.pyplot import *
plot([1,2,3])
show()
# other code
Desafortunadamente, no sé cómo continuar explorando interactivamente la figura creada por show()
mientras el programa realiza cálculos adicionales.
¿Es posible en absoluto? A veces, los cálculos son largos y sería útil que procedieran durante el examen de los resultados intermedios.
Bueno, tuve muchos problemas para entender los comandos de no bloqueo ... Pero finalmente, logré volver a trabajar en el ejemplo " Libro de cocina / Matplotlib / Animaciones - Animar elementos de trama seleccionados ", por lo que funciona con hilos ( y pasa datos entre hilos). a través de variables globales, oa través de un Pip multiproceso ) en Python 2.6.5 en Ubuntu 10.04.
El script se puede encontrar aquí: Animating_selected_plot_elements-thread.py - de lo contrario, se pega a continuación ( con menos comentarios ) como referencia:
import sys
import gtk, gobject
import matplotlib
matplotlib.use(''GTKAgg'')
import pylab as p
import numpy as nx
import time
import threading
ax = p.subplot(111)
canvas = ax.figure.canvas
# for profiling
tstart = time.time()
# create the initial line
x = nx.arange(0,2*nx.pi,0.01)
line, = ax.plot(x, nx.sin(x), animated=True)
# save the clean slate background -- everything but the animated line
# is drawn and saved in the pixel buffer background
background = canvas.copy_from_bbox(ax.bbox)
# just a plain global var to pass data (from main, to plot update thread)
global mypass
# http://docs.python.org/library/multiprocessing.html#pipes-and-queues
from multiprocessing import Pipe
global pipe1main, pipe1upd
pipe1main, pipe1upd = Pipe()
# the kind of processing we might want to do in a main() function,
# will now be done in a "main thread" - so it can run in
# parallel with gobject.idle_add(update_line)
def threadMainTest():
global mypass
global runthread
global pipe1main
print "tt"
interncount = 1
while runthread:
mypass += 1
if mypass > 100: # start "speeding up" animation, only after 100 counts have passed
interncount *= 1.03
pipe1main.send(interncount)
time.sleep(0.01)
return
# main plot / GUI update
def update_line(*args):
global mypass
global t0
global runthread
global pipe1upd
if not runthread:
return False
if pipe1upd.poll(): # check first if there is anything to receive
myinterncount = pipe1upd.recv()
update_line.cnt = mypass
# restore the clean slate background
canvas.restore_region(background)
# update the data
line.set_ydata(nx.sin(x+(update_line.cnt+myinterncount)/10.0))
# just draw the animated artist
ax.draw_artist(line)
# just redraw the axes rectangle
canvas.blit(ax.bbox)
if update_line.cnt>=500:
# print the timing info and quit
print ''FPS:'' , update_line.cnt/(time.time()-tstart)
runthread=0
t0.join(1)
print "exiting"
sys.exit(0)
return True
global runthread
update_line.cnt = 0
mypass = 0
runthread=1
gobject.idle_add(update_line)
global t0
t0 = threading.Thread(target=threadMainTest)
t0.start()
# start the graphics update thread
p.show()
print "out" # will never print - show() blocks indefinitely!
Espero que esto ayude a alguien,
¡Aclamaciones!
En mi caso, quería que aparecieran varias ventanas a medida que se estaban calculando. Para referencia, este es el camino:
from matplotlib.pyplot import draw, figure, show
f1, f2 = figure(), figure()
af1 = f1.add_subplot(111)
af2 = f2.add_subplot(111)
af1.plot([1,2,3])
af2.plot([6,5,4])
draw()
print ''continuing computation''
show()
PD. Una guía bastante útil para la interfaz OO de matplotlib .
En mi opinión, las respuestas en este hilo proporcionan métodos que no funcionan para todos los sistemas y en situaciones más complejas como las animaciones. Sugiero ver la respuesta de MikeTex en el siguiente hilo, donde se ha encontrado un método robusto: ¿Cómo esperar hasta que termine la animación de matplotlib?
En mi sistema, show () no se bloquea, aunque quería que la secuencia de comandos esperara a que el usuario interactúe con el gráfico (y recopile datos utilizando devoluciones de llamada ''pick_event'') antes de continuar.
Para bloquear la ejecución hasta que se cierre la ventana de la trama, utilicé lo siguiente:
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(x,y)
# set processing to continue when window closed
def onclose(event):
fig.canvas.stop_event_loop()
fig.canvas.mpl_connect(''close_event'', onclose)
fig.show() # this call does not block on my system
fig.canvas.start_event_loop_default() # block here until window closed
# continue with further processing, perhaps using result from callbacks
Sin embargo, tenga en cuenta que canvas.start_event_loop_default () produjo la siguiente advertencia:
C:/Python26/lib/site-packages/matplotlib/backend_bases.py:2051: DeprecationWarning: Using default event loop until function specific to this GUI is implemented
warnings.warn(str,DeprecationWarning)
aunque el guion aun corria.
En muchos casos es más conveniente hasta guardar la imagen como un archivo .png en el disco duro. Aquí es por qué:
Ventajas:
- Puede abrirlo, echarle un vistazo y cerrarlo en cualquier momento del proceso. Esto es particularmente conveniente cuando su aplicación se ejecuta durante mucho tiempo.
- Nada aparece y no estás obligado a tener las ventanas abiertas. Esto es particularmente conveniente cuando se trata de muchas figuras.
- Se puede acceder a su imagen para una referencia posterior y no se pierde al cerrar la ventana de la figura.
Retirarse:
- Lo único en lo que puedo pensar es que tendrás que ir a buscar la carpeta y abrir la imagen tú mismo.
Es mejor consultar siempre con la biblioteca que está utilizando si admite el uso de forma no bloqueante .
Pero si desea una solución más genérica, o si no hay otra manera, puede ejecutar cualquier cosa que bloquee en un proceso separado utilizando el módulo de multprocessing
incluido en python. La computación continuará:
from multiprocessing import Process
from matplotlib.pyplot import plot, show
def plot_graph(*args):
for data in args:
plot(data)
show()
p = Process(target=plot_graph, args=([1, 2, 3],))
p.start()
print ''yay''
print ''computation continues...''
print ''that rocks.''
print ''Now lets wait for the graph be closed to continue...:''
p.join()
Eso tiene la sobrecarga de iniciar un nuevo proceso y, a veces, es más difícil de depurar en escenarios complejos, así que prefiero la otra solución (utilizando las llamadas de API sin bloqueo de matplotlib
)
Es posible que desee leer este documento en la documentación de matplotlib
, titulada:
Si desea abrir varias figuras, mientras mantiene todas abiertas, este código funcionó para mí:
show(block=False)
draw()
Si entiendo la pregunta correctamente, usar Ipython (o Ipython QT o Ipython notebook) le permitiría trabajar de manera interactiva con el gráfico mientras que los cálculos se ubican en segundo plano. http://ipython.org/
Si está trabajando en la consola, es decir, IPython
podría usar plt.show(block=False)
como se plt.show(block=False)
en las otras respuestas. Pero si eres perezoso puedes escribir:
plt.show(0)
Que será lo mismo.
También quise que mis gráficos se ejecuten el resto del código (y luego se sigan mostrando) incluso si hay un error (a veces uso gráficos para la depuración). Codifiqué este pequeño truco para que cualquier parcela dentro de esta declaración se comporte como tal.
Es probable que esto sea un poco no estándar y no recomendable para el código de producción. Probablemente hay muchos "errores" ocultos en este código.
from contextlib import contextmanager
@contextmanager
def keep_plots_open(keep_show_open_on_exit=True, even_when_error=True):
''''''
To continue excecuting code when plt.show() is called
and keep the plot on displaying before this contex manager exits
(even if an error caused the exit).
''''''
import matplotlib.pyplot
show_original = matplotlib.pyplot.show
def show_replacement(*args, **kwargs):
kwargs[''block''] = False
show_original(*args, **kwargs)
matplotlib.pyplot.show = show_replacement
pylab_exists = True
try:
import pylab
except ImportError:
pylab_exists = False
if pylab_exists:
pylab.show = show_replacement
try:
yield
except Exception, err:
if keep_show_open_on_exit and even_when_error:
print "*********************************************"
print "Error early edition while waiting for show():"
print "*********************************************"
import traceback
print traceback.format_exc()
show_original()
print "*********************************************"
raise
finally:
matplotlib.pyplot.show = show_original
if pylab_exists:
pylab.show = show_original
if keep_show_open_on_exit:
show_original()
# ***********************
# Running example
# ***********************
import pylab as pl
import time
if __name__ == ''__main__'':
with keep_plots_open():
pl.figure(''a'')
pl.plot([1,2,3], [4,5,6])
pl.plot([3,2,1], [4,5,6])
pl.show()
pl.figure(''b'')
pl.plot([1,2,3], [4,5,6])
pl.show()
time.sleep(1)
print ''...''
time.sleep(1)
print ''...''
time.sleep(1)
print ''...''
this_will_surely_cause_an_error
Si / cuando implemento un correcto "mantenga los gráficos abiertos (incluso si ocurre un error) y permita que se muestren nuevos gráficos", quisiera que la secuencia de comandos se cierre correctamente si ninguna interferencia del usuario le indica lo contrario (para fines de ejecución por lotes).
Puedo usar algo así como una pregunta de tiempo de espera "¡Fin del guión! / NPresione p si desea que la salida del trazado esté en pausa (tiene 5 segundos):" de https://.com/questions/26704840/corner-cases-for-my-wait-for-user-input-interruption-implementation .
También tuve que agregar plt.pause(0.001)
a mi código para que realmente funcionara dentro de un bucle for (de lo contrario solo mostraría la primera y la última gráfica):
import matplotlib.pyplot as plt
plt.scatter([0], [1])
plt.draw()
plt.show(block=False)
for i in range(10):
plt.scatter([i], [i+1])
plt.draw()
plt.pause(0.001)
Tratar
from matplotlib.pyplot import *
plot([1,2,3])
show(block=False)
# other code
# [...]
# Put
show()
# at the very end of your script
# to make sure Python doesn''t bail out
# before you finished examining.
La documentación de show()
dice:
En el modo no interactivo, muestre todas las figuras y bloquee hasta que las figuras se hayan cerrado; en el modo interactivo no tiene efecto a menos que las cifras se hayan creado antes de un cambio del modo no interactivo al modo interactivo (no recomendado). En ese caso muestra las figuras pero no bloquea.
Un solo argumento experimental de palabra clave,
block
, puede configurarse enTrue
oFalse
para anular el comportamiento de bloqueo descrito anteriormente.
Use la palabra clave ''bloque'' para anular el comportamiento de bloqueo, por ejemplo,
from matplotlib.pyplot import show, plot
plot(1)
show(block=False)
# your code
para continuar su código.
Use las llamadas de matplotlib
que no bloquearán:
Utilizando draw()
:
from matplotlib.pyplot import plot, draw, show
plot([1,2,3])
draw()
print ''continue computation''
# at the end call show to ensure window won''t close.
show()
Usando el modo interactivo:
from matplotlib.pyplot import plot, ion, show
ion() # enables interactive mode
plot([1,2,3]) # result shows immediatelly (implicit draw())
print ''continue computation''
# at the end call show to ensure window won''t close.
show()
IMPORTANTE : Solo para aclarar algo. Supongo que los comandos están dentro de un script .py
y el script se llama usando, por ejemplo, python script.py
desde la consola.
Una forma simple que funciona para mí es:
- Use el bloque = Falso dentro del espectáculo: plt.show (bloque = Falso)
- Use otro show () al final de la secuencia de comandos .py.
Ejemplo de archivo script.py
:
plt.imshow(*something*)
plt.colorbar()
plt.xlabel("true ")
plt.ylabel("predicted ")
plt.title(" the matrix")
# Add block = False
plt.show(block = False)
# OTHER CALCULATIONS AND CODE
# the next is the last line of my script
plt.show()
plt.figure(1)
plt.imshow(your_first_image)
plt.figure(2)
plt.imshow(your_second_image)
plt.show(block=False) # That''s important
raw_input("Press ENTER to exist") # Useful when you run your Python script from the terminal and you want to hold the running to see your figures until you press Enter