HCL-Based Color Scales for plotly

This article shows a series of different plots and figures using the plotly graphing library using color maps based on the colorspace package.

Scatterplot

The following example shows the number of motorbikes recorded by an automatic traffic counting station in the Harz Mountains (Germany), an region very popular with bikers. The number of bikes (y-axis) is plotted against the daily
mean temperature (x-axis) and colored by season using custom colors from a modified version of the HCL-based qualitative color palette “Dark 3”.

from colorspace import qualitative_hcl, dataset 
import pandas as pd
import plotly.express as px

# Loading HarzTraffic data set
df = dataset("HarzTraffic")       

# Palette (modified "Dark 3" sequential palette)
pal = qualitative_hcl("Dark 3", h1 = -150, h2 = 120)

# Creating plot
fig = px.scatter(df, x = "temp", y = "bikes", color = "season",
        labels = {"temp": "daily mean temperature [deg C]", "bikes": "number of bikes"},
        title = "Number of bikes per day given season<br>Sonnenberg, Harz, Germany",    
        color_discrete_sequence = pal.colors(4))
fig.update_traces(marker = dict(size = 7))   
fig.update_layout(template = "plotly_white")
fig.show()

Multi-group histogram

The next example shows a multi-group distribution plot based on the ‘HarzTraffic’ data set where the distribution of the daily maximum temperature is shown given the prevailing season. The colors are based on an adjusted qualitative HCL-based palette using “Dark 3” as template (adjusting hues).

from colorspace import qualitative_hcl, dataset
import plotly.figure_factory as ff
import numpy as np

# Palette to be used
pal = qualitative_hcl("Dark 3", h1 = -180, h2 = 100)

# Loading data
df = dataset("HarzTraffic")

# Creating objects for plotting
group_labels = ["winter", "spring", "summer", "autumn"]
hist_data    = []
for n in group_labels:
    hist_data.append(df.loc[df.season == n, "tempmax"])

# Create distplot with custom bin_size
fig = ff.create_distplot(hist_data, group_labels, bin_size=.2,
          colors = pal.colors(4))
fig.update_layout(template = "plotly_white",
          title_text = "Distribution of daily maximum temperature<br>given season. " +
                       "Sonnenberg, Harz, Germany")
fig.show()
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
Cell In[2], line 18
     15     hist_data.append(df.loc[df.season == n, "tempmax"])
     17 # Create distplot with custom bin_size
---> 18 fig = ff.create_distplot(hist_data, group_labels, bin_size=.2,
     19           colors = pal.colors(4))
     20 fig.update_layout(template = "plotly_white",
     21           title_text = "Distribution of daily maximum temperature<br>given season. " +
     22                        "Sonnenberg, Harz, Germany")
     23 fig.show()

File /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/plotly/figure_factory/_distplot.py:178, in create_distplot(hist_data, group_labels, bin_size, curve_type, colors, rug_text, histnorm, show_hist, show_curve, show_rug)
    175 if rug_text is None:
    176     rug_text = []
--> 178 validate_distplot(hist_data, curve_type)
    179 utils.validate_equal_length(hist_data, group_labels)
    181 if isinstance(bin_size, (float, int)):

File /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/plotly/figure_factory/_distplot.py:47, in validate_distplot(hist_data, curve_type)
     42     raise exceptions.PlotlyError(
     43         "curve_type must be defined as " "'kde' or 'normal'"
     44     )
     46 if not scipy:
---> 47     raise ImportError("FigureFactory.create_distplot requires scipy")

ImportError: FigureFactory.create_distplot requires scipy

Heatmap

Plotting the joint distribution of the daily minimum and maximum temperature (2021-2023) at station Sonnenberg using the sequential HCL-based color palette “YlOrRd” (yellow-orange-red).

from colorspace import sequential_hcl, datasets
import plotly.express as px

# Loading data
df = dataset("HarzTraffic")

fig = px.density_heatmap(df, x = "tempmin", y = "tempmax",
         title = "Joint distribution of daily minimum and maximum tmeperature",
         color_continuous_scale = sequential_hcl("YlOrRd", rev = True)(51))
fig.show()

Alternatively a fully customised sequential palette is used for the following figure, showing the same information as the plot above.

from colorspace import sequential_hcl, dataset
import plotly.express as px

# Loading data
df = dataset("HarzTraffic")

pal = sequential_hcl(h = [330, 170], c = [45, 70, 10],
                     l = [25, 95], power = [0.5, 1.5])

# Creating plot
fig = px.density_heatmap(df, x = "tempmin", y = "tempmax",
         title = "Joint distribution of daily minimum and maximum tmeperature",
         color_continuous_scale = pal.colors(21, rev = True))
fig.show()

Three-dimensional surface

Finally, the example below shows the topographic data of Maunga Whau (Mt Eden) located in the Auckland volcanic field on a 10m by 10m grid using the HCL-based terrain color palette, a multi-hue sequential palette.

from colorspace import terrain_hcl, dataset
import plotly.graph_objects as go
import numpy as np

volcano = dataset("volcano") / 100.

# Custom set of colors to be used
cols = terrain_hcl().colors(51) 

# Plotting data
fig = go.Figure(data = [go.Surface(z = volcano, colorscale = cols)],
                layout = go.Layout(title = "Maunga Whau (Mt Eden)"))
fig.update_layout(template = "plotly_white")
fig.show()