Matplotlib Agg与Cairo的后端区别

18 投票
1 回答
11246 浏览
提问于 2025-04-17 01:46

你好,

我想从matplotlib绘图生成高质量的PDF文件。我用其他代码生成了一大堆数字,然后用plt.imshow把它们画成图。如果我现在用plt.savefig生成PDF,我发现不同的后端会产生很大的差异。最重要的是,使用Agg或MacOSX后端生成的文件非常大,而使用Cairo后端生成的文件相对较小(下面有例子)。另一方面,Cairo后端在与TeX标签渲染一起使用时,文本看起来很奇怪,这在TeX文档中显得很糟糕。因此,我的问题有两个:

  1. 使用Agg后端,是否可以生成小的PDF(也就是说,可能不需要将光栅图像插值到更高的分辨率)?
  2. 是否可以更改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' )

生成的PDF大小为15Kb,但x轴标签看起来很糟糕。

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' )

生成的PDF大小为986Kb,效果很好。

我应该补充一下,我在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

1 个回答

6

正如steabert在上面的评论中提到的,有一个解决办法就是先把图形导出成其他格式,然后再转换成PDF。根据我之前的例子,整个流程可能是这样的:

import os
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.eps')

os.system('epspdf agg.eps agg.pdf')

这样生成的文件大小是16 Kb,看起来效果不错。不过有一点和之前的例子不同:使用(E)PS格式时,似乎忽略了插值选项'interpolation='nearest'',也就是说,最终的PDF里图像看起来有点模糊。幸运的是,我对此可以接受,但这个问题可能值得进一步研究一下。

撰写回答