Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e89114e

Browse filesBrowse files
authored
Merge pull request #14645 from anntzer/with_extremes
Add a helper to copy a colormap and set its extreme colors.
2 parents 03c293b + 05b9573 commit e89114e
Copy full SHA for e89114e

File tree

Expand file treeCollapse file tree

7 files changed

+47
-30
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+47
-30
lines changed
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
`.Colormap.set_extremes` and `.Colormap.with_extremes`
2+
``````````````````````````````````````````````````````
3+
4+
Because the `.Colormap.set_bad`, `.Colormap.set_under` and `.Colormap.set_over`
5+
methods modify the colormap in place, the user must be careful to first make a
6+
copy of the colormap if setting the extreme colors e.g. for a builtin colormap.
7+
8+
The new ``Colormap.with_extremes(bad=..., under=..., over=...)`` can be used to
9+
first copy the colormap and set the extreme colors on that copy.
10+
11+
The new `.Colormap.set_extremes` method is provided for API symmetry with
12+
`.Colormap.with_extremes`, but note that it suffers from the same issue as the
13+
earlier individual setters.

‎examples/images_contours_and_fields/image_masked.py

Copy file name to clipboardExpand all lines: examples/images_contours_and_fields/image_masked.py
+1-6Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
The second subplot illustrates the use of BoundaryNorm to
99
get a filled contour effect.
1010
"""
11-
from copy import copy
1211

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

2726
# Set up a colormap:
28-
# use copy so that we do not mutate the global colormap instance
29-
palette = copy(plt.cm.gray)
30-
palette.set_over('r', 1.0)
31-
palette.set_under('g', 1.0)
32-
palette.set_bad('b', 1.0)
27+
palette = plt.cm.gray.with_extremes(over='r', under='g', bad='b')
3328
# Alternatively, we could use
3429
# palette.set_bad(alpha = 0.0)
3530
# to make the bad region transparent. This is the default.

‎examples/images_contours_and_fields/quadmesh_demo.py

Copy file name to clipboardExpand all lines: examples/images_contours_and_fields/quadmesh_demo.py
+2-6Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
This demo illustrates a bug in quadmesh with masked data.
1010
"""
1111

12-
import copy
13-
1412
from matplotlib import cm, pyplot as plt
1513
import numpy as np
1614

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

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

‎examples/specialty_plots/leftventricle_bulleye.py

Copy file name to clipboardExpand all lines: examples/specialty_plots/leftventricle_bulleye.py
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,8 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None):
162162
# The second example illustrates the use of a ListedColormap, a
163163
# BoundaryNorm, and extended ends to show the "over" and "under"
164164
# value colors.
165-
cmap3 = mpl.colors.ListedColormap(['r', 'g', 'b', 'c'])
166-
cmap3.set_over('0.35')
167-
cmap3.set_under('0.75')
165+
cmap3 = (mpl.colors.ListedColormap(['r', 'g', 'b', 'c'])
166+
.with_extremes(over='0.35', under='0.75'))
168167
# If a ListedColormap is used, the length of the bounds array must be
169168
# one greater than the length of the color list. The bounds must be
170169
# monotonically increasing.

‎lib/matplotlib/colors.py

Copy file name to clipboardExpand all lines: lib/matplotlib/colors.py
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767

6868
import base64
6969
from collections.abc import Sized
70+
import copy
7071
import functools
7172
import inspect
7273
import io
@@ -687,6 +688,28 @@ def set_over(self, color='k', alpha=None):
687688
if self._isinit:
688689
self._set_extremes()
689690

691+
def set_extremes(self, *, bad=None, under=None, over=None):
692+
"""
693+
Set the colors for masked (*bad*) values and, when ``norm.clip =
694+
False``, low (*under*) and high (*over*) out-of-range values.
695+
"""
696+
if bad is not None:
697+
self.set_bad(bad)
698+
if under is not None:
699+
self.set_under(under)
700+
if over is not None:
701+
self.set_over(over)
702+
703+
def with_extremes(self, *, bad=None, under=None, over=None):
704+
"""
705+
Return a copy of the colormap, for which the colors for masked (*bad*)
706+
values and, when ``norm.clip = False``, low (*under*) and high (*over*)
707+
out-of-range values, have been set accordingly.
708+
"""
709+
new_cm = copy.copy(self)
710+
new_cm.set_extremes(bad=bad, under=under, over=over)
711+
return new_cm
712+
690713
def _set_extremes(self):
691714
if self._rgba_under:
692715
self._lut[self._i_under] = self._rgba_under

‎lib/matplotlib/tests/test_image.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_image.py
+2-8Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -799,10 +799,7 @@ def test_mask_image_over_under():
799799
(2 * np.pi * 0.5 * 1.5))
800800
Z = 10*(Z2 - Z1) # difference of Gaussians
801801

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

871-
cm = copy(plt.get_cmap('viridis'))
872-
cm.set_over('r')
873-
cm.set_under('b')
874-
cm.set_bad('k')
868+
cm = plt.get_cmap('viridis').with_extremes(over='r', under='b', bad='k')
875869

876870
N = 20
877871
n = colors.Normalize(vmin=0, vmax=N*N-1)

‎tutorials/colors/colorbar_only.py

Copy file name to clipboardExpand all lines: tutorials/colors/colorbar_only.py
+4-7Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,8 @@
8686
fig, ax = plt.subplots(figsize=(6, 1))
8787
fig.subplots_adjust(bottom=0.5)
8888

89-
cmap = mpl.colors.ListedColormap(['red', 'green', 'blue', 'cyan'])
90-
cmap.set_over('0.25')
91-
cmap.set_under('0.75')
89+
cmap = (mpl.colors.ListedColormap(['red', 'green', 'blue', 'cyan'])
90+
.with_extremes(over='0.25', under='0.75'))
9291

9392
bounds = [1, 2, 4, 7, 8]
9493
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
@@ -114,10 +113,8 @@
114113
fig, ax = plt.subplots(figsize=(6, 1))
115114
fig.subplots_adjust(bottom=0.5)
116115

117-
cmap = mpl.colors.ListedColormap(['royalblue', 'cyan',
118-
'yellow', 'orange'])
119-
cmap.set_over('red')
120-
cmap.set_under('blue')
116+
cmap = (mpl.colors.ListedColormap(['royalblue', 'cyan', 'yellow', 'orange'])
117+
.with_extremes(over='red', under='blue'))
121118

122119
bounds = [-1.0, -0.5, 0.0, 0.5, 1.0]
123120
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.