Skip to content

Removal of deprecated API cm #26965

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

Merged
merged 1 commit into from
Feb 8, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions ci/mypy-stubtest-allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ matplotlib.figure.Figure.set_constrained_layout
matplotlib.figure.Figure.set_constrained_layout_pads
matplotlib.figure.Figure.set_tight_layout

# 3.7 deprecations
matplotlib.cm.register_cmap
matplotlib.cm.unregister_cmap

# positional-only argument name lacking leading underscores
matplotlib.axes._base._AxesBase.axis

Expand Down
22 changes: 22 additions & 0 deletions doc/api/next_api_changes/removals/26965-ER.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Removal of top-level cmap registration and access functions in ``mpl.cm``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

As part of the `multi-step refactoring of colormap registration
<https://github.com/matplotlib/matplotlib/issues/20853>`_, the following functions have
been removed:

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

Use `matplotlib.cm.ColormapRegistry.get_cmap` if you have a `str`, `None` or a
`matplotlib.colors.Colormap` object that you want to convert to a `.Colormap`
object.
- ``matplotlib.cm.register_cmap``; use `matplotlib.colormaps.register
<.ColormapRegistry.register>` instead.
- ``matplotlib.cm.unregister_cmap``; use `matplotlib.colormaps.unregister
<.ColormapRegistry.unregister>` instead.
- ``matplotlib.pyplot.register_cmap``; use `matplotlib.colormaps.register
<.ColormapRegistry.register>` instead.

The `matplotlib.pyplot.get_cmap` function will stay available for backward
compatibility.
2 changes: 1 addition & 1 deletion doc/api/prev_api_changes/api_changes_0.99.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Changes in 0.99
NumPy arrays.

* User-generated colormaps can now be added to the set recognized
by :func:`matplotlib.cm.get_cmap`. Colormaps can be made the
by ``matplotlib.cm.get_cmap``. Colormaps can be made the
default and applied to the current image using
:func:`matplotlib.pyplot.set_cmap`.

Expand Down
9 changes: 5 additions & 4 deletions doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,11 @@ Exception changes
~~~~~~~~~~~~~~~~~
Various APIs that raised a `ValueError` for incorrectly typed inputs now raise
`TypeError` instead: `.backend_bases.GraphicsContextBase.set_clip_path`,
``blocking_input.BlockingInput.__call__``, `.cm.register_cmap`, `.dviread.DviFont`,
`.rcsetup.validate_hatch`, ``.rcsetup.validate_animation_writer_path``, `.spines.Spine`,
many classes in the :mod:`matplotlib.transforms` module and :mod:`matplotlib.tri`
package, and Axes methods that take a ``norm`` parameter.
``blocking_input.BlockingInput.__call__``, ``matplotlib.cm.register_cmap``,
`.dviread.DviFont`, `.rcsetup.validate_hatch`,
``.rcsetup.validate_animation_writer_path``, `.spines.Spine`, many classes in
the :mod:`matplotlib.transforms` module and :mod:`matplotlib.tri` package, and
Axes methods that take a ``norm`` parameter.

