wflynny
wflynny

Reputation: 18521

Multiline alignment of Matplotlib legend LaTeX text

The following code yields the figure below:

import numpy as np
import matplotlib.pyplot as plt

xs = np.random.rand(100)
ys = np.random.rand(100)
r, p = 0.930, 1e-5
label = '$T_m$\n$\\rho = %.3f, p = %.1e$'%(r, p)

fig, ax = plt.subplots()
ax.scatter(xs, ys, label=label)
ax.legend()
plt.show()

enter image description here

I would like the legend text centered, i.e. the '$T_m$' centered in the first line. I've tried using the str.format mini-language with various things like

label = '{0:{x}^25}\n{1:.3f}, {2:.1e}'.format('$T_m$', r, p, x=' ')

which I thought would work because the following gives

>>> print ax.get_legend_handles_labels()
([<matplotlib.collections.PathCollection object at 0x7fa099286590>],
 [u'     $\\Delta T_{m}$      \n$\\rho=0.930, p=1.2 \\times 10^{-5}$'])

but the whitespace gets stripped in the label. I can't use any latex space ('\;' or '\\mbox{}') for the fill character because they are multiple characters. I also tried using the multialignment='center' keyword in various places, but it is not a valid kwarg to ax.legend.

How can I get centered multiline alignment in my legend text? Ultimately, I will several legend handles where label text can have either more characters in the second line (shown here) or more characters in the first line (opposite as shown here).

I am using python 2.7.6 and matplotlib 1.4.3.

Upvotes: 4

Views: 2431

Answers (1)

hitzg
hitzg

Reputation: 12701

As you figured out yourself the key is the multialignment argument. However, it is not an argument to the legend function, but merely a propery of Text Atrists. So the trick is to save a handle of the legend and then set this propery for each text element:

leg = ax.legend()
for t in leg.texts:
    t.set_multialignment('center')

Result:

enter image description here

Upvotes: 6

Related Questions