diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index b1cd08d955a7..16b0377a43bc 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -1006,24 +1006,34 @@ def _reset_locator_formatter_scale(self): self.locator = None self.minorlocator = None self.formatter = None - if ((self.spacing == 'uniform') and - ((self.boundaries is not None) or - isinstance(self.norm, colors.BoundaryNorm))): - funcs = (self._forward_boundaries, self._inverse_boundaries) - self.ax.set_xscale('function', functions=funcs) - self.ax.set_yscale('function', functions=funcs) - self.__scale = 'function' - elif hasattr(self.norm, '_scale') and (self.norm._scale is not None): + if (self.boundaries is not None or + isinstance(self.norm, colors.BoundaryNorm)): + if self.spacing == 'uniform': + funcs = (self._forward_boundaries, self._inverse_boundaries) + self.ax.set_xscale('function', functions=funcs) + self.ax.set_yscale('function', functions=funcs) + self.__scale = 'function' + elif self.spacing == 'proportional': + self.__scale = 'linear' + self.ax.set_xscale('linear') + self.ax.set_yscale('linear') + elif hasattr(self.norm, '_scale') and self.norm._scale is not None: + # use the norm's scale: self.ax.set_xscale(self.norm._scale) self.ax.set_yscale(self.norm._scale) self.__scale = self.norm._scale.name - else: + elif type(self.norm) is colors.Normalize: + # plain Normalize: self.ax.set_xscale('linear') self.ax.set_yscale('linear') - if type(self.norm) is colors.Normalize: - self.__scale = 'linear' - else: - self.__scale = 'manual' + self.__scale = 'linear' + else: + # norm._scale is None or not an attr: derive the scale from + # the Norm: + funcs = (self.norm, self.norm.inverse) + self.ax.set_xscale('function', functions=funcs) + self.ax.set_yscale('function', functions=funcs) + self.__scale = 'function' def _locate(self, x): """ diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index f678a4ffefd5..3b7e5988eab7 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1152,7 +1152,7 @@ def __init__(self, vmin=None, vmax=None, clip=False): self.vmin = _sanitize_extrema(vmin) self.vmax = _sanitize_extrema(vmax) self.clip = clip - self._scale = scale.LinearScale(axis=None) + self._scale = None # will default to LinearScale for colorbar @staticmethod def process_value(value): @@ -1334,6 +1334,16 @@ def __call__(self, value, clip=None): result = np.atleast_1d(result)[0] return result + def inverse(self, value): + if not self.scaled(): + raise ValueError("Not invertible until both vmin and vmax are set") + (vmin,), _ = self.process_value(self.vmin) + (vmax,), _ = self.process_value(self.vmax) + (vcenter,), _ = self.process_value(self.vcenter) + + result = np.interp(value, [0, 0.5, 1.], [vmin, vcenter, vmax]) + return result + class CenteredNorm(Normalize): def __init__(self, vcenter=0, halfrange=None, clip=False): diff --git a/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_twoslope.png b/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_twoslope.png new file mode 100644 index 000000000000..27d9227dcfe0 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_twoslope.png differ diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index ac054755c4c1..6167618575dd 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -771,3 +771,17 @@ def test_inset_colorbar_layout(): np.testing.assert_allclose(cb.ax.get_position().bounds, [0.87, 0.342, 0.0237, 0.315], atol=0.01) assert cb.ax.outer_ax in ax.child_axes + + +@image_comparison(['colorbar_twoslope.png'], remove_text=True, + style='mpl20') +def test_twoslope_colorbar(): + # Note that the first tick = 20, and should be in the middle + # of the colorbar (white) + fig, ax = plt.subplots() + + norm = mcolors.TwoSlopeNorm(20, 0, 100) + pc = ax.pcolormesh(np.arange(1, 11), np.arange(1, 11), + np.arange(100).reshape(10, 10), + norm=norm, cmap='RdBu_r') + fig.colorbar(pc) diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 81dd65bab713..ae004e957591 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -1406,6 +1406,5 @@ def test_norm_deepcopy(): norm = mcolors.Normalize() norm.vmin = 0.0002 norm2 = copy.deepcopy(norm) - assert isinstance(norm2._scale, mscale.LinearScale) + assert norm2._scale is None assert norm2.vmin == norm.vmin - assert norm2._scale is not norm._scale
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: