matplotlib / matplotlib

matplotlib: plotting with Python
https://matplotlib.org/stable/
20.28k stars 7.65k forks source link

[Bug]: Edgecolor doesn't work with pcolormesh #21825

Open zxdawn opened 2 years ago

zxdawn commented 2 years ago

Bug summary

Edgecolor isn't shown in pcolomesh with matplotlib (3.5.0). It works in 3.2.2.

Code for reproduction

import matplotlib.pyplot as plt 
import numpy as np

Z = np.random.rand(5, 5) 
plt.pcolormesh(Z, cmap='viridis', fc='none', edgecolor='face', lw=5)

Actual outcome

test_3 5 0

Expected outcome

test_3 2 2

Additional information

No response

Operating system

Ubuntu

Matplotlib Version

3.5.0

Matplotlib Backend

QtAgg

Python version

3.8.12

Jupyter version

No response

Installation

conda

jklymak commented 2 years ago

I think that was a deliberate fix - if you set the edge color to be the facecolor and you set the facecolor to "none" I'd expect the edgecolor to also be "none". That this behaved like you see in 3.2.2 I would consider a bug. (probably done in https://github.com/matplotlib/matplotlib/pull/18480)

If you really need this visualization, I could imagine a edgecolor='mapped' as a possible value as well to get back the old behaviour. But it is frankly a unique visualization technique, and perhaps deserving of its own custom method.

zxdawn commented 2 years ago

@jklymak If I use plt.pcolormesh(Z, cmap='viridis', fc='none', edgecolor='mapped', lw=5), it will raise this error:

~/miniconda3/lib/python3.9/site-packages/matplotlib/colors.py in to_rgba_array(c, alpha)
    357 
    358     if isinstance(c, str):
--> 359         raise ValueError("Using a string of single character colors as "
    360                          "a color sequence is not supported. The colors can "
    361                          "be passed as an explicit list instead.")

ValueError: Using a string of single character colors as a color sequence is not supported. The colors can be passed as an explicit list instead.

This visualization is useful when plotting one 2D variable as the backgound and overlaying another 2D variable as edges.

jklymak commented 2 years ago

"Mapped" would be a feature request to get you the behaviour you want, not something that already exists.

greglucas commented 2 years ago

Note, you can get that effect now by using None for edgecolor. plt.pcolormesh(Z, cmap='viridis', fc='none', edgecolor=None, lw=5)

See here for a good example of the options: https://github.com/matplotlib/matplotlib/pull/18480#issuecomment-751126066 Maybe something like that should be added to the docs/examples somewhere similar to the Quadmesh shading argument...

zxdawn commented 2 years ago

@greglucas Ha, thanks! The difference between 'none' and None is confusing, hah.

greglucas commented 2 years ago

Yes, I agree it is. In matplotlib, None is generally taken to meant "use the default value", and "none" the string is meant to be "don't draw this".

jklymak commented 2 years ago

Hah, thats great @greglucas Thanks!

jklymak commented 2 years ago

Sorry, I shouldn't have closed this. This has a reasonable todo in that there could/should be a defining example of the different combinations.

zxdawn commented 2 years ago

I'm not sure whether I find another issue. The facecolor can't be manually changed by color=(....). Here's the question I posted on StackOverflow.

jklymak commented 2 years ago

Yes, that is a different issue. I'm 95% certain there is an open issue for rgba pcolormesh, but that feature does not currently exist.