You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Updating the facecolors of a collection before its first draw has no effect #24479
Create e.g. a pathcollection (a scatter plot) not mapping any array, but with directly set colors; then update one of the facecolors before the first draw of the collection. This change has no effect and gets cancelled.
Code for reproduction
importmatplotlib.pyplotaspltsc1=plt.scatter([0, 1, 2], [0, 1, 2], c=["r", "g", "b"])
sc2=plt.scatter([0, 1, 2], [2, 3, 4], c=["r", "g", "b"])
# Update sc1 before the first draw.sc1.get_facecolors()[2] = (0, 0, 0, 1) # i.e. black.plt.gcf().canvas.draw()
# Update sc2 after the first draw.sc2.get_facecolors()[2] = (0, 0, 0, 1) # i.e. blackplt.show()
Actual outcome
Note that the third point of sc1 is incorrectly blue, whereas the third point of sc2 is correctly black.
Expected outcome
Both third points are black.
Additional information
First noted by @chahak13 in #24474 (comment).
I haven't done a full bisect but did check that this broke at some point between 3.3.4 and 3.4.0, and I suspect #18480 introduced the issue (in the changes related to update_scalarmappable); attn @efiring.
This is not a bug. There was never any intention that one could change the colors by mutating the output of get_facecolors(). If you want to change the colors, you need to use the setter.
importmatplotlib.pyplotaspltsc1=plt.scatter([0, 1, 2], [0, 1, 2], c=["r", "g", "b"])
# Update sc1 before the first draw.fc=sc1.get_facecolors()
fc[0] = (0, 0, 0, 1) # i.e. black. instead of redsc1.set_facecolors(fc)
plt.gcf().canvas.draw()
plt.show()
Ah, thanks for pointing this out.
Do you think get_facecolors() could return e.g. a read-only view on the colors to prevent the users from getting this wrong? Or at least the limitation should be documented. (Note that the limitation is somewhat subtle, as directly mutating the array will sometimes work (e.g. after a draw has been triggered, AFAICT).
Just for slightly more concrete discussion of the implementation, the primary thing the setter does (in regards to why just editing the getter's output is insufficient) is store the direct input to self._original_facecolor before actually computing the RGBA array
This is done so that the colors can be recomputed according to what users expect.
Recomputing happens in e.g. set_alpha, but also in update_scalarmappable, which is called directly from draw.
By using the getter, editing and then using the setter, the values used to recompute colors are updated as well.
So while I understand the functions name implies the functions behavior but I believe it might be better to state the difference explicitly as what I had stated in #27233
Would that be a good change? As mentioned in the issue I was attempting to change that but also there were a lot of get and set functions, so just to ask for some opinion
Activity
efiring commentedon Nov 17, 2022
This is not a bug. There was never any intention that one could change the colors by mutating the output of
get_facecolors(). If you want to change the colors, you need to use the setter.anntzer commentedon Nov 17, 2022
Ah, thanks for pointing this out.
Do you think get_facecolors() could return e.g. a read-only view on the colors to prevent the users from getting this wrong? Or at least the limitation should be documented. (Note that the limitation is somewhat subtle, as directly mutating the array will sometimes work (e.g. after a draw has been triggered, AFAICT).
ksunden commentedon Nov 17, 2022
Just for slightly more concrete discussion of the implementation, the primary thing the setter does (in regards to why just editing the getter's output is insufficient) is store the direct input to
self._original_facecolorbefore actually computing the RGBA arrayThis is done so that the colors can be recomputed according to what users expect.
Recomputing happens in e.g.
set_alpha, but also inupdate_scalarmappable, which is called directly fromdraw.By using the getter, editing and then using the setter, the values used to recompute colors are updated as well.
Jacfger commentedon Oct 31, 2023
So while I understand the functions name implies the functions behavior but I believe it might be better to state the difference explicitly as what I had stated in #27233
Would that be a good change? As mentioned in the issue I was attempting to change that but also there were a lot of get and set functions, so just to ask for some opinion