8000 FIX: CenteredNorm use vmin/vmax for halfrange · matplotlib/matplotlib@ff2811b · GitHub
[go: up one dir, main page]

Skip to content

Commit ff2811b

Browse files
committed
FIX: CenteredNorm use vmin/vmax for halfrange
This changes CenteredNorm to use vmin and vmax to represent the halfrange rather than storing it separately and needing to update the vmin/vmax in all of the methods. Additionally, if you now change vcenter, the halfrange does not automatically update.
1 parent 8cf9fc1 commit ff2811b

File tree

3 files changed

+26
-30
lines changed

3 files changed

+26
-30
lines changed

lib/matplotlib/colors.py

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,26 +1518,18 @@ def __init__(self, vcenter=0, halfrange=None, clip=False):
15181518
# calling the halfrange setter to set vmin and vmax
15191519
self.halfrange = halfrange
15201520

1521-
def _set_vmin_vmax(self):
1522-
"""
1523-
Set *vmin* and *vmax* based on *vcenter* and *halfrange*.
1524-
"""
1525-
self.vmax = self._vcenter + self._halfrange
1526-
self.vmin = self._vcenter - self._halfrange
1527-
15281521
def autoscale(self, A):
15291522
"""
15301523
Set *halfrange* to ``max(abs(A-vcenter))``, then set *vmin* and *vmax*.
15311524
"""
15321525
A = np.asanyarray(A)
1533-
self._halfrange = max(self._vcenter-A.min(),
1534-
A.max()-self._vcenter)
1535-
self._set_vmin_vmax()
1526+
self.halfrange = max(self._vcenter-A.min(),
1527+
A.max()-self._vcenter)
15361528

15371529
def autoscale_None(self, A):
15381530
"""Set *vmin* and *vmax*."""
15391531
A = np.asanyarray(A)
1540-
if self._halfrange is None and A.size:
1532+
if self.halfrange is None and A.size:
15411533
self.autoscale(A)
15421534

15431535
@property
@@ -1548,32 +1540,24 @@ def vcenter(self):
15481540
def vcenter(self, vcenter):
15491541
if vcenter != self._vcenter:
15501542
self._vcenter = vcenter
1543+
# Trigger an update of the vmin/vmax values through the setter
1544+
self.halfrange = self.halfrange
15511545
self._changed()
1552-
if self.vmax is not None:
1553-
# recompute halfrange assuming vmin and vmax represent
1554-
# min and max of data
1555-
self._halfrange = max(self._vcenter-self.vmin,
1556-
self.vmax-self._vcenter)
1557-
self._set_vmin_vmax()
15581546

15591547
@property
15601548
def halfrange(self):
1561-
return self._halfrange
1549+
if self.vmin is None or self.vmax is None:
1550+
return None
1551+
return (self.vmax - self.vmin) / 2
15621552

15631553
@halfrange.setter
15641554
def halfrange(self, halfrange):
15651555
if halfrange is None:
1566-
self._halfrange = None
15671556
self.vmin = None
15681557
self.vmax = None
15691558
else:
1570-
self._halfrange = abs(halfrange)
1571-
1572-
def __call__(self, value, clip=None):
1573-
if self._halfrange is not None:
1574-
# enforce symmetry, reset vmin and vmax
1575-
self._set_vmin_vmax()
1576-
return super().__call__(value, clip=clip)
1559+
self.vmin = self.vcenter - abs(halfrange)
1560+
self.vmax = self.vcenter + abs(halfrange)
15771561

15781562

15791563
def make_norm_from_scale(scale_cls, base_norm_cls=None, *, init=None):

lib/matplotlib/tests/test_colorbar.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,17 @@ def test_negative_boundarynorm():
10601060
np.testing.assert_allclose(cb.ax.get_yticks(), clevs)
10611061

10621062

1063+
def test_centerednorm():
1064+
# Test default centered norm gets expanded with non-singular limits
1065+
# when plot data is all equal (autoscale halfrange == 0)
1066+
fig, ax = plt.subplots(figsize=(1, 3))
1067+
1068+
norm = mcolors.CenteredNorm()
1069+
mappable = ax.pcolormesh(np.zeros((3, 3)), norm=norm)
1070+
fig.colorbar(mappable)
1071+
assert (norm.vmin, norm.vmax) == (-0.1, 0.1)
1072+
1073+
10631074
@image_comparison(['nonorm_colorbars.svg'], style='mpl20')
10641075
def test_nonorm():
10651076
plt.rcParams['svg.fonttype'] = 'none'

lib/matplotlib/tests/test_colors.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,11 +485,12 @@ def test_CenteredNorm():
485485
norm(np.linspace(-1.0, 0.0, 10))
486486
assert norm.vmax == 1.0
487487
assert norm.halfrange == 1.0
488-
# set vcenter to 1, which should double halfrange
488+
# set vcenter to 1, which should move the center but leave the
489+
# halfrange unchanged
489490
norm.vcenter = 1
490-
assert norm.vmin == -1.0
491-
assert norm.vmax == 3.0
492-
assert norm.halfrange == 2.0
491+
assert norm.vmin == 0
492+
assert norm.vmax == 2
493+
assert norm.halfrange == 1
493494

494495

495496
@pytest.mark.parametrize("vmin,vmax", [[-1, 2], [3, 1]])

0 commit comments

Comments
 (0)
0