Skip to content

Y-axis labels are impossible to align by baseline #1734

Closed

Description

@jpaalasm

As the example below shows, axis labels are not aligned by text baseline by default, which would be typographically correct.

import pylab

fig, ((ax1, ax2), (ax3, ax4)) = pylab.subplots(2, 2, figsize=(4,3.8))

for ax in ax1, ax2, ax3, ax4:
    ax.set_xticks([])
    ax.set_yticks([])

ax1.set_ylabel("aaaaaaaajaaaaaaa")
ax3.set_ylabel("aaaaaaaaaaaaaaaa")

ax3.set_xlabel("aaaaaaaajaaaaaaa")
ax4.set_xlabel("aaaaaaaaaaaaaaaa")

For the x-axis labels, alignment by baseline is possible to configure (code below), but it seems to be impossible to do for y-axis labels, because set_horizontalalignment("baseline") is not allowed.

ax3.xaxis.get_label().set_verticalalignment("baseline")
ax4.xaxis.get_label().set_verticalalignment("baseline")
ax3.xaxis.labelpad = 15
ax4.xaxis.labelpad = 15

Activity

  1. jpaalasm commented on Mar 13, 2013

    @jpaalasm
    Author

    Here's a screenshot that shows the incorrect label alignment.

    incorrect label alignment

  2. pelson commented on Mar 13, 2013

    @pelson
    Member

    Because the text is rotated on the yaxis, you still want to use vertical alignment for the y labels. Adding:

    ax1.yaxis.get_label().set_verticalalignment("baseline")
    ax3.yaxis.get_label().set_verticalalignment("baseline")
    

    Seems to do the trick for me. Can you confirm?

    I've labelled this as a confirmed bug because this behaviour is a surprise to me - I'd be interested in seeing if we can use the baseline vertical alignment for labels as default.

    Thanks for raising @jpaalasm.

  3. jpaalasm commented on Mar 13, 2013

    @jpaalasm
    Author

    Well, that does not work, because verticalalignment is not vertical with respect to the rotated text, but with respect to the figure.

    It produces the following result (matplotlib 1.2.0).

    verticalalignment

  4. pelson commented on Mar 13, 2013

    @pelson
    Member
    import pylab
    
    fig, ((ax1, ax2), (ax3, ax4)) = pylab.subplots(2, 2, figsize=(4,3.8))
    
    for ax in ax1, ax2, ax3, ax4:
        ax.set_xticks([])
        ax.set_yticks([])
    
    ax1.set_ylabel("aaaaaaaajaaaaaaa")
    ax3.set_ylabel("aaaaaaaaaaaaaaaa")
    
    ax3.set_xlabel("aaaaaaaajaaaaaaa")
    ax4.set_xlabel("aaaaaaaaaaaaaaaa")
    
    ax3.xaxis.labelpad = 15
    ax4.xaxis.labelpad = 15
    ax4.xaxis.get_label().set_verticalalignment("baseline")
    ax3.xaxis.get_label().set_verticalalignment("baseline")
    
    ax1.yaxis.get_label().set_verticalalignment("baseline")
    ax3.yaxis.get_label().set_verticalalignment("baseline")
    
    pylab.show()
    

    Definitely works for me. Are you using the Macos backend by any chance? Are you able to confirm that this work for you on any Agg backend (TkAgg?).

  5. jpaalasm commented on Mar 13, 2013

    @jpaalasm
    Author

    I am using TkAgg (I put "print matplotlib.get_backend()" just above pylab.show() to find out), but the figure I get is exactly the same as what I uploaded in the previous comment.

  6. pelson commented on Mar 13, 2013

    @pelson
    Member

    My apologies @jpaalasm - I was in the middle of doing some mpl development and wasn't able to try this out on v1.3. I can see the same behaviour in mpl v1.2.1.

    Interestingly, this behaviour was changed by @pwuertz in b9fba92. I'm afraid I don't know of a workaround for using anything other than the master repository.

  7. pwuertz commented on Mar 13, 2013

    @pwuertz
    Contributor

    Yea, this scenario was one of the reasons why I proposed this anchored-rotation patch. With the default text rotation model up to matplotlib v1.2 the rotated text is aligned by its bounding box in the un-rotated system. There is no way to define a baseline there.

    There should be a workaround for v1.2 by applying the same settings found in b9fba92. Try something like this:

    ylabel = ax1.yaxis.get_label()
    ylabel.set_rotation_mode('anchor')
    ylabel.set_va('baseline')
    ylabel.set_ha('center')
    ylabel.set_rotation('vertical')
    

    Hopefully this works for you, but be aware that this change may trigger some bugs. I remember one or two follow-up patches that had to be applied to v1.3.

  8. pwuertz commented on Mar 13, 2013

    @pwuertz
    Contributor

    (sorry wrong button)

  9. pwuertz commented on Mar 13, 2013

    @pwuertz
    Contributor

    @pelson I guess the reason for not making baseline the default alignment is that matplotlib uses a fixed layout by default. So if you set 'baseline' instead of 'top' for the xlabel and include some huge symbol (maybe an integral sign), it will probably collide with the graph or the ticks. You'd have to use tight_layout for more reliable positioning.

  10. mdboom commented on May 21, 2013

    @mdboom
    Member

    It seems that setting the va to baseline works on master, so I think we can consider this closed. @jpaalasm, @pwuertz: do you agree?

    We probably will want to move to using baseline as the default in a future release of matplotlib. Maybe we should create a new 1.4.x targetted issue for that?

  11. pwuertz commented on May 22, 2013

    @pwuertz
    Contributor

    @mdboom: Agreed. With anchored rotation as the default this issue is solved.
    A new issue for 1.4.x could discuss the side-effects I raised above concerning default-baseline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions