Skip to content

Commit fcf1c0c

Browse files
committed
FIX: add missing method to ColormapRegistry
After putting pending deprecations on `cm.get_cmap` we discovered that downstream libraries (pandas) were using the deprecated method to normalize between `None` (to get the default colormap), strings, and Colormap instances. This adds a method to `ColormapRegistry` to do this normalization. This can not replace our internal helper due to variations in what exceptions are raised. Closes matplotlib#23981
1 parent eb44018 commit fcf1c0c

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

doc/api/prev_api_changes/api_changes_3.6.0/deprecations.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,13 @@ In Matplotlib 3.6 we have marked those top level functions as pending
5252
deprecation with the intention of deprecation in Matplotlib 3.7. The following
5353
functions have been marked for pending deprecation:
5454

55-
- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead
55+
- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead if you
56+
have a `str`.
57+
58+
**Added 3.6.1** Use `matplotlib.cm.ColormapRegistry.get_cmap` if you
59+
have a string, `None` or a `matplotlib.colors.Colormap` object that you want
60+
to convert to a `matplotlib.colors.Colormap` instance. Raises `KeyError`
61+
rather than `ValueError` for missing strings.
5662
- ``matplotlib.cm.register_cmap``; use `matplotlib.colormaps.register
5763
<.ColormapRegistry.register>` instead
5864
- ``matplotlib.cm.unregister_cmap``; use `matplotlib.colormaps.unregister
@@ -305,7 +311,7 @@ Backend-specific deprecations
305311
private functions if you rely on it.
306312
- ``backend_svg.generate_transform`` and ``backend_svg.generate_css``
307313
- ``backend_tk.NavigationToolbar2Tk.lastrect`` and
308-
``backend_tk.RubberbandTk.lastrect``
314+
``backend_tk.RubberbandTk.lastrect``
309315
- ``backend_tk.NavigationToolbar2Tk.window``; use ``toolbar.master`` instead.
310316
- ``backend_tools.ToolBase.destroy``; To run code upon tool removal, connect to
311317
the ``tool_removed_event`` event.

lib/matplotlib/cm.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,39 @@ def unregister(self, name):
193193
"colormap.")
194194
self._cmaps.pop(name, None)
195195

196+
def get_cmap(self, cmap):
197+
"""
198+
Ensure that at given object is a converted to a color map.
199+
200+
If *cmap* in `None`, returns the Colormap named by :rc:`image.cmap`.
201+
202+
Parameters
203+
----------
204+
cmap : str, Colormap, None
205+
206+
- if a `~matplotlib.colors.Colormap`, return it
207+
- if a string, look it up in mpl.colormaps
208+
- if None, look up the default color map in mpl.colormaps
209+
210+
Returns
211+
-------
212+
Colormap
213+
214+
Raises
215+
------
216+
KeyError
217+
"""
218+
# get the default color map
219+
if cmap is None:
220+
return self[mpl.rcParams["image.cmap"]]
221+
222+
# if the user passed in a Colormap, simply return it
223+
if isinstance(cmap, colors.Colormap):
224+
return cmap
225+
226+
# otherwise, it must be a string so look it up
227+
return self[cmap]
228+
196229

197230
# public access to the colormaps should be via `matplotlib.colormaps`. For now,
198231
# we still create the registry here, but that should stay an implementation
@@ -281,7 +314,12 @@ def _get_cmap(name=None, lut=None):
281314
# pyplot.
282315
get_cmap = _api.deprecated(
283316
'3.6',
284-
name='get_cmap', pending=True, alternative="``matplotlib.colormaps[name]``"
317+
name='get_cmap',
318+
pending=True,
319+
alternative=(
320+
"``matplotlib.colormaps[name]`` " +
321+
"or ``matplotlib.colormaps.get_cmap(obj)``"
322+
)
285323
)(_get_cmap)
286324

287325

@@ -687,6 +725,8 @@ def _ensure_cmap(cmap):
687725
"""
688726
Ensure that we have a `.Colormap` object.
689727
728+
For internal use to preserve type stability of errors.
729+
690730
Parameters
691731
----------
692732
cmap : None, str, Colormap
@@ -698,6 +738,7 @@ def _ensure_cmap(cmap):
698738
Returns
699739
-------
700740
Colormap
741+
701742
"""
702743
if isinstance(cmap, colors.Colormap):
703744
return cmap

lib/matplotlib/tests/test_colors.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,21 @@ def test_register_cmap():
109109
cm.register_cmap('nome', cmap='not a cmap')
110110

111111

112+
def test_ensure_cmap():
113+
cr = mpl.colormaps
114+
new_cm = mcolors.ListedColormap(cr["viridis"].colors, name='v2')
115+
116+
# check None, str, and Colormap pass
117+
assert cr.get_cmap('plasma') == cr["plasma"]
118+
assert cr.get_cmap(cr["magma"]) == cr["magma"]
119+
120+
# check default default
121+
assert cr.get_cmap(None) == cr[mpl.rcParams['image.cmap']]
122+
bad_cmap = 'AardvarksAreAwkward'
123+
with pytest.raises(KeyError, match=bad_cmap):
124+
cr.get_cmap(bad_cmap)
125+
126+
112127
def test_double_register_builtin_cmap():
113128
name = "viridis"
114129
match = f"Re-registering the builtin cmap {name!r}."

0 commit comments

Comments
 (0)