1515 normalization.
1616"""
1717
18+ from collections .abc import MutableMapping
1819import functools
1920
2021import numpy as np
@@ -49,7 +50,7 @@ def revcmap(data):
4950LUTSIZE = mpl .rcParams ['image.lut' ]
5051
5152
52- def _gen_cmap_d ():
53+ def _gen_cmap_registry ():
5354 """
5455 Generate a dict mapping standard colormap names to standard colormaps, as
5556 well as the reversed colormaps.
@@ -65,12 +66,56 @@ def _gen_cmap_d():
6566 # Generate reversed cmaps.
6667 for cmap in list (cmap_d .values ()):
6768 rmap = cmap .reversed ()
69+ cmap ._global = True
70+ rmap ._global = True
6871 cmap_d [rmap .name ] = rmap
6972 return cmap_d
7073
7174
72- cmap_d = _gen_cmap_d ()
73- locals ().update (cmap_d )
75+ class _DeprecatedCmapDictWrapper (MutableMapping ):
76+ """Dictionary mapping for deprecated _cmap_d access."""
77+
78+ def __init__ (self , cmap_registry ):
79+ self ._cmap_registry = cmap_registry
80+
81+ def __delitem__ (self , key ):
82+ self ._warn_deprecated ()
83+ self ._cmap_registry .__delitem__ (key )
84+
85+ def __getitem__ (self , key ):
86+ self ._warn_deprecated ()
87+ return self ._cmap_registry .__getitem__ (key )
88+
89+ def __iter__ (self ):
90+ self ._warn_deprecated ()
91+ return self ._cmap_registry .__iter__ ()
92+
93+ def __len__ (self ):
94+ self ._warn_deprecated ()
95+ return self ._cmap_registry .__len__ ()
96+
97+ def __setitem__ (self , key , val ):
98+ self ._warn_deprecated ()
99+ self ._cmap_registry .__setitem__ (key , val )
100+
101+ def get (self , key , default = None ):
102+ self ._warn_deprecated ()
103+ return self ._cmap_registry .get (key , default )
104+
105+ def _warn_deprecated (self ):
106+ cbook .warn_deprecated (
107+ "3.3" ,
108+ message = "The global colormaps dictionary is no longer "
109+ "considered public API." ,
110+ alternative = "Please use register_cmap() and get_cmap() to "
111+ "access the contents of the dictionary."
112+ )
113+
114+
115+ _cmap_registry = _gen_cmap_registry ()
116+ locals ().update (_cmap_registry )
117+ # This is no longer considered public API
118+ cmap_d = _DeprecatedCmapDictWrapper (_cmap_registry )
74119
75120
76121# Continue with definitions ...
@@ -95,6 +140,13 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
95140 and the resulting colormap is registered. Instead of this implicit
96141 colormap creation, create a `.LinearSegmentedColormap` and use the first
97142 case: ``register_cmap(cmap=LinearSegmentedColormap(name, data, lut))``.
143+
144+ Notes
145+ -----
146+ Registering a colormap stores a reference to the colormap object
147+ which can currently be modified and inadvertantly change the global
148+ colormap state. This behavior is deprecated and in Matplotlib 3.5
149+ the registered colormap will be immutable.
98150 """
99151 cbook ._check_isinstance ((str , None ), name = name )
100152 if name is None :
@@ -104,7 +156,8 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
104156 raise ValueError ("Arguments must include a name or a "
105157 "Colormap" ) from err
106158 if isinstance (cmap , colors .Colormap ):
107- cmap_d [name ] = cmap
159+ cmap ._global = True
160+ _cmap_registry [name ] = cmap
108161 return
109162 if lut is not None or data is not None :
110163 cbook .warn_deprecated (
@@ -117,7 +170,8 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
117170 if lut is None :
118171 lut = mpl .rcParams ['image.lut' ]
119172 cmap = colors .LinearSegmentedColormap (name , data , lut )
120- cmap_d [name ] = cmap
173+ cmap ._global = True
174+ _cmap_registry [name ] = cmap
121175
122176
123177def get_cmap (name = None , lut = None ):
@@ -127,11 +181,17 @@ def get_cmap(name=None, lut=None):
127181 Colormaps added with :func:`register_cmap` take precedence over
128182 built-in colormaps.
129183
184+ Notes
185+ -----
186+ Currently, this returns the global colormap object, which is deprecated.
187+ In Matplotlib 3.5, you will no longer be able to modify the global
188+ colormaps in-place.
189+
130190 Parameters
131191 ----------
132192 name : `matplotlib.colors.Colormap` or str or None, default: None
133- If a `.Colormap` instance, it will be returned. Otherwise, the name of
134- a colormap known to Matplotlib, which will be resampled by *lut*. The
193+ If a `.Colormap` instance, it will be returned. Otherwise, the name of
194+ a colormap known to Matplotlib, which will be resampled by *lut*. The
135195 default, None, means :rc:`image.cmap`.
136196 lut : int or None, default: None
137197 If *name* is not already a Colormap instance and *lut* is not None, the
@@ -141,11 +201,11 @@ def get_cmap(name=None, lut=None):
141201 name = mpl .rcParams ['image.cmap' ]
142202 if isinstance (name , colors .Colormap ):
143203 return name
144- cbook ._check_in_list (sorted (cmap_d ), name = name )
204+ cbook ._check_in_list (sorted (_cmap_registry ), name = name )
145205 if lut is None :
146- return cmap_d [name ]
206+ return _cmap_registry [name ]
147207 else :
148- return cmap_d [name ]._resample (lut )
208+ return _cmap_registry [name ]._resample (lut )
149209
150210
151211class ScalarMappable :
0 commit comments