-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
FIX: move title(s) up if subscripts hang too low. #11502
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
FIX: move title(s) up if subscripts hang too low. #11502
Conversation
OK, so this "only" fails 50 tests - all of which have titles (i.e. about 16 individual tests). If this is an OK approach I will regenerate the test images. Pros: large subscript titles won't drop down below the top of the axes. Cons: The baseline of a title like "platypus" would be displaced vertically from the top of the axes relative to a title like "aardvark" |
I don't think the con is even true:
So, 👍 |
👍 Can you check if those tests are actually testing titles? Any which are not should probably have the title removed (to reduce our exposure to font-related changes in general). Is this just a matter of tuning the padding just right to make it match? |
2c7594e
to
7108a60
Compare
OK: I decided I didn't like this approach because it allowed no way to align the titles (at their baselines) without manually doing This is also going to fail far fewer tests.... After: |
This only fails two tests in tight_layout where for some reason the x/y line gets shifted by a point for some funky reason. It happens locally as well, so I can re-produce. Its a little funky and likely to do with pixel snapping, but is harmless to the test... |
d44c84d
to
9e0a8b3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apart from the two minor specific comments, this looks good to me.
But doesn't it need one added test like the illustrations that are given above to motivate the PR?
lib/matplotlib/axes/_base.py
Outdated
for title in titles: | ||
x, y0 = title.get_position() | ||
y = 1.0 | ||
y = 1 | ||
# need to start agin in case of window resizing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment.
lib/matplotlib/axes/_base.py
Outdated
y = 1 | ||
bt = title.get_window_extent(renderer) | ||
# need to do twice to get right for manual resizing | ||
for nn in range(1): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is doing it only once. Does it really need to be done twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once works!
Thanks @efiring test added... |
ac877a4
to
cb636e6
Compare
lib/matplotlib/axes/_base.py
Outdated
y = max(y, yn) | ||
else: | ||
bb = ax.get_window_extent(renderer) | ||
top = np.max((top, bb.ymax)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that it's particular important, but I would just use the builtin max()
. It's easier to read and also faster for just two numbers.
lib/matplotlib/axes/_base.py
Outdated
y = self.transAxes.inverted().transform( | ||
(0., top - dy))[1] | ||
title.set_position((x, y)) | ||
ymax = np.max((y, ymax)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Builtin max()
?
lib/matplotlib/axes/_base.py
Outdated
y = 1 | ||
bt = title.get_window_extent(renderer) | ||
dy = bt.ymin - top | ||
if dy < 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICS this dy
value is not used again. In that case, it would be more clear to:
if title.get_window_extent(renderer).ymin < top:
# title overlaps the Axes
...
IMO the temporary variables do not add to the clarity of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, leftovers from debugging where the temporary variables were used a few more times ;-)
lib/matplotlib/axes/_base.py
Outdated
y = self.transAxes.inverted().transform( | ||
(0., top))[1] | ||
title.set_position((x, y)) | ||
bt = title.get_window_extent(renderer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please add a short comment, why you do the setting of the position in two steps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, yes, it should be exactly the same w/ or w/o the extra block, but emperically its not with the state that get_extents
is in now... 😢 Comment added...
cb636e6
to
a04c64c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave it up to you, if you want to update the max()
usages.
lib/matplotlib/axes/_base.py
Outdated
y = max(y, yn) | ||
else: | ||
bb = ax.get_window_extent(renderer) | ||
top = max((top, bb.ymax)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
max(top, bb.ymax)
would work as well, i.e. multiple arguments instead of a tuple. It's even slightly more clean.
TST: Add test for large subscript
a04c64c
to
e38c544
Compare
Thanks @timhoffm , fixed! |
PR Summary
Partially adresses #11468. See also #11499 for multiline fixes...
EDIT:
Currently if a title has a large subscript, usually because it is math text (though large title font sizes can do the same thing), it will overhang the axes.
This PR adjusts the title position so this doesn't happen. It moves all three titles (left, right and centre) to the same level to maintain consistency of the baseline on the axes.
Note that the new version can overspill the top of the figure unless
tight_layout
orconstrained_layout
are used. But that overspill is still better than spilling down over the axes in my opinion.Code
PR Checklist