По-перше, (хоча це зовсім не змінить продуктивність), розгляньте можливість очищення коду, подібно до цього:
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)
У наведеному вище прикладі я отримую близько 10 кадрів в секунду.
Просто коротко, залежно від вашого конкретного випадку використання, matplotlib може бути не найкращим вибором. Він орієнтований на показники якості публікації, а не на показ у режимі реального часу.
Однак є багато речей, які ви можете зробити, щоб пришвидшити цей приклад.
Є дві основні причини, чому це так само повільно, як і зараз.
1) Телефонування fig.canvas.draw()
перерисовує все . Це ваше вузьке місце. У вашому випадку вам не потрібно перемальовувати такі речі, як межі осей, позначки галочок тощо.
2) У вашому випадку є багато підзаголовків із великою кількістю міток. Вони малюють довго.
І те, і інше можна виправити за допомогою бліттингу.
Щоб ефективно виконувати блітінг, вам доведеться використовувати специфічний код. На практиці, якщо ви дійсно стурбовані плавною анімацією, ви, як правило, вбудовуєте графіки matplotlib в якийсь набір інструментів gui, тому це не велика проблема.
Однак, не знаючи трохи більше про те, що ви робите, я не можу вам там допомогти.
Тим не менше, існує нейтральний до графічного інтерфейсу спосіб, який все ще є досить швидким.
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)
Це дає мені ~ 200 кадрів в секунду.
Щоб зробити це трохи зручнішим, є animations
в останніх версіях matplotlib модуль.
Як приклад:
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()