Skip to content

Commit

Permalink
ENH: future proof against matplotlib's evolving API
Browse files Browse the repository at this point in the history
  • Loading branch information
neutrinoceros committed Sep 6, 2022
1 parent 1e76ef9 commit f7dd6fe
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 24 deletions.
4 changes: 2 additions & 2 deletions cmasher/cli_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

# Package imports
import e13tools as e13
from matplotlib import cm as mplcm
import numpy as np

# CMasher imports
from cmasher import __version__
from cmasher.utils import _get_cmap
import cmasher as cmr

# All declaration
Expand Down Expand Up @@ -180,7 +180,7 @@ def cli_lang_usage_r():
def get_cmap(cmap):
# Try to obtain the colormap from MPL
try:
cmap = mplcm.get_cmap(cmap)
cmap = _get_cmap(cmap)

# If this does not work, try to expand given cmap in setuptools-style
except ValueError:
Expand Down
15 changes: 7 additions & 8 deletions cmasher/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
# Package imports
import cmocean as cmo
import matplotlib.pyplot as plt
from matplotlib import cm as mplcm
from matplotlib.colors import ListedColormap as LC
from matplotlib.legend import Legend
import numpy as np
Expand All @@ -21,7 +20,7 @@
from cmasher.utils import (
create_cmap_mod, create_cmap_overview, get_bibtex, get_cmap_list,
get_sub_cmap, import_cmaps, set_cmap_legend_entry, take_cmap_colors,
view_cmap)
view_cmap, _get_cmap)

# Save the path to this directory
dirpath = path.dirname(__file__)
Expand Down Expand Up @@ -49,7 +48,7 @@ class Test_create_cmap_mod(object):
# Test if a standalone module of rainforest can be created
def test_standalone_rainforest(self):
# Obtain the currently registered version of rainforest
cmap_old = mplcm.get_cmap('cmr.rainforest')
cmap_old = _get_cmap('cmr.rainforest')

# Create standalone module for rainforest
cmap_path = create_cmap_mod('rainforest')
Expand All @@ -60,7 +59,7 @@ def test_standalone_rainforest(self):
spec.loader.exec_module(mod)

# Check if the colormap in MPL has been updated
cmap_new = mplcm.get_cmap('cmr.rainforest')
cmap_new = _get_cmap('cmr.rainforest')
assert cmap_new is mod.cmap
assert cmap_old is not cmap_new

Expand All @@ -70,7 +69,7 @@ def test_standalone_rainforest(self):
# Test if a standalone module of infinity can be created
def test_standalone_infinity(self):
# Obtain the currently registered version of infinity
cmap_old = mplcm.get_cmap('cmr.infinity')
cmap_old = _get_cmap('cmr.infinity')

# Create standalone module for infinity
cmap_path = create_cmap_mod('infinity')
Expand All @@ -81,7 +80,7 @@ def test_standalone_infinity(self):
spec.loader.exec_module(mod)

# Check if the colormap in MPL has been updated
cmap_new = mplcm.get_cmap('cmr.infinity')
cmap_new = _get_cmap('cmr.infinity')
assert cmap_new is mod.cmap
assert cmap_old is not cmap_new

Expand Down Expand Up @@ -116,7 +115,7 @@ def test_list_cat(self):

# Test if providing all MPL colormap objects works
def test_mpl_cmaps_objs(self):
cmaps = map(mplcm.get_cmap, mpl_cmaps)
cmaps = map(_get_cmap, mpl_cmaps)
create_cmap_overview(cmaps, sort='perceptual')

# Test if providing all MPL colormap names works
Expand Down Expand Up @@ -215,7 +214,7 @@ def test_CMasher_cmaps(self, cm_name):
# Check if provided cm_name is registered in CMasher and MPL
for name in (cm_name, cm_name+'_r'):
cmr_cmap = getattr(cmr, name)
mpl_cmap = mplcm.get_cmap('cmr.'+name)
mpl_cmap = _get_cmap('cmr.'+name)
assert isinstance(cmr_cmap, LC)
assert isinstance(mpl_cmap, LC)
assert getattr(cmrcm, name) is cmr_cmap
Expand Down
44 changes: 31 additions & 13 deletions cmasher/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
import warnings

# Package imports
from packaging.version import Version
from colorspacious import cspace_converter
from matplotlib import cm as mplcm
from matplotlib.artist import Artist
from matplotlib.collections import LineCollection
from matplotlib.colors import Colormap, ListedColormap as LC, to_hex, to_rgb
from matplotlib.legend import Legend
from matplotlib.legend_handler import HandlerBase
from matplotlib.image import AxesImage
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

Expand All @@ -46,7 +47,7 @@
# Type aliases
CMAP = Union[str, Colormap]
RGB = Union[Iterable[Iterable[Union[float, int]]], Iterable[str]]

MPL_VERSION = Version(mpl.__version__)

