Bug summary
As noted in #8802, the pcolormesh test stages a masked array but does not use it. This is probably because masked array support is broken in PDF output with the gouraud shading option.
Code for reproduction
This is a modification of the test_axes.test_pcolormesh function:
I suspect that the root cause is actually a bit different. ScalarMappable.to_rgba() converts the C values to colors by calling the cmap(C). On a masked array, this returns a regular array with (0, 0, 0, 0) at the masked points:
x = np.ma.masked_equal([0, 0.2, 0, 0.4, 0.6], 0)
plt.get_cmap('jet')(x)
Apparently, the pdf backend does not handle the transparency, which explains the black coloring.
There are two potential issues:
Is it intended that cmap() converts masked arrays into regular arrays? If so, that should be documented. Otherwise, the implementation should be changed.
the pdf backend does not respect transparency.
Edit: Just saw #14313, so converting masked values to (0, 0, 0, 0) is intended. Hence, we should improve that documentation a litte and the issue here is the pdf backend not respecting transparency.
@timhoffm:
Note that the pdf problem is specific to the gouraud shading option of pcolormesh. Apart from that, the pdf backend handles transparency correctly. I suspect the gouraud shading is rarely used.
@jkseppan Is there any chance you could add RGBA support to the draw_gouraud_triangle and draw_gouraud_triangles (and maybe related points) in the pdf backend?
It seems to me that agg is drawing the triangle edges without using the alpha channel for transparency but does apply it to the shading. Can that be the intention? You can see it in the masked-array example above, but even clearer with something like
In [5]: import matplotlib.pyplot as plt
...: import numpy as np
...:
...: n = 12
...: x = np.linspace(-1.5, 1.5, n)
...: y = np.linspace(-1.5, 1.5, n*2)
...: X, Y = np.meshgrid(x, y)
...: Qx = np.cos(Y) - np.cos(X)
...: Qz = np.sin(Y) + np.sin(X)
...: Qx = (Qx + 1.1)
...: Z = np.hypot(X, Y) / 5
...: Z = (Z - Z.min()) / Z.ptp()
...:
...: plt.pcolormesh(Qx, Qz, Z, shading='gouraud', alpha=0.1)
...: plt.savefig('testing.png')
Activity
anntzer commented on May 26, 2019
At the risk of sounding like a broken record, this is also fixed by mplcairo :p
timhoffm commented on May 31, 2019
I suspect that the root cause is actually a bit different. ScalarMappable.to_rgba() converts the C values to colors by calling the cmap(C). On a masked array, this returns a regular array with (0, 0, 0, 0) at the masked points:
x = np.ma.masked_equal([0, 0.2, 0, 0.4, 0.6], 0) plt.get_cmap('jet')(x)results in
array([[0. , 0. , 0. , 0. ], [0. , 0.3 , 1. , 1. ], [0. , 0. , 0. , 0. ], [0.16129032, 1. , 0.80645161, 1. ], [0.80645161, 1. , 0.16129032, 1. ]])Apparently, the pdf backend does not handle the transparency, which explains the black coloring.
There are two potential issues:
Edit: Just saw #14313, so converting masked values to (0, 0, 0, 0) is intended. Hence, we should improve that documentation a litte and the issue here is the pdf backend not respecting transparency.
efiring commented on May 31, 2019
@timhoffm:
Note that the pdf problem is specific to the gouraud shading option of pcolormesh. Apart from that, the pdf backend handles transparency correctly. I suspect the gouraud shading is rarely used.
efiring commented on May 31, 2019
@jkseppan Is there any chance you could add RGBA support to the draw_gouraud_triangle and draw_gouraud_triangles (and maybe related points) in the pdf backend?
jkseppan commented on Jun 2, 2019
I'm taking a look. This seems to be somewhat nontrivial, otherwise Michael would have implemented it in the code originally.
jkseppan commented on Jun 2, 2019
It seems to me that agg is drawing the triangle edges without using the alpha channel for transparency but does apply it to the shading. Can that be the intention? You can see it in the masked-array example above, but even clearer with something like
In [5]: import matplotlib.pyplot as plt ...: import numpy as np ...: ...: n = 12 ...: x = np.linspace(-1.5, 1.5, n) ...: y = np.linspace(-1.5, 1.5, n*2) ...: X, Y = np.meshgrid(x, y) ...: Qx = np.cos(Y) - np.cos(X) ...: Qz = np.sin(Y) + np.sin(X) ...: Qx = (Qx + 1.1) ...: Z = np.hypot(X, Y) / 5 ...: Z = (Z - Z.min()) / Z.ptp() ...: ...: plt.pcolormesh(Qx, Qz, Z, shading='gouraud', alpha=0.1) ...: plt.savefig('testing.png')jkseppan commented on Jun 2, 2019
See #14414
efiring commented on Jun 6, 2019
Closed by #14414