Skip to content

Commit

Permalink
Merge pull request #23549 from QuLogic/colorbar-dividers
Browse files Browse the repository at this point in the history
FIX: Don't clip colorbar dividers
  • Loading branch information
tacaswell committed Aug 9, 2022
2 parents 149a039 + 930bd2f commit 8a495e9
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 29 deletions.
35 changes: 28 additions & 7 deletions lib/matplotlib/colorbar.py
Expand Up @@ -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
Expand Down Expand Up @@ -650,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.
Expand Down Expand Up @@ -760,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):
"""
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 45 additions & 22 deletions lib/matplotlib/tests/test_colorbar.py
Expand Up @@ -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():
Expand Down

0 comments on commit 8a495e9

Please sign in to comment.