Prima di tutto, (anche se questo non cambierà affatto le prestazioni) prendi in considerazione la pulizia del tuo codice, in modo simile a questo:
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 l'esempio sopra, ottengo circa 10 fps.
Solo una breve nota, a seconda del tuo esatto caso d'uso, matplotlib potrebbe non essere un'ottima scelta. È orientato verso cifre di qualità da pubblicazione, non visualizzazione in tempo reale.
Tuttavia, ci sono molte cose che puoi fare per accelerare questo esempio.
Ci sono due ragioni principali per cui questo è così lento.
1) Il richiamo fig.canvas.draw()ridisegna tutto . È il tuo collo di bottiglia. Nel tuo caso, non è necessario ridisegnare elementi come i confini degli assi, le etichette di spunta, ecc.
2) Nel tuo caso, ci sono molte sottotrame con molte etichette di graduazione. Questi richiedono molto tempo per disegnare.
Entrambi questi possono essere risolti utilizzando blitting.
Per eseguire il blitting in modo efficiente, dovrai utilizzare il codice specifico del backend. In pratica, se sei davvero preoccupato per le animazioni fluide, di solito stai incorporando i grafici matplotlib in una sorta di toolkit della GUI, comunque, quindi questo non è un grosso problema.
Tuttavia, senza sapere qualcosa di più su quello che stai facendo, non posso aiutarti.
Tuttavia, esiste un modo per farlo neutrale rispetto alla gui che è ancora ragionevolmente veloce.
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)
Questo mi dà ~ 200 fps.
Per renderlo un po 'più conveniente, c'è un animationsmodulo nelle versioni recenti di matplotlib.
Come esempio:
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()