If extra kwargs are passed to `.LogScale`, `TypeError` will now be
raised instead of `ValueError`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Please pass capstyles ("miter", "round", "bevel") and joinstyles ("butt",

Passing raw data to ``register_cmap()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passing raw data via parameters *data* and *lut* to `.register_cmap()` is
Passing raw data via parameters *data* and *lut* to ``matplotlib.cm.register_cmap()`` is
deprecated. Instead, explicitly create a `.LinearSegmentedColormap` and pass
it via the *cmap* parameter:
``register_cmap(cmap=LinearSegmentedColormap(name, data, lut))``.
Expand Down
2 changes: 1 addition & 1 deletion doc/api/prev_api_changes/api_changes_3.4.0/behaviour.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ time, not at draw time.
Raise or warn on registering a colormap twice
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When using `matplotlib.cm.register_cmap` to register a user provided or
When using ``matplotlib.cm.register_cmap`` to register a user provided or
third-party colormap it will now raise a `ValueError` if trying to over-write
one of the built in colormaps and warn if trying to over write a user
registered colormap. This may raise for user-registered colormaps in the
Expand Down
8 changes: 4 additions & 4 deletions doc/api/prev_api_changes/api_changes_3.6.0/behaviour.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Behaviour changes
``plt.get_cmap`` and ``matplotlib.cm.get_cmap`` return a copy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Formerly, `~.pyplot.get_cmap` and `.cm.get_cmap` returned a global version of a
`.Colormap`. This was prone to errors as modification of the colormap would
propagate from one location to another without warning. Now, a new copy of the
colormap is returned.
Formerly, `~.pyplot.get_cmap` and ``matplotlib.cm.get_cmap`` returned a global version
of a `.Colormap`. This was prone to errors as modification of the colormap would
propagate from one location to another without warning. Now, a new copy of the colormap
is returned.

Large ``imshow`` images are now downsampled
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
8 changes: 4 additions & 4 deletions doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ also be based on ``mpl_toolkits.axisartist``. This behavior is consistent with
``plt.get_cmap`` and ``matplotlib.cm.get_cmap`` return a copy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Formerly, `~.pyplot.get_cmap` and `.cm.get_cmap` returned a global version of a
`.Colormap`. This was prone to errors as modification of the colormap would
propagate from one location to another without warning. Now, a new copy of the
colormap is returned.
Formerly, `~.pyplot.get_cmap` and ``matplotlib.cm.get_cmap`` returned a global version
of a `.Colormap`. This was prone to errors as modification of the colormap would
propagate from one location to another without warning. Now, a new copy of the colormap
is returned.

``TrapezoidMapTriFinder`` uses different random number generator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion doc/users/prev_whats_new/whats_new_1.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ minimum and maximum colorbar extensions.
Z = np.cos(X) * np.sin(0.5*Y)

clevs = [-.75, -.5, -.25, 0., .25, .5, .75]
cmap = plt.cm.get_cmap(name='jet', lut=8)
cmap = plt.get_cmap(name='jet', lut=8)

ax1 = plt.subplot(211)
cs1 = plt.contourf(x, y, Z, clevs, cmap=cmap, extend='both')
Expand Down
2 changes: 1 addition & 1 deletion doc/users/prev_whats_new/whats_new_3.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ for out-of-range and masked values.
New ``cm.unregister_cmap`` function
-----------------------------------

`.cm.unregister_cmap` allows users to remove a colormap that they have
``matplotlib.cm.unregister_cmap`` allows users to remove a colormap that they have
previously registered.

New ``CenteredNorm`` for symmetrical data around a center
Expand Down
6 changes: 3 additions & 3 deletions doc/users/prev_whats_new/whats_new_3.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ To register new colormaps use::

plt.colormaps.register(my_colormap)

We recommend to use the new API instead of the `~.cm.get_cmap` and
`~.cm.register_cmap` functions for new code. `matplotlib.cm.get_cmap` and
`matplotlib.cm.register_cmap` will eventually be deprecated and removed.
We recommend to use the new API instead of the ``matplotlib.cm.get_cmap`` and
``matplotlib.cm.register_cmap`` functions for new code. ``matplotlib.cm.get_cmap`` and
``matplotlib.cm.register_cmap`` will eventually be deprecated and removed.
Within `.pyplot`, ``plt.get_cmap()`` and ``plt.register_cmap()`` will continue
to be supported for backward compatibility.

Expand Down
2 changes: 1 addition & 1 deletion galleries/examples/color/custom_cmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,4 @@
# - `matplotlib.colors.LinearSegmentedColormap.from_list`
# - `matplotlib.cm`
# - `matplotlib.cm.ScalarMappable.set_cmap`
# - `matplotlib.cm.register_cmap`
# - `matplotlib.cm.ColormapRegistry.register`
2 changes: 1 addition & 1 deletion lib/matplotlib/_cm.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def _ch_helper(gamma, s, r, h, p0, p1, x):
def cubehelix(gamma=1.0, s=0.5, r=-1.5, h=1.0):
"""
Return custom data dictionary of (r, g, b) conversion functions, which can
be used with :func:`register_cmap`, for the cubehelix color scheme.
be used with `.ColormapRegistry.register`, for the cubehelix color scheme.

Unlike most other color schemes cubehelix was designed by D.A. Green to
be monotonically increasing in terms of perceived brightness.
Expand Down
131 changes: 2 additions & 129 deletions lib/matplotlib/cm.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ class ColormapRegistry(Mapping):
def __init__(self, cmaps):
self._cmaps = cmaps
self._builtin_cmaps = tuple(cmaps)
# A shim to allow register_cmap() to force an override
self._allow_override_builtin = False

def __getitem__(self, item):
try:
Expand Down Expand Up @@ -146,10 +144,8 @@ def register(self, cmap, *, name=None, force=False):
# unless explicitly asked to
raise ValueError(
f'A colormap named "{name}" is already registered.')
elif (name in self._builtin_cmaps
and not self._allow_override_builtin):
# We don't allow overriding a builtin unless privately
# coming from register_cmap()
elif name in self._builtin_cmaps:
# We don't allow overriding a builtin.
raise ValueError("Re-registering the builtin cmap "
f"{name!r} is not allowed.")

Expand Down Expand Up @@ -236,129 +232,6 @@ def get_cmap(self, cmap):
globals().update(_colormaps)


@_api.deprecated("3.7", alternative="``matplotlib.colormaps.register(name)``")
def register_cmap(name=None, cmap=None, *, override_builtin=False):
"""
Add a colormap to the set recognized by :func:`get_cmap`.

Register a new colormap to be accessed by name ::

LinearSegmentedColormap('swirly', data, lut)
register_cmap(cmap=swirly_cmap)

Parameters
----------
name : str, optional
The name that can be used in :func:`get_cmap` or :rc:`image.cmap`

If absent, the name will be the :attr:`~matplotlib.colors.Colormap.name`
attribute of the *cmap*.

cmap : matplotlib.colors.Colormap
Despite being the second argument and having a default value, this
is a required argument.

override_builtin : bool

Allow built-in colormaps to be overridden by a user-supplied
colormap.

Please do not use this unless you are sure you need it.
"""
_api.check_isinstance((str, None), name=name)
if name is None:
try:
name = cmap.name
except AttributeError as err:
raise ValueError("Arguments must include a name or a "
"Colormap") from err
# override_builtin is allowed here for backward compatibility
# this is just a shim to enable that to work privately in
# the global ColormapRegistry
_colormaps._allow_override_builtin = override_builtin
_colormaps.register(cmap, name=name, force=override_builtin)
_colormaps._allow_override_builtin = False


def _get_cmap(name=None, lut=None):
"""
Get a colormap instance, defaulting to rc values if *name* is None.

Parameters
----------
name : `~matplotlib.colors.Colormap` or str or None, default: None
If a `.Colormap` instance, it will be returned. Otherwise, the name of
a colormap known to Matplotlib, which will be resampled by *lut*. The
default, None, means :rc:`image.cmap`.
lut : int or None, default: None
If *name* is not already a Colormap instance and *lut* is not None, the
colormap will be resampled to have *lut* entries in the lookup table.

Returns
-------
Colormap
"""
if name is None:
name = mpl.rcParams['image.cmap']
if isinstance(name, colors.Colormap):
return name
_api.check_in_list(sorted(_colormaps), name=name)
if lut is None:
return _colormaps[name]
else:
return _colormaps[name].resampled(lut)

# do it in two steps like this so we can have an un-deprecated version in
# pyplot.
get_cmap = _api.deprecated(
'3.7',
name='get_cmap',
alternative=(
"``matplotlib.colormaps[name]`` " +
"or ``matplotlib.colormaps.get_cmap(obj)``"
)
)(_get_cmap)


@_api.deprecated("3.7",
alternative="``matplotlib.colormaps.unregister(name)``")
def unregister_cmap(name):
"""
Remove a colormap recognized by :func:`get_cmap`.

You may not remove built-in colormaps.

If the named colormap is not registered, returns with no error, raises
if you try to de-register a default colormap.

.. warning::

Colormap names are currently a shared namespace that may be used
by multiple packages. Use `unregister_cmap` only if you know you
have registered that name before. In particular, do not
unregister just in case to clean the name before registering a
new colormap.

Parameters
----------
name : str
The name of the colormap to be un-registered

Returns
-------
ColorMap or None
If the colormap was registered, return it if not return `None`

Raises
------
ValueError
If you try to de-register a default built-in colormap.
"""
cmap = _colormaps.get(name, None)
_colormaps.unregister(name)
return cmap


def _auto_norm_from_scale(scale_cls):
"""
Automatically generate a norm class from *scale_cls*.
Expand Down
2 changes: 0 additions & 2 deletions lib/matplotlib/cm.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ class ColormapRegistry(Mapping[str, colors.Colormap]):

_colormaps: ColormapRegistry = ...

def get_cmap(name: str | colors.Colormap | None = ..., lut: int | None = ...) -> colors.Colormap: ...

class ScalarMappable:
cmap: colors.Colormap | None
colorbar: Colorbar | None
Expand Down
42 changes: 29 additions & 13 deletions lib/matplotlib/pyplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@
from matplotlib.scale import get_scale_names # noqa: F401

from matplotlib.cm import _colormaps
from matplotlib.cm import register_cmap # type: ignore # noqa: F401
from matplotlib.colors import _color_sequences
from matplotlib.colors import _color_sequences, Colormap

import numpy as np

Expand Down Expand Up @@ -104,7 +103,6 @@
QuadMesh,
)
from matplotlib.colorbar import Colorbar
from matplotlib.colors import Colormap
from matplotlib.container import (
BarContainer,
ErrorbarContainer,
Expand Down Expand Up @@ -2362,14 +2360,33 @@ def clim(vmin: float | None = None, vmax: float | None = None) -> None:
im.set_clim(vmin, vmax)


# eventually this implementation should move here, use indirection for now to
# avoid having two copies of the code floating around.
def get_cmap(
name: Colormap | str | None = None,
lut: int | None = None
) -> Colormap:
return cm._get_cmap(name=name, lut=lut) # type: ignore
get_cmap.__doc__ = cm._get_cmap.__doc__ # type: ignore
def get_cmap(name: Colormap | str | None = None, lut: int | None = None) -> Colormap:
"""
Get a colormap instance, defaulting to rc values if *name* is None.

Parameters
----------
name : `~matplotlib.colors.Colormap` or str or None, default: None
If a `.Colormap` instance, it will be returned. Otherwise, the name of
a colormap known to Matplotlib, which will be resampled by *lut*. The
default, None, means :rc:`image.cmap`.
lut : int or None, default: None
If *name* is not already a Colormap instance and *lut* is not None, the
colormap will be resampled to have *lut* entries in the lookup table.

Returns
-------
Colormap
"""
if name is None:
name = rcParams['image.cmap']
if isinstance(name, Colormap):
return name
_api.check_in_list(sorted(_colormaps), name=name)
if lut is None:
return _colormaps[name]
else:
return _colormaps[name].resampled(lut)


def set_cmap(cmap: Colormap | str) -> None:
Expand All @@ -2384,8 +2401,7 @@ def set_cmap(cmap: Colormap | str) -> None:
See Also
--------
colormaps
matplotlib.cm.register_cmap
matplotlib.cm.get_cmap
get_cmap
"""
cmap = get_cmap(cmap)

Expand Down
Loading