8000 Fix colorbar dividers with explicit limits · matplotlib/matplotlib@930bd2f · GitHub
[go: up one dir, main page]

Skip to content

Commit 930bd2f

Browse files
committed
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).
1 parent 8fa6bd5 commit 930bd2f

File tree

3 files changed

+71
-28
lines changed

3 files changed

+71
-28
lines changed

lib/matplotlib/colorbar.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -651,12 +651,31 @@ def _add_solids(self, X, Y, C):
651651
if not self.drawedges:
652652
if len(self._y) >= self.n_rasterize:
653653
self.solids.set_rasterized(True)
654-
if self.drawedges:
655-
start_idx = 0 if self._extend_lower() else 1
656-
end_idx = len(X) if self._extend_upper() else -1
657-
self.dividers.set_segments(np.dstack([X, Y])[start_idx:end_idx])
658-
else:
654+
self._update_dividers()
655+
656+
def _update_dividers(self):
657+
if not self.drawedges:
659658
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)
660679

661680
def _add_solids_patches(self, X, Y, C, mappable):
662681
hatches = mappable.hatches * len(C) # Have enough hatches.
@@ -761,7 +780,8 @@ def _do_extends(self, ax=None):
761780
zorder=np.nextafter(self.ax.patch.zorder, -np.inf))
762781
self.ax.add_patch(patch)
763782
self._extend_patches.append(patch)
764-
return
783+
784+
self._update_dividers()
765785

766786
def add_lines(self, *args, **kwargs):
767787
"""
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