Reputation: 4311
I am doing a plot with matplotlib and creating a legend for this (see code below). I want the legends rows be aligned horizontally such that the relations >
and <
are aligned. Trying to adapt this and this code of similar problems, i got stuck.
I understand the basic idea: use \makebox[width][alignment]{math expression before aligment}<math expression after alignment
as label, such that the space used by that epsilon-expression always uses the same space and is aligned to the right, hence there is free space to the left.
But the \hfill
-methods used in the links only work if there is text before it the hfill, or if the alignment is standard (left). The solution must be quite near and any help would be appreciated.
This is how the text of the legend should look like
import numpy
from matplotlib import pyplot as plt
plt.rc('text', usetex=True) # needed for interpeting tex strings, but changes appearence of axis-tick labels also
fig = plt.figure(1,figsize=(12.0, 8.0))
plt.ion()
# does not align the '<', '<' and '>' in the legend
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{$\varepsilon_i$}$< -\xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{$|\varepsilon_i|$}$< \xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{$\varepsilon_i$}$ > \xi$')
# \hfill doesnt change anything
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{\hfill$\varepsilon_i$}$< -\xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{\hfill$|\varepsilon_i|$}$< \xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[24cm][r]{\hfill$\varepsilon_i$}$ > \xi$')
# the relations are aligned, but i do not want to plot the 'bla' for this
plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{bla\hfill$\varepsilon_i$}$< -\xi$')
plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{bla\hfill$|\varepsilon_i|$}$< \xi$')
plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{bla\hfill$\varepsilon_i$}$ > \xi$')
plt.legend(loc='upper right')
plt.show()
Upvotes: 2
Views: 1878
Reputation: 13467
Here's a solution where LaTeX perfectly alignes math, but the user has to take the pain to position it inside the legend. The idea is to
array
into it manuallyHere's the code:
#!/usr/bin/python3
from numpy import arange
import matplotlib
from matplotlib import pyplot as plt
custom_preamble = {
"text.usetex": True,
"text.latex.preamble": [
r"\usepackage{amsmath}", # for the array macros
],
}
matplotlib.rcParams.update(custom_preamble)
x = arange(5)
y = arange(5)
fig = plt.figure()
ax = fig.add_subplot(111)
l1, = ax.plot(x, y)
l2, = ax.plot(x * 2, y)
l3, = ax.plot(x * 3, y)
leg = ax.legend(
[l1, l2, l3],
["", "", ""],
bbox_to_anchor = (0.98, 0.25),
handletextpad = 4, # space between lines and text -- used here as a placeholder
labelspacing = 0.1, # space between lines in a legend
)
leg.set_zorder(1)
ax.text(0.955, 0.21,
r"\begin{array}{rcl}"
r" \varepsilon_i & < & -\xi"
r"\\ |\varepsilon_i| & < & \xi"
r"\\ \varepsilon_i & > & \xi"
r"\end{array}",
transform = ax.transAxes,
horizontalalignment = 'right',
verticalalignment = 'top',
zorder = 5,
)
fig.savefig("mwe.png")
Result:
You might want to compile it twice: on the first compilation it might give You error, but all other tries would go fine.
As to a space between <
sign in a legend -- it might be reduced with say:
ax.text(0.94, 0.21,
r"\begin{array}{r@{}c@{}l}"
r" \varepsilon_i \,\,& < &\,\, -\xi"
r"\\ |\varepsilon_i| \,\,& < &\,\, \xi"
r"\\ \varepsilon_i \,\,& > &\,\, \xi"
r"\end{array}",
(everything else the same). This gives:
Upvotes: 2