-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
BF: text not drawn shouldn't count for tightbbox #18772
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
BF: text not drawn shouldn't count for tightbbox #18772
Conversation
ax.annotate('BIG LONG STRING', xy=(1.25, 2), xytext=(10.5, 1.75), | ||
annotation_clip=False) |
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 test was actually "buggy" as originally written. Because of the value of xy
, with annotation_clip=None
, this text never got drawn, and as such should never have contributed to the tight_layout
in the first place. The code fixed this, causing this test to fail (since it no longer tested what it was intended to).
Adding annotation_clip=False
fixes the test to check for what it originally intended (by actually drawing the text way off screen).
I don't think visibility affects the extents of any of the artists? Its up to whatever uses the extents to decide whether to include them or not. I actually don't think the current code is correct - it should just return the extent. |
Okay, but it affects I'm fine if you tell me that |
You can easily argue the converse that the user put the empty thing out there for a reason, and we should respect it. i.e. imagine they are toggling the text on and off, but want the plot size to stay the same. I think all I'm suggesting is that we should be careful about changing this, and to make every effort to make it consistent with other artists. |
But this will not cause the plot to stay the same size (unless the text is on the top left of the plot, and
I see your point and will update the PR momentarily to more carefully address the issue which (in my mind, at least) seems more definitely like a bug...(the case of |
Update: @jklymak. You're right that most artists don't seem to change their Arguably, this should not be the case, since other figures don't do this. But I'd want other people's opinions on whether to change this, because changing this either way would be a major change to For now, I'll just leave it as-is, and implement Update Update: Putting this logic into |
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 block, just because one pixel is better than no pixels ;-)
Happy to work with you though on the underlying problem.
The relevant code is here: matplotlib/lib/matplotlib/axes/_base.py Lines 4389 to 4407 in 4fb84b4
So it seems you are saying that the clipping extent is not correct for an Annotation? Thats seems to be the underlying bug, otherwise the clipping should have worked to exclude this artist from the bbox calc. |
So as far as I can see, Annotations don't define their clipping extent. In which case you can't really expect them to be clipped. The proper solution is to implement clipping for them. |
This was also my first response, however, as I read into the logic of the code further I changed my own mind. Tell me if the following makes sense.
I think the clipping extents are correct for an For example, adding logic that includes the axes box as an extra "clip" box for the The actual logic for whether the matplotlib/lib/matplotlib/text.py Line 1935 in 4fb84b4
which hands off to this helper function, which enforces the special "do we show this annotation" logic required by the matplotlib/lib/matplotlib/text.py Lines 1517 to 1524 in 4fb84b4
whereas in the matplotlib/lib/matplotlib/text.py Lines 876 to 877 in 4fb84b4
So when the value returned from |
I initially (incorrectly) thought this logic belonged in So my new PR would be something like just the following patch: in def get_tightbbox(self, renderer):
# docstring inherited
if not self._check_xy(renderer):
return Bbox.null()
return super().get_tightbbox(renderer)
|
ee81bdf
to
062d54a
Compare
Okay, I solved the underlying issue, while leaving the existing behavior of This change now only affects annotations with Arguably, |
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.
Needs and API change note.
.. I dropped the release critical flag - this has been like this forever, right? |
Yes it has. I tagged it this way because it was technically a "bug", but of course will go with your judgement. |
... one persons "Critical" is different depending on need. FWIW< you can always manually exclude any artist using |
Fair. I mean for my purposes I can just require this branch/master for now. Added API changes. |
I agree with @jklymak on the use of critical for this, we tend to save that for things like seg-faults, egregious regressions, or bugs that make plots wrong. Things that make the library unusable rather than inconvenient. |
PR Summary
In short, there is a difference between our treatment of
Annotation
objects at draw time versus when computingget_tightbbox
.If
aanText
is the empty string''
, orAnnotation
hasannotation_clip=None
and its position (in data space) is outside the data limits of its parentAxes
, then that annotation is simply not drawn (Annotation.draw
simply returns immediately).On the other hand, this check is missing
Annotation.get_window_extents
.Annotation.get_tightbbox
should check for this condition and return aBbox.null
, so that e.g.tight_layout
correctly excludes them from theBbox
calculation.Edit: The bug this is solving is that
returns
instead of
because of the "invisible" text box down in the bottom-left hand corner, whose existence should not have been included in
tight_layout
(viatightbbox
) due to the default value ofannotation_clip
.PR Checklist
pytest
passes).flake8
on changed files to check).flake8-docstrings
andpydocstyle<4
and runflake8 --docstring-convention=all
).doc/users/next_whats_new/
(follow instructions in README.rst there).doc/api/next_api_changes/
(follow instructions in README.rst there).