-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
FIX: ColorbarAxes properly in the axes stack #20484
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
cda330a
to
aaaee32
Compare
e94d77c
to
eb879a9
Compare
c2cf781
to
4c7dbd7
Compare
4c7dbd7
to
fb768c7
Compare
... of course this turned out more complicated for some of the reasons I think @greglucas found - in particular |
... 98.5% sure CI failures are unrelated to this PR (see #20487) |
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.
Bummer you ran into that here too! I didn't realize the AxesStack wasn't being updated, but this actually simplifies a lot of the interactive code I was working on as well, so thanks for this!
I never did get up to speed on the axes_grid
implementation, but making it more similar to a normal colorbar seems good to me. I guess I'd suggest that piece being a separate PR (or at least a separate commit) solely focused on that piece.
else: | ||
outer_ax = parent | ||
|
||
# swap axes in the stack if its in there: |
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'm not sure how it wouldn't be there if you've created it above or gotten it passed in? But, wouldn't you want to add(self)
regardless of whether the outer one is there or not?
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.
There was some test where we made a colorbar and it didn't actually ever get added. I can take ti out again to figure out which one...
for attr in ["get_position", "set_position", "set_aspect"]: | ||
for attr in ["get_position", "set_aspect", | ||
"_remove_method", "_set_position", | ||
"set_position", "cla", "draw"]: |
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'm still not sure about these only being mapped to the outer_ax... I would have thought it should be something like:
def draw(self, renderer):
super().draw(renderer)
self.outer_ax.draw(renderer)
so that you draw both the inner and outer? Same for the cla and remove. The position's I think are appropriate to map straight to the outer though.
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.
inner is an artist on outer, so inner gets drawn if outer gets drawn ;-)
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.
Oh yeah, it is an inset of the outer! Makes sense now, thanks for clarifying.
if userax: | ||
self._colorbar_info = 'user' | ||
# point the parent's methods all at this axes... | ||
origdict = parent.__dict__ | ||
parent.__dict__ = self.__dict__ |
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 just update it?
parent.__dict__ = self.__dict__ | |
parent.__dict__.update(self.__dict__) |
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.
Oh, maybe? Thanks!
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.
No, sadly not. I'll admit I'm probably not enough of a pythionista to dig around in the guts like this. Its pretty apparent to me that this copies all the attributes over, but if you iterate through __dict__
like a normal dictionary it does not capture everything in __dict__
. Its all a little confusing. If someone has a more elegant less tacky way to do this, we can certainly try that approach...
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.
Maybe try {**parent.__dict__, **self.__dict__}
which would produce a new dict...
@greglucas thanks for taking a look. The problem with making the axes grid stuff a different PR is that of course the changes needed to get picking to work break axes_grid. (I honestly didn't set out to fix axes grid ;-) |
I guess the other approach here is rather than create a new container axes to just attach the stuff we want to the existing axes, and re-direct the appropriate attributes to the inner axes, keeping the outer axes as similar as possible. I avoided that route because I think far more of the "inner" methods are user-facing, but it certainly is difficult to do this dance robustly. |
OK, having thought about this a lot of the day, here is another approach: Old, we did a bunch of drawing by hand New proposal: instead of trying to replace |
Closing for #20501 |
PR Summary
Closes #20479
ColorbarAxes was not sitting in the figure Axes stacks correctly - rather cb.outer_axes was still in the queue. Which worked fine, but didn't make mouseevents pass through properly.
The solution here is to swap cb.ax for cb.outer_axes in the figure axes stacks, and to redefine
draw
on the ColorbarAxes to draw the outer axes first (i.e. set the aspect ratio and size of the bounding box for the colorbar).I was testing on the following, though the real test is simply that cb.ax appears in the figure axes list now:
PR Checklist
pytest
passes).flake8
on changed files to check).flake8-docstrings
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).