23

Is it possible to change the line opacity but not the marker opacity? I found that I can set the opacity of the entire line including markers (opacity = .5) and the one of the marker (e.g. marker={"opacity":1}).

As shown in this example:

import plotly
import plotly.graph_objs as go
plotly.offline.init_notebook_mode(connected=True)  # I'm running in a jupyter notebook

x = np.arange(0,10)
ys = [np.random.rand(10) for _ in range(3)]

lines = []
for y in ys:
    line = go.Scatter(x=x, y=y, mode="markers+lines", opacity=.5, marker={'symbol': 'x', 'size': "15", "opacity":1})
    lines.append(line)           
fig = go.Figure(
    data=lines,
    layout=go.Layout(showlegend=True)
)
plotly.offline.iplot(fig)

See result here: current result

My problem is the following: My data points are important, the lines are just visual aid. I want to make the lines .5-opaque but have the markers fully opaque.
However, when I set opacity=.5, marker={'opacity':1} the opacity of the marker is also reduced. (I believe that the marker-opacity is defined in the range [0, line-opacity].

Is there any way I can get the colour of the line and adjust its opacity (perhaps even after creating the line, but before plotting it). I know that I could create two traces, one with the points and one with the lines. However, I would like them to be the same colour without having to manually specify the colours. (The number of traces is varying, so I prefer sticking to the standard mechanism that assigns the different colours)

EDIT: My current solution is to set the line-width to 0.5 so it looks better, but obviously this solution works for me and might not be useful to people who want bold and less opaque lines.

EDIT: Github issue concerning this problem/feature request/behaviour: https://github.com/plotly/plotly.js/issues/2684

stklik
  • 834
  • 1
  • 8
  • 19
  • Seems like a bug, since parent properties are still getting updated to child properties, even though the child properties are getting set, can you raise it up with the plotly team? Are you interested in a solution with two traces, one for marker and one for line? – Naren Murali May 30 '18 at 18:05
  • @NarenMurali I thought of the two traces as a backup. I'm posting because I was interested in an 'official' solution. – stklik May 31 '18 at 08:39
  • 1
    Just as a fallback, please raise an issue ticket [here](https://github.com/plotly/plotly.js/issues), they might give some advice, but I think they should ignore the opacity of the trace, if they specify the opacity of the marker! – Naren Murali May 31 '18 at 08:43

2 Answers2

25

TL;DR - one could use: line=dict(color='rgba(255, 0, 0, 0.5)') - example from @david Parks

Line objects don't have opacity attributes but you can assign colors using RGBA and set the alpha. You have to assign a color for the markers using RGBA or it will inherit from the line.

In the following example, I create three random lines with random colors. I then assign the same color to the markers and lines but use string concatenation to change the opacity on the lines versus the markers. The markers will be fully opaque while the lines will be 80% transparent.

import plotly
import numpy as np
import plotly.graph_objs as go

plotly.offline.init_notebook_mode(connected=True)
x = np.arange(0,10)
ys = [np.random.rand(10) for _ in range(3)]

lines = []
dots = []
for y in ys:
    my_color = ('rgba('+str(np.random.randint(0, high = 256))+','+
                str(np.random.randint(0, high = 256))+','+
                str(np.random.randint(0, high = 256)))
    # my_color := "rgba( 143, 82, 244"
    line = go.Scatter(
            x=x, 
            y=y, 
            mode="lines+markers", 
            marker={ 
                    'symbol': 'x', 
                    'size': "15", 
                    'color':my_color+',1)' # "rgba( 143, 82, 244,1)"
                    },
            line={
                "color":my_color+',0.2)'
            })
    lines.append(line)  

fig = go.Figure(
    data=lines,
    layout=go.Layout(showlegend=True)
)
plotly.offline.iplot(fig)

enter image description here

lwileczek
  • 2,084
  • 18
  • 27
  • 1
    Your solution does not work (for me at least). The documentation does not mention `opacity` as an attribute of the line and an attempt to set it results in `PlotlyDictKeyError: 'opacity' is not allowed in 'line'` – stklik May 31 '18 at 08:42
  • 1
    @iwileczek this works, but makes the markers a different color from the line. It would be interesting to do this step as a form of post-processing after getting the chosen line-color and applying rgba-transformations on them. Also check out the Github Issue where I requested an official feature without having to set the general colour manually. – stklik May 31 '18 at 14:28
  • you could make them the same by concatenating strings. See edits. – lwileczek May 31 '18 at 14:36
  • 2
    A simplified example: `line=dict(color='rgba(255, 0, 0, 0.5)')` creates a red line, half opacity. – David Parks Apr 08 '20 at 23:44
5

Here is the link of the best answer I found : https://github.com/plotly/plotly.js/issues/2684#issuecomment-641023041 , where you use a function to convert color under hex format to rgba format that enables defining alpha opacity on last argument as mentioned on other answers.

def hex_to_rgba(h, alpha):
    '''
    converts color value in hex format to rgba format with alpha transparency
    '''
    return tuple([int(h.lstrip('#')[i:i+2], 16) for i in (0, 2, 4)] + [alpha])

Then you can use it with

import plotly.graph_objects as go
import plotly.express as px
COLORS = px.colors.qualitative.D3

hex_color = COLORS[0]  # Blue

traces = [
    go.Scatter(
        x=[0, 1],
        y=[0, 1],
        name='Identity line',
        showlegend=False,
        line=dict(
            color='rgba' + str(hex_to_rgba(
                h=hex_color,
                alpha=0.25
            )),
            width=2,
            dash='dash'
        ),
        marker=dict(
            size=7,
            symbol='circle',
            color='rgba' + str(hex_to_rgba(
                h=hex_color,
                alpha=1
            ))
        ),
    )
]

layout = go.Layout(template='simple_white')
figure = go.Figure(data=traces, layout=layout)
figure.show()

So here for blue color : hex format is '#1F77B4' and rgba format is 'rgba(31, 119, 180, 0.5)'

Yasser Sami
  • 101
  • 1
  • 5