현재 다른 파이썬 플로팅 라이브러리를 평가하고 있습니다. 지금은 matplotlib를 시도하고 있으며 성능에 매우 실망합니다. 다음 예제는 SciPy 예제 에서 수정되었으며 초당 ~ 8 프레임 만 제공합니다!
속도를 높이는 방법이 있습니까? 아니면 다른 플로팅 라이브러리를 선택해야합니까?
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)
답변
먼저 (성능에 전혀 영향을주지 않지만) 다음과 같이 코드를 정리하는 것이 좋습니다.
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)
위의 예에서는 약 10fps를 얻습니다.
정확한 사용 사례에 따라 matplotlib는 좋은 선택이 아닐 수 있습니다. 실시간 디스플레이가 아닌 출판 품질의 수치를 지향합니다.
그러나이 예제의 속도를 높이기 위해 수행 할 수있는 작업이 많이 있습니다.
이것이 느린 이유는 크게 두 가지입니다.
1) 호출하면 모든 것이fig.canvas.draw()
다시 그려 집니다. 병목 현상입니다. 귀하의 경우 축 경계, 눈금 레이블 등과 같은 것을 다시 그릴 필요가 없습니다.
2) 귀하의 경우에는 눈금 레이블이 많은 서브 플롯이 많이 있습니다. 그리는 데 시간이 오래 걸립니다.
둘 다 블리 팅을 사용하여 수정할 수 있습니다.
블리 팅을 효율적으로 수행하려면 백엔드 별 코드를 사용해야합니다. 실제로 부드러운 애니메이션에 대해 정말로 걱정한다면, 어쨌든 일종의 GUI 툴킷에 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)
이것은 ~ 200fps를 제공합니다.
이것을 좀 더 편리하게 만들기 위해 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()
답변
Matplotlib는 훌륭한 출판 품질의 그래픽을 만들지 만 속도에 최적화되어 있지는 않습니다. 속도를 염두에두고 설계된 다양한 파이썬 플로팅 패키지가 있습니다.
- http://vispy.org
- http://pyqtgraph.org/
- http://docs.enthought.com/chaco/
- http://pyqwt.sourceforge.net/
[편집 : pyqwt는 더 이상 유지되지 않습니다. 이전 관리자는 pyqtgraph를 추천합니다] - http://code.google.com/p/guiqwt/
답변
시작하려면 Joe Kington의 답변 은 GUI 중립적 접근 방식을 사용하여 매우 좋은 조언을 제공하며, 그의 조언 (특히 Blitting에 대한)을 확실히 받아 실행해야합니다. 이 접근 방식에 대한 자세한 내용은 Matplotlib Cookbook을 참조하십시오.
그러나 비 GUI 중립 (GUI 편향?) 접근 방식은 플로팅 속도를 높이는 데 중요합니다. 즉, 백엔드 는 속도를 플롯하는 데 매우 중요합니다.
matplotlib에서 다른 것을 가져 오기 전에 다음 두 줄을 넣으십시오.
import matplotlib
matplotlib.use('GTKAgg')
물론 대신 사용할 수있는 다양한 옵션이 GTKAgg
있지만 앞서 언급 한 요리 책에 따르면 이것이 가장 빠릅니다. 더 많은 옵션은 백엔드에 대한 링크를 참조하십시오.
답변
Joe Kington이 제안한 첫 번째 솔루션 (.copy_from_bbox & .draw_artist & canvas.blit)의 경우 fig.canvas.draw () 라인 뒤 의 배경을 캡처해야했습니다 . 그렇지 않으면 배경이 효과가 없었고 다음과 같은 결과를 얻었습니다. 당신이 언급했습니다. fig.show () 뒤에 넣으면 Michael Browne이 제안한대로 작동하지 않습니다.
따라서 canvas.draw () 뒤에 배경 선 을 넣으십시오 .
[...]
fig.show()
# We need to draw the canvas before we start animating...
fig.canvas.draw()
# Let's capture the background of the figure
backgrounds = [fig.canvas.copy_from_bbox(ax.bbox) for ax in axes]
답변
이것은 많은 사람들에게 적용되지 않을 수 있지만 일반적으로 Linux에서 컴퓨터를 작동하므로 기본적으로 matplotlib 플롯을 PNG 및 SVG로 저장합니다. 이것은 Linux에서는 잘 작동하지만 Windows 7 설치 [Python (x, y) 또는 Anaconda의 MiKTeX]에서는 참을 수 없을 정도로 느리기 때문에이 코드를 추가했으며 모든 것이 다시 잘 작동합니다.
import platform # Don't save as SVG if running under Windows.
#
# Plot code goes here.
#
fig.savefig('figure_name.png', dpi = 200)
if platform.system() != 'Windows':
# In my installations of Windows 7, it takes an inordinate amount of time to save
# graphs as .svg files, so on that platform I've disabled the call that does so.
# The first run of a script is still a little slow while everything is loaded in,
# but execution times of subsequent runs are improved immensely.
fig.savefig('figure_name.svg')