diff --git a/doc/users/next_whats_new/colormap_with_alpha b/doc/users/next_whats_new/colormap_with_alpha new file mode 100644 index 000000000000..7bc9a84618a2 --- /dev/null +++ b/doc/users/next_whats_new/colormap_with_alpha @@ -0,0 +1,5 @@ +Tuning transparency of colormaps +-------------------------------- +The new method `.Colormap.with_alpha` allows to create a new colormap with the same +color values but a new uniform alpha value. This is handy if you want to modify only +the transparency of mapped colors for an Artist. diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index d8954c8e50db..b8a7bf404064 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -943,6 +943,25 @@ def _set_extremes(self): self._lut[self._i_over] = self._lut[self.N - 1] self._lut[self._i_bad] = self._rgba_bad + def with_alpha(self, alpha): + """ + Return a copy of the colormap with a new uniform transparency. + + Parameters + ---------- + alpha : float + The alpha blending value, between 0 (transparent) and 1 (opaque). + """ + if not isinstance(alpha, Real): + raise TypeError(f"'alpha' must be numeric or None, not {type(alpha)}") + if not 0 <= alpha <= 1: + ValueError("'alpha' must be between 0 and 1, inclusive") + new_cm = self.copy() + if not new_cm._isinit: + new_cm._init() + new_cm._lut[:, 3] = alpha + return new_cm + def _init(self): """Generate the lookup table, ``self._lut``.""" raise NotImplementedError("Abstract class only") diff --git a/lib/matplotlib/colors.pyi b/lib/matplotlib/colors.pyi index 9fb758cb146c..3e761c949068 100644 --- a/lib/matplotlib/colors.pyi +++ b/lib/matplotlib/colors.pyi @@ -111,6 +111,7 @@ class Colormap: under: ColorType | None = ..., over: ColorType | None = ... ) -> Colormap: ... + def with_alpha(self, alpha: float) -> Colormap: ... def is_gray(self) -> bool: ... def resampled(self, lutsize: int) -> Colormap: ... def reversed(self, name: str | None = ...) -> Colormap: ... diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 465d9d294a09..bb90806f38ee 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -20,7 +20,7 @@ import matplotlib.scale as mscale from matplotlib.rcsetup import cycler from matplotlib.testing.decorators import image_comparison, check_figures_equal -from matplotlib.colors import is_color_like, to_rgba_array +from matplotlib.colors import is_color_like, to_rgba_array, ListedColormap @pytest.mark.parametrize('N, result', [ @@ -248,6 +248,17 @@ def test_LinearSegmentedColormap_from_list_bad_under_over(): assert mcolors.same_color(cmap.get_over(), "y") +def test_colormap_with_alpha(): + cmap = ListedColormap(["red", "green", ("blue", 0.8)]) + cmap2 = cmap.with_alpha(0.5) + # color is the same: + vals = [0, 0.5, 1] # numeric positions that map to the listed colors + assert_array_equal(cmap(vals)[:, :3], cmap2(vals)[:, :3]) + # alpha of cmap2 is changed: + assert_array_equal(cmap(vals)[:, 3], [1, 1, 0.8]) + assert_array_equal(cmap2(vals)[:, 3], [0.5, 0.5, 0.5]) + + def test_BoundaryNorm(): """ GitHub issue #1258: interpolation was failing with numpy