# %% HELPER CLASSES
# Define legend handler class for artists that use colormaps
Expand All @@ -72,6 +73,23 @@ def create_artists(self, legend, artist, xdescent, ydescent, width, height,


# %% HELPER FUNCTIONS
# wrap matplotlib.cm API, use non-deprecated API when available
def _get_cmap(name: str) -> Colormap:
if MPL_VERSION >= Version("3.5"):
return mpl.colormaps[name]
else:
# deprecated API
return mpl.cm.get_cmap(name)


def _register_cmap(cmap: Colormap, *, name: Optional[str] = None) -> None:
if MPL_VERSION >= Version("3.5"):
mpl.colormaps.register(cmap, name=name)
else:
# deprecated API
mpl.cm.register_cmap(name=name, cmap=cmap)


# Define function for obtaining the sorting order for lightness ranking
def _get_cmap_lightness_rank(cmap: CMAP) -> Tuple[
int, int, float, float, float, str]:
Expand Down Expand Up @@ -108,7 +126,7 @@ def _get_cmap_lightness_rank(cmap: CMAP) -> Tuple[
"""

# Obtain the colormap
cmap = mplcm.get_cmap(cmap)
cmap = _get_cmap(cmap)
cm_type = get_cmap_type(cmap)

# Determine lightness profile stats for sequential/diverging/cyclic
Expand Down Expand Up @@ -203,7 +221,7 @@ def _get_cmap_perceptual_rank(cmap: CMAP) -> Tuple[
"""

# Obtain the colormap
cmap = mplcm.get_cmap(cmap)
cmap = _get_cmap(cmap)
cm_type = get_cmap_type(cmap)

# Determine perceptual range for sequential/diverging/cyclic
Expand Down Expand Up @@ -503,7 +521,7 @@ def sort(x):
# Loop over all cmaps and add their Colormap objects
for cmap in cmaps:
if isinstance(cmap, str):
cmaps_dict[cm_type].append(mplcm.get_cmap(cmap))
cmaps_dict[cm_type].append(_get_cmap(cmap))
else:
cmaps_dict[cm_type].append(cmap)

Expand All @@ -520,14 +538,14 @@ def sort(x):
for cmap in cmaps:
cm_type = get_cmap_type(cmap)
if isinstance(cmap, str):
cmaps_dict[cm_type].append(mplcm.get_cmap(cmap))
cmaps_dict[cm_type].append(_get_cmap(cmap))
else:
cmaps_dict[cm_type].append(cmap)
else:
# Loop over all cmaps and add their Colormap objects
for cmap in cmaps:
if isinstance(cmap, str):
cmaps_list.append(mplcm.get_cmap(cmap))
cmaps_list.append(_get_cmap(cmap))
else:
cmaps_list.append(cmap)

Expand Down Expand Up @@ -856,7 +874,7 @@ def get_cmap_type(cmap: CMAP) -> str:
"""

# Obtain the colormap
cmap = mplcm.get_cmap(cmap)
cmap = _get_cmap(cmap)

# Get RGB values for colormap
rgb = cmap(np.arange(cmap.N))[:, :3]
Expand Down Expand Up @@ -980,7 +998,7 @@ def get_sub_cmap(
"""

# Obtain the colormap
cmap = mplcm.get_cmap(cmap)
cmap = _get_cmap(cmap)

# Check value of N to determine suffix for the name
suffix = '_sub' if N is None else '_qual'
Expand Down Expand Up @@ -1191,14 +1209,14 @@ def register_cmap(name: str, data: RGB) -> None:
cm_type = get_cmap_type(cmap_mpl)

# Add cmap to matplotlib's cmap list
mplcm.register_cmap(cmap=cmap_mpl)
_register_cmap(cmap=cmap_mpl)
setattr(cmrcm, cmap_cmr.name, cmap_cmr)
cmrcm.__all__.append(cmap_cmr.name)
cmrcm.cmap_d[cmap_cmr.name] = cmap_cmr
cmrcm.cmap_cd[cm_type][cmap_cmr.name] = cmap_cmr

# Add reversed cmap to matplotlib's cmap list
mplcm.register_cmap(cmap=cmap_mpl_r)
_register_cmap(cmap=cmap_mpl_r)
setattr(cmrcm, cmap_cmr_r.name, cmap_cmr_r)
cmrcm.__all__.append(cmap_cmr_r.name)
cmrcm.cmap_d[cmap_cmr_r.name] = cmap_cmr_r
Expand Down Expand Up @@ -1328,7 +1346,7 @@ def take_cmap_colors(
return_fmt = return_fmt.lower()

# Obtain the colormap
cmap = mplcm.get_cmap(cmap)
cmap = _get_cmap(cmap)

# Check if provided cmap_range is valid
if not ((0 <= cmap_range[0] <= 1) and (0 <= cmap_range[1] <= 1)):
Expand Down Expand Up @@ -1388,7 +1406,7 @@ def view_cmap(
"""

# Obtain cmap
cmap = mplcm.get_cmap(cmap)
cmap = _get_cmap(cmap)

# Check if show_grayscale is True
if show_grayscale:
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ colorspacious>=1.1.0
e13tools>=0.9.4
matplotlib>=2.2.4
numpy>=1.16.0

packaging>=20.9

0 comments on commit f7dd6fe

Please sign in to comment.