plotly.py icon indicating copy to clipboard operation
plotly.py copied to clipboard

Bar plot has bad additive color algebra when opacity<1

Open mcstarioni opened this issue 2 years ago • 2 comments

I need to plot a few histograms and for aethetical reasons i prefer to make them semi-transparent and in overlay mode. I have a problem with how plotly handles color additions. I am aware that there is an additive color scheme and subtractive color scheme. I am not sure what scheme in used when plotly combines semi-transparent colors, but the result is absolutely unsatisfactory. What i expected: Given 2 original colors "#FD3216", "#00FE35". Mix them in 3'd color like in this site, then display it with given opacity. I expect it to be "#7e9825", but with opacity. Same for dark and light modes. What i got: In dark - "#37BD2B", in light "#4DD341". In dark mode the color is almost indestinguishable from one of parent colors, for almost any color sequence.

Here is the code to reproduce the issue:

import torch
from plotly import graph_objects as go, colors

clr_seq = iter(colors.qualitative.Light24)
N_bins = 20
distributions = {'A': torch.normal(0, 1, [1000]),
                 'B': torch.normal(1, 2, [1000]),}
fig = go.Figure()
for k, v in distributions.items():
    fig.add_bar(
        **dict(zip('yx', torch.histogram(
            v, N_bins, range=[-5, 5]))),
        name=k, marker_opacity=0.7, marker_color=next(clr_seq))
fig.update_layout(barmode='overlay', template='plotly_white')
fig.show()

image image image

mcstarioni avatar Nov 08 '23 14:11 mcstarioni

Also i have spotted with lower opactiy, color blending gets better:

import torch
from plotly import graph_objects as go, colors
from plotly.subplots import make_subplots

N_bins = 20
distributions = {'A': torch.normal(0, 2, [1000]),
                 'B': torch.normal(3, 2, [1000]),
                 'C': torch.normal(-3, 2, [1000])}
# fig = go.Figure()
fig = make_subplots(rows=1, cols=2)
for c, opacity in zip([1, 2], [0.1, 0.7]):
    clr_seq = iter(colors.qualitative.Light24)
    for k, v in distributions.items():
        fig.add_bar(
            **dict(zip('yx', torch.histogram(
                v, N_bins, range=[-7, 7]))),
            name=f'{k}_{c}', marker_opacity=opacity,
            marker_color=next(clr_seq), row=1, col=c)

fig.update_layout(barmode='overlay', template='plotly_white')
fig.show()

image image image

So question is how can we keep color blending like on the left part, but increase its color intensity to levels of the right part?

mcstarioni avatar Nov 08 '23 15:11 mcstarioni

Thank you for creating this issue, @mcstarioni . We don't do the blending ourselves, that’s handled by the browser. If you are able to identify certain CSS settings that would make this better, we could consider it as a new feature request.

Coding-with-Adam avatar Nov 08 '23 16:11 Coding-with-Adam

Hi - we are tidying up stale issues and PRs in Plotly's public repositories so that we can focus on things that are still important to our community. Since this one has been sitting for a while, I'm going to close it; if it is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. If you'd like to submit a PR, we'd be happy to prioritize a review, and if it's a request for tech support, please post in our community forum. Thank you - @gvwilson

gvwilson avatar Jul 11 '24 17:07 gvwilson

@gvwilson Hello, im using version of Plotly '5.9.0' and issue is still there. I found a simple one line css that solves it: .trace.bars{ mix-blend-mode: multiply; }

Before: image After: image Also another variant that is good is mix-blend-mode: lighten; image

Must be a simple fix.

mcstarioni avatar Jul 16 '24 15:07 mcstarioni