Skip to content

pcolormesh support for masked arrays is incomplete #14327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
efiring opened this issue May 26, 2019 · 8 comments
Closed

pcolormesh support for masked arrays is incomplete #14327

efiring opened this issue May 26, 2019 · 8 comments

Comments

@efiring
Copy link
Member

efiring commented May 26, 2019

Bug report

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:

import matplotlib.pyplot as plt
import numpy as np

def test_pcolormesh():
    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()

    # The color array can include masked values:
    Zm = np.ma.masked_where(np.abs(Qz) < 0.5 * np.max(Qz), Z)

    fig, axs = plt.subplots(2, 3)
    kw = dict(vmin=0, vmax=1)
    for ax, zz in zip(axs, [Z, Zm]):
        ax[0].pcolormesh(Qx, Qz, zz, lw=0.5, edgecolors='k', **kw)
        ax[1].pcolormesh(Qx, Qz, zz, lw=2, edgecolors=['b', 'w'], **kw)
        ax[2].pcolormesh(Qx, Qz, zz, shading="gouraud", **kw)
    return fig

fig = test_pcolormesh()
fig.savefig('test_pcolormesh.png')
fig.savefig('test_pcolormesh.pdf')

Actual outcome
The pdf (converted to a png for display here) is black in the masked region with gouraud shading:
test_pcolormesh_from_pdf
but the png is as expected.
test_pcolormesh

@anntzer
Copy link
Contributor

anntzer commented May 26, 2019

At the risk of sounding like a broken record, this is also fixed by mplcairo :p

@timhoffm
Copy link
Member

timhoffm commented 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:

  • 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.

@efiring
Copy link
Member Author

efiring commented 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
Copy link
Member Author

efiring commented 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
Copy link
Member

jkseppan commented 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
Copy link
Member

jkseppan commented 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')

testing

@jkseppan
Copy link
Member

jkseppan commented Jun 2, 2019

See #14414

@efiring
Copy link
Member Author

efiring commented Jun 6, 2019

Closed by #14414

@efiring efiring closed this as completed Jun 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants