我有一个二维数组,我想使用 matplotlib 从中生成等高线图。保存为 PNG(或其他光栅格式)时一切正常,但是为了将图形包含在论文中,我需要保存为 postscript 格式。
问题是,当我保存到 postscript 时,我得到的文件非常大(一些 MB)。看起来 Matplotlib 以矢量格式保存所有内容。虽然这对轴和标签有意义,但如果光栅化会降低,我希望等高线图本身以光栅格式(我知道可以嵌入在后记中)。有人知道怎么做吗?我正在使用 Agg 后端。
4 回答
您可以设置:
plt.gcf().set_rasterized(True)
在 plt.savefig 之前
这是一个最小的工作示例。我使用sega_sai的代码已经有一段时间了,没有任何问题。
from matplotlib.collections import Collection
from matplotlib.artist import allow_rasterization
import matplotlib.pyplot as plt
class ListCollection(Collection):
def __init__(self, collections, **kwargs):
Collection.__init__(self, **kwargs)
self.set_collections(collections)
def set_collections(self, collections):
self._collections = collections
def get_collections(self):
return self._collections
@allow_rasterization
def draw(self, renderer):
for _c in self._collections:
_c.draw(renderer)
def insert_rasterized_contour_plot(c):
collections = c.collections
for _c in collections:
_c.remove()
cc = ListCollection(collections, rasterized=True)
ax = plt.gca()
ax.add_artist(cc)
return cc
if __name__ == '__main__':
import numpy as np
x, y = np.meshgrid(*(np.linspace(-1,1,500),)*2)
z = np.sin(20*x**2)*np.cos(30*y)
c = plt.contourf(x,y,z,30)
plt.savefig('fig_normal.pdf')
insert_rasterized_contour_plot(c)
plt.savefig('fig_rasterized.pdf')
在我的电脑上,这会导致:
fig_normal.pdf:文件大小为 5810 KByte,需要约 5 秒才能在 Adobe Reader 中呈现
fig_rasterized.pdf:文件大小为 60 KB,直接在 Adobe Reader 中呈现
不幸的是,我没有设法从这个或这个答案运行解决方案。但是,我发现了一个简单的 1 行解决方法。
因此,可以为轴设置光栅化级别
ax.set_rasterization_zorder(Z)
这样,所有 zorder 小于 Z 的对象都将被光栅化。
对我来说,它看起来像这样:
plt.contourf(<all plotting properties>, zorder=-2)
ax.set_rasterization_zorder(-1)
以这种方式,轮廓是光栅格式,但所有其他对象(线条、文本)都是其顶部的矢量。对于我的图,大小从 ~4 Mb 到 ~400 kb。
好的,最后我找到了自己问题的答案。它需要在 matplotlib 邮件列表中进行艰难的挖掘,所以我在这里链接了相关线程,希望它对其他人也有帮助,并且可能更容易找到(顺便说一句,没有人回复那个可怜的人发送消息)。
我将在这里用文字总结这个想法。正如sega_sai 建议的那样,必须使用该set_rasterized
方法。然而,正如我在评论中解释的那样,不是将该方法应用于整个图形,而是将该方法应用于构成等高线图的线条。诀窍是首先为它们创建一个“容器”并将其栅格化,而不是栅格化每一行(这是我已经尝试过的,但结果很糟糕)。这工作正常。在我链接的讨论中,您可以找到执行此操作的代码。