From 8fa6bd536f68cd76fd926e81d8f175f3d3b0076f Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 3 Aug 2022 21:40:59 -0400 Subject: [PATCH 1/2] Don't clip colorbar dividers They are sometimes right on the edge of the Axes, and the last (or possibly first) don't get drawn due to clipping. Because the divider line width is the same as the Axes frame line width, we don't have to worry about it going outside when unclipped. Fixes #22864 --- lib/matplotlib/colorbar.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index b790390ee2f7..a46c410c7b2b 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -434,7 +434,8 @@ def __init__(self, ax, mappable=None, *, cmap=None, self.dividers = collections.LineCollection( [], colors=[mpl.rcParams['axes.edgecolor']], - linewidths=[0.5 * mpl.rcParams['axes.linewidth']]) + linewidths=[0.5 * mpl.rcParams['axes.linewidth']], + clip_on=False) self.ax.add_collection(self.dividers) self._locator = None From 930bd2f031617e18225f319121ded60daa1c54cd Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 9 Aug 2022 00:05:58 -0400 Subject: [PATCH 2/2] Fix colorbar dividers with explicit limits In this case, place dividers at the same place internally, but then always place a divider at the Axes limits (when there's an extend triangle there). --- lib/matplotlib/colorbar.py | 32 +++++++-- .../test_colorbar/extend_drawedges.png | Bin 0 -> 16748 bytes lib/matplotlib/tests/test_colorbar.py | 67 ++++++++++++------ 3 files changed, 71 insertions(+), 28 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_colorbar/extend_drawedges.png diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index a46c410c7b2b..3c5f71fcad06 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -651,12 +651,31 @@ def _add_solids(self, X, Y, C): if not self.drawedges: if len(self._y) >= self.n_rasterize: self.solids.set_rasterized(True) - if self.drawedges: - start_idx = 0 if self._extend_lower() else 1 - end_idx = len(X) if self._extend_upper() else -1 - self.dividers.set_segments(np.dstack([X, Y])[start_idx:end_idx]) - else: + self._update_dividers() + + def _update_dividers(self): + if not self.drawedges: self.dividers.set_segments([]) + return + # Place all *internal* dividers. + if self.orientation == 'vertical': + lims = self.ax.get_ylim() + bounds = (lims[0] < self._y) & (self._y < lims[1]) + else: + lims = self.ax.get_xlim() + bounds = (lims[0] < self._y) & (self._y < lims[1]) + y = self._y[bounds] + # And then add outer dividers if extensions are on. + if self._extend_lower(): + y = np.insert(y, 0, lims[0]) + if self._extend_upper(): + y = np.append(y, lims[1]) + X, Y = np.meshgrid([0, 1], y) + if self.orientation == 'vertical': + segments = np.dstack([X, Y]) + else: + segments = np.dstack([Y, X]) + self.dividers.set_segments(segments) def _add_solids_patches(self, X, Y, C, mappable): hatches = mappable.hatches * len(C) # Have enough hatches. @@ -761,7 +780,8 @@ def _do_extends(self, ax=None): zorder=np.nextafter(self.ax.patch.zorder, -np.inf)) self.ax.add_patch(patch) self._extend_patches.append(patch) - return + + self._update_dividers() def add_lines(self, *args, **kwargs): """ diff --git a/lib/matplotlib/tests/baseline_images/test_colorbar/extend_drawedges.png b/lib/matplotlib/tests/baseline_images/test_colorbar/extend_drawedges.png new file mode 100644 index 0000000000000000000000000000000000000000..864eeefbae10c1d13a5e050777accff8eceb1da4 GIT binary patch literal 16748 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 Sqg&|fu~G`Rvv1yi^1lE!^I(7g literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index 50f3498d12dc..2dd9692dc2e3 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -931,28 +931,51 @@ def test_proportional_colorbars(): fig.colorbar(CS3, spacing=spacings[j], ax=axs[i, j]) -@pytest.mark.parametrize("extend, coloroffset, res", [ - ('both', 1, [np.array([[0., 0.], [0., 1.]]), - np.array([[1., 0.], [1., 1.]]), - np.array([[2., 0.], [2., 1.]])]), - ('min', 0, [np.array([[0., 0.], [0., 1.]]), - np.array([[1., 0.], [1., 1.]])]), - ('max', 0, [np.array([[1., 0.], [1., 1.]]), - np.array([[2., 0.], [2., 1.]])]), - ('neither', -1, [np.array([[1., 0.], [1., 1.]])]) - ]) -def test_colorbar_extend_drawedges(extend, coloroffset, res): - cmap = plt.get_cmap("viridis") - bounds = np.arange(3) - nb_colors = len(bounds) + coloroffset - colors = cmap(np.linspace(100, 255, nb_colors).astype(int)) - cmap, norm = mcolors.from_levels_and_colors(bounds, colors, extend=extend) - - plt.figure(figsize=(5, 1)) - ax = plt.subplot(111) - cbar = Colorbar(ax, cmap=cmap, norm=norm, orientation='horizontal', - drawedges=True) - assert np.all(np.equal(cbar.dividers.get_segments(), res)) +@image_comparison(['extend_drawedges.png'], remove_text=True, style='mpl20') +def test_colorbar_extend_drawedges(): + params = [ + ('both', 1, [[[1.1, 0], [1.1, 1]], + [[2, 0], [2, 1]], + [[2.9, 0], [2.9, 1]]]), + ('min', 0, [[[1.1, 0], [1.1, 1]], + [[2, 0], [2, 1]]]), + ('max', 0, [[[2, 0], [2, 1]], + [[2.9, 0], [2.9, 1]]]), + ('neither', -1, [[[2, 0], [2, 1]]]), + ] + + plt.rcParams['axes.linewidth'] = 2 + + fig = plt.figure(figsize=(10, 4)) + subfigs = fig.subfigures(1, 2) + + for orientation, subfig in zip(['horizontal', 'vertical'], subfigs): + if orientation == 'horizontal': + axs = subfig.subplots(4, 1) + else: + axs = subfig.subplots(1, 4) + fig.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95) + + for ax, (extend, coloroffset, res) in zip(axs, params): + cmap = plt.get_cmap("viridis") + bounds = np.arange(5) + nb_colors = len(bounds) + coloroffset + colors = cmap(np.linspace(100, 255, nb_colors).astype(int)) + cmap, norm = mcolors.from_levels_and_colors(bounds, colors, + extend=extend) + + cbar = Colorbar(ax, cmap=cmap, norm=norm, orientation=orientation, + drawedges=True) + # Set limits such that only two colours are visible, and the + # dividers would be outside the Axes, to ensure that a) they are + # not drawn outside, and b) a divider still appears between the + # main colour and the extension. + if orientation == 'horizontal': + ax.set_xlim(1.1, 2.9) + else: + ax.set_ylim(1.1, 2.9) + res = np.array(res)[:, :, [1, 0]] + np.testing.assert_array_equal(cbar.dividers.get_segments(), res) def test_negative_boundarynorm():