How can I export legend markers from matplotlib one at a time?

心不动则不痛 提交于 2019-12-24 05:12:34

问题


I have a matplotlib legend that looks like this:

What's an easy way to export the markers as separate .pdf files? In other words, I want to end up with three separate .pdfs, one with a blue X, one with a gold +, etc.

Ultimately what I want to do is to use these markers in an inline legend in a Latex figure caption, but I figure I'll ask about that part on the Latex SE site.


回答1:


An idea to export the legend handles to a file would be to save the created figure as pdf but crop it to the part of interest.

This can be done by specifying a bounding box bbox to the bbox_inches argument within the call to savefig

plt.savefig("file.pdf", dpi="figure", bbox_inches=bbox )

Now we just need to find out the bounding box to use. This can be done by finding the DrawingArea for each of the legend handles and transform its bounding box to coordinates in inches. This is done in a function export_legend_handles in the code below.

Unfortunately, while writing that code, I found that the marker may acutally exceed the DrawingArea. Since I haven't found an automatic way to find the real size of the handle outside the DrawingArea, one may need to extend/shrink the bounding box manually by some pixels. For this purpose, the below function has a parameter d which allows to set those pixel offsets and for this test case I have already put some decent values in.

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(422)

x = np.arange(12)
a = np.random.rand(len(x), 3)

markers=["x", "+", "o"]
fig, ax = plt.subplots()
for i in range(a.shape[1]):
    ax.plot(x, a[:,i], linestyle="", marker=markers[i], label=markers[i]*6)

leg = ax.legend(framealpha=1)

def export_legend_handles(fig, leg, filename=None, ext=[".pdf", ".png"], d = [0,0,0,3]):
    """ d = [left, bottom, right, top] pixel to add in the respective dimension """
    import matplotlib.transforms as mtransforms
    boxes = []
    fig.canvas.draw()
    trans = fig.dpi_scale_trans.inverted()
    for vpack in leg._legend_handle_box.get_children():
        for hpack in vpack.get_children():
            drawbox = hpack.get_children()[0]
            w, h, xd, yd = drawbox.get_extent(fig.canvas.get_renderer())
            ox, oy = drawbox.get_offset()  
            pixbox = mtransforms.Bbox.from_bounds(ox-d[0],oy-d[1],w+d[0]+d[2],h+d[1]+d[3])
            inchbox = pixbox.transformed(trans) 
            boxes.append(inchbox)

    filename = filename if filename else __file__[:-3]
    for i, box in enumerate(boxes):
        for ex in ext:
            plt.savefig(filename+str(i)+ex, dpi="figure", bbox_inches=box)

export_legend_handles(fig, leg, d = [-5,0,-5,3])
plt.show()

This produces a plot like the following

and saves the legend handles as pdf and png images, which then look as follows



来源:https://stackoverflow.com/questions/43021593/how-can-i-export-legend-markers-from-matplotlib-one-at-a-time

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