我正在寻找一种编程方式,以将图例添加到matplotlib
图的外部中,以便在将图形保存到svg文件时不会被裁剪。在以下示例中,您将看到在生成的svg图片中裁剪了x轴标签和图例:
import matplotlib
import matplotlib.backends.backend_svg
fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')
Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])
legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],loc='upper right',borderpad=0.06,handletextpad=0.1,handlelength=1.5,bbox_to_anchor=(1.0, 1.235),frameon=False,columnspacing=1.0,ncol=2)
fig.set_canvas(matplotlib.backends.backend_svg.FigureCanvasSVG(fig))
fig.savefig('C:\plot.svg')
fig.clear()
理想情况下,我想创建图,然后通过某种方法不扩展画布以裁剪现有的空白,以使图更紧凑。仅应扩展画布的那些区域,否则将导致裁剪的元素(如外部图例或轴标签)。 我唯一的限制是我无法使用pyplot
。
当然,我可以对图例属性进行调整,直到找到一个可能适用于该图的配置。但是我希望对于任何一种情节,都有一种通用的解决方案。
任何答案都值得赞赏。
答案 0 :(得分:1)
将bbox_inches='tight'
传递到savefig()
无效吗?
import matplotlib
import matplotlib.backends.backend_svg
fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')
Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])
legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],loc='upper right',borderpad=0.06,handletextpad=0.1,handlelength=1.5,bbox_to_anchor=(1.0, 1.235),frameon=False,columnspacing=1.0,ncol=2)
fig.set_canvas(matplotlib.backends.backend_svg.FigureCanvasSVG(fig))
fig.savefig('C:\plot.jpg', bbox_inches='tight')
fig.clear()
答案 1 :(得分:1)
如果我正确理解,您想限制"tight"
选项仅扩展图形,而不裁剪图形。由于没有这样的预定义选项,因此您需要首先计算紧密框并仅使用其中小于或大于图形范围的值。
import matplotlib.figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.transforms import Bbox
fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')
Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])
legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],
loc='upper right',borderpad=0.06,handletextpad=0.1,
handlelength=1.5,bbox_to_anchor=(1.0, 1.235),
frameon=False,columnspacing=1.0,ncol=2)
canvas = FigureCanvasAgg(fig)
fig.canvas.draw()
renderer = fig._cachedRenderer
tightbox = fig.get_tightbbox(renderer)
w,h = fig.get_size_inches()
bbox = Bbox.from_extents(min(tightbox.x0,0), min(tightbox.y0,0),
max(tightbox.x1,w), max(tightbox.y1,h))
fig.savefig('cropplot.png', bbox_inches=bbox, facecolor="#fff9e3")
在这里,我使图的背景色彩丰富,可以很好地看到边界。 还要注意,我用普通的agg画布替换了svg画布,因为否则没有可用的渲染器。
以下代码应适用于matplotlib
的旧版本。它将使图形宽度保持不变,仅在垂直方向上扩展图形。
import matplotlib.figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
def CreateTightBbox(fig):
from matplotlib.transforms import Affine2D, Bbox, TransformedBbox
from matplotlib import rcParams
w,h = fig.get_size_inches()
renderer = fig._cachedRenderer
bbox_artists = fig.get_default_bbox_extra_artists()
bbox_filtered = []
for a in bbox_artists:
bbox = a.get_window_extent(renderer)
if a.get_clip_on():
clip_box = a.get_clip_box()
if clip_box is not None:
bbox = Bbox.intersection(bbox, clip_box)
clip_path = a.get_clip_path()
if clip_path is not None and bbox is not None:
clip_path = clip_path.get_fully_transformed_path()
bbox = Bbox.intersection(bbox, clip_path.get_extents())
if bbox is not None and (bbox.width != 0 or bbox.height != 0):
bbox_filtered.append(bbox)
if bbox_filtered:
_bbox = Bbox.union(bbox_filtered)
trans = Affine2D().scale(1.0 / fig.dpi)
bbox_extra = TransformedBbox(_bbox, trans)
bbox_inches = Bbox.union([fig.bbox_inches, bbox_extra])
pad = rcParams['savefig.pad_inches']
bbox_inches = bbox_inches.padded(pad)
bbox = Bbox.from_extents(0, min(bbox_inches.y0,0), w, max(bbox_inches.y1,h))
return bbox
#create the figure
fig = matplotlib.figure.Figure(figsize=(8,2))
subplot = fig.add_axes([0.1, 0.2, 0.8, 0.75], xlabel='x_label')
Sig_1, = subplot.plot([1,2,3], [1,2,3])
Sig_2, = subplot.plot([1,2,3], [4,5,6])
legend = subplot.legend([Sig_1, Sig_2], ['y_label_1', 'y_label_2'],
loc='upper right',borderpad=0.06,handletextpad=0.1,
handlelength=1.5,bbox_to_anchor=(1.0, 1.235),
frameon=False,columnspacing=1.0,ncol=2)
#set the canvas
canvas = FigureCanvasAgg(fig)
fig.canvas.draw()
w,h = fig.get_size_inches()
#create tight bbox
bbox = CreateTightBbox(fig)
#print bbox
fig.savefig('cropplot.png', bbox_inches=bbox, facecolor="#fff9e3")