【问题标题】:Matplotlib Agg Rendering Complexity ErrorMatplotlib Agg 渲染复杂度错误
【发布时间】:2012-02-11 03:45:16
【问题描述】:

我正在尝试使用 Python matplotlib 打印 600 dpi 图形。但是 Python 绘制了 8 个图形中的 2 个,并输出错误:

OverflowError: Agg rendering complexity exceeded. Consider downsampling or decimating your data.

我正在绘制大量数据(每列 7,500,000 个数据),所以我猜这可能是一些过载问题,或者我需要设置一个大的 cell_block_limit。

我尝试在 Google 上搜索更改 cell_block_limit 的解决方案,但无济于事。什么是好的方法?

代码如下:-

        import matplotlib.pyplot as plt
        from matplotlib.ticker import MultipleLocator, FormatStrFormatter

        majorLocator   = MultipleLocator(200)
        majorFormatter = FormatStrFormatter('%d')
        minorLocator   = MultipleLocator(20)

        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.xaxis.set_major_locator(majorLocator)
        ax.xaxis.set_major_formatter(majorFormatter)
        ax.xaxis.set_minor_locator(minorLocator)
        ax.xaxis.set_ticks_position('bottom')
        ax.xaxis.grid(True,which='minor')
        ax.yaxis.grid(True)
        plt.plot(timemat,fildata)
        plt.xlabel(plotxlabel,fontsize=14)
        plt.ylabel(plotylabel,fontsize=14)      
        plt.title(plottitle,fontsize=16)
        fig.savefig(plotsavetitle,dpi=600)

【问题讨论】:

  • 这是很多数据,考虑到 1600x1200 将“只有”1,920,000 个像素。你想制作什么样的情节?如果它是一个直方图,你可以将它们装箱,一条线可以被二次采样..
  • 它是来自加速度计的数据,以 1500 Hz 采样以捕获高频冲击。我正在尝试制作简单的电压(V)与时间图。因此,首先我为时间数组生成类似数量的数据,并根据时间绘制信号。是的,它很大,但我相信它会变得更大,因为我们正在进行 2 到 4 小时的实验。请告诉我如何对一条线进行二次采样...非常感谢!
  • 在输入上使用切片(在两个轴上)。例如,要选择数组 x 的每 10 个元素,您可以使用 x[::10]
  • 但是,有没有办法在不抽取任何数据的情况下绘制数据?
  • 将其拆分为单独的图。除非图像真的很宽,否则您无法将那么多信息放入图像中。但是,鉴于您所说的高频冲击,也许对您更有帮助的可能是查看频谱的高频部分(FFT)而不是时域。

标签: python python-3.x matplotlib


【解决方案1】:

除了@Lennart 指出不需要完整分辨率之外,您还可以考虑类似以下的情节。

如果您使用原始数组的 2D 视图和 axis 关键字 arg 到 x.min()x.max() 等,计算“分块”版本的最大值/平均值/最小值非常简单有效。

即使使用过滤,绘制它也比绘制完整数组快得多。

(注意:要绘制这么多点,您必须稍微调低噪音水平。否则您将得到您提到的OverflowError。如果您想比较绘制“完整”数据集,请更改y += 0.3 * y.max() np.random... 行更像0.1 或将其完全删除。)

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1977)

# Generate some very noisy but interesting data...
num = 1e7
x = np.linspace(0, 10, num)
y = np.random.random(num) - 0.5
y.cumsum(out=y) 
y += 0.3 * y.max() * np.random.random(num)

fig, ax = plt.subplots()

# Wrap the array into a 2D array of chunks, truncating the last chunk if 
# chunksize isn't an even divisor of the total size.
# (This part won't use _any_ additional memory)
chunksize = 10000
numchunks = y.size // chunksize 
ychunks = y[:chunksize*numchunks].reshape((-1, chunksize))
xchunks = x[:chunksize*numchunks].reshape((-1, chunksize))

# Calculate the max, min, and means of chunksize-element chunks...
max_env = ychunks.max(axis=1)
min_env = ychunks.min(axis=1)
ycenters = ychunks.mean(axis=1)
xcenters = xchunks.mean(axis=1)

# Now plot the bounds and the mean...
ax.fill_between(xcenters, min_env, max_env, color='gray', 
                edgecolor='none', alpha=0.5)
ax.plot(xcenters, ycenters)

fig.savefig('temp.png', dpi=600)

【讨论】:

  • 太棒了!查看数据的极其丰富和创新的方式! +++
【解决方案2】:

使用 600dpi 时,您必须将绘图设置为 13 米宽,才能在不抽取数据的情况下绘制数据。 :-)

我建议将数据分成几百甚至一千个样本长的片段,然后从中提取最大值。

类似这样的:

def chunkmax(data, chunk_size):
    source = iter(data)
    chunk = []
    while True:
        for i in range(chunk_size):
            chunk.append(next(source))

        yield max(chunk)

然后,如果 chunk_size 为 1000,您可以绘制 7500 个点,然后您可以轻松地看到数据中的冲击来自何处。 (除非数据非常嘈杂,否则您必须对其进行平均以查看是否存在阻塞。但这也很容易修复)。

【讨论】:

  • 谢谢!似乎真的没有其他方法可以绘制高 dpi 图。
  • 仅供参考:虽然这是一个很好的建议,但上面的实际代码对于 numpy 数组来说效率非常低。你最好做chunks = data.reshape((-1, chunk_size)); max_filtered = chunks.max(axis=1)之类的事情。 (假设块大小是总大小的偶数除数的简单情况......不过,一个通用示例只是额外的一两行。)
  • @JoeKington:哦,他使用 numpy?我没明白。真的迭代一个 numpy 数组效率低下吗?哦,好吧。
  • @LennartRegebro - 好吧,如果他存储 >1e7 个浮点数(2e6 的 8 列),我假设他正在使用 numpy(否则他会遇到内存问题)。 Matplotlib 无论如何都会将其转换为 numpy 数组。无论如何,与遍历列表相比,遍历 numpy 数组是低效的。主要原因是内存效率。在这种大小下,使用列表存储大型浮点数组的开销变得非常明显。 numpy 使用的内存是列表的 1/4 来存储大量浮点数/整数/等。
  • @JoeKington:好吧,要绘制它们,您不需要存储它们。 :-) 上述函数有意与生成器一起使用,因此您不必一次将数据全部加载到内存中。 (当然,其他部分可能需要这样做)。
猜你喜欢
  • 1970-01-01
  • 2011-11-19
  • 2019-03-09
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多