Skip to content

Commit 5ff1f17

Browse files
committed
Handle single colors in ContourSet
1 parent 4310fff commit 5ff1f17

File tree

3 files changed

+50
-10
lines changed

3 files changed

+50
-10
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Specifying a single color in ``contour`` and ``contourf``
2+
---------------------------------------------------------
3+
4+
`~.Axes.contour` and `~.Axes.contourf` previously accepted a single color
5+
provided it was expressed as a string. This restriction has now been removed
6+
and a single color in any format described in the :ref:`colors_def` tutorial
7+
may be passed.
8+
9+
.. plot::
10+
:include-source: true
11+
:alt: Two-panel example contour plots. The left panel has all transparent red contours. The right panel has all dark blue contours.
12+
13+
import matplotlib.pyplot as plt
14+
15+
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 3))
16+
z = [[0, 1], [1, 2]]
17+
18+
ax1.contour(z, colors=('r', 0.4))
19+
ax2.contour(z, colors=(0.1, 0.2, 0.5))
20+
21+
plt.show()

lib/matplotlib/contour.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,11 @@ def __init__(self, ax, *args,
702702
self._extend_min = self.extend in ['min', 'both']
703703
self._extend_max = self.extend in ['max', 'both']
704704
if self.colors is not None:
705+
if mcolors.is_color_like(self.colors):
706+
color_sequence = [self.colors]
707+
else:
708+
color_sequence = self.colors
709+
705710
ncolors = len(self.levels)
706711
if self.filled:
707712
ncolors -= 1
@@ -718,19 +723,19 @@ def __init__(self, ax, *args,
718723
total_levels = (ncolors +
719724
int(self._extend_min) +
720725
int(self._extend_max))
721-
if (len(self.colors) == total_levels and
726+
if (len(color_sequence) == total_levels and
722727
(self._extend_min or self._extend_max)):
723728
use_set_under_over = True
724729
if self._extend_min:
725730
i0 = 1
726731

727-
cmap = mcolors.ListedColormap(self.colors[i0:None], N=ncolors)
732+
cmap = mcolors.ListedColormap(color_sequence[i0:None], N=ncolors)
728733

729734
if use_set_under_over:
730735
if self._extend_min:
731-
cmap.set_under(self.colors[0])
736+
cmap.set_under(color_sequence[0])
732737
if self._extend_max:
733-
cmap.set_over(self.colors[-1])
738+
cmap.set_over(color_sequence[-1])
734739

735740
# label lists must be initialized here
736741
self.labelTexts = []
@@ -1498,10 +1503,12 @@ def _initialize_x_y(self, z):
14981503
The sequence is cycled for the levels in ascending order. If the
14991504
sequence is shorter than the number of levels, it's repeated.
15001505
1501-
As a shortcut, single color strings may be used in place of
1502-
one-element lists, i.e. ``'red'`` instead of ``['red']`` to color
1503-
all levels with the same color. This shortcut does only work for
1504-
color strings, not for other ways of specifying colors.
1506+
As a shortcut, single color may be used in place of one-element lists, i.e.
1507+
``'red'`` instead of ``['red']`` to color all levels with the same color.
1508+
1509+
.. versionchanged:: 3.10
1510+
Previously a single color had to be expressed as a string, but now any
1511+
valid color format may be passed.
15051512
15061513
By default (value *None*), the colormap specified by *cmap*
15071514
will be used.
@@ -1569,10 +1576,10 @@ def _initialize_x_y(self, z):
15691576
15701577
An existing `.QuadContourSet` does not get notified if
15711578
properties of its colormap are changed. Therefore, an explicit
1572-
call `.QuadContourSet.changed()` is needed after modifying the
1579+
call ``QuadContourSet.changed()`` is needed after modifying the
15731580
colormap. The explicit call can be left out, if a colorbar is
15741581
assigned to the `.QuadContourSet` because it internally calls
1575-
`.QuadContourSet.changed()`.
1582+
``QuadContourSet.changed()``.
15761583
15771584
Example::
15781585

lib/matplotlib/tests/test_contour.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,18 @@ def test_given_colors_levels_and_extends():
171171
plt.colorbar(c, ax=ax)
172172

173173

174+
@pytest.mark.parametrize('color', ['green', ('r', 0.5), (0.1, 0.2, 0.5, 0.3)])
175+
@pytest.mark.parametrize('extend', ['neither', 'both'])
176+
@pytest.mark.parametrize('levels', [[0.5, 1, 1.5], [0.5, 0.75, 1, 1.25, 1.5]])
177+
def test_single_color_and_extend(color, levels, extend):
178+
z = [[0, 1], [1, 2]]
179+
180+
_, ax = plt.subplots()
181+
cs = ax.contour(z, levels=levels, colors=color, extend=extend)
182+
for c in cs.get_edgecolors():
183+
assert same_color(c, color)
184+
185+
174186
@image_comparison(['contour_log_locator.svg'], style='mpl20', remove_text=False)
175187
def test_log_locator_levels():
176188

0 commit comments

Comments
 (0)