Skip to content

Commit 1c6f993

Browse files
committed
ENH: Accept ('color', alpha) tuple to define a color
1 parent f10d0d1 commit 1c6f993

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

lib/matplotlib/colors.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,13 @@ def _to_rgba_no_colorcycle(c, alpha=None):
315315
*alpha* is ignored for the color value ``"none"`` (case-insensitive),
316316
which always maps to ``(0, 0, 0, 0)``.
317317
"""
318+
if isinstance(c, tuple) and len(c) == 2:
319+
if alpha is None:
320+
c, alpha = c
321+
else:
322+
c = c[0]
323+
if alpha is not None and not 0 <= alpha <= 1:
324+
raise ValueError("'alpha' must be between 0 and 1, inclusive")
318325
orig_c = c
319326
if c is np.ma.masked:
320327
return (0., 0., 0., 0.)
@@ -428,6 +435,11 @@ def to_rgba_array(c, alpha=None):
428435
# Special-case inputs that are already arrays, for performance. (If the
429436
# array has the wrong kind or shape, raise the error during one-at-a-time
430437
# conversion.)
438+
if isinstance(c, tuple) and len(c) == 2:
439+
if alpha is None:
440+
c, alpha = c
441+
else:
442+
c = c[0]
431443
if np.iterable(alpha):
432444
alpha = np.asarray(alpha).ravel()
433445
if (isinstance(c, np.ndarray) and c.dtype.kind in "if"
@@ -464,9 +476,11 @@ def to_rgba_array(c, alpha=None):
464476
return np.array([to_rgba(c, a) for a in alpha], float)
465477
else:
466478
return np.array([to_rgba(c, alpha)], float)
467-
except (ValueError, TypeError):
468-
pass
469-
479+
except (ValueError, TypeError) as e:
480+
if e.__repr__() == """ValueError("'alpha' must be between 0 and 1, """\
481+
"""inclusive")""":
482+
# ValueError is from _to_rgba_no_colorcycle().
483+
raise e
470484
if isinstance(c, str):
471485
raise ValueError(f"{c!r} is not a valid color value.")
472486

lib/matplotlib/tests/test_colors.py

+56
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,62 @@ def test_to_rgba_array_alpha_array():
13011301
assert_array_equal(c[:, 3], alpha)
13021302

13031303

1304+
@pytest.mark.parametrize('rgba_alpha, alpha',
1305+
[(('black', 1), 0.5), (('#000000', 0.5), None)])
1306+
def test_to_rgba_array_color_alpha_tuple(rgba_alpha, alpha):
1307+
"""to_rgba_array() accepts tuple (color, alpha) argument."""
1308+
booleans = mcolors.to_rgba_array(rgba_alpha, alpha=alpha) \
1309+
== mcolors.to_rgba_array('black', alpha=0.5)
1310+
assert booleans.all()
1311+
1312+
1313+
def test_to_rgba_array_color_alpha_tuple_multiple_colors():
1314+
"""to_rgba_array() accepts tuple (array of colors, alpha) argument."""
1315+
color_array = np.array([[1., 1., 1., 1.], [0., 0., 1., 0.]])
1316+
booleans = mcolors.to_rgba_array((color_array, 0.5), alpha=None) \
1317+
== np.array([[1., 1., 1., 0.5], [0., 0., 1., 0.5]])
1318+
assert booleans.all()
1319+
1320+
color_sequence = [[1., 1., 1., 1.], [0., 0., 1., 0.]]
1321+
booleans = mcolors.to_rgba_array((color_sequence, 1), alpha=0.5) \
1322+
== np.array([[1., 1., 1., 0.5], [0., 0., 1., 0.5]])
1323+
assert booleans.all()
1324+
1325+
1326+
@pytest.mark.parametrize('rgba_alpha',
1327+
[('black', -2), ('#000000', -2), ('#000', -2),
1328+
('#000000ff', 2), ((0.0, 0.0, 0.0, 0.0), 2)])
1329+
def test_to_rgba_array_color_alpha_tuple_invalid_alpha(rgba_alpha):
1330+
"""
1331+
to_rgba_array() rejects tuple (color, alpha) argument when
1332+
alpha is not between 0 and 1.
1333+
"""
1334+
with pytest.raises(ValueError, match="'alpha' must be between 0 and 1,"):
1335+
mcolors.to_rgba_array(rgba_alpha)
1336+
1337+
1338+
@pytest.mark.parametrize('rgba_alpha, alpha',
1339+
[(('white', 1), 0.5), (('#ffffff', 1), 0.5),
1340+
(('#ffffff00', 0.5), None),
1341+
(((1.0, 1.0, 1.0, 1.0), 0.5), None)])
1342+
def test_to_rgba_color_alpha_tuple(rgba_alpha, alpha):
1343+
"""to_rgba() accepts tuple (color, alpha) argument."""
1344+
assert mcolors.to_rgba(rgba_alpha, alpha=alpha) \
1345+
== mcolors.to_rgba('white', alpha=0.5)
1346+
1347+
1348+
@pytest.mark.parametrize('rgba_alpha',
1349+
[('blue', -2), ('#0000ff', -2), ('#00f', -2),
1350+
('#0000ffff', 2), ((0.0, 0.0, 1.0, 1.0), 2)])
1351+
def test_to_rgba_color_alpha_tuple_invalid_alpha(rgba_alpha):
1352+
"""
1353+
to_rgba() rejects tuple (color, alpha) argument when alpha
1354+
is not between 0 and 1.
1355+
"""
1356+
with pytest.raises(ValueError, match="'alpha' must be between 0 and 1"):
1357+
mcolors.to_rgba(rgba_alpha)
1358+
1359+
13041360
def test_failed_conversions():
13051361
with pytest.raises(ValueError):
13061362
mcolors.to_rgba('5')

0 commit comments

Comments
 (0)