15
15
normalization.
16
16
"""
17
17
18
- from collections .abc import Mapping , MutableMapping
18
+ from collections .abc import Mapping
19
19
20
20
import numpy as np
21
21
from numpy import ma
@@ -52,52 +52,10 @@ def _gen_cmap_registry():
52
52
# Generate reversed cmaps.
53
53
for cmap in list (cmap_d .values ()):
54
54
rmap = cmap .reversed ()
55
- cmap ._global = True
56
- rmap ._global = True
57
55
cmap_d [rmap .name ] = rmap
58
56
return cmap_d
59
57
60
58
61
- class _DeprecatedCmapDictWrapper (MutableMapping ):
62
- """Dictionary mapping for deprecated _cmap_d access."""
63
-
64
- def __init__ (self , cmap_registry ):
65
- self ._cmap_registry = cmap_registry
66
-
67
- def __delitem__ (self , key ):
68
- self ._warn_deprecated ()
69
- self ._cmap_registry .__delitem__ (key )
70
-
71
- def __getitem__ (self , key ):
72
- self ._warn_deprecated ()
73
- return self ._cmap_registry .__getitem__ (key )
74
-
75
- def __iter__ (self ):
76
- self ._warn_deprecated ()
77
- return self ._cmap_registry .__iter__ ()
78
-
79
- def __len__ (self ):
80
- self ._warn_deprecated ()
81
- return self ._cmap_registry .__len__ ()
82
-
83
- def __setitem__ (self , key , val ):
84
- self ._warn_deprecated ()
85
- self ._cmap_registry .__setitem__ (key , val )
86
-
87
- def get (self , key , default = None ):
88
- self ._warn_deprecated ()
89
- return self ._cmap_registry .get (key , default )
90
-
91
- def _warn_deprecated (self ):
92
- _api .warn_deprecated (
93
- "3.3" ,
94
- message = "The global colormaps dictionary is no longer "
95
- "considered public API." ,
96
- alternative = "Please use register_cmap() and get_cmap() to "
97
- "access the contents of the dictionary."
98
- )
99
-
100
-
101
59
class ColormapRegistry (Mapping ):
102
60
r"""
103
61
Container for colormaps that are known to Matplotlib by name.
@@ -125,6 +83,7 @@ class ColormapRegistry(Mapping):
125
83
"""
126
84
def __init__ (self , cmaps ):
127
85
self ._cmaps = cmaps
86
+ self ._builtin_cmaps = tuple (cmaps )
128
87
129
88
def __getitem__ (self , item ):
130
89
try :
@@ -177,23 +136,60 @@ def register(self, cmap, *, name=None, force=False):
177
136
registered name. True supports overwriting registered colormaps
178
137
other than the builtin colormaps.
179
138
"""
139
+ _api .check_isinstance (colors .Colormap , cmap = cmap )
140
+
180
141
name = name or cmap .name
181
- if name in self and not force :
182
- raise ValueError (
183
- f'A colormap named "{ name } " is already registered.' )
184
- register_cmap (name , cmap .copy ())
142
+ if name in self :
143
+ if force :
144
+ _api .warn_external (f"Trying to register the cmap { name !r} "
145
+ "which already exists." )
146
+
147
+ else :
148
+ raise ValueError (
149
+ f"Trying to re-register the builtin cmap { name !r} ."
150
+ if name in self ._builtin_cmaps else
151
+ f'A colormap named "{ name } " is already registered.' )
152
+
153
+ self ._cmaps [name ] = cmap .copy ()
185
154
155
+ def unregister (self , name ):
156
+ """
157
+ Remove a colormap from the registry.
158
+
159
+ You cannot remove built-in colormaps.
160
+
161
+ If the named colormap is not registered, returns with no error, raises
162
+ if you try to de-register a default colormap.
163
+
164
+ .. warning::
165
+
166
+ Colormap names are currently a shared namespace that may be used
167
+ by multiple packages. Use `unregister` only if you know you
168
+ have registered that name before. In particular, do not
169
+ unregister just in case to clean the name before registering a
170
+ new colormap.
171
+
172
+ Parameters
173
+ ----------
174
+ name : str
175
+ The name of the colormap to be removed.
176
+
177
+ Raises
178
+ ------
179
+ ValueError
180
+ If you try to remove a default built-in colormap.
181
+ """
182
+ if name in self ._builtin_cmaps :
183
+ raise ValueError (f"cannot unregister { name !r} which is a builtin "
184
+ "colormap." )
185
+ self ._cmaps .pop (name , None )
186
186
187
- _cmap_registry = _gen_cmap_registry ()
188
- globals ().update (_cmap_registry )
189
- # This is no longer considered public API
190
- cmap_d = _DeprecatedCmapDictWrapper (_cmap_registry )
191
- __builtin_cmaps = tuple (_cmap_registry )
192
187
193
188
# public access to the colormaps should be via `matplotlib.colormaps`. For now,
194
189
# we still create the registry here, but that should stay an implementation
195
190
# detail.
196
- _colormaps = ColormapRegistry (_cmap_registry )
191
+ _colormaps = ColormapRegistry (_gen_cmap_registry ())
192
+ globals ().update (_colormaps )
197
193
198
194
199
195
def register_cmap (name = None , cmap = None , * , override_builtin = False ):
@@ -223,14 +219,6 @@ def register_cmap(name=None, cmap=None, *, override_builtin=False):
223
219
colormap.
224
220
225
221
Please do not use this unless you are sure you need it.
226
-
227
- Notes
228
- -----
229
- Registering a colormap stores a reference to the colormap object
230
- which can currently be modified and inadvertently change the global
231
- colormap state. This behavior is deprecated and in Matplotlib 3.5
232
- the registered colormap will be immutable.
233
-
234
222
"""
235
223
_api .check_isinstance ((str , None ), name = name )
236
224
if name is None :
@@ -239,21 +227,7 @@ def register_cmap(name=None, cmap=None, *, override_builtin=False):
239
227
except AttributeError as err :
240
228
raise ValueError ("Arguments must include a name or a "
241
229
"Colormap" ) from err
242
- if name in _cmap_registry :
243
- if not override_builtin and name in __builtin_cmaps :
244
- msg = f"Trying to re-register the builtin cmap { name !r} ."
245
- raise ValueError (msg )
246
- else :
247
- msg = f"Trying to register the cmap { name !r} which already exists."
248
- _api .warn_external (msg )
249
-
250
- if not isinstance (cmap , colors .Colormap ):
251
- raise ValueError ("You must pass a Colormap instance. "
252
- f"You passed { cmap } a { type (cmap )} object." )
253
-
254
- cmap ._global = True
255
- _cmap_registry [name ] = cmap
256
- return
230
+ _colormaps .register (cmap , name = name , force = override_builtin )
257
231
258
232
259
233
def get_cmap (name = None , lut = None ):
@@ -263,12 +237,6 @@ def get_cmap(name=None, lut=None):
263
237
Colormaps added with :func:`register_cmap` take precedence over
264
238
built-in colormaps.
265
239
266
- Notes
267
- -----
268
- Currently, this returns the global colormap object, which is deprecated.
269
- In Matplotlib 3.5, you will no longer be able to modify the global
270
- colormaps in-place.
271
-
272
240
Parameters
273
241
----------
274
242
name : `matplotlib.colors.Colormap` or str or None, default: None
@@ -283,11 +251,11 @@ def get_cmap(name=None, lut=None):
283
251
name = mpl .rcParams ['image.cmap' ]
284
252
if isinstance (name , colors .Colormap ):
285
253
return name
286
- _api .check_in_list (sorted (_cmap_registry ), name = name )
254
+ _api .check_in_list (sorted (_colormaps ), name = name )
287
255
if lut is None :
288
- return _cmap_registry [name ]
256
+ return _colormaps [name ]
289
257
else :
290
- return _cmap_registry [name ]._resample (lut )
258
+ return _colormaps [name ]._resample (lut )
291
259
292
260
293
261
def unregister_cmap (name ):
@@ -321,14 +289,10 @@ def unregister_cmap(name):
321
289
------
322
290
ValueError
323
291
If you try to de-register a default built-in colormap.
324
-
325
292
"""
326
- if name not in _cmap_registry :
327
- return
328
- if name in __builtin_cmaps :
329
- raise ValueError (f"cannot unregister { name !r} which is a builtin "
330
- "colormap." )
331
- return _cmap_registry .pop (name )
293
+ cmap = _colormaps .get (name , None )
294
+ _colormaps .unregister (name )
295
+ return cmap
332
296
333
297
334
298
class ScalarMappable :
0 commit comments