# How to plot polygons with color assigned according to a continuous colorscale

Hi,

I am trying to plot polygons that are arbitrarily placed in the XY plane and assign a color to each polygon according to a colorscale. So far, I thought of using Heatmap but that didnâ€™t work well because I want to plot arbitrary polygons. I also tried Choropleth but it looks like polygons are overlaid over the world map. The closest I got to achieve what I want is with the following code:

``````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]]

vals = [1, 2]

fig = go.Figure()

for (x,y, v) in zip(x_polygons, y_polygons, vals):

mode = 'none',
fillcolor=px.colors.sequential.Viridis[v],
name = f"v ={v}",
)

)

fig.show()
``````

but I need to interpolate between discrete color values for non-integer values of `vals` and this doesnâ€™t show a colorscale on the side. There must be a better way to achieve what I want but I couldnâ€™t figure it out so far. Any idea?

Hi @bastien,

Welcome to Plotly forum!
plotly.py doesnâ€™t provide a function that maps a value to a color in a colorscale. All these mappings are performed by plotly.js. Recently a similar question was addressed , and these are the proposed solutions: Hover background color on scatter 3d.

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
<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):
mode = 'none',
fillcolor = str(get_colors_for_vals(np.array([v]), vmin, vmax, pl_colors)[0]),
name = f"v ={v}",
)

)
fig.show()
``````

@bastien

If your polygons are rectangular and do not have other shapes you can define them as bars:

``````fig= go.Figure(go.Bar(x=[5, 25], y = [2.5, 2.5], marker_color= [1.1, 2.2], width=10,
marker_cmin=0, marker_cmax=10, marker_colorscale='Viridis',
marker_showscale=True))
``````