-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add new method Colormap.with_alpha() #29525
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
Conversation
fe27630
to
680bf7c
Compare
badc5b9
to
cbee37d
Compare
new_cm = self.copy() | ||
if not new_cm._isinit: | ||
new_cm._init() | ||
new_cm._lut[:, 3] = alpha |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has the unintended(?) consequence of allowing an array as well. If that array is the wrong size, folks are going to perhaps get cryptic size mismatch errors? Did we want to give thought to handling that, or just wait and see if it's a problem in real life? I'm actually unsure of how a user would get how big the lookup table is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I’m aware of this. I’ve intentionally specified this as float in the docstring and type annotation. Every other possibility accepted value is an implementation detail. I didn’t want to explicitly check for array and raise on that.
I’m also unsure how helpful a per-element alpha is. I assume varying alpha in a color map is less used compared to making the whole mapping semi-transparent.
Therefore, I’ve not included official varying alpha support for now. We can always later expand on it and also then decide whether the implementation just stays as is or whether we want additional safety checks and better error handling for arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll chime in here and say that I sometimes do use varying alpha in colormaps. This is useful for hiding/washing-out less important features/regions. Making a linear ramp that goes from 0.2-> 1 or something like that along with the low-high values. You can do that here with: alpha=np.linspace(0.2, 1, cmap.N)
(are we getting rid of N though?) You can also imagine wanting to make the center white region of the RdBu transparent instead of just white, so a triangular ramp is helpful on diverging colormaps.
Example I added to mplcairo where the rendering of varying alpha between patches is better than with Agg: https://github.com/matplotlib/mplcairo/blob/247583de20b94d5c1a0d773e720d64e741b122df/examples/quadmesh.py#L22-L26
All this to say, I think the varying alpha is a useful feature, and making it easier would be nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you've already got a nice enough way of doing that here? I guess I'm thinking that it might be helpful to do as Jody mentioned and put some validation on alpha right away. Raise if it is not a float(s) between 0-1 or if it is of a different length than N.
We also have the colorbar set_alpha method, so might be worth also thinking about how this will play with that (I think that colorbar.set_alpha() still wins on the colorbar, but the collections would be mapped with the cmap alpha here)
https://matplotlib.org/stable/api/colorbar_api.html#matplotlib.colorbar.Colorbar.set_alpha
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please focus on getting this through quickly as a minimal public API, so that #29044 can move forward?
I’m happy to discuss arrays, validation and Colorbar alpha in a follow-up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure of the urgency here to avoid changing a visual test.
We have a continual problem with the color/alpha/facecolor/edgecolor dance - maybe this is the solution, but it doesn't seem right. OTOH, adding more ways to sculpt colormaps seems like a net positive regardless of the current issue that spurred this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a continual problem with the color/alpha/facecolor/edgecolor dance - maybe this is the solution, but it doesn't seem right.
I don't understand the second half. If "this" means this PR, it's not supposed to solve any general problem with color/alpha/facecolor/edgecolor. This PR is a simple and straight forward extension of the Colormap functionality. It was motivated through a specific test in another PR that could better be written using this functionality. Not more not less.
I've added a range check for the float. I don't oversee whether array alpha is a meaningful API, in particular in the context of LinearSegementedColormap, where the lookup-table is basically an implementation detail. Therefore I want to keep things simple here.
cbee37d
to
2b12be4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good minimal update, and the check also removed the option of allowing an array alpha for now too so that can be revisited later.
alpha : float | ||
The alpha blending value, between 0 (transparent) and 1 (opaque). | ||
""" | ||
if not 0 <= alpha <= 1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is going to return ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
is someone inputs an array.
if not 0 <= alpha <= 1: | |
if (len(alpha) > 1) or (not 0 <= alpha <= 1)): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your observation on the error is correct, and to me this is intended. What's wrong with that? / What would you expect instead? I can't make sense of the suggestion, because it would raise on floats ("object of type 'float' has no len()").
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is cryptic if someone passes an utterable iterable. You probably want something like:
if (isinstance(x, Iterable) and hasattr(x, "__len__") and len(alpha) > 1):
raise(ValueError, 'alpha must be a single value, not a list or array')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, we don't jump extra hoops to catch types that are not supported and give them a nicer error message.
But granted, Artist.set_alpha
does something similar, so I've taken the same approach as there.
We currently do not have a way of adjusting only the transparency of the mapped colors of the artist, e.g. the fill in contourf(). The Artist alpha parameter also affects lines and hatches. The simplest solution is to support creating semi-transparent colormaps, which can then be used via `contourf(..., cmap=plt.colormaps['jet'].with_alpha(0.5))`. See also matplotlib#29044 (comment).
2b12be4
to
226b2f2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to self merge if green
Co-authored-by: Elliott Sales de Andrade <[email protected]>
We currently do not have a way of adjusting only the transparency of the
mapped colors of the artist, e.g. the fill in contourf(). Using the object-wide
Artist alpha parameter is not a solution as it also affects lines and hatches.
The simplest solution is to support creating semi-transparent colormaps, which can then be used via
contourf(..., cmap=plt.colormaps['jet'].with_alpha(0.5))
. See also #29044 (comment).Side-note: This is the minimal implementation for applying one global override. One could imagine other ways like merging with the existing alpha or providing an array of individual alpha values. I intentionally kept this PR focus and think that the overwrite behavior should be the default. One can later add optional parameters to allow for alpha-merging if desired.