我正在努力加快将图表保存到图像的过程。现在我正在创建一个cString对象,我使用savefig保存图表;但我真的非常感谢任何帮助改进这种保存图像的方法。我必须做几十次这个操作,而savefig命令非常慢;必须有更好的方法。我读了一些关于将其保存为未压缩的原始图像的内容,但我不知道如何做到这一点。如果我可以切换到另一个更快的后端,我真的不关心agg。
即:
RAM = cStringIO.StringIO()
CHART = plt.figure(....
**code for creating my chart**
CHART.savefig(RAM, format='png')
我一直在使用带有FigureCanvasAgg后端的matplotlib。
谢谢!
答案 0 :(得分:33)
如果您只想要原始缓冲区,请尝试fig.canvas.print_rgb
,fig.canvas.print_raw
等(两者之间的差异是raw
是rgba,而rgb
是rgb。还有print_png
,print_ps
等)
这将使用fig.dpi
而不是savefig
(100 dpi)的默认dpi值。尽管如此,即使比较fig.canvas.print_raw(f)
和fig.savefig(f, format='raw', dpi=fig.dpi)
,print_canvas
版本稍微快一点也要快得多,因为它不会重新设置轴补丁的颜色等等。 ,savefig
默认执行。
尽管如此,大部分时间花在以原始格式保存数字上的只是绘制数字,这是无法绕过的。
无论如何,作为一个毫无意义但又有趣的例子,请考虑以下因素:
import matplotlib.pyplot as plt
import numpy as np
import cStringIO
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
num = 50
max_dim = 10
x = max_dim / 2 * np.ones(num)
s, c = 100 * np.random.random(num), np.random.random(num)
scat = ax.scatter(x,x,s,c)
ax.axis([0,max_dim,0,max_dim])
ax.set_autoscale_on(False)
for i in xrange(1000):
xy = np.random.random(2*num).reshape(num,2) - 0.5
offsets = scat.get_offsets() + 0.3 * xy
offsets.clip(0, max_dim, offsets)
scat.set_offsets(offsets)
scat._sizes += 30 * (np.random.random(num) - 0.5)
scat._sizes.clip(1, 300, scat._sizes)
fig.canvas.draw()
如果我们查看原始抽奖时间:
import matplotlib.pyplot as plt
import numpy as np
import cStringIO
fig = plt.figure()
ax = fig.add_subplot(111)
num = 50
max_dim = 10
x = max_dim / 2 * np.ones(num)
s, c = 100 * np.random.random(num), np.random.random(num)
scat = ax.scatter(x,x,s,c)
ax.axis([0,max_dim,0,max_dim])
ax.set_autoscale_on(False)
for i in xrange(1000):
xy = np.random.random(2*num).reshape(num,2) - 0.5
offsets = scat.get_offsets() + 0.3 * xy
offsets.clip(0, max_dim, offsets)
scat.set_offsets(offsets)
scat._sizes += 30 * (np.random.random(num) - 0.5)
scat._sizes.clip(1, 300, scat._sizes)
fig.canvas.draw()
我的机器需要大约25秒。
如果我们将原始RGBA缓冲区转储到cStringIO缓冲区,它实际上在~22秒时稍微快一点(这只是因为我使用的是交互式后端!否则它将是等效的。):
import matplotlib.pyplot as plt
import numpy as np
import cStringIO
fig = plt.figure()
ax = fig.add_subplot(111)
num = 50
max_dim = 10
x = max_dim / 2 * np.ones(num)
s, c = 100 * np.random.random(num), np.random.random(num)
scat = ax.scatter(x,x,s,c)
ax.axis([0,max_dim,0,max_dim])
ax.set_autoscale_on(False)
for i in xrange(1000):
xy = np.random.random(2*num).reshape(num,2) - 0.5
offsets = scat.get_offsets() + 0.3 * xy
offsets.clip(0, max_dim, offsets)
scat.set_offsets(offsets)
scat._sizes += 30 * (np.random.random(num) - 0.5)
scat._sizes.clip(1, 300, scat._sizes)
ram = cStringIO.StringIO()
fig.canvas.print_raw(ram)
ram.close()
如果我们将此与使用savefig
进行比较,并使用相对设置的dpi:
import matplotlib.pyplot as plt
import numpy as np
import cStringIO
fig = plt.figure()
ax = fig.add_subplot(111)
num = 50
max_dim = 10
x = max_dim / 2 * np.ones(num)
s, c = 100 * np.random.random(num), np.random.random(num)
scat = ax.scatter(x,x,s,c)
ax.axis([0,max_dim,0,max_dim])
ax.set_autoscale_on(False)
for i in xrange(1000):
xy = np.random.random(2*num).reshape(num,2) - 0.5
offsets = scat.get_offsets() + 0.3 * xy
offsets.clip(0, max_dim, offsets)
scat.set_offsets(offsets)
scat._sizes += 30 * (np.random.random(num) - 0.5)
scat._sizes.clip(1, 300, scat._sizes)
ram = cStringIO.StringIO()
fig.savefig(ram, format='raw', dpi=fig.dpi)
ram.close()
这需要大约23.5秒。基本上,savefig
只设置一些默认参数并调用print_raw
,在这种情况下,所以差别很小。
现在,如果我们将原始图像格式与压缩图像格式(png)进行比较,我们会发现更显着的差异:
import matplotlib.pyplot as plt
import numpy as np
import cStringIO
fig = plt.figure()
ax = fig.add_subplot(111)
num = 50
max_dim = 10
x = max_dim / 2 * np.ones(num)
s, c = 100 * np.random.random(num), np.random.random(num)
scat = ax.scatter(x,x,s,c)
ax.axis([0,max_dim,0,max_dim])
ax.set_autoscale_on(False)
for i in xrange(1000):
xy = np.random.random(2*num).reshape(num,2) - 0.5
offsets = scat.get_offsets() + 0.3 * xy
offsets.clip(0, max_dim, offsets)
scat.set_offsets(offsets)
scat._sizes += 30 * (np.random.random(num) - 0.5)
scat._sizes.clip(1, 300, scat._sizes)
ram = cStringIO.StringIO()
fig.canvas.print_png(ram)
ram.close()
这需要~52秒!显然,压缩图像会产生很多开销。
无论如何,这可能是一个不必要的复杂例子......我想我只是想避免实际的工作......
答案 1 :(得分:2)
我还需要快速生成大量的情节。我发现多处理可以提高绘图速度和可用内核数量。例如,如果在一个进程中100个绘图需要10秒,那么当任务分成4个核心时需要大约3秒。