Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vertical alignment of matplotlib legend labels with LaTeX math

When mixing labels that have subscripts with labels without them, they do not vertically align properly in the legend. Since matplotlib determines bounding boxes internally based on printing characters, using a vphantom character does not work to align these legend labels, and I have not had any luck changing the vertical alignment of the labels with set_va, either.

Below is a MWE that illustrates problem I am trying to solve. I would like the labels to align to the text baseline if at all possible, otherwise to the text top.

import numpy as np
import matplotlib as mpl
mpl.rcParams['text.usetex'] = True
import matplotlib.pyplot as plt

x = np.arange(10)
plt.plot(x, np.random.uniform(size=(10,)), c='red', label=r'test')
plt.scatter(x, np.random.uniform(size=(10,)), c='blue', label=r'test${}_{xy}$')
plt.legend(ncol=2)                                                                          
plt.show()

mwe image

like image 970
emprice Avatar asked Nov 04 '16 13:11

emprice


2 Answers

Set the text.latex.preview parameter to True:

import numpy as np
import matplotlib as mpl
mpl.rcParams['text.usetex'] = True
mpl.rcParams['text.latex.preview'] = True
import matplotlib.pyplot as plt

x = np.arange(10)
plt.plot(x, np.random.uniform(size=(10,)), c='red', label=r'test')
plt.scatter(x, np.random.uniform(size=(10,)), c='blue', label=r'test${}_{xy}$')
plt.legend(ncol=2)                                                      

plt.show()

Image with baseline-aligned labels

For the effect of the preview argument, also refer to this example.

like image 105
pulupa Avatar answered Dec 10 '22 09:12

pulupa


You can have a look on Text alignment in a Matplotlib legend.

Or you can just shift down the second legend text,

h_legend = plt.legend(ncol=2)
y_shift = -2.5
h_legend.texts[1].set_position((0, y_shift))

You can peak your shift distance based on the extent of the legend window using something like:

h_legend = plt.legend(ncol=2)    
renderer = plt.gcf().canvas.get_renderer()
y_shift = -0.2*h_legend.texts[0].get_window_extent(renderer).height
h_legend.texts[1].set_position((0, y_shift))

this will shift the second text by 20% of the full legend window height.

like image 35
hashmuke Avatar answered Dec 10 '22 09:12

hashmuke