8000 Merge pull request #23549 from QuLogic/colorbar-dividers · matplotlib/matplotlib@8a495e9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8a495e9

Browse files
authored
Merge pull request #23549 from QuLogic/colorbar-dividers
FIX: Don't clip colorbar dividers
2 parents 149a039 + 930bd2f commit 8a495e9

File tree

3 files changed

+73
-29
lines changed

3 files changed

+73
-29
lines changed

lib/matplotlib/colorbar.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,8 @@ def __init__(self, ax, mappable=None, *, cmap=None,
434434
self.dividers = collections.LineCollection(
435435
[],
436436
colors=[mpl.rcParams['axes.edgecolor']],
437-
linewidths=[0.5 * mpl.rcParams['axes.linewidth']])
437+
linewidths=[0.5 * mpl.rcParams['axes.linewidth']],
438+
clip_on=False)
438439
self.ax.add_collection(self.dividers)
439440

440441
self._locator = None
@@ -650,12 +651,31 @@ def _add_solids(self, X, Y, C):
650651
if not self.drawedges:
651652
if len(self._y) >= self.n_rasterize:
652653
self.solids.set_rasterized(True)
653-
if self.drawedges:
654-
start_idx = 0 if self._extend_lower() else 1
655-
end_idx = len(X) if self._extend_upper() else -1
656-
self.dividers.set_segments(np.dstack([X, Y])[start_idx:end_idx])
657-
else:
654+
self._update_dividers()
655+
656+
def _update_dividers(self):
657+
if not self.drawedges:
658658
self.dividers.set_segments([])
659+
return
660+
# Place all *internal* dividers.
661+
if self.orientation == 'vertical':
662+
lims = self.ax.get_ylim()
663+
bounds = (lims[0] < self._y) & (self._y < lims[1])
664+
else:
665+
lims = self.ax.get_xlim()
666+
bounds = (lims[0] < self._y) & (self._y < lims[1])
667+
y = self._y[bounds]
668+
# And then add outer dividers if extensions are on.
669+
if self._extend_lower():
670+
y = np.insert(y, 0, lims[0])
671+
if self._extend_upper():
672+
y = np.append(y, lims[1])
673+
X, Y = np.meshgrid([0, 1], y)
674+
if self.orientation == 'vertical':
675+
segments = np.dstack([X, Y])
676+
else:
677+
segments = np.dstack([Y, X])
678+
self.dividers.set_segments(segments)
659679

660680
def _add_solids_patches(self, X, Y, C, mappable):
661681
hatches = mappable.hatches * len(C) # Have enough hatches.
@@ -760,7 +780,8 @@ def _do_extends(self, ax=None):
760780
zorder=np.nextafter(self.ax.patch.zorder, -np.inf))
761781
self.ax.add_patch(patch)
762782
self._extend_patches.append(patch)
763-
return
783+
784+
self._update_dividers()
764785

765786
def add_lines(self, *args, **kwargs):
766787
"""
Loading

lib/matplotlib/tests/test_colorbar.py

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -931,28 +931,51 @@ def test_proportional_colorbars():
931931
fig.colorbar(CS3, spacing=spacings[j], ax=axs[i, j])
932932

933933

934-
@pytest.mark.parametrize("extend, coloroffset, res", [
935-
('both', 1, [np.array([[0., 0.], [0., 1.]]),
936-
np.array([[1., 0.], [1., 1.]]),
937-
np.array([[2., 0.], [2., 1.]])]),
938-
('min', 0, [np.array([[0., 0.], [0., 1.]]),
939-
np.array([[1., 0.], [1., 1.]])]),
940-
('max', 0, [np.array([[1., 0.], [1., 1.]]),
941-
np.array([[2., 0.], [2., 1.]])]),
942-
('neither', -1, [np.array([[1., 0.], [1., 1.]])])
943-
])
944-
def test_colorbar_extend_drawedges(extend, coloroffset, res):
945-
cmap = plt.get_cmap("viridis")
946-
bounds = np.arange(3)
947-
nb_colors = len(bounds) + coloroffset
948-
colors = cmap(np.linspace(100, 255, nb_colors).astype(int))
949-
cmap, norm = mcolors.from_levels_and_colors(bounds, colors, extend=extend)
950-
951-
plt.figure(figsize=(5, 1))
952-
ax = plt.subplot(111)
953-
cbar = Colorbar(ax, cmap=cmap, norm=norm, orientation='horizontal',
954-
drawedges=True)
955-
assert np.all(np.equal(cbar.dividers.get_segments(), res))
934+
@image_comparison(['extend_drawedges.png'], remove_text=True, style='mpl20')
935+
def test_colorbar_extend_drawedges():
936+
params = [
937+
('both', 1, [[[1.1, 0], [1.1, 1]],
938+
[[2, 0], [2, 1]],
939+
[[2.9, 0], [2.9, 1]]]),
940+
('min', 0, [[[1.1, 0], [1.1, 1]],
941+
[[2, 0], [2, 1]]]),
942+
('max', 0, [[[2, 0], [2, 1]],
943+
[[2.9, 0], [2.9, 1]]]),
944+
('neither', -1, [[[2, 0], [2, 1]]]),
945+
]
946+
947+
plt.rcParams['axes.linewidth'] = 2
948+
949+
fig = plt.figure(figsize=(10, 4))
950+
subfigs = fig.subfigures(1, 2)
951+
952+
for orientation, subfig in zip(['horizontal', 'vertical'], subfigs):
953+
if orientation == 'horizontal':
954+
axs = subfig.subplots(4, 1)
955+
else:
956+
axs = subfig.subplots(1, 4)
957+
fig.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95)
958+
959+
for ax, (extend, coloroffset, res) in zip(axs, params):
960+
cmap = plt.get_cmap("viridis")
961+
bounds = np.arange(5)
962+
nb_colors = len(bounds) + coloroffset
963+
colors = cmap(np.linspace(100, 255, nb_colors).astype(int))
964+
cmap, norm = mcolors.from_levels_and_colors(bounds, colors,
965+
extend=extend)
966+
967+
cbar = Colorbar(ax, cmap=cmap, norm=norm, orientation=orientation,
968+
drawedges=True)
969+
# Set limits such that only two colours are visible, and the
970+
# dividers would be outside the Axes, to ensure that a) they are
971+
# not drawn outside, and b) a divider still appears between the
972+
# main colour and the extension.
973+
if orientation == 'horizontal':
974+
ax.set_xlim(1.1, 2.9)
975+
else:
976+
ax.set_ylim(1.1, 2.9)
977+
res = np.array(res)[:, :, [1, 0]]
978+
np.testing.assert_array_equal(cbar.dividers.get_segments(), res)
956979

957980

958981
def test_negative_boundarynorm():

0 commit comments

Comments
 (0)
0