diff --git a/doc/api/next_api_changes/behavior/26307-AL.rst b/doc/api/next_api_changes/behavior/26307-AL.rst new file mode 100644 index 000000000000..a83366f012b3 --- /dev/null +++ b/doc/api/next_api_changes/behavior/26307-AL.rst @@ -0,0 +1,4 @@ +Colorbars of single-value norms now map that value to the lowest color, not the midpoint color +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This behavior is consistent with e.g. how `~.Axes.imshow` handle inputs with +``vmin == vmax``. diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index af61e4671ff4..5539f818d909 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -1088,8 +1088,13 @@ def _process_values(self): # If we still aren't scaled after autoscaling, use 0, 1 as default self.norm.vmin = 0 self.norm.vmax = 1 - self.norm.vmin, self.norm.vmax = mtransforms.nonsingular( - self.norm.vmin, self.norm.vmax, expander=0.1) + + # Only expand vmax if needed, to match Normalize's behavior of mapping + # everything to 0 if the norm is singular. + vmin, vmax = sorted([self.norm.vmin, self.norm.vmax]) + self.norm.vmin = vmin + _, self.norm.vmax = mtransforms.nonsingular(vmin, vmax, expander=0.1) + if (not isinstance(self.norm, colors.BoundaryNorm) and (self.boundaries is None)): b = self.norm.inverse(b) diff --git a/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_single_scatter.png b/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_single_scatter.png deleted file mode 100644 index 18d9cf02add0..000000000000 Binary files a/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_single_scatter.png and /dev/null differ diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index 74742d8c2369..a1929bfb6daf 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -265,18 +265,17 @@ def test_gridspec_make_colorbar(): plt.subplots_adjust(top=0.95, right=0.95, bottom=0.2, hspace=0.25) -@image_comparison(['colorbar_single_scatter.png'], remove_text=True, - savefig_kwarg={'dpi': 40}) def test_colorbar_single_scatter(): - # Issue #2642: if a path collection has only one entry, - # the norm scaling within the colorbar must ensure a - # finite range, otherwise a zero denominator will occur in _locate. + # Issue #2642: If a path collection has only one entry, the norm scaling within the + # colorbar must ensure a finite range, otherwise a zero denominator will occur in + # _locate. Also, adding the colorbar must not change the value's normalization. plt.figure() - x = y = [0] - z = [50] - cmap = mpl.colormaps['jet'].resampled(16) - cs = plt.scatter(x, y, z, c=z, cmap=cmap) + v = 50 + cs = plt.scatter([0], [0], c=[50]) + old_normed = cs.norm(v) plt.colorbar(cs) + new_normed = cs.norm(v) + assert old_normed == new_normed @pytest.mark.parametrize('use_gridspec', [True, False])