-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Change colorbar for contour to have the proper axes limits... #13506
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
963bc27
to
9ad0d94
Compare
3bc20eb
to
982616c
Compare
Thanks for doing this! |
@wsoofi. Thanks, It was your PR that inspired the need for it. It’s really not good to have the colorbar behave differently for different mappables but there were some subtleties that needed some work. |
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.
Looks 👍 , I'm just not quite sure what a bit of code is doing.
were made children of the normal axes tickers. | ||
|
||
This version of Matplotlib extends that to mappables made by contours, and | ||
allows the axes to run between the lesser the lowest boundary in the contour |
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.
allows the axes to run between the lesser the lowest boundary in the contour | |
allows the axes to run between the lowest boundary in the contour |
190e9cb
to
4e0d077
Compare
@dstansby, thanks fixed. The except happens when the |
Ok I guess the logic I had assumed proportional was true. Im not sure I get the other case It’s like we are treating the contours as categories, which seems strange to me. |
An example of where this is useful is in contouring bottom topography with contourf. One might want contour levels at 0, 50, 100, 250, 500, 1000, 2000, 5000. Yes, in a sense each interval is a category that gets a color. The interval boundaries need to be labeled, and each interval in the colorbar has to be large enough so that the labels don't collide. Hence the 'uniform' option, in which each interval gets the same space on the colorbar. |
Thanks @efiring, I think I fixed this. I'll add tests as well! |
6281da5
to
7d190d3
Compare
7d190d3
to
7b3ea96
Compare
d12c113
to
6d7c885
Compare
Test added. Not sure if there should be more... |
@@ -578,13 +580,11 @@ def _reset_locator_formatter_scale(self): | |||
""" | |||
self.locator = None | |||
self.formatter = None | |||
if (isinstance(self.norm, colors.LogNorm) | |||
and self._use_auto_colorbar_locator()): |
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.
Why can that be left out?
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 we want the axes to be logarithmic in this case, but I agree its open to interpretation:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
z = np.arange(24).reshape(4, 6) + 1
z = np.power(2, z)
fig, axs = plt.subplots(1, 2, constrained_layout=True)
ax = axs[0]
cs = ax.contourf(z, levels=np.power(10., [1, 2, 6.5, 10] ), norm=mcolors.LogNorm())
fig.colorbar(cs, ax=ax, spacing='proportional')
ax = axs[1]
cs = ax.contourf(z, levels=np.power(10, [1, 2, 6.5, 10]), norm=mcolors.LogNorm())
fig.colorbar(cs, ax=ax, spacing='uniform')
plt.show()
With this change:
Without this change:
Before this PR:
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.
👍 Looks reasonable.
@@ -578,13 +580,11 @@ def _reset_locator_formatter_scale(self): | |||
""" | |||
self.locator = None | |||
self.formatter = None | |||
if (isinstance(self.norm, colors.LogNorm) | |||
and self._use_auto_colorbar_locator()): |
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.
👍 Looks reasonable.
ping @efiring, or anyone else interested in colorbars |
PR Summary
We've changed colorbars to mostly behave like other axes, so for instance,
print(cbar.ax.get_ylim())
actually returns the axes limits of the colorbar.However, that did not work for colorbars made with
contour
, which were still normalized with limits between 0 and 1. Now this axes are normalized between vmin and vmax for the colorbar (not necessarily the vmin and vmax of the colormap norm, a subtlety that confused me for a while).This closes #13494 because that example would now simply read:
cbar.ax.axhline(desired_cbar_yvalue, color='r', linewidth=5)
rather than normalizing that between 0 and 1.
PR Checklist