0

I would like to update the text entries of matplotlib legends without having the size of the legend updated upon doing so.

Here is a MWE:

import matplotlib.pyplot as plt
from matplotlib import rcParams

fig, ax = plt.subplots()
ax.plot( [1,2], [2,1], label='$f_\mathrm{so}$')
ax.legend(loc='upper right')

rcParams['svg.fonttype'] = 'none'
fig.savefig('fig1.svg', format='svg')

texts = ax.get_legend().get_texts()
for text in texts:
  text.set_text( text.get_text().replace( r'\$', r'$' ).replace( r'$', r'\$' ) )

fig.savefig('fig2.svg', format='svg')

This is what the resulting files look like:

fig1.svg:
fig1.svg

fig2.svg:
actual appearance of fig2.svg

The legend box is well-sized in fig1.svg and I like to keep this size while only updating the legend text.
How could this be achieved?

Here is what I want fig2.svg to look like:
desired appearance of fig2.svg

Update

JohanC pointed me to this discussion which gave me a few more clues on how to tackle this.

So, with leg.get_window_extent() I am able to get the current extent of the legend before updating the texts.
With ax.legend( bbox_to_anchor=bbox, mode='expand', loc='lower left' ) I can then impose a new bbox to anchor to which I would make match the old size of the legend. The mode expand will have the labels run out of the legend box. This can work because my legend texts always get longer but never shorter.

The only thing that I didn't figure out is how to convert the values in the variable bbox into those that I need to pass to ax.legend.

import matplotlib.pyplot as plt
from matplotlib import rcParams

fig, ax = plt.subplots()
ax.plot( [1,2], [2,1], label='$f_\mathrm{so}$')
ax.legend(loc='upper right')

rcParams['svg.fonttype'] = 'none'
fig.savefig('fig1.svg', format='svg')

# Get bbox prior to updating the text
leg = ax.get_legend()
bbox = leg.get_window_extent()
print(bbox) # prints Bbox(x0=501.72589246961803, y0=386.94444444444446, x1=569.0555555555555, y1=415.4555555555556)

# Freeze the size of the legend bbox
bbox=(0.8,0.8,0.2,0.2) # Values of variable bbox above should be used
ax.legend( bbox_to_anchor=bbox, mode='expand', loc='lower left' )

# update the texts
texts = ax.get_legend().get_texts()
for text in texts:
  text.set_text( text.get_text().replace( r'\$', r'$' ).replace( r'$', r'\$' ) )

fig.show()
fig.savefig('fig2.svg', format='svg')

produces
fig2.svg new output

Bastian
  • 901
  • 7
  • 23
  • Did you look into [Fix size of legend in matplotlib](https://stackoverflow.com/questions/41026125/fix-size-of-legend-in-matplotlib)? – JohanC Feb 17 '21 at 11:56
  • Oh no I hadn't and this discussion provided some clues. I feel like I am halfway there now. I updated my question... – Bastian Feb 17 '21 at 13:39

0 Answers0