Skip to content

Commit 877cfe5

Browse files
committed
Deprecation warning for cmap_d.
1 parent 4915f44 commit 877cfe5

File tree

7 files changed

+90
-33
lines changed

7 files changed

+90
-33
lines changed

examples/images_contours_and_fields/demo_bboximage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
a = np.vstack((a, a))
3939

4040
# List of all colormaps; skip reversed colormaps.
41-
maps = sorted(m for m in plt.cm.cmap_d if not m.endswith("_r"))
41+
maps = sorted(m for m in plt.colormaps() if not m.endswith("_r"))
4242

4343
ncol = 2
4444
nrow = len(maps)//ncol + 1

lib/matplotlib/backends/qt_editor/figureoptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ def prepare_data(d, init):
140140
mappabledict[label] = mappable
141141
mappablelabels = sorted(mappabledict, key=cmp_key)
142142
mappables = []
143-
cmaps = [(cmap, name) for name, cmap in sorted(cm.cmap_d.items())]
143+
cmaps = [(cmap, name) for name, cmap in sorted(cm._cmap_registry.items())]
144144
for label in mappablelabels:
145145
mappable = mappabledict[label]
146146
cmap = mappable.get_cmap()
147-
if cmap not in cm.cmap_d.values():
147+
if cmap not in cm._cmap_registry.values():
148148
cmaps = [(cmap, cmap.name), *cmaps]
149149
low, high = mappable.get_clim()
150150
mappabledata = [

lib/matplotlib/cm.py

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
normalization.
1616
"""
1717

18+
from collections.abc import MutableMapping
1819
import functools
1920

2021
import numpy as np
@@ -49,7 +50,7 @@ def revcmap(data):
4950
LUTSIZE = 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.
@@ -71,10 +72,48 @@ def _gen_cmap_d():
7172
return cmap_d
7273

7374

74-
_cmap_d = _gen_cmap_d()
75-
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+
return self._cmap_registry.__iter__()
91+
92+
def __len__(self):
93+
return self._cmap_registry.__len__()
94+
95+
def __setitem__(self, key, val):
96+
self._warn_deprecated()
97+
self._cmap_registry.__setitem__(key, val)
98+
99+
def get(self, key, default=None):
100+
self._warn_deprecated()
101+
return self._cmap_registry.get(key, default)
102+
103+
def _warn_deprecated(self):
104+
cbook.warn_deprecated(
105+
"3.3",
106+
message="The global colormaps dictionary is no longer "
107+
"considered public API.",
108+
alternative="Please use register_cmap() and get_cmap() to "
109+
"access the contents of the dictionary."
110+
)
111+
112+
113+
_cmap_registry = _gen_cmap_registry()
114+
locals().update(_cmap_registry)
76115
# This is no longer considered public API
77-
cmap_d = _cmap_d
116+
cmap_d = _DeprecatedCmapDictWrapper(_cmap_registry)
78117

79118

80119
# Continue with definitions ...
@@ -99,6 +138,13 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
99138
and the resulting colormap is registered. Instead of this implicit
100139
colormap creation, create a `.LinearSegmentedColormap` and use the first
101140
case: ``register_cmap(cmap=LinearSegmentedColormap(name, data, lut))``.
141+
142+
Notes
143+
-----
144+
Registering a colormap stores a reference to the colormap object
145+
which can currently be modified and inadvertantly change the global
146+
colormap state. This behavior is deprecated and in Matplotlib 3.5
147+
the registered colormap will be immutable.
102148
"""
103149
cbook._check_isinstance((str, None), name=name)
104150
if name is None:
@@ -109,7 +155,7 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
109155
"Colormap") from err
110156
if isinstance(cmap, colors.Colormap):
111157
cmap._global = True
112-
_cmap_d[name] = cmap
158+
_cmap_registry[name] = cmap
113159
return
114160
if lut is not None or data is not None:
115161
cbook.warn_deprecated(
@@ -123,7 +169,7 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
123169
lut = mpl.rcParams['image.lut']
124170
cmap = colors.LinearSegmentedColormap(name, data, lut)
125171
cmap._global = True
126-
_cmap_d[name] = cmap
172+
_cmap_registry[name] = cmap
127173

128174

129175
def get_cmap(name=None, lut=None):
@@ -133,15 +179,18 @@ def get_cmap(name=None, lut=None):
133179
Colormaps added with :func:`register_cmap` take precedence over
134180
built-in colormaps.
135181
182+
Notes
183+
-----
184+
Currently, this returns the global colormap object, which is deprecated.
185+
In Matplotlib 3.5, you will no longer be able to modify the global
186+
colormaps in-place.
187+
136188
Parameters
137189
----------
138190
name : `matplotlib.colors.Colormap` or str or None, default: None
139-
If a `.Colormap` instance, it will be returned.
140-
Otherwise, the name of a colormap known to Matplotlib, which will
141-
be resampled by *lut*. Currently, this returns the global colormap
142-
object, which is deprecated. In Matplotlib 3.5, you will no longer be
143-
able to modify the global colormaps in-place.
144-
The default, None, means :rc:`image.cmap`.
191+
If a `.Colormap` instance, it will be returned. Otherwise, the name of
192+
a colormap known to Matplotlib, which will be resampled by *lut*. The
193+
default, None, means :rc:`image.cmap`.
145194
lut : int or None, default: None
146195
If *name* is not already a Colormap instance and *lut* is not None, the
147196
colormap will be resampled to have *lut* entries in the lookup table.
@@ -150,11 +199,11 @@ def get_cmap(name=None, lut=None):
150199
name = mpl.rcParams['image.cmap']
151200
if isinstance(name, colors.Colormap):
152201
return name
153-
cbook._check_in_list(sorted(_cmap_d), name=name)
202+
cbook._check_in_list(sorted(_cmap_registry), name=name)
154203
if lut is None:
155-
return _cmap_d[name]
204+
return _cmap_registry[name]
156205
else:
157-
return _cmap_d[name]._resample(lut)
206+
return _cmap_registry[name]._resample(lut)
158207

159208

160209
class ScalarMappable:

lib/matplotlib/colors.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -484,18 +484,15 @@ def makeMappingArray(N, data, gamma=1.0):
484484
return _create_lookup_table(N, data, gamma)
485485

486486

487-
def _deprecate_global_cmap(cmap):
488-
if hasattr(cmap, '_global') and cmap._global:
487+
def _warn_if_global_cmap_modified(cmap):
488+
if getattr(cmap, '_global', False):
489489
cbook.warn_deprecated(
490490
"3.3",
491491
message="You are modifying the state of a globally registered "
492-
"colormap. In future versions, you will not be able "
493-
"to modify a globally registered colormap directly. "
494-
"To eliminate this warning until then, you can make "
495-
"a copy of the requested colormap before modifying it. ",
496-
alternative="To modify a colormap without overwriting the "
497-
"global state, you can make a copy of the colormap "
498-
f"first. cmap = copy.copy(mpl.cm.get_cmap({cmap.name})"
492+
"colormap. In future versions, you will not be able to "
493+
"modify a registered colormap in-place. To remove this "
494+
"warning, you can make a copy of the colormap first. "
495+
f"cmap = mpl.cm.get_cmap({cmap.name}).copy()"
499496
)
500497

501498

@@ -619,28 +616,28 @@ def __copy__(self):
619616

620617
def set_bad(self, color='k', alpha=None):
621618
"""Set the color for masked values."""
619+
_warn_if_global_cmap_modified(self)
622620
self._rgba_bad = to_rgba(color, alpha)
623621
if self._isinit:
624622
self._set_extremes()
625-
_deprecate_global_cmap(self)
626623

627624
def set_under(self, color='k', alpha=None):
628625
"""
629626
Set the color for low out-of-range values when ``norm.clip = False``.
630627
"""
628+
_warn_if_global_cmap_modified(self)
631629
self._rgba_under = to_rgba(color, alpha)
632630
if self._isinit:
633631
self._set_extremes()
634-
_deprecate_global_cmap(self)
635632

636633
def set_over(self, color='k', alpha=None):
637634
"""
638635
Set the color for high out-of-range values when ``norm.clip = False``.
639636
"""
637+
_warn_if_global_cmap_modified(self)
640638
self._rgba_over = to_rgba(color, alpha)
641639
if self._isinit:
642640
self._set_extremes()
643-
_deprecate_global_cmap(self)
644641

645642
def _set_extremes(self):
646643
if self._rgba_under:

lib/matplotlib/pyplot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1948,7 +1948,7 @@ def colormaps():
19481948
<https://www.mathworks.com/matlabcentral/fileexchange/2662-cmrmap-m>`_
19491949
by Carey Rappaport
19501950
"""
1951-
return sorted(cm.cmap_d)
1951+
return sorted(cm._cmap_registry)
19521952

19531953

19541954
def _setup_pyplot_info_docstrings():

lib/matplotlib/tests/test_colors.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ def test_colormap_global_set_warn():
126126
plt.register_cmap(cmap=orig_cmap)
127127

128128

129+
def test_colormap_dict_deprecate():
130+
# Make sure we warn on get and set access into cmap_d
131+
with pytest.warns(cbook.MatplotlibDeprecationWarning,
132+
match="The global colormaps dictionary is no longer"):
133+
cm = plt.cm.cmap_d['viridis']
134+
135+
with pytest.warns(cbook.MatplotlibDeprecationWarning,
136+
match="The global colormaps dictionary is no longer"):
137+
plt.cm.cmap_d['test'] = cm
138+
139+
129140
def test_colormap_copy():
130141
cm = plt.cm.Reds
131142
cm_copy = copy.copy(cm)
@@ -874,7 +885,7 @@ def test_pandas_iterable(pd):
874885
assert_array_equal(cm1.colors, cm2.colors)
875886

876887

877-
@pytest.mark.parametrize('name', sorted(cm.cmap_d))
888+
@pytest.mark.parametrize('name', sorted(plt.colormaps()))
878889
def test_colormap_reversing(name):
879890
"""
880891
Check the generated _lut data of a colormap and corresponding reversed

lib/matplotlib/tests/test_pickle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def test_shared():
190190
assert fig.axes[1].get_xlim() == (10, 20)
191191

192192

193-
@pytest.mark.parametrize("cmap", cm.cmap_d.values())
193+
@pytest.mark.parametrize("cmap", cm._cmap_registry.values())
194194
def test_cmap(cmap):
195195
pickle.dumps(cmap)
196196

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy