Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/matplotlib/colorbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,8 @@ def remove(self):

try:
ax = self.mappable.axes
if ax is None:
return
except AttributeError:
return
try:
Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/colorizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,8 @@ def _ensure_norm(norm, n_components=1):
_api.check_isinstance((colors.MultiNorm, None, tuple), norm=norm)
if norm is None:
norm = colors.MultiNorm(['linear']*n_components)
else: # iterable, i.e. multiple strings or Normalize objects
elif not isinstance(norm, colors.MultiNorm):
# iterable, i.e. multiple strings or Normalize objects
norm = colors.MultiNorm(norm)
if isinstance(norm, colors.MultiNorm) and norm.n_components == n_components:
return norm
Expand Down
7 changes: 6 additions & 1 deletion lib/matplotlib/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -3575,11 +3575,16 @@ def autoscale_None(self, A):
- If structured array, must have `n_components` fields. Each field
is used for the limits of one constituent norm.
"""
changed = False
with self.callbacks.blocked():
A = self._iterable_components_in_data(A, self.n_components)
for n, a in zip(self.norms, A):
vmin, vmax = n.vmin, n.vmax
n.autoscale_None(a)
self._changed()
if vmin != n.vmin or vmax != n.vmax:
changed = True
if changed:
self._changed()

def scaled(self):
"""Return whether both *vmin* and *vmax* are set on all constituent norms."""
Expand Down
15 changes: 15 additions & 0 deletions lib/matplotlib/tests/test_colorbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1254,3 +1254,18 @@ def test_colorbar_format_string_and_old():
plt.imshow([[0, 1]])
cb = plt.colorbar(format="{x}%")
assert isinstance(cb._formatter, StrMethodFormatter)


def test_remove_colorbar_with_no_mappable():
fig, ax = plt.subplots()
cb = mpl.colorbar.Colorbar(ax)
cb.remove()


def test_cbar_wrong_figures():
fig0, ax0 = plt.subplots()
fig1, ax1 = plt.subplots()
im0 = ax0.imshow([[0, 1], [2, 3]])
im1 = ax1.imshow([[0, 1], [2, 3]])
with pytest.raises(ValueError, match="not all parents share"):
fig0.colorbar(im0, ax=[im0, im1])
19 changes: 19 additions & 0 deletions lib/matplotlib/tests/test_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,25 @@ def test_colorizer_multinorm_explicit():
assert_array_almost_equal(ca.to_rgba(data), res)


def test_colorizer_multinorm_instance():
# An existing MultiNorm is used as is, not wrapped in a new MultiNorm.
norm = mcolors.MultiNorm(['linear', 'log'])
ca = mcolorizer.Colorizer('BiOrangeBlue', norm)
assert ca.norm is norm


def test_multi_norm_autoscale_none_only_signals_change():
norm = mcolors.MultiNorm(['linear', 'linear'])
calls = []
norm.callbacks.connect('changed', lambda: calls.append(True))
data = [[0, 1, 2], [3, 4, 5]]
norm.autoscale_None(data)
assert len(calls) == 1
# limits are already set, so nothing changes and no signal is emitted
norm.autoscale_None(data)
assert len(calls) == 1


def test_get_set_clim_raises():
fig, ax = plt.subplots(1, 1)
x_0 = np.arange(9, dtype='float32').reshape(3, 3)
Expand Down
Loading