Question

I need to save matplotlib figures to pdf. I am following the instructions on the Matplotlib howto, except that instead of displaying results, I'm saving it to pdf. Strangely, the pdf canvas is not affected by the canvas resize. Conversely, saving to png works properly with the enlarged canvas.

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))

def on_draw(event):
    bboxes = []
    for label in labels:
        bbox = label.get_window_extent()
        # the figure transform goes from relative coords->pixels and we
        # want the inverse of that
        bboxi = bbox.inverse_transformed(fig.transFigure)
        bboxes.append(bboxi)

    # this is the bbox that bounds all the bboxes, again in relative
    # figure coords
    bbox = mtransforms.Bbox.union(bboxes)
    if fig.subplotpars.left < bbox.width:
        # we need to move it over
        fig.subplots_adjust(left=1.1*bbox.width) # pad a little
        fig.canvas.draw()
    return False

fig.canvas.mpl_connect('draw_event', on_draw)

plt.savefig("test.pdf", format="pdf")

screen capture of pdf image

UPDATE

plt.tight_layout()

does it for title and axis ticks, but ignores the legend if it is placed outside the frame, as in the figure below. Notice that I placed the legend to the right of the figure.

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
p1, = plt.plot(range(10))
p2, = plt.plot(range(10,0,-1))
ax.set_yticks((2,5,7))
plt.labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))
plt.legend([p2, p1], ["line with a loong label", "line with an even longer label, dude!"],\
           loc="center left", bbox_to_anchor=(1, 0.5))
plt.tight_layout()
plt.savefig("test.pdf", format="pdf")
Was it helpful?

Solution

A possible hack is by replacing plt.tight_layout() with

plt.tight_layout(rect = [0, 0, 0.4, 1])

but that is not very nice. What works for me is using the argument bbox_inches:

plt.savefig("test.pdf", format="pdf", bbox_inches = 'tight')

OTHER TIPS

Use can try this example and solve your problem.

import matplotlib.pyplot as plt
import numpy as np
sin, cos = np.sin, np.cos

fig = plt.figure(frameon = False)
fig.set_size_inches(5, 8)
ax = plt.Axes(fig, [0., 0., 1., 1.], )
ax.set_axis_off()
fig.add_axes(ax)

x = np.linspace(-4, 4, 20)
y = np.linspace(-4, 4, 20)
X, Y = np.meshgrid(x, y)
deg = np.arctan(Y**3-3*Y-X)
plt.quiver(X, Y, cos(deg), sin(deg), pivot = 'tail', units = 'dots', color = 'red', )
plt.savefig('/tmp/test.png', dpi = 200)

You can make the resultant image 1000x1600 pixels by setting the figure to be 5x8 inches

fig.set_size_inches(5, 8)
and saving with DPI = 200:

plt.savefig('/tmp/test.png', dpi = 200)
The code to remove the border was taken from here.

(The image posted above is not to scale since 1000x1600 is rather large).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top