Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: add missing method to ColormapRegistry #24111

Merged
merged 5 commits into from Oct 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions doc/api/prev_api_changes/api_changes_3.6.0/deprecations.rst
Expand Up @@ -52,7 +52,12 @@ In Matplotlib 3.6 we have marked those top level functions as pending
deprecation with the intention of deprecation in Matplotlib 3.7. The following
functions have been marked for pending deprecation:

- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead
- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead if you
have a `str`.

**Added 3.6.1** Use `matplotlib.cm.ColormapRegistry.get_cmap` if you
have a string, `None` or a `matplotlib.colors.Colormap` object that you want
to convert to a `matplotlib.colors.Colormap` instance.
- ``matplotlib.cm.register_cmap``; use `matplotlib.colormaps.register
<.ColormapRegistry.register>` instead
- ``matplotlib.cm.unregister_cmap``; use `matplotlib.colormaps.unregister
Expand Down Expand Up @@ -305,7 +310,7 @@ Backend-specific deprecations
private functions if you rely on it.
- ``backend_svg.generate_transform`` and ``backend_svg.generate_css``
- ``backend_tk.NavigationToolbar2Tk.lastrect`` and
``backend_tk.RubberbandTk.lastrect``
``backend_tk.RubberbandTk.lastrect``
- ``backend_tk.NavigationToolbar2Tk.window``; use ``toolbar.master`` instead.
- ``backend_tools.ToolBase.destroy``; To run code upon tool removal, connect to
the ``tool_removed_event`` event.
Expand Down
48 changes: 41 additions & 7 deletions lib/matplotlib/cm.py
Expand Up @@ -61,12 +61,6 @@ class ColormapRegistry(Mapping):
r"""
Container for colormaps that are known to Matplotlib by name.

.. admonition:: Experimental

While we expect the API to be final, we formally mark it as
experimental for 3.5 because we want to keep the option to still adapt
the API for 3.6 should the need arise.

The universal registry instance is `matplotlib.colormaps`. There should be
no need for users to instantiate `.ColormapRegistry` themselves.

Expand Down Expand Up @@ -193,6 +187,38 @@ def unregister(self, name):
"colormap.")
self._cmaps.pop(name, None)

def get_cmap(self, cmap):
"""
Return a color map specified through *cmap*.

Parameters
----------
cmap : str or `~matplotlib.colors.Colormap` or None

- if a `.Colormap`, return it
- if a string, look it up in ``mpl.colormaps``
- if None, return the Colormap defined in :rc:`image.cmap`

Returns
-------
Colormap
"""
# get the default color map
if cmap is None:
return self[mpl.rcParams["image.cmap"]]

# if the user passed in a Colormap, simply return it
if isinstance(cmap, colors.Colormap):
return cmap
if isinstance(cmap, str):
_api.check_in_list(sorted(_colormaps), cmap=cmap)
# otherwise, it must be a string so look it up
return self[cmap]
raise TypeError(
'get_cmap expects None or an instance of a str or Colormap . ' +
f'you passed {cmap!r} of type {type(cmap)}'
)


# public access to the colormaps should be via `matplotlib.colormaps`. For now,
# we still create the registry here, but that should stay an implementation
Expand Down Expand Up @@ -281,7 +307,12 @@ def _get_cmap(name=None, lut=None):
# pyplot.
get_cmap = _api.deprecated(
'3.6',
name='get_cmap', pending=True, alternative="``matplotlib.colormaps[name]``"
name='get_cmap',
pending=True,
alternative=(
"``matplotlib.colormaps[name]`` " +
"or ``matplotlib.colormaps.get_cmap(obj)``"
)
)(_get_cmap)


Expand Down Expand Up @@ -687,6 +718,8 @@ def _ensure_cmap(cmap):
"""
Ensure that we have a `.Colormap` object.

For internal use to preserve type stability of errors.

Parameters
----------
cmap : None, str, Colormap
Expand All @@ -698,6 +731,7 @@ def _ensure_cmap(cmap):
Returns
-------
Colormap

"""
if isinstance(cmap, colors.Colormap):
return cmap
Expand Down
20 changes: 20 additions & 0 deletions lib/matplotlib/tests/test_colors.py
Expand Up @@ -109,6 +109,26 @@ def test_register_cmap():
cm.register_cmap('nome', cmap='not a cmap')


def test_colormaps_get_cmap():
cr = mpl.colormaps

# check str, and Colormap pass
assert cr.get_cmap('plasma') == cr["plasma"]
assert cr.get_cmap(cr["magma"]) == cr["magma"]

# check default
assert cr.get_cmap(None) == cr[mpl.rcParams['image.cmap']]

# check ValueError on bad name
bad_cmap = 'AardvarksAreAwkward'
with pytest.raises(ValueError, match=bad_cmap):
cr.get_cmap(bad_cmap)

# check TypeError on bad type
with pytest.raises(TypeError, match='object'):
cr.get_cmap(object())


def test_double_register_builtin_cmap():
name = "viridis"
match = f"Re-registering the builtin cmap {name!r}."
Expand Down