diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 68530e0695aa..cf31178b7696 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -824,6 +824,12 @@ def _get_ticker_locator_formatter(self): b = self.norm.boundaries if locator is None: locator = ticker.FixedLocator(b, nbins=10) + elif isinstance(self.norm, colors.NoNorm): + if locator is None: + # put ticks on integers between the boundaries of NoNorm + nv = len(self._values) + base = 1 + int(nv / 10) + locator = ticker.IndexLocator(base=base, offset=.5) elif self.boundaries is not None: b = self._boundaries[self._inside] if locator is None: @@ -835,11 +841,6 @@ def _get_ticker_locator_formatter(self): locator = self._long_axis().get_major_locator() if minorlocator is None: minorlocator = self._long_axis().get_minor_locator() - if isinstance(self.norm, colors.NoNorm): - # default locator: - nv = len(self._values) - base = 1 + int(nv / 10) - locator = ticker.IndexLocator(base=base, offset=0) if minorlocator is None: minorlocator = ticker.NullLocator() @@ -1097,6 +1098,9 @@ def _process_values(self): # otherwise values are set from the boundaries if isinstance(self.norm, colors.BoundaryNorm): b = self.norm.boundaries + elif isinstance(self.norm, colors.NoNorm): + # NoNorm has N blocks, so N+1 boundaries, centered on integers: + b = np.arange(self.cmap.N + 1) - .5 else: # otherwise make the boundaries from the size of the cmap: N = self.cmap.N + 1 diff --git a/lib/matplotlib/tests/baseline_images/test_colorbar/nonorm_colorbars.svg b/lib/matplotlib/tests/baseline_images/test_colorbar/nonorm_colorbars.svg new file mode 100644 index 000000000000..85f92c3c8d64 --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_colorbar/nonorm_colorbars.svg @@ -0,0 +1,151 @@ + + + + + + + + 2021-12-06T14:23:33.155376 + image/svg+xml + + + Matplotlib v3.6.0.dev954+ged9e9c2ef2.d20211206, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + 2 + + + + + + + + + + 3 + + + + + + + + + + 4 + + + + + + + + + + + + + + + diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index 1521e0c5ed74..c6d021a1e8c9 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -7,10 +7,11 @@ from matplotlib import rc_context from matplotlib.testing.decorators import image_comparison import matplotlib.pyplot as plt -from matplotlib.colors import BoundaryNorm, LogNorm, PowerNorm, Normalize +from matplotlib.colors import ( + BoundaryNorm, LogNorm, PowerNorm, Normalize, NoNorm +) from matplotlib.colorbar import Colorbar from matplotlib.ticker import FixedLocator - from matplotlib.testing.decorators import check_figures_equal @@ -913,3 +914,18 @@ def test_negative_boundarynorm(): cb = fig.colorbar(cm.ScalarMappable(cmap=cmap, norm=norm), cax=ax) np.testing.assert_allclose(cb.ax.get_ylim(), [clevs[0], clevs[-1]]) np.testing.assert_allclose(cb.ax.get_yticks(), clevs) + + +@image_comparison(['nonorm_colorbars.svg'], remove_text=False, + style='mpl20') +def test_nonorm(): + plt.rcParams['svg.fonttype'] = 'none' + data = [1, 2, 3, 4, 5] + + fig, ax = plt.subplots(figsize=(6, 1)) + fig.subplots_adjust(bottom=0.5) + + norm = NoNorm(vmin=min(data), vmax=max(data)) + cmap = cm.get_cmap("viridis", len(data)) + mappable = cm.ScalarMappable(norm=norm, cmap=cmap) + cbar = fig.colorbar(mappable, cax=ax, orientation="horizontal")