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

Skip to content

Commit 2dde636

Browse files
committed
FIX: Update the callback in scalar mappable on norm change
When changing a ScalarMappable's norm, the previous norm callback wasn't being removed and updated with the new one. This adds that capability to the norm setter.
1 parent 89f8a7f commit 2dde636

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

lib/matplotlib/cm.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,13 @@ def __init__(self, norm=None, cmap=None):
257257
The colormap used to map normalized data values to RGBA colors.
258258
"""
259259
self._A = None
260-
self.norm = None # So that the setter knows we're initializing.
260+
self._norm = None # So that the setter knows we're initializing.
261261
self.set_norm(norm) # The Normalize instance of this ScalarMappable.
262262
self.cmap = None # So that the setter knows we're initializing.
263263
self.set_cmap(cmap) # The Colormap instance of this ScalarMappable.
264264
#: The last colorbar associated with this ScalarMappable. May be None.
265265
self.colorbar = None
266266
self.callbacksSM = cbook.CallbackRegistry()
267-
# Connect to the Norm's callback
268-
self._id_norm = self.norm.callbacksNorm.connect('changed',
269-
self.changed)
270267

271268
def _scale_norm(self, norm, vmin, vmax):
272269
"""
@@ -454,6 +451,30 @@ def set_cmap(self, cmap):
454451
if not in_init:
455452
self.changed() # Things are not set up properly yet.
456453

454+
@property
455+
def norm(self):
456+
return self._norm
457+
458+
@norm.setter
459+
def norm(self, norm):
460+
_api.check_isinstance((colors.Normalize, None), norm=norm)
461+
if norm is None:
462+
norm = colors.Normalize()
463+
464+
if norm is self.norm:
465+
# We aren't updating anything
466+
return
467+
468+
in_init = self.norm is None
469+
# Remove the current callback and connect to the new one
470+
if not in_init:
471+
self.norm.callbacksNorm.disconnect(self._id_norm)
472+
self._norm = norm
473+
self._id_norm = self.norm.callbacksNorm.connect('changed',
474+
self.changed)
475+
if not in_init:
476+
self.changed()
477+
457478
def set_norm(self, norm):
458479
"""
459480
Set the normalization instance.
@@ -468,13 +489,7 @@ def set_norm(self, norm):
468489
the norm of the mappable will reset the norm, locator, and formatters
469490
on the colorbar to default.
470491
"""
471-
_api.check_isinstance((colors.Normalize, None), norm=norm)
472-
in_init = self.norm is None
473-
if norm is None:
474-
norm = colors.Normalize()
475492
self.norm = norm
476-
if not in_init:
477-
self.changed() # Things are not set up properly yet.
478493

479494
def autoscale(self):
480495
"""

lib/matplotlib/tests/test_colors.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,13 +1450,15 @@ def test_scalarmappable_norm_update():
14501450
norm.clip = True
14511451
assert sm.stale
14521452
# change to the CenteredNorm and TwoSlopeNorm to test those
1453+
# Also make sure that updating the norm directly and with
1454+
# set_norm both update the Norm callback
14531455
norm = mcolors.CenteredNorm()
1454-
sm = matplotlib.cm.ScalarMappable(norm=norm, cmap='plasma')
1456+
sm.norm = norm
14551457
sm.stale = False
14561458
norm.vcenter = 1
14571459
assert sm.stale
14581460
norm = mcolors.TwoSlopeNorm(vcenter=0, vmin=-1, vmax=1)
1459-
sm = matplotlib.cm.ScalarMappable(norm=norm, cmap='plasma')
1461+
sm.set_norm(norm)
14601462
sm.stale = False
14611463
norm.vcenter = 1
14621464
assert sm.stale

0 commit comments

Comments
 (0)