Em primeiro lugar, (embora isso não mude o desempenho de forma alguma), considere limpar seu código, semelhante a este:
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)
Com o exemplo acima, obtenho cerca de 10 fps.
Apenas uma nota rápida, dependendo do seu caso de uso exato, matplotlib pode não ser uma ótima escolha. É orientado para números de qualidade de publicação, não para exibição em tempo real.
No entanto, há muitas coisas que você pode fazer para acelerar este exemplo.
Existem duas razões principais pelas quais isso é tão lento quanto é.
1) Chamar fig.canvas.draw()
redesenha tudo . É o seu gargalo. No seu caso, você não precisa redesenhar coisas como os limites dos eixos, rótulos de escala, etc.
2) No seu caso, há muitos subplots com muitos rótulos de escala. Demora muito para desenhar.
Ambos podem ser corrigidos usando blitting.
Para fazer blitting com eficiência, você terá que usar um código específico do backend. Na prática, se você está realmente preocupado com animações suaves, normalmente está incorporando gráficos matplotlib em algum tipo de kit de ferramentas de interface do usuário, então isso não é um grande problema.
Porém, sem saber um pouco mais sobre o que você está fazendo, não posso te ajudar nisso.
No entanto, existe uma maneira neutra de gui de fazer isso que ainda é razoavelmente 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)
Isso me dá ~ 200 fps.
Para tornar isso um pouco mais conveniente, há um animations
módulo nas versões recentes do matplotlib.
Como um exemplo:
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()