Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vertical text alignment in multi-line legend entries #2295

Closed
shikasta-net opened this issue Aug 13, 2013 · 10 comments
Closed

Vertical text alignment in multi-line legend entries #2295

shikasta-net opened this issue Aug 13, 2013 · 10 comments

Comments

@shikasta-net
Copy link

Hello, I have a problem which seems to be uncommon and I think might be a design bug. Whenever I have an entry in a legend with more than one line of text, the marker is always placed on the last line, not the first. Also, I don't seem to be able to specify the vertical position anywhere so there is no way to override this. As an example:

lag_time-concentration_cfc

The label is created with latex, but does the same with ordinary text, I generate the legend with the command:

page.legend(handles, labels, borderaxespad=0.5, handleheight=1.2, labelspacing=0.5, bbox_to_anchor=(0.06,lgnd_height/(fig_height+lgnd_height)), loc='upper left')

where the anchor is to sort out the external positioning, but has no effect as the same result is produced by
page.legend(handles, labels, loc=1)
but isn't so clear an illustration.

Thanks.

@shikasta-net
Copy link
Author

I think I found the problem:
In legend._init_legend_box(handles, labels) is the hardcoded property
label_prop = dict(verticalalignment='baseline')
Unfortunately I'm currently using a managed machine and can't tweak this line, but I suspect it should say 'top'.

EDIT:
It wasn't that line it was further down:
itemBoxes = [HPacker(pad=0,
sep=self.handletextpad * fontsize,
children=[h, t], align="baseline")
for h, t in handle_label[i0:i0 + di]]
I managed to sort of fix it from within my own code by including this just after the legend is constructed:
cb = leg._legend_box._children[-1]._children[0]
for ib in cb._children :
ib.align = "center"
But for some reason 'top' doesn't work here, only center

@pelson
Copy link
Member

pelson commented Aug 14, 2013

Hi @shikasta-net - the best place to get help with these kinds of issues is on the matplotlib-users mailing list. Ideally we try use the issue tracker here for distilled bug reports (short, simple, self contained, correct, examples) and fixes.

It sounds like you've actually already solved your problem, so I'll go ahead and close this. Feel free to drop a message on matplotlib-users if you have any follow on questions.

Thanks!

@pelson pelson closed this as completed Aug 14, 2013
@efiring
Copy link
Member

efiring commented Aug 14, 2013

@pelson, I think @shikasta-net is actually pointing to a possible bug or non-optimal design and a possible fix within mpl (legend code). Maybe @leejjoon can take a quick look at it.

@pelson
Copy link
Member

pelson commented Aug 15, 2013

@pelson, I think @shikasta-net is actually pointing to a possible bug or non-optimal design

I think you're probably right. But it's not really a SSCCE which would make the bug easy to confirm and could be quickly turned into a unit test.

Personally I think the place for discussing problems which could be either user error or an actual bug is the mailing list. Once a bug has been identified, and a simple SSCCE can be produced to re-create (where appropriate and feasible) I think that should be moved into the issue tracker. Anything else results in the issue tracker being overloaded with unfocused problems which certainly de-motivates me, and I suspect others, from finding an issue to resolve and addressing it with a PR.

@leejjoon
Copy link
Contributor

Can anyone else reproduce the result by @shikasta-net? The legend handles and texts are supposed to be center-aligned when the texts have multi-lines, and it is center-aligned in my installation.

@shikasta-net: please post a simple example that reproduce the bug. Also let us know which version of matplotlib you are using.

@shikasta-net
Copy link
Author

Thanks for having a look, I'm just in the final days of writing my PhD thesis so I don't have much energy to spare. Here is a `minimal' example or matplotlib 1.3 (python 2.6) and result that I get:

from pylab import *
from matplotlib.backends.backend_pdf import PdfPages

from matplotlib import rc

ofile = PdfPages('./example.pdf')
page = figure(figsize=(8, 3))
fig = page.add_subplot(1,1,1)

rc('text', usetex=True)
fig.plot([0,1,5,9], [2,5,8,4], color='blue', label=r'When tex is used to typeset labels,\newline this happens')

fig.plot([0,1,5,9], [7,8,5,6], color='red', label='where as using non-raw strings and line break,\n this happens')

page.tight_layout()
handles, labels = fig.get_legend_handles_labels()
page.legend(handles, labels, loc=8)
ofile.savefig(page)
ofile.close()

example

As you can see, my workaround above simply fixes the fact that matplotlib can't tell that the LaTeX text is multi-line.

I hope that helps.

@mdboom
Copy link
Member

mdboom commented Aug 15, 2013

MEP14 is an ongoing effort to improve text handling in general. I don't really have time to look at an immediate fix right now, but I wanted to add this comment so I can follow up on this as part of my MEP14 effort later.

@pelson
Copy link
Member

pelson commented Aug 15, 2013

Thanks @shikasta-net and good luck for that final push 😄

@Jerry-Ma
Copy link

I am sorry to dig this up but the solution posted by @shikasta-net really helped me. In the light of that, I managed to make it aligns to the "top".

The situation is that by looking at the source code in offsetbox.py, the 'top' align mode doesn't actually do the job, as it says:

...
elif align in ["left", "top"]:
    descent = 0.
    offsets = [d for h, d in hd_list]
...

After making the following change, it works perfectly:

     offsets = [height - h + d for h, d in hd_list]

Hopefully this will help.

@inviridi
Copy link

inviridi commented Feb 1, 2017

Apologies for resurrecting this thread! I think this would be very helpful to have in mpl... unfortunately I was not able to get it working with the changes in the source of mpl 2.0 as suggested above. Is there something else I could try?

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants