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

Skip to content

Commit 9ef1caa

Browse files
committed
FIX: fix twoslope norm for colorbars
1 parent 8fec6ea commit 9ef1caa

File tree

4 files changed

+29
-10
lines changed

4 files changed

+29
-10
lines changed

lib/matplotlib/colors.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,9 +1300,13 @@ def __call__(self, value, clip=None):
13001300

13011301
if not self.vmin <= self.vcenter <= self.vmax:
13021302
raise ValueError("vmin, vcenter, vmax must increase monotonically")
1303+
# must linearly extrapolate for ticks on colorbars that go
1304+
# beyond vmin and vmax:
1305+
min = self.vmin - (self.vcenter - self.vmin)
1306+
max = self.vmax + (self.vmax - self.vcenter)
13031307
result = np.ma.masked_array(
1304-
np.interp(result, [self.vmin, self.vcenter, self.vmax],
1305-
[0, 0.5, 1.]), mask=np.ma.getmask(result))
1308+
np.interp(result, [min, self.vcenter, max],
1309+
[-0.5, 0.5, 1.5]), mask=np.ma.getmask(result))
13061310
if is_scalar:
13071311
result = np.atleast_1d(result)[0]
13081312
return result
@@ -1313,8 +1317,9 @@ def inverse(self, value):
13131317
(vmin,), _ = self.process_value(self.vmin)
13141318
(vmax,), _ = self.process_value(self.vmax)
13151319
(vcenter,), _ = self.process_value(self.vcenter)
1316-
1317-
result = np.interp(value, [0, 0.5, 1.], [vmin, vcenter, vmax])
1320+
min = vmin - (vcenter - vmin)
1321+
max = vmax + (vmax - vcenter)
1322+
result = np.interp(value, [-0.5, 0.5, 1.5], [min, vcenter, max])
13181323
return result
13191324

13201325

lib/matplotlib/tests/test_colorbar.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -776,11 +776,12 @@ def test_inset_colorbar_layout():
776776
@image_comparison(['colorbar_twoslope.png'], remove_text=True,
777777
style='mpl20')
778778
def test_twoslope_colorbar():
779-
# Note that the first tick = 20, and should be in the middle
779+
# Note that the second tick = 20, and should be in the middle
780780
# of the colorbar (white)
781+
# There should be no tick right at the bottom, nor at the top.
781782
fig, ax = plt.subplots()
782783

783-
norm = mcolors.TwoSlopeNorm(20, 0, 100)
784+
norm = mcolors.TwoSlopeNorm(20, 5, 95)
784785
pc = ax.pcolormesh(np.arange(1, 11), np.arange(1, 11),
785786
np.arange(100).reshape(10, 10),
786787
norm=norm, cmap='RdBu_r')

tutorials/colors/colormapnorms.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@
277277
# longitude depends on latitude.
278278
ax.set_aspect(1 / np.cos(np.deg2rad(49)))
279279
ax.set_title('TwoSlopeNorm(x)')
280-
fig.colorbar(pcm, shrink=0.6)
280+
cb = fig.colorbar(pcm, shrink=0.6)
281+
cb.set_ticks([-500, 0, 1000, 2000, 3000, 4000])
281282
plt.show()
282283

283284

@@ -312,7 +313,8 @@ def _inverse(x):
312313
# ----------------------------------------------------------
313314
#
314315
# The `.TwoSlopeNorm` described above makes a useful example for
315-
# defining your own norm.
316+
# defining your own norm. Note for the colorbar to work, you must
317+
# define an inverse for your norm:
316318

317319

318320
class MidpointNormalize(colors.Normalize):
@@ -323,9 +325,18 @@ def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
323325
def __call__(self, value, clip=None):
324326
# I'm ignoring masked values and all kinds of edge cases to make a
325327
# simple example...
326-
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
328+
# Note also that we must extrapolate linearly beyond vmin/vmax
329+
min = self.vmin - (self.vcenter - self.vmin)
330+
max = self.vmax + (self.vmax - self.vcenter)
331+
x, y = [min, self.vcenter, max], [-0.5, 0.5, 1.5]
327332
return np.ma.masked_array(np.interp(value, x, y))
328333

334+
def inverse(self, value):
335+
min = self.vmin - (self.vcenter - self.vmin)
336+
max = self.vmax + (self.vmax - self.vcenter)
337+
y, x = [min, self.vcenter, max], [-0.5, 0.5, 1.5]
338+
return np.interp(value, x, y)
339+
329340

330341
fig, ax = plt.subplots()
331342
midnorm = MidpointNormalize(vmin=-500., vcenter=0, vmax=4000)
@@ -334,5 +345,7 @@ def __call__(self, value, clip=None):
334345
cmap=terrain_map, shading='auto')
335346
ax.set_aspect(1 / np.cos(np.deg2rad(49)))
336347
ax.set_title('Custom norm')
337-
fig.colorbar(pcm, shrink=0.6, extend='both')
348+
cb = fig.colorbar(pcm, shrink=0.6, extend='both')
349+
cb.set_ticks([-500, 0, 1000, 2000, 3000, 4000])
350+
338351
plt.show()

0 commit comments

Comments
 (0)