Skip to content

Fix colorbar exponents #22313

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

Merged
merged 2 commits into from
Mar 9, 2022
Merged

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented Jan 25, 2022

PR Summary

Fix offsetText for colorbars with extends so they are above the extends... Closes #22312

Before

CbarOffsetPosBroke

After

CbarOffsetPosFixed

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

@jklymak jklymak added this to the v3.5.2 milestone Jan 25, 2022
@jklymak jklymak added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Jan 25, 2022
@jklymak jklymak force-pushed the fix-colorbar-exponents branch from a97402c to 5d38073 Compare January 25, 2022 12:13
@jklymak
Copy link
Member Author

jklymak commented Jan 25, 2022

... note that horizontal colorbars don't suffer from this problem so nothing was changed for XAxis....

# Special case for colorbars:
bbox = self.axes.spines['outline'].get_window_extent()
else:
bbox = self.axes.bbox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to update the axes.bbox in Colorbar to be the full spines outline? Move it up a level, so everything is referencing the same full bbox rather than just the text here. I'm not sure if that would mess up the tickers to draw in the extends region or not then...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ax.transAxes comes from the ax.bbox, so I don't think that would work as the axes extends are drawn in transAxes. I appreciate what you are saying though, it is a bit of a hack to special-case colorbars here...

Another alternative is to turn the axis off, use ax.get_tightbbox() and then turn the axis back on again. But I think get_tightbbox can get pretty expensive depending on artists. This is quite fast...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try to paraphrase: the colorbar axes has additional decorations which are outside the bbox but need to be taken into accout for shifting the offset text? In that case, do we need a concept for "bbox with decorations"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do, it's called get_tightbbox. However that is defined on the axes and takes into account the axis, and this exponent is part of the axis, so you get an infinite recursion. I guess we could change get_tightbbox to accept a list of artists to exclude, but I'm not convinced that is any better than this solution. And again get_tightbbox can be very expensive.

Copy link
Member

@timhoffm timhoffm Jan 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation. I don't claim to I know how the correct or practical solution. I was just trying to understand what's going on.

@jklymak jklymak marked this pull request as draft January 26, 2022 20:44
@jklymak
Copy link
Member Author

jklymak commented Jan 26, 2022

... moved to draft. cb.ax.set_title has the sae problem (though that usage is more rare, I expect)

@jklymak jklymak force-pushed the fix-colorbar-exponents branch from 07bf9b2 to 2fd7a26 Compare February 2, 2022 13:31
@jklymak jklymak closed this Feb 3, 2022
@jklymak jklymak reopened this Feb 3, 2022
@jklymak jklymak marked this pull request as ready for review February 3, 2022 08:08
@jklymak jklymak force-pushed the fix-colorbar-exponents branch 2 times, most recently from 1933d58 to 4c371d0 Compare February 4, 2022 12:31
@tacaswell tacaswell closed this Feb 11, 2022
@tacaswell tacaswell reopened this Feb 11, 2022
@tacaswell
Copy link
Member

Power-cycled now that we have fixed CI

Copy link
Member

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc failure appears relevant.

@jklymak
Copy link
Member Author

jklymak commented Feb 11, 2022

Yes it does look relevant. Are you trying to get 3.5.2 out the door? I'm away from my computer until next wed (16 feb). Looks like the check for outline in the colorbar spine dict is not correct.

@QuLogic
Copy link
Member

QuLogic commented Feb 11, 2022

No, not yet, probably next week.

@jklymak
Copy link
Member Author

jklymak commented Feb 12, 2022

I can fix the 17th or so, but not before. If anyone wants to push a check to the PR it's not a problem. Thanks!

@@ -505,7 +505,7 @@ def my_plotter(ax, data1, data2, param_dict):

pc = axs[1, 1].scatter(data1, data2, c=data3, cmap='RdBu_r')
fig.colorbar(pc, ax=axs[1, 1], extend='both')
axs[1, 1].set_title('scatter()');
axs[1, 1].set_title('scatter()')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these semicolons dont' work anyways, so removed it here...

@jklymak
Copy link
Member Author

jklymak commented Feb 21, 2022

OK, I admit to being quite stymied by the doc failure. What is happening is that the quick_start code is somehow creating a second figure in the pyplot registry, and this second figure is not quite setup properly. You can check this by adding print statements to the matplotlib_scraper in sphinx_gallery and seeing that it tries to create two figures for this part of the example.

The root of the problem seems to be the deepcopy in norm:

norm = copy.deepcopy(self.norm)

If I remove this, then the sphinx scraper doesn't create the extra figure.

