2424from matplotlib import _api , colors , cbook
2525from matplotlib ._cm import datad
2626from matplotlib ._cm_listed import cmaps as cmaps_listed
27+ from matplotlib .cbook import _warn_external
2728
2829
2930LUTSIZE = mpl .rcParams ['image.lut' ]
@@ -95,12 +96,12 @@ def _warn_deprecated(self):
9596locals ().update (_cmap_registry )
9697# This is no longer considered public API
9798cmap_d = _DeprecatedCmapDictWrapper (_cmap_registry )
98-
99+ __builtin_cmaps = tuple ( _cmap_registry )
99100
100101# Continue with definitions ...
101102
102103
103- def register_cmap (name = None , cmap = None ):
104+ def register_cmap (name = None , cmap = None , * , override_builtin = False ):
104105 """
105106 Add a colormap to the set recognized by :func:`get_cmap`.
106107
@@ -121,13 +122,20 @@ def register_cmap(name=None, cmap=None):
121122 Despite being the second argument and having a default value, this
122123 is a required argument.
123124
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.
124131
125132 Notes
126133 -----
127134 Registering a colormap stores a reference to the colormap object
128135 which can currently be modified and inadvertantly change the global
129136 colormap state. This behavior is deprecated and in Matplotlib 3.5
130137 the registered colormap will be immutable.
138+
131139 """
132140 cbook ._check_isinstance ((str , None ), name = name )
133141 if name is None :
@@ -136,10 +144,18 @@ def register_cmap(name=None, cmap=None):
136144 except AttributeError as err :
137145 raise ValueError ("Arguments must include a name or a "
138146 "Colormap" ) from err
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 )
139154
140155 if not isinstance (cmap , colors .Colormap ):
141156 raise ValueError ("You must pass a Colormap instance. "
142157 f"You passed { cmap } a { type (cmap )} object." )
158+
143159 cmap ._global = True
144160 _cmap_registry [name ] = cmap
145161 return
@@ -179,6 +195,47 @@ def get_cmap(name=None, lut=None):
179195 return _cmap_registry [name ]._resample (lut )
180196
181197
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+
182239class ScalarMappable :
183240 """
184241 A mixin class to map scalar data to RGBA.
0 commit comments