Add a helper to copy a colormap and set its extreme colors. by anntzer · Pull Request #14645 · matplotlib/matplotlib · GitHub
Skip to content
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
13 changes: 13 additions & 0 deletions doc/users/next_whats_new/2019-06-28-AL.rst
7 changes: 1 addition & 6 deletions examples/images_contours_and_fields/image_masked.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
The second subplot illustrates the use of BoundaryNorm to
get a filled contour effect.
"""
from copy import copy

import numpy as np
import matplotlib.pyplot as plt
Expand All @@ -25,11 +24,7 @@
Z = (Z1 - Z2) * 2

# Set up a colormap:
# use copy so that we do not mutate the global colormap instance
palette = copy(plt.cm.gray)
palette.set_over('r', 1.0)
palette.set_under('g', 1.0)
palette.set_bad('b', 1.0)
palette = plt.cm.gray.with_extremes(over='r', under='g', bad='b')
# Alternatively, we could use
# palette.set_bad(alpha = 0.0)
# to make the bad region transparent. This is the default.
Expand Down
8 changes: 2 additions & 6 deletions examples/images_contours_and_fields/quadmesh_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
This demo illustrates a bug in quadmesh with masked data.
"""

import copy

from matplotlib import cm, pyplot as plt
import numpy as np

Expand All @@ -30,10 +28,8 @@
axs[0].pcolormesh(Qx, Qz, Z, shading='gouraud')
axs[0].set_title('Without masked values')

# You can control the color of the masked region. We copy the default colormap
# before modifying it.
cmap = copy.copy(cm.get_cmap(plt.rcParams['image.cmap']))
cmap.set_bad('y', 1.0)
# You can control the color of the masked region.
cmap = cm.get_cmap(plt.rcParams['image.cmap']).with_extremes(bad='y')
axs[1].pcolormesh(Qx, Qz, Zm, shading='gouraud', cmap=cmap)
axs[1].set_title('With masked values')

Expand Down
5 changes: 2 additions & 3 deletions examples/specialty_plots/leftventricle_bulleye.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,8 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None):
# The second example illustrates the use of a ListedColormap, a
# BoundaryNorm, and extended ends to show the "over" and "under"
# value colors.
cmap3 = mpl.colors.ListedColormap(['r', 'g', 'b', 'c'])
cmap3.set_over('0.35')
cmap3.set_under('0.75')
cmap3 = (mpl.colors.ListedColormap(['r', 'g', 'b', 'c'])
.with_extremes(over='0.35', under='0.75'))
# If a ListedColormap is used, the length of the bounds array must be
# one greater than the length of the color list. The bounds must be
# monotonically increasing.
Expand Down
23 changes: 23 additions & 0 deletions lib/matplotlib/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@

import base64
from collections.abc import Sized
import copy
import functools
import inspect
import io
Expand Down Expand Up @@ -687,6 +688,28 @@ def set_over(self, color='k', alpha=None):
if self._isinit:
self._set_extremes()

def set_extremes(self, *, bad=None, under=None, over=None):
"""
Set the colors for masked (*bad*) values and, when ``norm.clip =
False``, low (*under*) and high (*over*) out-of-range values.
"""
if bad is not None:
self.set_bad(bad)
if under is not None:
self.set_under(under)
if over is not None:
self.set_over(over)

def with_extremes(self, *, bad=None, under=None, over=None):
"""
Return a copy of the colormap, for which the colors for masked (*bad*)
values and, when ``norm.clip = False``, low (*under*) and high (*over*)
out-of-range values, have been set accordingly.
"""
new_cm = copy.copy(self)
new_cm.set_extremes(bad=bad, under=under, over=over)
return new_cm

def _set_extremes(self):
if self._rgba_under:
self._lut[self._i_under] = self._rgba_under
Expand Down
10 changes: 2 additions & 8 deletions lib/matplotlib/tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -799,10 +799,7 @@ def test_mask_image_over_under():
(2 * np.pi * 0.5 * 1.5))
Z = 10*(Z2 - Z1) # difference of Gaussians

palette = copy(plt.cm.gray)
palette.set_over('r', 1.0)
palette.set_under('g', 1.0)
palette.set_bad('b', 1.0)
palette = plt.cm.gray.with_extremes(over='r', under='g', bad='b')
Zm = np.ma.masked_where(Z > 1.2, Z)
fig, (ax1, ax2) = plt.subplots(1, 2)
im = ax1.imshow(Zm, interpolation='bilinear',
Expand Down Expand Up @@ -868,10 +865,7 @@ def test_imshow_endianess():
remove_text=True, style='mpl20')
def test_imshow_masked_interpolation():

cm = copy(plt.get_cmap('viridis'))
cm.set_over('r')
cm.set_under('b')
cm.set_bad('k')
cm = plt.get_cmap('viridis').with_extremes(over='r', under='b', bad='k')

N = 20
n = colors.Normalize(vmin=0, vmax=N*N-1)
Expand Down
11 changes: 4 additions & 7 deletions tutorials/colors/colorbar_only.py