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

Add deprecation for colormaps #20853

Closed
QuLogic opened this issue Aug 18, 2021 · 19 comments
Closed

Add deprecation for colormaps #20853

QuLogic opened this issue Aug 18, 2021 · 19 comments
Labels
Maintenance Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. topic: color/color & colormaps
Milestone

Comments

@QuLogic
Copy link
Member

QuLogic commented Aug 18, 2021

This is tracking for the next stage of the colormap registry, pulled out of the original PR so that it doesn't get lost. (Originally written by @timhoffm)

Overall goal

The registry is a more natural structure for managing colormaps. We have data and corresponding functions that are tightly related. IMHO it's a much nicer API for the user and easier to extend. And we get rid of some API quirks in the functions like get_cmap(.. lut=...) or the parameter order register_cmap(name, cmap) where name is optional.

Target state

  • the matplotlib.cm colormap functions should eventually be removed:
    • matplotlib.cm.register_cmap(...) - use mpl.colormaps.register(...) instead
    • matplotlib.cm.unregister_cmap(...) - use mpl.colormaps.unregister(...) instead
    • matplotlib.cm.get_cmap(name) - use mpl.colormaps[name] instead, followed by .resampled() if needed to cover get_cmap(lut=...).
  • I'm open for discussion if we keep the pyplot functions or replace them with the registry as well. Suggestion on pyplot:
    • eventually remove plt.register_cmap - use mpl.colormaps.register(...) instead. - This is a fundamental operation and IMHO beyond the scope of pyplot
    • keep plt.get_cmap() - This is too widely used to be removed. But eventually remove its lut parameter in favor of plt.get_cmap().resampled().

Transition path

While I would like to eventually remove the matplotlib.cm functions, I propose a prolonged transition path because they are quite fundamental functions also used in third party libraries:

  • For 3.5: introduce the registry as is in this PR; discourage the cm functions. This is to see if we have missed something important in the design and get user feedback. - Maybe we should declare the registry experimental.
  • For 3.6: Introduce a pending deprecation on all functions that we want to eventually remove. This is the time where all downstream libraries should start switching to using the registry.
  • For 3.7 (or later): Deprecate all the functions we want to remove.
  • For 3.9 (or later): Remove all the functions we want to remove.

I strongly advocate to introduce this PR in 3.5. If everything goes well, we don't need modifications (only extensions) to the registry, which means that downstream libraries would have 3.5 as a minimum dependency when they switch to the registry.

On read-only colormaps

