Skip to content

Deprecate cm #27579

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

Closed
wants to merge 14 commits into from
Closed
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
111 changes: 108 additions & 3 deletions ci/mypy-stubtest-allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,127 @@ matplotlib.ticker.LogitLocator.nonsingular
matplotlib.backend_bases._Mode.__new__
matplotlib.units.Number.__hash__

# Property read-write vs read-only weirdness, fix if possible
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additions in this file seem unrelated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look like they are an older version of this file being reintroduced

matplotlib.offsetbox.DraggableBase.canvas
matplotlib.offsetbox.DraggableBase.cids
matplotlib.transforms.BboxTransform.is_separable
matplotlib.transforms.BboxTransformFrom.is_separable
matplotlib.transforms.BboxTransformTo.is_separable
matplotlib.transforms.BlendedAffine2D.is_separable
matplotlib.transforms.CompositeGenericTransform.is_separable
matplotlib.transforms.TransformWrapper.input_dims
matplotlib.transforms.TransformWrapper.is_separable
matplotlib.transforms.TransformWrapper.output_dims

# 3.6 Pending deprecations
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
# 3.8 deprecations
matplotlib.cbook.get_sample_data
matplotlib.contour.ContourSet.allkinds
matplotlib.contour.ContourSet.allsegs
matplotlib.contour.ContourSet.tcolors
matplotlib.contour.ContourSet.tlinewidths
matplotlib.ticker.LogLocator.__init__
matplotlib.ticker.LogLocator.set_params

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

# Aliases (dynamically generated, not type hinted)
matplotlib.collections.Collection.get_aa
matplotlib.collections.Collection.get_antialiaseds
matplotlib.collections.Collection.get_dashes
matplotlib.collections.Collection.get_ec
matplotlib.collections.Collection.get_edgecolors
matplotlib.collections.Collection.get_facecolors
matplotlib.collections.Collection.get_fc
matplotlib.collections.Collection.get_linestyles
matplotlib.collections.Collection.get_linewidths
matplotlib.collections.Collection.get_ls
matplotlib.collections.Collection.get_lw
matplotlib.collections.Collection.get_transOffset
matplotlib.collections.Collection.set_aa
matplotlib.collections.Collection.set_antialiaseds
matplotlib.collections.Collection.set_dashes
matplotlib.collections.Collection.set_ec
matplotlib.collections.Collection.set_edgecolors
matplotlib.collections.Collection.set_facecolors
matplotlib.collections.Collection.set_fc
matplotlib.collections.Collection.set_linestyles
matplotlib.collections.Collection.set_linewidths
matplotlib.collections.Collection.set_ls
matplotlib.collections.Collection.set_lw
matplotlib.collections.Collection.set_transOffset
matplotlib.lines.Line2D.get_aa
matplotlib.lines.Line2D.get_c
matplotlib.lines.Line2D.get_ds
matplotlib.lines.Line2D.get_ls
matplotlib.lines.Line2D.get_lw
matplotlib.lines.Line2D.get_mec
matplotlib.lines.Line2D.get_mew
matplotlib.lines.Line2D.get_mfc
matplotlib.lines.Line2D.get_mfcalt
matplotlib.lines.Line2D.get_ms
matplotlib.lines.Line2D.set_aa
matplotlib.lines.Line2D.set_c
matplotlib.lines.Line2D.set_ds
matplotlib.lines.Line2D.set_ls
matplotlib.lines.Line2D.set_lw
matplotlib.lines.Line2D.set_mec
matplotlib.lines.Line2D.set_mew
matplotlib.lines.Line2D.set_mfc
matplotlib.lines.Line2D.set_mfcalt
matplotlib.lines.Line2D.set_ms
matplotlib.patches.Patch.get_aa
matplotlib.patches.Patch.get_ec
matplotlib.patches.Patch.get_fc
matplotlib.patches.Patch.get_ls
matplotlib.patches.Patch.get_lw
matplotlib.patches.Patch.set_aa
matplotlib.patches.Patch.set_ec
matplotlib.patches.Patch.set_fc
matplotlib.patches.Patch.set_ls
matplotlib.patches.Patch.set_lw
matplotlib.text.Text.get_c
matplotlib.text.Text.get_family
matplotlib.text.Text.get_font
matplotlib.text.Text.get_font_properties
matplotlib.text.Text.get_ha
matplotlib.text.Text.get_name
matplotlib.text.Text.get_size
matplotlib.text.Text.get_style
matplotlib.text.Text.get_va
matplotlib.text.Text.get_variant
matplotlib.text.Text.get_weight
matplotlib.text.Text.set_c
matplotlib.text.Text.set_family
matplotlib.text.Text.set_font
matplotlib.text.Text.set_font_properties
matplotlib.text.Text.set_ha
matplotlib.text.Text.set_ma
matplotlib.text.Text.set_name
matplotlib.text.Text.set_size
matplotlib.text.Text.set_stretch
matplotlib.text.Text.set_style
matplotlib.text.Text.set_va
matplotlib.text.Text.set_variant
matplotlib.text.Text.set_weight
matplotlib.axes._base._AxesBase.get_fc
matplotlib.axes._base._AxesBase.set_fc

# Other dynamic python behaviors not type hinted
matplotlib.rcsetup.defaultParams

# Maybe should be abstractmethods, required for subclasses, stubs define once
matplotlib.tri.*TriInterpolator.__call__
matplotlib.tri.*TriInterpolator.gradient

# Functionally a method call, but actually a class instance, type hinted as former
matplotlib.rcsetup.validate_fillstyle

# TypeVar used only in type hints
matplotlib.backend_bases.FigureCanvasBase._T
matplotlib.backend_managers.ToolManager._T
Expand Down
27 changes: 27 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,27 @@
As part of a `multi-step process
<https://github.com/matplotlib/matplotlib/issues/20853>`_ we are refactoring
the global state for managing the registered colormaps.

In Matplotlib 3.5 we added a `.ColormapRegistry` class and exposed an instance
at the top level as ``matplotlib.colormaps``. The existing top level functions
in `matplotlib.cm` (``get_cmap``, ``register_cmap``, ``unregister_cmap``) were
changed to be aliases around the same instance.

In Matplotlib 3.7 those top level functions were deprecated. 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 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
<.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
2 changes: 1 addition & 1 deletion 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,7 +294,7 @@ 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`,
``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.
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
2 changes: 1 addition & 1 deletion 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,7 +4,7 @@ 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
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.
Expand Down
2 changes: 1 addition & 1 deletion 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,7 +20,7 @@ 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
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.
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
138 changes: 2 additions & 136 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 @@ -229,136 +225,6 @@ def get_cmap(self, 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
# detail.
_colormaps = ColormapRegistry(_gen_cmap_registry())
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
Loading