Skip to content

Commit 5258ffc

Browse files
authored
Merge pull request matplotlib#26096 from greglucas/sm-masked-rgba
FIX: Handle masked arrays for RGBA input with ScalarMappables
2 parents 7ad3bc2 + 3b710eb commit 5258ffc

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``ScalarMappable.to_rgba()`` now respects the mask of RGB(A) arrays
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Previously, the mask was ignored. Now the alpha channel is set to 0 if any
4+
component (R, G, B, or A) is masked.

lib/matplotlib/cm.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ def to_rgba(self, x, alpha=None, bytes=False, norm=True):
450450
treated as an RGB or RGBA array, and no mapping will be done.
451451
The array can be `~numpy.uint8`, or it can be floats with
452452
values in the 0-1 range; otherwise a ValueError will be raised.
453-
If it is a masked array, the mask will be ignored.
453+
If it is a masked array, any masked elements will be set to 0 alpha.
454454
If the last dimension is 3, the *alpha* kwarg (defaulting to 1)
455455
will be used to fill in the transparency. If the last dimension
456456
is 4, the *alpha* kwarg is ignored; it does not
@@ -493,6 +493,10 @@ def to_rgba(self, x, alpha=None, bytes=False, norm=True):
493493
else:
494494
raise ValueError("Image RGB array must be uint8 or "
495495
"floating point; found %s" % xx.dtype)
496+
# Account for any masked entries in the original array
497+
# If any of R, G, B, or A are masked for an entry, we set alpha to 0
498+
if np.ma.is_masked(x):
499+
xx[np.any(np.ma.getmaskarray(x), axis=2), 3] = 0
496500
return xx
497501
except AttributeError:
498502
# e.g., x is not an ndarray; so try mapping it

lib/matplotlib/tests/test_colors.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,48 @@ def test_to_rgba_error_with_color_invalid_alpha_tuple():
13531353
mcolors.to_rgba(('blue', 2.0))
13541354

13551355

1356+
@pytest.mark.parametrize("bytes", (True, False))
1357+
def test_scalarmappable_to_rgba(bytes):
1358+
sm = cm.ScalarMappable()
1359+
alpha_1 = 255 if bytes else 1
1360+
1361+
# uint8 RGBA
1362+
x = np.ones((2, 3, 4), dtype=np.uint8)
1363+
expected = x.copy() if bytes else x.astype(np.float32)/255
1364+
np.testing.assert_array_equal(sm.to_rgba(x, bytes=bytes), expected)
1365+
# uint8 RGB
1366+
expected[..., 3] = alpha_1
1367+
np.testing.assert_array_equal(sm.to_rgba(x[..., :3], bytes=bytes), expected)
1368+
# uint8 masked RGBA
1369+
xm = np.ma.masked_array(x, mask=np.zeros_like(x))
1370+
xm.mask[0, 0, 0] = True
1371+
expected = x.copy() if bytes else x.astype(np.float32)/255
1372+
expected[0, 0, 3] = 0
1373+
np.testing.assert_array_equal(sm.to_rgba(xm, bytes=bytes), expected)
1374+
# uint8 masked RGB
1375+
expected[..., 3] = alpha_1
1376+
expected[0, 0, 3] = 0
1377+
np.testing.assert_array_equal(sm.to_rgba(xm[..., :3], bytes=bytes), expected)
1378+
1379+
# float RGBA
1380+
x = np.ones((2, 3, 4), dtype=float) * 0.5
1381+
expected = (x * 255).astype(np.uint8) if bytes else x.copy()
1382+
np.testing.assert_array_equal(sm.to_rgba(x, bytes=bytes), expected)
1383+
# float RGB
1384+
expected[..., 3] = alpha_1
1385+
np.testing.assert_array_equal(sm.to_rgba(x[..., :3], bytes=bytes), expected)
1386+
# float masked RGBA
1387+
xm = np.ma.masked_array(x, mask=np.zeros_like(x))
1388+
xm.mask[0, 0, 0] = True
1389+
expected = (x * 255).astype(np.uint8) if bytes else x.copy()
1390+
expected[0, 0, 3] = 0
1391+
np.testing.assert_array_equal(sm.to_rgba(xm, bytes=bytes), expected)
1392+
# float masked RGB
1393+
expected[..., 3] = alpha_1
1394+
expected[0, 0, 3] = 0
1395+
np.testing.assert_array_equal(sm.to_rgba(xm[..., :3], bytes=bytes), expected)
1396+
1397+
13561398
def test_failed_conversions():
13571399
with pytest.raises(ValueError):
13581400
mcolors.to_rgba('5')

0 commit comments

Comments
 (0)