5

When you set bbox_inches = 'tight' in Matplotlib's savefig() function, it tries to find the tightest bounding box that encapsulates all the content in your figure window. Unfortunately, the tightest bounding box appears to include invisible axes.

For example, here is a snippet where setting bbox_inches = 'tight' works as desired:

import matplotlib.pylab as plt
fig = plt.figure(figsize = (5,5))
data_ax = fig.add_axes([0.2, 0.2, 0.6, 0.6])
data_ax.plot([1,2], [1,2])
plt.savefig('Test1.pdf', bbox_inches = 'tight', pad_inches = 0)

which produces:

Nice tight bounding box

The bounds of the saved pdf correspond to the bounds of the content. This is great, except that I like to use a set of invisible figure axes to place annotations in. If the invisible axes extend beyond the bounds of the visible content, then the pdf bounds are larger than the visible content. For example:

import matplotlib.pylab as plt
fig = plt.figure(figsize = (5,5))
fig_ax = fig.add_axes([0, 0, 1, 1], frame_on = False)
fig_ax.xaxis.set_visible(False)
fig_ax.yaxis.set_visible(False)
data_ax = fig.add_axes([0.2, 0.2, 0.6, 0.6])
data_ax.plot([1,2], [1,2])
plt.savefig('Test2.pdf', bbox_inches = 'tight', pad_inches = 0)

producing

Loose bounding box

How can I force savefig() to ignore invisible items in the figure window? The only solution I have come up with is to calculate the bounding box myself and explicitly specify the bbox to savefig().

In case it matters, I am running Matplotlib 1.2.1 under Python 2.7.3 on Mac OS X 10.8.5.

4

2 回答 2

3

中的相关函数(被canvas.print_figure调用figure.savefig以生成边界框)backend_bases.py

def get_tightbbox(self, renderer):
    """
    Return a (tight) bounding box of the figure in inches.

    It only accounts axes title, axis labels, and axis
    ticklabels. Needs improvement.
    """

    bb = []
    for ax in self.axes:
        if ax.get_visible():
            bb.append(ax.get_tightbbox(renderer))

    _bbox = Bbox.union([b for b in bb if b.width != 0 or b.height != 0])

    bbox_inches = TransformedBbox(_bbox,
                                  Affine2D().scale(1. / self.dpi))

    return bbox_inches

决定轴是否“可见”的唯一考虑因素是ax.get_visible()返回 true,即使轴中没有可见(artist.get_visible() == False或简单透明)艺术家。

您观察到的边界框行为是正确的行为。

于 2013-10-12T15:30:18.417 回答
1

tcaswell,谢谢你的帮助。我最初的问题是,“如何强制 savefig() 忽略图形窗口中的不可见项目?” 当我把fig_ax.set_visible(False)thensavefig()忽略不可见的轴。不幸的是,当我设置时,fig_ax.set_visible(False)放置在 fig_ax 中的任何艺术家也是不可见的。我回到我发布的原始情节,其中fig_ax不存在。

正如您在评论中暗示的那样,tcaswell,我认为正确的解决方案是避免创建fig_ax. 我目前正在将我的注释和数据轴标签放在默认的图形对象fig中。这有点烦人,因为fig使用标准化图形单位而不是 mm 单位,但我可以处理它。

于 2013-10-13T03:01:09.170 回答