The registry colormap access already returns copies of the colormaps and by that implements the change to get_cmap, which is scheduled to take effect in 3.6 (#19766). He can be quicker here, because the new API does not have to maintain backward compatibility for the deprecation period.
Other than that, the registry is independent of cmap mutability.

Originally posted by @timhoffm in #18503 (comment)

@tacaswell
Copy link
Member

A flaw in our plans is that get_cmap take as second lut argument which we do not have a public API to do. There is a private API for this (cmap._resample() via #5283). I think this is show-stopping to get this done for 3.6.

I'm still going to try and get the PR to do all of this done, but am skeptical we want to force it through.

@timhoffm
Copy link
Member

As written in #23668 (review), it's ok to postpone get_cmap to 3.7 if it's too complicated.

@jklymak
Copy link
Member

jklymak commented Aug 19, 2022

Given that we are linking this issue in the What's New, I'd really appreciate it if the issue was edited to explicitly explain what is being deprecated, and what is replacing it. I've been following this peripherally, and even for me, the comment above, cut and pasted from elsewhere, is too vague for me to understand the roadmap, so I fear that our users are not going to understand it either. Or in #23668 or whatever follows from it, lay it out in the what's new and don't refer to a cryptic issue?

@timhoffm
Copy link
Member

timhoffm commented Aug 19, 2022

@jklymak I've rewritten the "Target state" and "Transition path" paragraphs above. Is that clearer now?

@tacaswell tacaswell modified the milestones: v3.6.0, v3.7.0 Aug 25, 2022
QuLogic added a commit to QuLogic/matplotlib that referenced this issue Dec 30, 2022
QuLogic added a commit to QuLogic/matplotlib that referenced this issue Dec 30, 2022
QuLogic added a commit to QuLogic/matplotlib that referenced this issue Dec 31, 2022
@QuLogic
Copy link
Member Author

QuLogic commented Jan 7, 2023

The deprecation was bumped in #24846 for 3.7; this now moves to 3.9 for the final part.

@Baharis
Copy link

Baharis commented Jun 26, 2023

Colormaps can be still accessed in version 3.7.0 using the following syntax: getattr(matplotlib.cm, 'colormap_name', None) or matplotlib.cm.jet. This seems to be the simplest way to use a default colormap without a try/except block. It also does not raise any DeprecationWarnings. Is this syntax discouraged or expected to be deprecated in the future?

Issue #19609 mentions this disambiguity, but does not really address my question.

@s-banach
Copy link

The deprecation warning says to use matplotlib.colormaps, but there is no file colormaps.py, and my type checker complains "colormaps is not a known member of module matplotlib".
The default colormaps should all be static code, there's no need to do any fancy dynamic stuff that breaks type checkers.

@timhoffm
Copy link
Member

timhoffm commented Jul 21, 2023

colormaps is a private variable in matplotlib.cm, which is imported to public names in the namespaces matplotlib and matplotlib.pyplot. Nothing dynamic. I would have expected that type checkers can handle this.

from matplotlib.cm import _colormaps as colormaps

@ksunden
Copy link
Member

ksunden commented Jul 21, 2023

Note that matplotlib 3.8 (due out soon) will ship with our own type stubs (for the first time) that will help clarify this to type checkers.

from matplotlib.cm import _colormaps as colormaps

Colormaps in the registry are actually a dynamic set of things, that can be changed at run time (and many such as the <name>_r are generated dynamically as well).

Note that most of this implementation was done before static type checking was a thing in Python, and well I have personally invested time into trying to make it better and more usable, there certainly are still (and will be for the foreseeable future) rough edges of the static type checkability of Matplotlib.

(@timhoffm, I think the lack of a __all__ may be making the type checkers ignore the import, but it is included in the pyi file)

@ksunden
Copy link
Member

ksunden commented Jul 21, 2023

(__all__ is in the version of __init__.py on main, but not for any released version)

@s-banach
Copy link

Sorry for sending a grumpy message, and thank you for your thoughtful response.

@timhoffm
Copy link
Member

At least PyCharm seems not to be able to pick up the type also on master:
image

It may be worth reconsidering the setup logic and distribute the CorormapRegistry to matplotlib and pyplot via a function cm._get_colormaps.

@ksunden
Copy link
Member

ksunden commented Jul 22, 2023

Hmmm, my editor integration (powered by pyright), and mypy/pyright cli with default settings at least, are perfectly happy with it:

import matplotlib
from typing import reveal_type

col = matplotlib.colormaps
reveal_type(col)

Mypy cli:

$ mypy test.py
test.py:5: note: Revealed type is "matplotlib.cm.ColormapRegistry"
Success: no issues found in 1 source file

Pyright cli:

$ pyright test.py
/home/kyle/play/test.py
  /home/kyle/play/test.py:5:13 - information: Type of "col" is "ColormapRegistry"
0 errors, 0 warnings, 1 information 

(Editor is literally just inlined version of pyright CLI)

Not sure what pycharm is using to do type checking, but those two are generally considered the biggest ones...

tfardet added a commit to tfardet/mpl_chord_diagram that referenced this issue Dec 17, 2023
`get_cmap` is deprecated, see matplotlib/matplotlib#20853

Co-authored-by: Tanguy Fardet <tanguyfardet@protonmail.com>
Reviewed-on: https://codeberg.org/tfardet/mpl_chord_diagram/pulls/43
Reviewed-by: Guillermo Pérez-Hernández <gph82@noreply.codeberg.org>
@WeatherGod
Copy link
Member

Colormaps can be still accessed in version 3.7.0 using the following syntax: getattr(matplotlib.cm, 'colormap_name', None) or matplotlib.cm.jet. This seems to be the simplest way to use a default colormap without a try/except block. It also does not raise any DeprecationWarnings. Is this syntax discouraged or expected to be deprecated in the future?

Issue #19609 mentions this disambiguity, but does not really address my question.

Re-upping this. I just came across some old code that I'm updating. Is matplotlib.cm.Blues going to break in the near future?

@timhoffm
Copy link
Member

timhoffm commented Feb 8, 2024

There are no concrete plans to remove matplotlib.cm.Blues in the near future. Though I would not recommend using these. matplotlib.colormaps['Blues'] is clearer, only a bit longer and also works for custom registered colormaps. If we remove this, it will get a regular deprecation period, so you'll have two minor versions of heads up.

@QuLogic
Copy link
Member Author

QuLogic commented Feb 9, 2024

I believe this is complete with the merging of #26965.

@QuLogic QuLogic closed this as completed Feb 9, 2024
@geo7
Copy link

geo7 commented Feb 12, 2024

(Edited) for anyone daft like me to replace:

color_map = mpl.cm.get_cmap(name="cool", lut=100)

you can do the following:

color_map = mpl.colormaps["cool"].resampled(100)

@Erotemic
Copy link

Would have been nice to see deprecation warnings for mpl.cm.get_cmap rather than running into errors after it was entirely removed. Maybe I missed them in which case, ignore the noise.

@alhom
Copy link

alhom commented May 22, 2024

Yes, it would have been nice... and it seems related to Python choices for default warnings, though:
https://peps.python.org/pep-0565/

Now that we manually enabled DeprecationWarnings, we also found out that distutils is being deprecated.... which we are currently using to account for deprecated APIs...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Maintenance Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. topic: color/color & colormaps
Projects
None yet
Development

No branches or pull requests