I am producing a publication-quality plot to be embedded in latex and I would like to be very precise in terms of sizes and fonts (so that fonts are of the same size in the article as in the plot). To prevent the plot from scaling in latex I would like to have it exact size, but I cannot. Here is my code:
import matplotlib.pyplot as plt
from matplotlib import rc, rcParams
from numpy import sin
rc('font', family='serif', serif='Computer Modern Roman', size=8)
width_in = 5
fig = plt.figure(1, figsize=(width_in, 2))
ax = fig.add_subplot(111)
fig.savefig('test.eps', bbox_inches='tight', pad_inches=0)
The problem is with bbox_inches='tight' and pad_inches=0. Adding those options makes my plot 4.76 inches wide instead of declared 5 inches. But I want them to save space. So how to solve it?
Edit: Well, the answers suggest to remove
pad_inches=0 and use just the
tight_layout(). Then the images is of right size, however it has still some white padding around. I can remove it with
fig.tight_layout(pad=0), but then the figure title it moved inside the box, which looks ugly. On the other hand I can use
tight_layout(rect=[...]) and obtain the desired result, but it is a manual work to get the numbers right - I don't like it. Thus, currently I don't see any easy and general solution to my problem.
The problem you are having is that
bbox_inches='tight' just removes all of the extra white space around your figure, it does not actually re-arrange anything in your figure, after it has been rendered.
You might need to tweak the parameters you pass to
tight_layout (tutorial) to get your desired effect.
Hopefully this gets you pointed in the right direction.
Your original plot must have whitespace around it, otherwise bbox_inches=tight would not remove any of the area. There are two solutions to this that I know of:
The simple method is to use
tight_layout as mentioned by tcaswell.
The more complicated, but more controllable method is to avoid using
fig.add_subplot(111) and instead use
fig.add_axes() which allows you to be much more strict in terms of how large your axes are when you define the axes instance. You can then tweak the size of your axes to take up as much of the figure area as required to maintain a 5" figure area. Once you have done this, I would recommend simply not using
bbox_inches or set it to None (the default) to avoid unnessicary cropping.
fig.add_axes() requires a
rect parameter as its first argument which consists of
[left_position, bottom_position, width, height] each of which range from 0 to 1.
Edit: After going through the
tight_layout tutorial again, I have realized that it covers pretty much everything. I hadn't realized that it was able to maintain the aspect ratio of the axes instance easily, even if the aspect ratio of the figure is different from that of the axes instance. I tend to try to be very explicit when I define my axes areas because I deal with satellite imagery and try to keep it as the native sensor resolution or some factor of that sensor resolution, which requires a little bit more control.