En primer lugar, (aunque esto no cambiará el rendimiento en absoluto) considere limpiar su código, similar a esto:
import matplotlib.pyplot as plt
import numpy as np
import time
x = np.arange(0, 2*np.pi, 0.01)
y = np.sin(x)
fig, axes = plt.subplots(nrows=6)
styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
lines = [ax.plot(x, y, style)[0] for ax, style in zip(axes, styles)]
fig.show()
tstart = time.time()
for i in xrange(1, 20):
for j, line in enumerate(lines, start=1):
line.set_ydata(np.sin(j*x + i/10.0))
fig.canvas.draw()
print 'FPS:' , 20/(time.time()-tstart)
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.
import matplotlib.pyplot as plt
import numpy as np
import time
x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)
fig, axes = plt.subplots(nrows=6)
fig.show()
# We need to draw the canvas before we start animating...
fig.canvas.draw()
styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
def plot(ax, style):
return ax.plot(x, y, style, animated=True)[0]
lines = [plot(ax, style) for ax, style in zip(axes, styles)]
# Let's capture the background of the figure
backgrounds = [fig.canvas.copy_from_bbox(ax.bbox) for ax in axes]
tstart = time.time()
for i in xrange(1, 2000):
items = enumerate(zip(lines, axes, backgrounds), start=1)
for j, (line, ax, background) in items:
fig.canvas.restore_region(background)
line.set_ydata(np.sin(j*x + i/10.0))
ax.draw_artist(line)
fig.canvas.blit(ax.bbox)
print 'FPS:' , 2000/(time.time()-tstart)
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:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)
fig, axes = plt.subplots(nrows=6)
styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
def plot(ax, style):
return ax.plot(x, y, style, animated=True)[0]
lines = [plot(ax, style) for ax, style in zip(axes, styles)]
def animate(i):
for j, line in enumerate(lines, start=1):
line.set_ydata(np.sin(j*x + i/10.0))
return lines
# We'd normally specify a reasonable "interval" here...
ani = animation.FuncAnimation(fig, animate, xrange(1, 200),
interval=0, blit=True)
plt.show()