24
24
from matplotlib import _api , colors , cbook
25
25
from matplotlib ._cm import datad
26
26
from matplotlib ._cm_listed import cmaps as cmaps_listed
27
+ from matplotlib .cbook import _warn_external
27
28
28
29
29
30
LUTSIZE = mpl .rcParams ['image.lut' ]
@@ -95,37 +96,46 @@ def _warn_deprecated(self):
95
96
locals ().update (_cmap_registry )
96
97
# This is no longer considered public API
97
98
cmap_d = _DeprecatedCmapDictWrapper (_cmap_registry )
98
-
99
+ __builtin_cmaps = tuple ( _cmap_registry )
99
100
100
101
# Continue with definitions ...
101
102
102
103
103
- def register_cmap (name = None , cmap = None , data = None , lut = None ):
104
+ def register_cmap (name = None , cmap = None , * , override_builtin = False ):
104
105
"""
105
106
Add a colormap to the set recognized by :func:`get_cmap`.
106
107
107
- It can be used in two ways::
108
+ Register a new colormap to be accessed by name ::
109
+
110
+ LinearSegmentedColormap('swirly', data, lut)
111
+ register_cmap(cmap=swirly_cmap)
108
112
109
- register_cmap(name='swirly', cmap=swirly_cmap)
113
+ Parameters
114
+ ----------
115
+ name : str, optional
116
+ The name that can be used in :func:`get_cmap` or :rc:`image.cmap`
110
117
111
- register_cmap(name='choppy', data=choppydata, lut=128)
118
+ If absent, the name will be the :attr:`~matplotlib.colors.Colormap.name`
119
+ attribute of the *cmap*.
112
120
113
- In the first case, * cmap* must be a :class:` matplotlib.colors.Colormap`
114
- instance. The *name* is optional; if absent, the name will
115
- be the :attr:`~matplotlib.colors.Colormap.name` attribute of the *cmap* .
121
+ cmap : matplotlib.colors.Colormap
122
+ Despite being the second argument and having a default value, this
123
+ is a required argument .
116
124
117
- The second case is deprecated. Here, the three arguments are passed to
118
- the :class:`~matplotlib.colors.LinearSegmentedColormap` initializer,
119
- and the resulting colormap is registered. Instead of this implicit
120
- colormap creation, create a `.LinearSegmentedColormap` and use the first
121
- case: ``register_cmap(cmap=LinearSegmentedColormap(name, data, lut))``.
125
+ override_builtin : bool
126
+
127
+ Allow built-in colormaps to be overridden by a user-supplied
128
+ colormap.
129
+
130
+ Please do not use this unless you are sure you need it.
122
131
123
132
Notes
124
133
-----
125
134
Registering a colormap stores a reference to the colormap object
126
135
which can currently be modified and inadvertantly change the global
127
136
colormap state. This behavior is deprecated and in Matplotlib 3.5
128
137
the registered colormap will be immutable.
138
+
129
139
"""
130
140
cbook ._check_isinstance ((str , None ), name = name )
131
141
if name is None :
@@ -134,23 +144,21 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
134
144
except AttributeError as err :
135
145
raise ValueError ("Arguments must include a name or a "
136
146
"Colormap" ) from err
137
- if isinstance (cmap , colors .Colormap ):
138
- cmap ._global = True
139
- _cmap_registry [name ] = cmap
140
- return
141
- if lut is not None or data is not None :
142
- cbook .warn_deprecated (
143
- "3.3" ,
144
- message = "Passing raw data via parameters data and lut to "
145
- "register_cmap() is deprecated since %(since)s and will "
146
- "become an error %(removal)s. Instead use: register_cmap("
147
- "cmap=LinearSegmentedColormap(name, data, lut))" )
148
- # For the remainder, let exceptions propagate.
149
- if lut is None :
150
- lut = mpl .rcParams ['image.lut' ]
151
- cmap = colors .LinearSegmentedColormap (name , data , lut )
147
+ if name in _cmap_registry :
148
+ if not override_builtin and name in __builtin_cmaps :
149
+ msg = f"Trying to re-register the builtin cmap { name !r} ."
150
+ raise ValueError (msg )
151
+ else :
152
+ msg = f"Trying to register the cmap { name !r} which already exists."
153
+ _warn_external (msg )
154
+
155
+ if not isinstance (cmap , colors .Colormap ):
156
+ raise ValueError ("You must pass a Colormap instance. "
157
+ f"You passed { cmap } a { type (cmap )} object." )
158
+
152
159
cmap ._global = True
153
160
_cmap_registry [name ] = cmap
161
+ return
154
162
155
163
156
164
def get_cmap (name = None , lut = None ):
@@ -187,6 +195,47 @@ def get_cmap(name=None, lut=None):
187
195
return _cmap_registry [name ]._resample (lut )
188
196
189
197
198
+ def unregister_cmap (name ):
199
+ """
200
+ Remove a colormap recognized by :func:`get_cmap`.
201
+
202
+ You may not remove built-in colormaps.
203
+
204
+ If the named colormap is not registered, returns with no error, raises
205
+ if you try to de-register a default colormap.
206
+
207
+ .. warning ::
208
+
209
+ Colormap names are currently a shared namespace that may be used
210
+ by multiple packages. Use `unregister_cmap` only if you know you
211
+ have registered that name before. In particular, do not
212
+ unregister just in case to clean the name before registering a
213
+ new colormap.
214
+
215
+ Parameters
216
+ ----------
217
+ name : str
218
+ The name of the colormap to be un-registered
219
+
220
+ Returns
221
+ -------
222
+ ColorMap or None
223
+ If the colormap was registered, return it if not return `None`
224
+
225
+ Raises
226
+ ------
227
+ ValueError
228
+ If you try to de-register a default built-in colormap.
229
+
230
+ """
231
+ if name not in _cmap_registry :
232
+ return
233
+ if name in __builtin_cmaps :
234
+ raise ValueError (f"cannot unregister { name !r} which is a builtin "
235
+ "colormap." )
236
+ return _cmap_registry .pop (name )
237
+
238
+
190
239
class ScalarMappable :
191
240
"""
192
241
A mixin class to map scalar data to RGBA.
0 commit comments