Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3790fd7

Browse files
tacaswelldstansby
andcommitted
ENH/API: be more defensive in cm.register_cmap + deregister
- raise if you try to over write a default colormap - warn if you try to over write a user-added colormap - add method to de-register a color map - add escape hatch to force re-registering builtin colormapsCo-Authored-By: David Stansby <dstansby@gmail.com>
1 parentd28cbf2 commit3790fd7

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Raise or warn on registering a color map twice
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
When using `matplotlib.cm.register_cmap` to register a user provided
5+
or third-party color map it will now raise a `ValueError` if trying to
6+
over-write one of the built in color maps and warn if trying to over
7+
write a user registered color map. This may raise for user-registered
8+
color maps in the future.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
Add ``cm.unregister_cmap`` function
3+
-----------------------------------
4+
5+
`.cm.unregister_cmap` allows users to remove a color map that they
6+
have previously registered.

‎lib/matplotlib/cm.py

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
frommatplotlibimport_api,colors,cbook
2525
frommatplotlib._cmimportdatad
2626
frommatplotlib._cm_listedimportcmapsascmaps_listed
27+
frommatplotlib.cbookimport_warn_external
2728

2829

2930
LUTSIZE=mpl.rcParams['image.lut']
@@ -95,12 +96,12 @@ def _warn_deprecated(self):
9596
locals().update(_cmap_registry)
9697
# This is no longer considered public API
9798
cmap_d=_DeprecatedCmapDictWrapper(_cmap_registry)
98-
99+
__builtin_cmaps=tuple(_cmap_registry)
99100

100101
# Continue with definitions ...
101102

102103

103-
defregister_cmap(name=None,cmap=None):
104+
defregister_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
ifnameisNone:
@@ -136,10 +144,18 @@ def register_cmap(name=None, cmap=None):
136144
exceptAttributeErroraserr:
137145
raiseValueError("Arguments must include a name or a "
138146
"Colormap")fromerr
147+
ifnamein_cmap_registry:
148+
ifnotoverride_builtinandnamein__builtin_cmaps:
149+
msg=f"Trying to re-register the builtin cmap{name!r}."
150+
raiseValueError(msg)
151+
else:
152+
msg=f"Trying to register the cmap{name!r} which already exists."
153+
_warn_external(msg)
139154

140155
ifnotisinstance(cmap,colors.Colormap):
141156
raiseValueError("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+
defunregister_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+
ifnamenotin_cmap_registry:
232+
return
233+
ifnamein__builtin_cmaps:
234+
raiseValueError(f"cannot unregister{name!r} which is a builtin "
235+
"colormap.")
236+
return_cmap_registry.pop(name)
237+
238+
182239
classScalarMappable:
183240
"""
184241
A mixin class to map scalar data to RGBA.

‎lib/matplotlib/tests/test_colors.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,45 @@ def test_resample():
6464

6565

6666
deftest_register_cmap():
67-
new_cm=copy.copy(plt.cm.viridis)
68-
cm.register_cmap('viridis2',new_cm)
69-
assertplt.get_cmap('viridis2')==new_cm
67+
new_cm=copy.copy(cm.get_cmap("viridis"))
68+
target="viridis2"
69+
cm.register_cmap(target,new_cm)
70+
assertplt.get_cmap(target)==new_cm
7071

7172
withpytest.raises(ValueError,
72-
match='Arguments must include a name or a Colormap'):
73+
match="Arguments must include a name or a Colormap"):
7374
cm.register_cmap()
7475

76+
withpytest.warns(UserWarning):
77+
cm.register_cmap(target,new_cm)
78+
79+
cm.unregister_cmap(target)
80+
withpytest.raises(ValueError,
81+
match=f'{target!r} is not a valid value for name;'):
82+
cm.get_cmap(target)
83+
# test that second time is error free
84+
cm.unregister_cmap(target)
85+
7586
withpytest.raises(ValueError,match="You must pass a Colormap instance."):
7687
cm.register_cmap('nome',cmap='not a cmap')
7788

7889

90+
deftest_double_register_builtin_cmap():
91+
name="viridis"
92+
match=f"Trying to re-register the builtin cmap{name!r}."
93+
withpytest.raises(ValueError,match=match):
94+
cm.register_cmap(name,cm.get_cmap(name))
95+
withpytest.warns(UserWarning):
96+
cm.register_cmap(name,cm.get_cmap(name),override_builtin=True)
97+
98+
99+
deftest_unregister_builtin_cmap():
100+
name="viridis"
101+
match=f'Can not unregister{name!r} which is a builtin color map.'
102+
withpytest.raises(ValueError,match=match):
103+
cm.unregister_cmap(name)
104+
105+
79106
deftest_colormap_global_set_warn():
80107
new_cm=plt.get_cmap('viridis')
81108
# Store the old value so we don't override the state later on.
@@ -97,7 +124,8 @@ def test_colormap_global_set_warn():
97124
new_cm.set_under('k')
98125

99126
# Re-register the original
100-
plt.register_cmap(cmap=orig_cmap)
127+
withpytest.warns(UserWarning):
128+
plt.register_cmap(cmap=orig_cmap,override_builtin=True)
101129

102130

103131
deftest_colormap_dict_deprecate():

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp