-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fixed Annotation draw method #4145
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
Conversation
@@ -2092,7 +2093,9 @@ def draw(self, renderer): | |||
self.arrow_patch.figure = self.figure | |||
self.arrow_patch.draw(renderer) | |||
|
|||
Text.draw(self, renderer) | |||
astext = copy.copy(self) | |||
astext.__class__ = Text |
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.
Evidently it works, but this seems like a hack. Maybe what it is telling us is that the Annotation could be implemented more cleanly via composition than via inheritance. That's speculation; I haven't looked closely.
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.
Yes, I agree, while going through the Text module, Annotation does seem like it might be better suited for composition rather than inheritance. There is some precedence for modifying the __class__
attribute in the codebase currently but ultimately it is a hack to get the desired MRO.
One alternative approach is to refactor the Text.draw
method to not reuse bbox_artist
but that just seems like a step in the wrong direction by duplicating code. Another is to design a Text
initialization that takes the derived class and returns a Text
instance.
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 think the problem is with bbox_artist() from patch.py, which adds a patch. It calls the object's get_window_extent(). For Annotations, that includes the arrow.
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.
Note that by "problem" I don't mean that bbox_artist() is broken, just that some assumption somewhere is broken at that point.
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.
@WeatherGod Yes, that is correct (see my comment on issue #4139).
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.
Well, if that is the case, then I am -1 on this kludge. We know exactly
what the problem is -- we shouldn't be using bbox_artist() for this.
Perhaps "bbox_text()"? It would work similarly to bbox_artist, but would
use the Text class's get_window_extent no matter what object is passed to
it?
As for precedence for explicitly changing an object's class, I am
assuming that you are referring to mplot3d. Yeah, let's not bring that wart
into matplotlib proper. I still haven't figured out a way to fix that.
On Mon, Feb 23, 2015 at 4:58 PM, Cimarron notifications@github.com wrote:
In lib/matplotlib/text.py
#4145 (comment):@@ -2092,7 +2093,9 @@ def draw(self, renderer):
self.arrow_patch.figure = self.figure
self.arrow_patch.draw(renderer)
Text.draw(self, renderer)
astext = copy.copy(self)
astext.**class** = Text
@WeatherGod https://github.com/WeatherGod Yes, that is correct (see my
comment on issue #4139
#4139).—
Reply to this email directly or view it on GitHub
https://github.com/matplotlib/matplotlib/pull/4145/files#r25206783.
Currently |
Right. Given that we are stuck with the present implementation, it looks like this PR is the simplest fix for the bug. |
def bbox_artist(artist, renderer, props=None, fill=True):
"""
This is a debug function to draw a rectangle around the bounding
box returned by
:meth:`~matplotlib.artist.Artist.get_window_extent` of an artist,
to test whether the artist is returning the correct bbox.
*props* is a dict of rectangle props with the additional property
'pad' that sets the padding around the bbox in points.
""" A bigger problem seems to be that we are using what is labeled as a debugging function in production code. It also looks like it results in the creation of a new artist during the draw which gets drawn to the canvas, but is not a child of the We probably should figure out a cleaner way to implement this (maybe fully adopting the 'fancy' way or adding a rectangle artist to the This is the sort of thing that will make serialization/export to other libraries 'interesting'... |
On the other hand, it looks like that bit of code dates from JDH from 2004 (e50ff69). |
For all we know, it may have started out as a debugging feature. I know I You are absolutely right, I didn't even think about the problem of adding On Mon, Feb 23, 2015 at 10:06 PM, Thomas A Caswell <notifications@github.com
|
|
I am +1 on that approach.
|
Closing in favor or #4178 |
Fix for issue #4139
This correctly draws the text portion of the annotation after incorporation of PR #4023.
Before
After