The deepcopy arose because of the extra state that @greglucas added to sync colorbars and mappables. The failure is on norms made with _make_norm_from_scale which @anntzer added. If I manually define Norm to have a __deepcopy__ that simply returns the copy, then the failure goes away. I'm hoping either @greglucas or @anntzer can take a look and help us figure out what the heck is going on.

Looking at the code here, it definitely somehow triggers this weirdness, but I'm not understanding why it should.

The reproducer here is to put print statements in sphinx_gallery/scrapers.py in the matplotlib scraper, and see that print(plt.get_fignums()) returns two figures for "Color mapped data" in quick_start.py:

##############################################################################
when running make html

@greglucas
Copy link
Contributor

Strange indeed... This looks like it is also not working correctly on the current docs build on main, although not failing.
https://67051-1385122-gh.circle-artifacts.com/0/doc/build/html/tutorials/introductory/quick_start.html?highlight=quick%20start#color-mapped-data

So, I don't think this PR is a culprit, just hitting a louder failure. I'll try and dig deeper this evening if @anntzer doesn't figure it out before that.

@jklymak
Copy link
Member Author

jklymak commented Feb 21, 2022

Ah, good catch. Yes, this PR is probably squeaking because the spine is squished to nothing in the weird second figure.

Again, it has something to do with the deepcopy in colorbar. If I remove that it seems to work fine. But the deepcopy has been around for a while, so I suspect some of the recent changes to the norms.

@anntzer
Copy link
Contributor

anntzer commented Feb 21, 2022

I probably won't have the time to investigate this for a few days, sorry. I'll try to get back to it later...

@greglucas
Copy link
Contributor

A fix to remove the deepcopy is in #22523, which solves the docs build here, but does not solve the underlying problem that could crop up somewhere else.

The root cause bisects to: #21597
So, definitely something going on with the deepcopy on transforms. Removing getstate/setstate also makes the example "work" again, but of course causes other issues with pickling. So something with expanding the weakrefs of the parents attribute I think. We could revert that deepcopy removal commit and lose the ability to copy figures as possibly the easiest solution if we hit other issues here.

@greglucas
Copy link
Contributor

#22523 will fix the doc build for the main branch with this PR, and this shouldn't be an issue on 3.5 as the failing code was introduced after the 3.5.x branched off. I've re-opened a separate issue to track the underlying issue here which is the picklability of norms: #20755

@timhoffm
Copy link
Member

timhoffm commented Mar 8, 2022

#22523 is in. @jklymak please rebase to see that the doc build is fixed with that.

@jklymak jklymak force-pushed the fix-colorbar-exponents branch from 522bc6d to 707d8a2 Compare March 8, 2022 06:44
@QuLogic QuLogic merged commit 698397f into matplotlib:main Mar 9, 2022
@lumberbot-app
Copy link

lumberbot-app bot commented Mar 9, 2022

Owee, I'm MrMeeseeks, Look at me.

There seem to be a conflict, please backport manually. Here are approximate instructions:

  1. Checkout backport branch and update it.
git checkout v3.5.x
git pull
  1. Cherry pick the first parent branch of the this PR on top of the older branch:
git cherry-pick -m1 698397f95b61d007137ead5e733f6a1b1ecff032
  1. You will likely have some merge/cherry-pick conflict here, fix them and commit:
git commit -am 'Backport PR #22313: Fix colorbar exponents'
  1. Push to a named branch:
git push YOURFORK v3.5.x:auto-backport-of-pr-22313-on-v3.5.x
  1. Create a PR against branch v3.5.x, I would have named this PR:

"Backport PR #22313 on branch v3.5.x (Fix colorbar exponents)"

And apply the correct labels and milestones.

Congratulations — you did some good work! Hopefully your backport PR will be tested by the continuous integration and merged soon!

Remember to remove the Still Needs Manual Backport label once the PR gets merged.

If these instructions are inaccurate, feel free to suggest an improvement.

@anntzer
Copy link
Contributor

anntzer commented Apr 8, 2022

@jklymak @greglucas Sorry I didn't have the time to look at this; I'm trying to catch up a bit now. If I understand correctly there may still be a bug wrt deepcopying norms made with make_norm_from_scale? (which #22523 works around, but may otherwise may still be present?) Do colorbars need to be involved at all? Do you have a repro I can look at? (other than reverting #22523, as that PR seems like a good idea to me regardless)

@greglucas
Copy link
Contributor

Yes, they are still broken and you actually had a patch :) You can add this to the current test:
#20755 (comment)

I also was curious on whether this would be one of the cases where a metaclass might help as being a kind of class factory here, but I didn't think about that too much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. topic: color/colorbar
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Wrong position of exponent label for extended colorbar
6 participants