# Change color of continuous line based on value

Is it possible to get a plot like below ( color line given y axis value as cutoff)

Hi @yogi_dhiman ,

I think there is no built in function for this. There are two possible solutions I came up with, the first does not answer your question but could be a option, the second includes some preparation of your data first.

The first is coloring the markers instead of the line:

import plotly.graph_objects as go
import numpy as np

# generate data
x = np.arange(0, 8*np.pi, 0.1)
y = np.sin(x)

# cutoff value
cutoff = 0

# generate color list
colors=['red' if val < cutoff else 'blue' for val in y]

# create trace
trace = go.Scatter(
x=x,
y=y,
mode='markers+lines',
marker={'color': colors},
line={'color': 'gray'}
)

# crate figure, plot
fig = go.Figure(data=trace)
fig.show()

result:

The second option adds each line segment between two points as a new trace. In proximity to the cutoff value the line color is not correct if one of the two y- values lies above the cutoff and the other y-value lies below the cutoff. If you prepare your data so that this does not occur (i.e serch for those cases and create a midpoint) the line color should be accurate.

import plotly.graph_objects as go
import itertools as it
import numpy as np

# generate data
x = np.arange(0, 8*np.pi, 0.1)
y = np.sin(x)

# cutoff value
cutoff = 0

# create coordinate  pairs
x_pairs = it.pairwise(x)
y_pairs = it.pairwise(y)

# generate color list
colors=['red' if any([i < cutoff for i in y_values]) else 'blue' for y_values in it.pairwise(y)]

# create base figure
fig = go.Figure()

for x, y, color in zip(x_pairs, y_pairs, colors):
go.Scatter(
x=x,
y=y,
mode='lines',
line={'color': color}
)
)

fig.update_layout(showlegend=False)

result:

mrep linecolor

2 Likes

I share a third solution with you, something that I have learned between trials and errors is that NaN values ββare not graphed in this way we could create a line of as many colors as you want and you only need to add a line for each color, having a base arrangement we separate it in as many arrays as colors you want filling each array with values ββwhen certain conditions are met and putting NaN when they are not.

The following function receives the source array as a parameter and returns two arrays to represent the change of direction in the graph.

sellline = [],
isSell = issell,
start = source.length - 3

if(source[start + 1] > source[start + 2]) {
sellline = [NaN, NaN]
}
else {
sellline = source.slice(source.length - 2)
}

for(let i = start; i >= 0; i -= 1) {
isBuy = (source[i] > source[i + 1]) && (source[i + 1] < source[i + 2])
}

if(!isSell) {
isSell = (source[i] < source[i + 1]) && (source[i + 1] > source[i + 2])
}

sellline.unshift(sellline[0] != NaN ? source[i] : NaN)
}

sellline.unshift(NaN)
else
sellline.unshift(source[i])
}

sellline.unshift(source[i])
if(sellline[1])
else
}
}

}

And then I just need to graph both arrangements

[{
id: this.id,
name: this.name,
type: 'line',
x: this.x,
xaxis: 'x',
yaxis: `y\${this.yaxi}`,
hoverinfo: 'none',
mode: 'lines',
cliponaxis: true,
visible: true,
opacity: this.opacity,
line: {
shape: 'spline',
smoothing: 0.5,
color: 'green',
width: this.width
}
},{
id: this.id,
name: this.name,
type: 'line',
x: this.x,
y: this.sell,
xaxis: 'x',
yaxis: `y\${this.yaxi}`,
hoverinfo: 'none',
mode: 'lines',
cliponaxis: true,
visible: true,
opacity: this.opacity,
line: {
shape: 'spline',
smoothing: 0.5,
color: 'red',
width: this.width
}
}])

And I only needed two strokes, one for each color, now the next challenge is to draw a cloud of ichimoku