✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

NEW! Google-AI Turbo colorscale

Turbo colorscale is a Plotly version of the Google-AI Turbo colormap https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html:

turbo = [[0.0, '#30123b'],
 [0.071, '#4145ab'],
 [0.143, '#4675ed'],
 [0.214, '#39a2fc'],
 [0.286, '#1bcfd4'],
 [0.357, '#24eca6'],
 [0.429, '#61fc6c'],
 [0.5, '#a4fc3b'],
 [0.571, '#d1e834'],
 [0.643, '#f3c63a'],
 [0.714, '#fe9b2d'],
 [0.786, '#f36315'],
 [0.857, '#d93806'],
 [0.929, '#b11901'],
 [1.0, '#7a0402']]

turbo_r = [[0.0, '#7a0402'],
 [0.071, '#b11901'],
 [0.143, '#d93806'],
 [0.214, '#f36315'],
 [0.286, '#fe9b2d'],
 [0.357, '#f3c63a'],
 [0.429, '#d1e834'],
 [0.5, '#a1fc3d'],
 [0.571, '#61fc6c'],
 [0.643, '#24eca6'],
 [0.714, '#1bcfd4'],
 [0.786, '#39a2fc'],
 [0.857, '#4675ed'],
 [0.929, '#4145ab'],
 [1.0, '#30123b']]

Plotly Turbo colorscale is derived from matplotlib Turbo colormap:
https://github.com/matplotlib/matplotlib/blob/4f42c6825fe311f18812f99701701cb484da7670/lib/matplotlib/_cm_listed.py#L1803

Online: https://chart-studio.plotly.com/~empet/15725/#/
https://chart-studio.plotly.com/~empet/15723

1 Like

Cool! Should we add it to plotly.colors ?

@nicolaskruchten I think it should be included in the list of Plotly colorscales since it is an alternative to Jet. I didn’t notice Jet being used by Plotly users (probably because of its drawbacks) .

OK, it’ll be in 4.10: https://github.com/plotly/plotly.py/issues/2656

1 Like

Sorry, didn’t make 4.10 … I’ll try for 4.11 :slight_smile:

@empet what do you think of adding some or all of these to Plotly? http://www.fabiocrameri.ch/colourmaps.php

Hah now I feel silly, seeing that your repo is listed in the official docs from that site! https://github.com/empet/scientific-colorscales/blob/master/scicolorscales.py

@nicolaskruchten The library scientific colormaps has at least two versions. My repo illustrates plots with colorscales derived from the first version.
The colormaps there are defined following the Kovesi idea, to ensure lightness linearity in the space CIECAM.

In 2019 when EHT Telescope released their Python library ehtplot to define colormaps for the blackhole,
I discovered an ehtplot function that asseses a colormap, i.e. whether it is perceptually uniform (i.e. it has linear lightness in the CAM2-UCS color space) or not. I used that function to test all Plotly coloscales, cmocean colormaps and a few matplotlib and scientific colormaps.
At that moment only Viridis, Plasma, Inferno, Magma and cmocean colormaps passed the test, while Kovesi colormaps, most of matplotlib and all scientific colormaps exhibited a nonlinear lightness in the CAM2-UCS space.

In a discussion on twitter with Stefan van de Walt, the co-creator of Viridis, and Fabio Crameri, the parent of scientific colorsmaps, I illustrated
with this image

that among other colormaps, the Fabio’s bamako colormap is not perceptually uniform in the above space. After this discussion Fabio released a second version. Comparing the arrays of r,g,b values in the two versions
I noticed that they do not coincide. I suspect that the second version contains perceptually uniform colormaps in the CAM2-UCS space (I haven’t checked them with ehtplot). Hence if you intend to add these colormaps to plotly colors, then their definition should be derived from the last version, 6.0, of the scientific colormaps.

OK, thanks! I’ll see if I have some time to convert the v6.0 maps into the format we need :slight_smile:

Do you think this is an appropriate way of converting from 256 RGB tuples to our format?

import hawaii
import numpy as np
import plotly.express as px

px.bar(x=[1]*100, y=["hawaii"]*100, color=range(100), 
           color_continuous_scale = [
               '#%02x%02x%02x' % tuple(x) for x in 
               np.clip(0, 255, np.round(np.array(hawaii.cm_data)*256)[::15].astype(int))
           ]
)

@nicolaskruchten

It’s OK, except the multilication np.array(...)*256 . I don’t understand why you don’t multiply by 255. The max element in the array of cm data is 1, and each r, g, b takes values
within {0,1,2, ... 255}. With the factor 256 you can get r, g, or b=256. np.clip restricts to the right set of values, but why you don’t define simply like this:

color_continuous_scale =  (np.array(hawaii.cm_data)*255)[::15].astype(int)

np.round rounds to a given number of decimals. Because the default decimals=0, it is not necessary.

or better:

color_continuous_scale =  (0.5+np.array(hawaii.cm_data)*255)[::15].astype(int)

The latter version rounds to the nearest integer.

For example if we get 123.7, then 123.7+0.5= 124.2 and as int we get 124.

For 123.2, 123.2+0.5=123.7, and as int it is 123.

Hehe, you’re right re the 256 vs 255, I’m glad I ran it by someone first :slight_smile:

Thanks!

Do you think that using only 16 values is enough? Internally, Plotly.js does not interpolate in CIECAM or CAM2-UCS so the result will not actually be quite as good as using more values, but I also think it’s a bit overkill to use all 256

For sequential colorscales I don’t think that you need more than 11-13 colors. Viridis, Plasma and all cmocean colorscales are perceptually uniform in CAM-UCS2 space and plotly uses only 13 colors for their definition. The usual linear interpolation, as I can remember, preserves the lightness linearity.