8000 Merge pull request #29052 from 3j14/fix-colors-from_list · matplotlib/matplotlib@46ea8f0 · GitHub
[go: up one dir, main page]

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 46ea8f0

Browse files
authored
Merge pull request #29052 from 3j14/fix-colors-from_list
FIX: Checks for (value, color) tuples in LinearSegmentedColormap.from_list
2 parents ae47a6e + d9b8020 commit 46ea8f0

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

lib/matplotlib/colors.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"""
4141

4242
import base64
43-
from collections.abc import Sized, Sequence, Mapping
43+
from collections.abc import Sequence, Mapping
4444
import functools
4545
import importlib
4646
import inspect
@@ -1180,7 +1180,8 @@ def from_list(name, colors, N=256, gamma=1.0, *, bad=None, under=None, over=None
11801180
range :math:`[0, 1]`; i.e. 0 maps to ``colors[0]`` and 1 maps to
11811181
``colors[-1]``.
11821182
If (value, color) pairs are given, the mapping is from *value*
1183-
to *color*. This can be used to divide the range unevenly.
1183+
to *color*. This can be used to divide the range unevenly. The
1184+
values must increase monotonically from 0 to 1.
11841185
N : int
11851186
The number of RGB quantization levels.
11861187
gamma : float
@@ -1195,14 +1196,26 @@ def from_list(name, colors, N=256, gamma=1.0, *, bad=None, under=None, over=None
11951196
if not np.iterable(colors):
11961197
raise ValueError('colors must be iterable')
11971198

1198-
if (isinstance(colors[0], Sized) and len(colors[0]) == 2
1199-
and not isinstance(colors[0], str)):
1200-
# List of value, color pairs
1201-
vals, colors = zip(*colors)
1202-
else:
1199+
try:
1200+
# Assume the passed colors are a list of colors
1201+
# and not a (value, color) tuple.
1202+
r, g, b, a = to_rgba_array(colors).T
12031203
vals = np.linspace(0, 1, len(colors))
1204+
except Exception as e:
1205+
# Assume the passed values are a list of
1206+
# (value, color) tuples.
1207+
try:
1208+
_vals, _colors = itertools.zip_longest(*colors)
1209+
except Exception as e2:
1210+
raise e2 from e
1211+
vals = np.asarray(_vals)
1212+
if np.min(vals) < 0 or np.max(vals) > 1 or np.any(np.diff(vals) <= 0):
1213+
raise ValueError(
1214+
"the values passed in the (value, color) pairs "
1215+
"must increase monotonically from 0 to 1."
1216+
)
1217+
r, g, b, a = to_rgba_array(_colors).T
12041218

1205-
r, g, b, a = to_rgba_array(colors).T
12061219
cdict = {
12071220
"red": np.column_stack([vals, r, r]),
12081221
"green": np.column_stack([vals, g, g]),

lib/matplotlib/tests/test_colors.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,3 +1780,34 @@ def test_colorizer_vmin_vmax():
17801780
assert ca.vmax == 3.0
17811781
assert ca.norm.vmin == 1.0
17821782
assert ca.norm.vmax == 3.0
1783+
1784+
1785+
def test_LinearSegmentedColormap_from_list_color_alpha_tuple():
1786+
"""
1787+
GitHub issue #29042: A bug in 'from_list' causes an error
1788+
when passing a tuple (str, float) where the string is a
1789+
color name or grayscale value and float is an alpha value.
1790+
"""
1791+
colors = [("red", 0.3), ("0.42", 0.1), "green"]
1792+
cmap = mcolors.LinearSegmentedColormap.from_list("lsc", colors, N=3)
1793+
assert_array_almost_equal(cmap([.0, 0.5, 1.]), to_rgba_array(colors))
1794+
1795+
1796+
@pytest.mark.parametrize("colors",
1797+
[[(0.42, "blue"), (.1, .1, .1, .1)],
1798+
["blue", (0.42, "red")],
1799+
["blue", (.1, .1, .1, .1), ("red", 2)],
1800+
[(0, "red"), (1.1, "blue")],
1801+
[(0.52, "red"), (0.42, "blue")]])
1802+
def test_LinearSegmentedColormap_from_list_invalid_inputs(colors):
1803+
with pytest.raises(ValueError):
1804+
mcolors.LinearSegmentedColormap.from_list("lsc", colors)
1805+
1806+
1807+
def test_LinearSegmentedColormap_from_list_value_color_tuple():
1808+
value_color_tuples = [(0, "red"), (0.6, "blue"), (1, "green")]
1809+
cmap = mcolors.LinearSegmentedColormap.from_list("lsc", value_color_tuples, N=11)
1810+
assert_array_almost_equal(
1811+
cmap([value for value, _ in value_color_tuples]),
1812+
to_rgba_array([color for _, color in value_color_tuples]),
1813+
)

0 commit comments

Comments
 (0)
0