Actualmente estoy evaluando diferentes bibliotecas de trazado de Python. Ahora mismo estoy probando matplotlib y estoy bastante decepcionado con el rendimiento. El siguiente ejemplo está modificado a partir de ejemplos de SciPy y me da solo ~ 8 cuadros por segundo.
¿Alguna forma de acelerar esto o debería elegir una biblioteca de trazado diferente?
from pylab import *
import time
ion()
fig = figure()
ax1 = fig.add_subplot(611)
ax2 = fig.add_subplot(612)
ax3 = fig.add_subplot(613)
ax4 = fig.add_subplot(614)
ax5 = fig.add_subplot(615)
ax6 = fig.add_subplot(616)
x = arange(0,2*pi,0.01)
y = sin(x)
line1, = ax1.plot(x, y, 'r-')
line2, = ax2.plot(x, y, 'g-')
line3, = ax3.plot(x, y, 'y-')
line4, = ax4.plot(x, y, 'm-')
line5, = ax5.plot(x, y, 'k-')
line6, = ax6.plot(x, y, 'p-')
# turn off interactive plotting - speeds things up by 1 Frame / second
plt.ioff()
tstart = time.time() # for profiling
for i in arange(1, 200):
line1.set_ydata(sin(x+i/10.0)) # update the data
line2.set_ydata(sin(2*x+i/10.0))
line3.set_ydata(sin(3*x+i/10.0))
line4.set_ydata(sin(4*x+i/10.0))
line5.set_ydata(sin(5*x+i/10.0))
line6.set_ydata(sin(6*x+i/10.0))
draw() # redraw the canvas
print 'FPS:' , 200/(time.time()-tstart)
python
matplotlib
memyself
fuente
fuente
Respuestas:
En primer lugar, (aunque esto no cambiará el rendimiento en absoluto) considere limpiar su código, similar a esto:
Con el ejemplo anterior, obtengo alrededor de 10 fps.
Solo una nota rápida, dependiendo de su caso de uso exacto, matplotlib puede no ser una gran opción. Está orientado a cifras de calidad de publicación, no a visualización en tiempo real.
Sin embargo, hay muchas cosas que puede hacer para acelerar este ejemplo.
Hay dos razones principales por las que esto es tan lento como lo es.
1) Llamar
fig.canvas.draw()
redibuja todo . Es tu cuello de botella. En su caso, no necesita volver a dibujar cosas como los límites de los ejes, las etiquetas de marca, etc.2) En su caso, hay muchas subtramas con muchas etiquetas de verificación. Estos toman mucho tiempo para dibujar.
Ambos pueden solucionarse mediante blitting.
Para hacer blitting de manera eficiente, deberá usar código específico de backend. En la práctica, si está realmente preocupado por las animaciones fluidas, generalmente está incrustando gráficos de matplotlib en algún tipo de kit de herramientas de interfaz gráfica de usuario, por lo que esto no es un gran problema.
Sin embargo, sin saber un poco más sobre lo que estás haciendo, no puedo ayudarte en eso.
No obstante, existe una forma de hacerlo sin interfaz gráfica de usuario que sigue siendo razonablemente rápida.
Esto me da ~ 200 fps.
Para que esto sea un poco más conveniente, hay una
animations
módulo en las versiones recientes de matplotlib.Como ejemplo:
fuente
animation
parece actualizar el gráfico porinterval
período de tiempo, ¿qué pasa si solo quiero actualizarlo cuando haya nuevos datos listos?Matplotlib produce excelentes gráficos con calidad de publicación, pero no está muy bien optimizado para la velocidad. Hay una variedad de paquetes de trazado de Python que están diseñados teniendo en cuenta la velocidad:
[editar: pyqwt ya no se mantiene; el mantenedor anterior recomienda pyqtgraph]
fuente
Para empezar, la respuesta de Joe Kington proporciona muy buenos consejos utilizando un enfoque de interfaz gráfica de usuario neutral, y definitivamente debe seguir su consejo (especialmente sobre Blitting) y ponerlo en práctica. Más información sobre este enfoque, lea el libro de cocina de Matplotlib
Sin embargo, el enfoque no neutral en GUI (¿sesgado en GUI?) Es clave para acelerar el trazado. En otras palabras, el backend es extremadamente importante para trazar la velocidad.
Coloque estas dos líneas antes de importar cualquier otra cosa de matplotlib:
Por supuesto, hay varias opciones para usar en lugar de
GTKAgg
, pero según el libro de cocina mencionado anteriormente, esta fue la más rápida. Consulte el enlace sobre backends para obtener más opciones.fuente
Para la primera solución propuesta por Joe Kington (.copy_from_bbox & .draw_artist & canvas.blit), tuve que capturar los fondos después la línea fig.canvas.draw (), de lo contrario, el fondo no tuvo ningún efecto y obtuve el mismo resultado que Mencionaste. Si lo coloca después de fig.show () todavía no funciona como lo propone Michael Browne.
Así que simplemente ponga la línea de fondo después de canvas.draw ():
fuente
Es posible que esto no se aplique a muchos de ustedes, pero generalmente estoy operando mis computadoras bajo Linux, por lo que de manera predeterminada guardo mis gráficos de matplotlib como PNG y SVG. Esto funciona bien en Linux, pero es insoportablemente lento en mis instalaciones de Windows 7 [MiKTeX en Python (x, y) o Anaconda], así que decidí agregar este código y las cosas funcionan bien allí nuevamente:
fuente