Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 29da23a

Browse files
authored
Merge pull request #20327 from jklymak/fix-colorbars-with-no-scale
2 parents ee577c5 + d1c5a6a commit 29da23a

File tree

5 files changed

+49
-16
lines changed

5 files changed

+49
-16
lines changed

lib/matplotlib/colorbar.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,24 +1005,34 @@ def _reset_locator_formatter_scale(self):
10051005
self.locator = None
10061006
self.minorlocator = None
10071007
self.formatter = None
1008-
if ((self.spacing == 'uniform') and
1009-
((self.boundaries is not None) or
1010-
isinstance(self.norm, colors.BoundaryNorm))):
1011-
funcs = (self._forward_boundaries, self._inverse_boundaries)
1012-
self.ax.set_xscale('function', functions=funcs)
1013-
self.ax.set_yscale('function', functions=funcs)
1014-
self.__scale = 'function'
1015-
elif hasattr(self.norm, '_scale') and (self.norm._scale is not None):
1008+
if (self.boundaries is not None or
1009+
isinstance(self.norm, colors.BoundaryNorm)):
1010+
if self.spacing == 'uniform':
1011+
funcs = (self._forward_boundaries, self._inverse_boundaries)
1012+
self.ax.set_xscale('function', functions=funcs)
1013+
self.ax.set_yscale('function', functions=funcs)
1014+
self.__scale = 'function'
1015+
elif self.spacing == 'proportional':
1016+
self.__scale = 'linear'
1017+
self.ax.set_xscale('linear')
1018+
self.ax.set_yscale('linear')
1019+
elif hasattr(self.norm, '_scale') and self.norm._scale is not None:
1020+
# use the norm's scale:
10161021
self.ax.set_xscale(self.norm._scale)
10171022
self.ax.set_yscale(self.norm._scale)
10181023
self.__scale = self.norm._scale.name
1019-
else:
1024+
elif type(self.norm) is colors.Normalize:
1025+
# plain Normalize:
10201026
self.ax.set_xscale('linear')
10211027
self.ax.set_yscale('linear')
1022-
if type(self.norm) is colors.Normalize:
1023-
self.__scale = 'linear'
1024-
else:
1025-
self.__scale = 'manual'
1028+
self.__scale = 'linear'
1029+
else:
1030+
# norm._scale is None or not an attr: derive the scale from
1031+
# the Norm:
1032+
funcs = (self.norm, self.norm.inverse)
1033+
self.ax.set_xscale('function', functions=funcs)
1034+
self.ax.set_yscale('function', functions=funcs)
1035+
self.__scale = 'function'
10261036

10271037
def _locate(self, x):
10281038
"""

lib/matplotlib/colors.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ def __init__(self, vmin=None, vmax=None, clip=False):
11261126
self.vmin = _sanitize_extrema(vmin)
11271127
self.vmax = _sanitize_extrema(vmax)
11281128
self.clip = clip
1129-
self._scale = scale.LinearScale(axis=None)
1129+
self._scale = None # will default to LinearScale for colorbar
11301130

11311131
@staticmethod
11321132
def process_value(value):
@@ -1308,6 +1308,16 @@ def __call__(self, value, clip=None):
13081308
result = np.atleast_1d(result)[0]
13091309
return result
13101310

1311+
def inverse(self, value):
1312+
if not self.scaled():
1313+
raise ValueError("Not invertible until both vmin and vmax are set")
1314+
(vmin,), _ = self.process_value(self.vmin)
1315+
(vmax,), _ = self.process_value(self.vmax)
1316+
(vcenter,), _ = self.process_value(self.vcenter)
1317+
1318+
result = np.interp(value, [0, 0.5, 1.], [vmin, vcenter, vmax])
1319+
return result
1320+
13111321

13121322
class CenteredNorm(Normalize):
13131323
def __init__(self, vcenter=0, halfrange=None, clip=False):

lib/matplotlib/tests/test_colorbar.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,3 +771,17 @@ def test_inset_colorbar_layout():
771771
np.testing.assert_allclose(cb.ax.get_position().bounds,
772772
[0.87, 0.342, 0.0237, 0.315], atol=0.01)
773773
assert cb.ax.outer_ax in ax.child_axes
774+
775+
776+
@image_comparison(['colorbar_twoslope.png'], remove_text=True,
777+
style='mpl20')
778+
def test_twoslope_colorbar():
779+
# Note that the first tick = 20, and should be in the middle
780+
# of the colorbar (white)
781+
fig, ax = plt.subplots()
782+
783+
norm = mcolors.TwoSlopeNorm(20, 0, 100)
784+
pc = ax.pcolormesh(np.arange(1, 11), np.arange(1, 11),
785+
np.arange(100).reshape(10, 10),
786+
norm=norm, cmap='RdBu_r')
787+
fig.colorbar(pc)

lib/matplotlib/tests/test_colors.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,5 @@ def test_norm_deepcopy():
14061406
norm = mcolors.Normalize()
14071407
norm.vmin = 0.0002
14081408
norm2 = copy.deepcopy(norm)
1409-
assert isinstance(norm2._scale, mscale.LinearScale)
1409+
assert norm2._scale is None
14101410
assert norm2.vmin == norm.vmin
1411-
assert norm2._scale is not norm._scale

0 commit comments

Comments
 (0)