matplotlib savefig bbox_inches = 'tight' does not ignore invisible axes

匿名 (未验证) 提交于 2019-12-03 00:55:01

问题:

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:

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

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.

回答1:

The relevant function (called by canvas.print_figure which is called by figure.savefig to generate the bounding box) in 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 

The only consideration that goes into deciding if an axes is 'visible' is if ax.get_visible() returns true, even if you have no visible (either artist.get_visible() == False or simple transparent) artists in the axes.

The bounding box behavior you observe is the correct behavior.



回答2:

tcaswell, thanks for your help. My original question was, "How can I force savefig() to ignore invisible items in the figure window?" When I put fig_ax.set_visible(False) then savefig() ignores the invisible axes. Unfortunately, when I set fig_ax.set_visible(False) then any artist placed in fig_ax is also invisible. I am back to the original plot I posted, where fig_ax does not exist.

As you intimated in your comment, tcaswell, I think the proper solution is avoid creating fig_ax. I am currently working on placing my annotations and data axis labels in the default figure object fig. It's a bit annoying since fig uses normalized figure units instead of mm units, but I can deal with it.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!