Thanks @empet!
I could get what I want after adapting the code you pointed at to my use case. There’s no colorscale on the side of the plot but I can show the value on hover and I suppose I could make up one using subplot if I really needed to. Here is the modified code snippet:
####### Functions to color polygons according to a colorscale ######
def hex_to_rgb(value):
"""Convert a hex-formatted color to rgb, ignoring alpha values."""
value = value.lstrip("#")
return [int(value[i:i + 2], 16) for i in range(0, 6, 2)]
def rbg_to_hex(c):
"""Convert an rgb-formatted color to hex, ignoring alpha values."""
return f"#{c[0]:02x}{c[1]:02x}{c[2]:02x}"
def get_colors_for_vals(vals, vmin, vmax, colorscale, return_hex=True):
"""Given a float array vals, interpolate based on a colorscale to obtain
rgb or hex colors. Inspired by
`user empet's answer in \
<community.plotly.com/t/hover-background-color-on-scatter-3d/9185/6>`_."""
from numbers import Number
from ast import literal_eval
if vmin >= vmax:
raise ValueError("`vmin` should be < `vmax`.")
if (len(colorscale[0]) == 2) and isinstance(colorscale[0][0], Number):
scale, colors = zip(*colorscale)
else:
scale = np.linspace(0, 1, num=len(colorscale))
colors = colorscale
scale = np.asarray(scale)
if colors[0][:3] == "rgb":
colors = np.asarray([literal_eval(color[3:]) for color in colors],
dtype=np.float_)
elif colors[0][0] == "#":
colors = np.asarray(list(map(hex_to_rgb, colors)), dtype=np.float_)
else:
raise ValueError("This colorscale is not supported.")
colorscale = np.hstack([scale.reshape(-1, 1), colors])
colorscale = np.vstack([colorscale, colorscale[0, :]])
colorscale_diffs = np.diff(colorscale, axis=0)
colorscale_diff_ratios = colorscale_diffs[:, 1:] / colorscale_diffs[:, [0]]
colorscale_diff_ratios[-1, :] = np.zeros(3)
vals_scaled = (vals - vmin) / (vmax - vmin)
left_bin_indices = np.digitize(vals_scaled, scale) - 1
left_endpts = colorscale[left_bin_indices]
vals_scaled -= left_endpts[:, 0]
diff_ratios = colorscale_diff_ratios[left_bin_indices]
vals_rgb = (
left_endpts[:, 1:] + diff_ratios * vals_scaled[:, np.newaxis] + 0.5
).astype(np.uint8)
if return_hex:
return list(map(rbg_to_hex, vals_rgb))
return [f"rgb{tuple(v)}" for v in vals_rgb]
#####################
import plotly
import numpy as np
import plotly.graph_objects as go
x_polygons = [[20.0, 30.0, 30.0, 20.0, 20.0], [0, 10, 10, 0, 0]]
y_polygons=[[2.5, 2.5, -2.5, -2.5, 2.5], [2.5, 2.5, -2.5, -2.5, 2.5]]
values = [1.1 , 2.2]
vmin = 0 #values.min()
vmax = 10 #values.max()
pl_colors = plotly.colors.sequential.Viridis
fig = go.Figure()
for (x, y, v) in zip(x_polygons, y_polygons, values):
fig.add_trace( go.Scatter(x=x, y=y, fill="toself",
mode = 'none',
fillcolor = str(get_colors_for_vals(np.array([v]), vmin, vmax, pl_colors)[0]),
name = f"v ={v}",
)
)
fig.show()