Axes class - set explicitly size (width/height) of axes in given units
The axes size is determined by the figure size and the figure spacings, which can be set using figure.subplots_adjust()
. In reverse this means that you can set the axes size by setting the figure size taking into acount the figure spacings:
import matplotlib.pyplot as pltdef set_size(w,h, ax=None): """ w, h: width, height in inches """ if not ax: ax=plt.gca() l = ax.figure.subplotpars.left r = ax.figure.subplotpars.right t = ax.figure.subplotpars.top b = ax.figure.subplotpars.bottom figw = float(w)/(r-l) figh = float(h)/(t-b) ax.figure.set_size_inches(figw, figh)fig, ax=plt.subplots()ax.plot([1,3,2])set_size(5,5)plt.show()
It appears that Matplotlib has helper classes that allow you to define axes with a fixed size Demo fixed size axes
I have found that ImportanceofBeingErnests answer which modifies that figure size to adjust the axes size provides inconsistent results with the paticular matplotlib settings I use to produce publication ready plots. Slight errors were present in the final figure size, and I was unable to find a way to solve the issue with his approach. For most use cases I think this is not a problem, however the errors were noticeable when combining multiple pdf's for publication.
In lieu of developing a minimum working example to find the real issue I am having with the figure resizing approach I instead found a work around which uses the fixed axes size utilising the divider class.
from mpl_toolkits.axes_grid1 import Divider, Sizedef fix_axes_size_incm(axew, axeh): axew = axew/2.54 axeh = axeh/2.54 #lets use the tight layout function to get a good padding size for our axes labels. fig = plt.gcf() ax = plt.gca() fig.tight_layout() #obtain the current ratio values for padding and fix size oldw, oldh = fig.get_size_inches() l = ax.figure.subplotpars.left r = ax.figure.subplotpars.right t = ax.figure.subplotpars.top b = ax.figure.subplotpars.bottom #work out what the new ratio values for padding are, and the new fig size. neww = axew+oldw*(1-r+l) newh = axeh+oldh*(1-t+b) newr = r*oldw/neww newl = l*oldw/neww newt = t*oldh/newh newb = b*oldh/newh #right(top) padding, fixed axes size, left(bottom) pading hori = [Size.Scaled(newr), Size.Fixed(axew), Size.Scaled(newl)] vert = [Size.Scaled(newt), Size.Fixed(axeh), Size.Scaled(newb)] divider = Divider(fig, (0.0, 0.0, 1., 1.), hori, vert, aspect=False) # the width and height of the rectangle is ignored. ax.set_axes_locator(divider.new_locator(nx=1, ny=1)) #we need to resize the figure now, as we have may have made our axes bigger than in. fig.set_size_inches(neww,newh)
Things worth noting:
- Once you call
set_axes_locator()
on an axis instance you break thetight_layout()
function. - The original figure size you choose will be irrelevent, and the final figure size is determined by the axes size you choose and the size of the labels/tick labels/outward ticks.
- This approach doesn't work with colour scale bars.
- This is my first ever stack overflow post.