I want to generate publication quality plots with matplotlib. For consistency reasons I want all diagrams (axes) to look the same, particularly in size. I look through many tutorials and came up with the following idea: 1. create a plot and determine the height of the axes in inches 2. add the legend and determine the height of the legend in inches 3. enlarge the figure height by the legend height in inches 4. shrink the new axes height to the original axes height to keep the legend in the figure area
Unfortunately, this is not working as intended. Any suggestions on the Code?
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms
# GENERATE DATA
x = np.arange(-2.*np.pi,4.*np.pi,0.01)
sin_arr = [np.sin(x-dx) for dx in np.arange(0.,2.*np.pi,0.5)]
# SET FIGURE SIZE AND RCPARAMETERS
plt.rcParams.update( {'figure.figsize' : [5.90551197, 3.64980712]} )
params = {
'text.usetex' : True,
'backend' :'ps',
## FONTS
"font.family" : "serif",
"font.serif" : [], # blank entries should cause plots to inherit fonts from the document
"font.monospace" : [],
## FONT SIZES
'axes.labelsize' : 12,
'font.size' : 12,
'legend.fontsize': 12,
'xtick.labelsize': 12,
'ytick.labelsize': 12,
## LINEWIDTH
'axes.linewidth' : 0.5,
'patch.linewidth': 0.5, # legend frame
'lines.linewidth': 1.5,
## LEGEND
'legend.edgecolor':'black',
'legend.frameon' :True,
'legend.fancybox' :False,
}
plt.rcParams.update(params)
# GENERATE PLOT
fig = plt.figure()
ax = fig.add_subplot(111)
for i,sin in enumerate(sin_arr):
ax.plot(x,sin,label=r'$\sin(x)$ '+str(i))
ax.set_xlabel(r'$\varepsilon$')
ax.set_ylabel(r'$\sigma$ in [MPa]', labelpad=15)
ax.set_xlim([0.,2.*np.pi])
# SHRINK PADDING
plt.tight_layout(pad=0)
# ADD LEGEND ON TOP OF AXES WITHOUT CHANGING AXES SIZE
legend = ax.legend( bbox_to_anchor=(0., 1.02, 1., .102),
loc='lower left',
ncol=3,
borderaxespad=0.,mode="expand" )
# GET LEGEND / AXES HEIGHT IN INCHES
ax_box = ax.get_window_extent() # AXES BBOX IN DISPLAY UNITS
leg_box = legend.get_bbox_to_anchor() # LEGEND BBOX IN DISPLAY UNITS
ax_box_inch = ax_box.transformed( fig.dpi_scale_trans.inverted() ) # TRANSFORM TO INCHES
leg_box_inch = leg_box.transformed( fig.dpi_scale_trans.inverted() ) # TRANSFORM TO INCHES
# ORIGINAL_AX_HEIGHT
ax_height_inch_orig = ax_box_inch.height
# CHANGE FINGURE TO FIT LEGEND
fig.set_size_inches(fig.get_figwidth(), fig.get_figheight() + leg_box_inch.height)
# GET NEW HEIGHT OF AXES
ax_box_new_inch = ax.get_window_extent().transformed( fig.dpi_scale_trans.inverted() )
ax_height_inch_new = ax_box_new_inch.height
factor = ax_height_inch_orig/ax_height_inch_new
# GET AXES BBOX IN FIGURE COORDINATES
ax_box = ax.get_window_extent().transformed( fig.transFigure.inverted() )
# CHANGE AXES TO ORIGINAL HEIHGT BUT WITH LEGEND FULLY VISIBLE
ax.set_position([ax_box.x0, ax_box.y0,ax_box.width, ax_box.height*factor])
plt.savefig('test.pdf',format='pdf',dpi=90)