Hacer que la ventana de matplotlib interactiva no aparezca en cada actualización (Windows 7)

Hoy actualicé matplotlib a la versión 2.0.2, después de no actualizar por posiblemente 3 años.

Ahora tengo el problema de que, en los gráficos interactivos, la ventana siempre aparece en la parte frontal, como si aquí se abriera la ventana de trazado de matplotlib, ya que la activa se había convertido en el comportamiento predeterminado.

¿Cómo puedo desactivarlo? No quiero que la ventana se abra al frente cada 5 segundos y aparezca sobre mi editor de texto, navegador, …

Quiero que permanezca en el orden z donde lo he colocado, ya sea al frente o detrás de una ventana activa.

Creo que la siguiente confirmación a partir del 31 de enero de 2016 es responsable de este comportamiento problemático: tkagg: elevar cada nueva ventana; direcciones parcialmente # 596

Se encontró un comentario relacionado en Github https://github.com/matplotlib/matplotlib/issues/596#issuecomment-305298577

parece que mi llamada a plt.pause es la que causa este problema, y ​​no la llamada plt.plot .

Cambiando el backend

El problema parece solo presente usando el backend Tk . Usando el backend de Qt , la ventana permanecería donde estaba mientras se actualizaba con plt.pause .

Para cambiar el backend usa esas líneas al principio de tu script.

 import matplotlib matplotlib.use("Qt4agg") # or "Qt5agg" depending on you version of Qt 

Modificando plt.pause

Si cambiar el backend no es una opción, lo siguiente podría ayudar. La causa de que la ventana aparezca constantemente en la parte delantera proviene de plt.pause llama a plt.show() internamente. Por lo tanto, implementas tu propia función de pause , sin llamar al show . Esto requiere estar en modo interactivo plt.ion() primero y luego al menos una vez llamar a plt.show() . Luego, puede actualizar la gráfica con la función mypause personalizada como se muestra a continuación.

 import matplotlib matplotlib.use("TkAgg") import matplotlib.pyplot as plt from time import time from random import random plt.ion() # set up the figure fig = plt.figure() plt.xlabel('Time') plt.ylabel('Value') plt.show(block=False) def mypause(interval): backend = plt.rcParams['backend'] if backend in matplotlib.rcsetup.interactive_bk: figManager = matplotlib._pylab_helpers.Gcf.get_active() if figManager is not None: canvas = figManager.canvas if canvas.figure.stale: canvas.draw() canvas.start_event_loop(interval) return t0 = time() t = [] y = [] while True: t.append( time()-t0 ) y.append( random() ) plt.gca().clear() plt.plot( t , y ) mypause(1) 

Utilizando una animation .

Finalmente, el uso de una clase matplotlib.animation haría que todo lo anterior matplotlib.animation obsoleto. Un ejemplo de matplotlib.animation.FuncAnimation se muestra en la página matplotlib .

Tuve el mismo problema en la Mac. No estoy seguro de si este es el mejor enfoque, pero en lugar de usar plt.pause(0.001) , fig.canvas.start_event_loop(0.001) a fig.canvas.start_event_loop(0.001) para actualizar cada fotogtwig en mi animación. Esto permite que las ventanas permanezcan en el fondo.

Es abril de 2019 y la función mypause () (copiada de la implementación actualizada de pyplot) para Matplotlib 3.0.3 debería parecerse más a

 import time import matplotlib.pyplot as plt def mypause(interval): manager = plt._pylab_helpers.Gcf.get_active() if manager is not None: canvas = manager.canvas if canvas.figure.stale: canvas.draw_idle() #plt.show(block=False) canvas.start_event_loop(interval) else: time.sleep(interval) 

Después de algunas pruebas (Qt5 backend / Spyder / Windows 7 64bit) las llamadas que hacen el truco para mí son:

 #plt.pause(0.001) #Brings plot to foreground #fig.canvas.draw() #Does not work #plt.draw_all() #Does not work #plt.draw() #Does not work #fig.canvas.flush_events() #Updates only if I click the figure #import time; time.sleep(0.001) #Does not help flush_events() #fig.canvas.draw_idle() #Does not work by itself #fig.canvas.start_event_loop(0.001) #Does not work by itself #mypause(0.001) #Works! #Works! fig.canvas.draw_idle() fig.canvas.start_event_loop(0.001) 

Si el higo es tu objeto figura. Cualquiera de los dos solos no funcionó en mi caso. Según la documentación de la animación , esto es esencialmente lo que hace FuncAnimation.

Reescribí el código para usar matplotlib.animation con la ayuda de esta página de documentación https://matplotlib.org/devdocs/api/animation_api.html#module-matplotlib.animation

Llegué a esa página a través de este https://matplotlib.org/devdocs/api/_as_gen/matplotlib.pyplot.pause.html

que establece lo siguiente sobre matplotlib.pyplot.pause

Esto se puede utilizar para la animación cruda. Para una animación más compleja, vea matplotlib.animation.

Esta función es experimental; Su comportamiento puede ser cambiado o extendido en una versión futura.