# Legend manipulation to control row height / column width for the legend labels/entries

The legend is pretty nifty and customizable, but I ran into a fun “feature” where I’m trying to make a sort of tabular-like environment within the legend, because I want to have 4 entries, and annotate each entry with different values. See the image below for an example of what I mean:

However, one minor caveat seems to be that when one has LaTeX included, and then trying to play around with the baseline options and so on, it just does not work to get them aligned properly. It seems each row inside the columns are completely isolated and unaware of other rows in other columns. The above picture is made with the following code below.

# Legend for analyses
leg_handles = []
leg_labels = []
leg_handles.append(mpatches.Patch(color=myBlue))
leg_labels.append(r"$8\ \mathrm{TeV}, 20.3\ \mathrm{fb}^{-1}$")
leg_handles.append(mpatches.Patch(color=myRed))
leg_labels.append(r"$\mathrm{Soft}\ 2\ell$")
leg_handles.append(mpatches.Patch(color=myYellow))
leg_labels.append(r"$2\ell$")
leg_handles.append(mpatches.Patch(color=myGreen, alpha=0.6))
leg_labels.append(r"$2\tau\ \mathrm{hadronic}$")
#leg_handles.append(mpatches.Patch(color=myLightGrey, alpha=lep_alpha, lw=0))
#leg_labels.append(r"LEP $\tilde{\mu}_R$ excluded")

leg_handles.extend([P0]*4)
leg_labels.append(r"$\tilde{\ell} \in [\tilde{e}, \tilde{\mu}]$")
leg_labels.append(r"$\tilde{\ell} \in [\tilde{e}, \tilde{\mu}]$")
leg_labels.append(r"$\tilde{\ell} \in [\tilde{e}, \tilde{\mu}]$")
leg_labels.append(r"$\tilde{\ell} = \tilde{\tau}$")
#leg_labels.append("")

leg_handles.extend([P0]*4)
leg_labels.append(r"arXiv:1403.5294")
leg_labels.append(r"arXiv:1911.12606")
leg_labels.append(r"CONF-2019-008")
leg_labels.append(r"CONF-2019-018")

leg = ax.legend(
leg_handles,
leg_labels,
frameon=False,
loc="upper left",
bbox_to_anchor=(0.37, 1.0),
title_fontsize="small",
fontsize="x-small",
ncol=3,
columnspacing=0.0,
)


You might think “ahhh, the vertical spacing is too small” so increasing it also doesn’t help. (e.g. labelspacing=1.0). However with some googling, I see a relevant (old) SO post (python - Vertical alignment of matplotlib legend labels with LaTeX math - Stack Overflow) but unfortunately seems text.latex.preview doesn’t exist anymore in recent versions of matplotlib. Even trying to adjust the vertical alignment of the individual text items also does not work. The closest I was able to get is to resize the LaTeX text to 70% of the original size

for t in leg.get_texts():
if 'tilde' in t.get_text():
t.set_fontsize(t.get_fontsize()*0.7)


but this is certainly not very generalizable… So instead, I went back to a single column and 4 entries, instead of making 12 dummy entries, which leads me here

at which point I can then manually align everything using combinations of \qquad, \!, \ , and \, (note \hspace is not supported). So I finally get this all aligned/spaced close enough with

leg_labels.append(r"$8\ \mathrm{TeV}, 20.3\ \mathrm{fb}^{-1}\!\qquad\tilde{\ell} \in [\tilde{e}, \tilde{\mu}]$      arXiv:1403.5294")
leg_handles.append(mpatches.Patch(color=myRed))
leg_labels.append(r"$\mathrm{Soft}\ 2\ell\qquad\qquad\qquad\!\,\,\ \tilde{\ell} \in [\tilde{e}, \tilde{\mu}]$      arXiv:1911.12606")
leg_handles.append(mpatches.Patch(color=myYellow))
leg_labels.append(r"$2\ell\qquad\qquad\qquad\qquad\,\,\ \ \tilde{\ell} \in [\tilde{e}, \tilde{\mu}]$      CONF-2019-008")
leg_handles.append(mpatches.Patch(color=myGreen, alpha=0.6))
leg_labels.append(r"$2\tau\ \mathrm{hadronic}\qquad\qquad\tilde{\ell} = \tilde{\tau}\,$            CONF-2019-018")


So I implore the community to save me from my own devices and help me find a better (or at least better-maintainable) way of doing this…

1 Like

Something like

from pylab import *
rcParams["text.usetex"] = True