Agg 和 Cairo 之间的 Matplotlib 后端差异
Hej,
我想从 matplotlib 绘图生成高质量的 PDF。使用其他代码,我生成了大量数字,并使用 plt.imshow 将其绘制在图中。如果我现在使用 plt.savefig 生成 PDF,我会注意到根据我使用的后端而存在很大差异。最重要的是,使用 Agg 或 MacOSX 后端生成的文件会变得很大,而使用 Cairo 则生成的文件相当小(请参见下面的示例)。另一方面,Cairo 后端结合 TeX 渲染标签生成奇怪的文本。这在 TeX 文档中看起来很糟糕。因此,我的问题是双重的:
- 是否可以使用 Agg 后端生成小型 PDF(即可能无需将光栅图像插值到更高分辨率)?
- 是否可以更改 Cairo 后端的一些文本设置,使其看起来与普通 TeX 类似(Agg 后端就是这种情况)
以下是一些用于测试目的的示例代码:
import matplotlib as mpl
mpl.use( "cairo" )
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['text.usetex'] = True
data = np.random.rand( 50, 50 )
plt.imshow( data, interpolation='nearest' )
plt.xlabel( 'X Label' )
plt.savefig( 'cairo.pdf' )
生成一个 15Kb 的 PDF,其中 xlabel 看起来很糟糕。
import matplotlib as mpl
mpl.use( "agg" )
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['text.usetex'] = True
data = np.random.rand( 50, 50 )
plt.imshow( data, interpolation='nearest' )
plt.xlabel( 'X Label' )
plt.savefig( 'agg.pdf' )
生成 986Kb 的 PDF,看起来不错。
我可能应该补充一点,我在 OSX 10.6.8 上使用 matplotlib 1.0.1 和 python 2.6.7。在评论中,有人请求 grep -a Font agg.pdf 的输出:
/Shading 6 0 R /Font 3 0 R >>
<< /FontFile 16 0 R /Descent -285 /FontBBox [ -174 -285 1001 953 ]
/StemV 50 /Flags 4 /XHeight 500 /Type /FontDescriptor
/FontName /NimbusSanL-Regu /CapHeight 1000 /FontFamily (Nimbus Sans L)
%!PS-AdobeFont-1.0: NimbusSanL-Regu 1.05a
FontDirectory/NimbusSanL-Regu known{/NimbusSanL-Regu findfont dup/UniqueID known{dup
/UniqueID get 5020902 eq exch/FontType get 1 eq and}{pop false}ifelse
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
/FontName /NimbusSanL-Regu def
/FontBBox [-174 -285 1001 953 ]readonly def
/FontInfo 9 dict dup begin
/BaseFont /NimbusSanL-Regu /Type /Font /Subtype /Type1
/FontDescriptor 15 0 R /Widths 13 0 R /LastChar 255 /FirstChar 0 >>
<< /FontFile 20 0 R /Descent -251 /FontBBox [ -34 -251 988 750 ] /StemV 50
/Flags 4 /XHeight 500 /Type /FontDescriptor /FontName /CMR12
/CapHeight 1000 /FontFamily (Computer Modern) /ItalicAngle 0 /Ascent 750 >>
%!PS-AdobeFont-1.0: CMR12 003.002
%Copyright: (<http://www.ams.org>), with Reserved Font Name CMR12.
% This Font Software is licensed under the SIL Open Font License, Version 1.1.
FontDirectory/CMR12 known{/CMR12 findfont dup/UniqueID known{dup
/UniqueID get 5000794 eq exch/FontType get 1 eq and}{pop false}ifelse
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
/FontName /CMR12 def
/FontBBox {-34 -251 988 750 }readonly def
/FontInfo 9 dict dup begin
/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMR12.) readonly def
<< /BaseFont /CMR12 /Type /Font /Subtype /Type1 /FontDescriptor 19 0 R
Hej,
I'd like to produce high quality PDFs from matplotlib plots. Using other code, I have produced a large array of numbers, which I plot in a figure using plt.imshow. If I now produce a PDF using plt.savefig, I notice strong differences depending on which backend I use. Most importantly, the produced files get huge with the Agg or MacOSX backend, while they are reasonably small with Cairo (see examples below). On the other hand, the Cairo backend produces weird text in conjunction with the TeX rendering of labels. This looks awful in the TeX document. My question is therefore twofold:
- Is it possible to produce small PDF (i.e. presumably without interpolating the raster image to a higher resolution) using the Agg backend?
- Can one change some text settings for the Cairo backend such that it looks similar to ordinary TeX (which is the case for the Agg backend)
Here is some example code for test purposes:
import matplotlib as mpl
mpl.use( "cairo" )
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['text.usetex'] = True
data = np.random.rand( 50, 50 )
plt.imshow( data, interpolation='nearest' )
plt.xlabel( 'X Label' )
plt.savefig( 'cairo.pdf' )
produces a PDF of 15Kb with a bad looking xlabel.
import matplotlib as mpl
mpl.use( "agg" )
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['text.usetex'] = True
data = np.random.rand( 50, 50 )
plt.imshow( data, interpolation='nearest' )
plt.xlabel( 'X Label' )
plt.savefig( 'agg.pdf' )
produces a PDF of 986Kb which looks good.
I should probably add that I use matplotlib 1.0.1 with python 2.6.7 on OSX 10.6.8. In the comments, someone requested the output of grep -a Font agg.pdf
:
/Shading 6 0 R /Font 3 0 R >>
<< /FontFile 16 0 R /Descent -285 /FontBBox [ -174 -285 1001 953 ]
/StemV 50 /Flags 4 /XHeight 500 /Type /FontDescriptor
/FontName /NimbusSanL-Regu /CapHeight 1000 /FontFamily (Nimbus Sans L)
%!PS-AdobeFont-1.0: NimbusSanL-Regu 1.05a
FontDirectory/NimbusSanL-Regu known{/NimbusSanL-Regu findfont dup/UniqueID known{dup
/UniqueID get 5020902 eq exch/FontType get 1 eq and}{pop false}ifelse
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
/FontName /NimbusSanL-Regu def
/FontBBox [-174 -285 1001 953 ]readonly def
/FontInfo 9 dict dup begin
/BaseFont /NimbusSanL-Regu /Type /Font /Subtype /Type1
/FontDescriptor 15 0 R /Widths 13 0 R /LastChar 255 /FirstChar 0 >>
<< /FontFile 20 0 R /Descent -251 /FontBBox [ -34 -251 988 750 ] /StemV 50
/Flags 4 /XHeight 500 /Type /FontDescriptor /FontName /CMR12
/CapHeight 1000 /FontFamily (Computer Modern) /ItalicAngle 0 /Ascent 750 >>
%!PS-AdobeFont-1.0: CMR12 003.002
%Copyright: (<http://www.ams.org>), with Reserved Font Name CMR12.
% This Font Software is licensed under the SIL Open Font License, Version 1.1.
FontDirectory/CMR12 known{/CMR12 findfont dup/UniqueID known{dup
/UniqueID get 5000794 eq exch/FontType get 1 eq and}{pop false}ifelse
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
/FontName /CMR12 def
/FontBBox {-34 -251 988 750 }readonly def
/FontInfo 9 dict dup begin
/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMR12.) readonly def
<< /BaseFont /CMR12 /Type /Font /Subtype /Type1 /FontDescriptor 19 0 R
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正如 steabert 在上面的评论中所建议的,解决方法是以不同的格式导出图形,然后将其转换为 PDF。根据上面的示例进行调整,工作流程可能如下所示:
生成一个 16 Kb 的文件,看起来不错。与上面提供的示例仍然有一个区别:使用 (E)PS 管道似乎忽略了 interpolation='nearest' 选项,即图像在最终 PDF 中显得模糊。幸运的是,我可以忍受这一点,但研究这个问题可能会很有趣。
As suggested by steabert in the comments above, a workaround is exporting the graphics in a different format and then convert it to PDF afterwards. Adjusting my example from above, the workflow could look something like this:
producing a file of 16 Kb which looks good. There is still one difference to the examples presented above: Using the (E)PS pipeline seems to ignore the interpolation='nearest' option, i.e. the image appears blurry in the final PDF. Luckily, I can live with that, but it might be interesting to look into this issue.