Skip to content

Instantly share code, notes, and snippets.

@jlmelville
Last active March 1, 2020 21:31
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jlmelville/be981e2f36485d8ef9616aef60fd52ab to your computer and use it in GitHub Desktop.
Save jlmelville/be981e2f36485d8ef9616aef60fd52ab to your computer and use it in GitHub Desktop.
# License: Apache 2.0
# A straightforward translation of the Python code:
turbo_colormap_data <- matrix(
c(
c(0.18995, 0.07176, 0.23217),
c(0.19483, 0.08339, 0.26149),
c(0.19956, 0.09498, 0.29024),
c(0.20415, 0.10652, 0.31844),
c(0.20860, 0.11802, 0.34607),
c(0.21291, 0.12947, 0.37314),
c(0.21708, 0.14087, 0.39964),
c(0.22111, 0.15223, 0.42558),
c(0.22500, 0.16354, 0.45096),
c(0.22875, 0.17481, 0.47578),
c(0.23236, 0.18603, 0.50004),
c(0.23582, 0.19720, 0.52373),
c(0.23915, 0.20833, 0.54686),
c(0.24234, 0.21941, 0.56942),
c(0.24539, 0.23044, 0.59142),
c(0.24830, 0.24143, 0.61286),
c(0.25107, 0.25237, 0.63374),
c(0.25369, 0.26327, 0.65406),
c(0.25618, 0.27412, 0.67381),
c(0.25853, 0.28492, 0.69300),
c(0.26074, 0.29568, 0.71162),
c(0.26280, 0.30639, 0.72968),
c(0.26473, 0.31706, 0.74718),
c(0.26652, 0.32768, 0.76412),
c(0.26816, 0.33825, 0.78050),
c(0.26967, 0.34878, 0.79631),
c(0.27103, 0.35926, 0.81156),
c(0.27226, 0.36970, 0.82624),
c(0.27334, 0.38008, 0.84037),
c(0.27429, 0.39043, 0.85393),
c(0.27509, 0.40072, 0.86692),
c(0.27576, 0.41097, 0.87936),
c(0.27628, 0.42118, 0.89123),
c(0.27667, 0.43134, 0.90254),
c(0.27691, 0.44145, 0.91328),
c(0.27701, 0.45152, 0.92347),
c(0.27698, 0.46153, 0.93309),
c(0.27680, 0.47151, 0.94214),
c(0.27648, 0.48144, 0.95064),
c(0.27603, 0.49132, 0.95857),
c(0.27543, 0.50115, 0.96594),
c(0.27469, 0.51094, 0.97275),
c(0.27381, 0.52069, 0.97899),
c(0.27273, 0.53040, 0.98461),
c(0.27106, 0.54015, 0.98930),
c(0.26878, 0.54995, 0.99303),
c(0.26592, 0.55979, 0.99583),
c(0.26252, 0.56967, 0.99773),
c(0.25862, 0.57958, 0.99876),
c(0.25425, 0.58950, 0.99896),
c(0.24946, 0.59943, 0.99835),
c(0.24427, 0.60937, 0.99697),
c(0.23874, 0.61931, 0.99485),
c(0.23288, 0.62923, 0.99202),
c(0.22676, 0.63913, 0.98851),
c(0.22039, 0.64901, 0.98436),
c(0.21382, 0.65886, 0.97959),
c(0.20708, 0.66866, 0.97423),
c(0.20021, 0.67842, 0.96833),
c(0.19326, 0.68812, 0.96190),
c(0.18625, 0.69775, 0.95498),
c(0.17923, 0.70732, 0.94761),
c(0.17223, 0.71680, 0.93981),
c(0.16529, 0.72620, 0.93161),
c(0.15844, 0.73551, 0.92305),
c(0.15173, 0.74472, 0.91416),
c(0.14519, 0.75381, 0.90496),
c(0.13886, 0.76279, 0.89550),
c(0.13278, 0.77165, 0.88580),
c(0.12698, 0.78037, 0.87590),
c(0.12151, 0.78896, 0.86581),
c(0.11639, 0.79740, 0.85559),
c(0.11167, 0.80569, 0.84525),
c(0.10738, 0.81381, 0.83484),
c(0.10357, 0.82177, 0.82437),
c(0.10026, 0.82955, 0.81389),
c(0.09750, 0.83714, 0.80342),
c(0.09532, 0.84455, 0.79299),
c(0.09377, 0.85175, 0.78264),
c(0.09287, 0.85875, 0.77240),
c(0.09267, 0.86554, 0.76230),
c(0.09320, 0.87211, 0.75237),
c(0.09451, 0.87844, 0.74265),
c(0.09662, 0.88454, 0.73316),
c(0.09958, 0.89040, 0.72393),
c(0.10342, 0.89600, 0.71500),
c(0.10815, 0.90142, 0.70599),
c(0.11374, 0.90673, 0.69651),
c(0.12014, 0.91193, 0.68660),
c(0.12733, 0.91701, 0.67627),
c(0.13526, 0.92197, 0.66556),
c(0.14391, 0.92680, 0.65448),
c(0.15323, 0.93151, 0.64308),
c(0.16319, 0.93609, 0.63137),
c(0.17377, 0.94053, 0.61938),
c(0.18491, 0.94484, 0.60713),
c(0.19659, 0.94901, 0.59466),
c(0.20877, 0.95304, 0.58199),
c(0.22142, 0.95692, 0.56914),
c(0.23449, 0.96065, 0.55614),
c(0.24797, 0.96423, 0.54303),
c(0.26180, 0.96765, 0.52981),
c(0.27597, 0.97092, 0.51653),
c(0.29042, 0.97403, 0.50321),
c(0.30513, 0.97697, 0.48987),
c(0.32006, 0.97974, 0.47654),
c(0.33517, 0.98234, 0.46325),
c(0.35043, 0.98477, 0.45002),
c(0.36581, 0.98702, 0.43688),
c(0.38127, 0.98909, 0.42386),
c(0.39678, 0.99098, 0.41098),
c(0.41229, 0.99268, 0.39826),
c(0.42778, 0.99419, 0.38575),
c(0.44321, 0.99551, 0.37345),
c(0.45854, 0.99663, 0.36140),
c(0.47375, 0.99755, 0.34963),
c(0.48879, 0.99828, 0.33816),
c(0.50362, 0.99879, 0.32701),
c(0.51822, 0.99910, 0.31622),
c(0.53255, 0.99919, 0.30581),
c(0.54658, 0.99907, 0.29581),
c(0.56026, 0.99873, 0.28623),
c(0.57357, 0.99817, 0.27712),
c(0.58646, 0.99739, 0.26849),
c(0.59891, 0.99638, 0.26038),
c(0.61088, 0.99514, 0.25280),
c(0.62233, 0.99366, 0.24579),
c(0.63323, 0.99195, 0.23937),
c(0.64362, 0.98999, 0.23356),
c(0.65394, 0.98775, 0.22835),
c(0.66428, 0.98524, 0.22370),
c(0.67462, 0.98246, 0.21960),
c(0.68494, 0.97941, 0.21602),
c(0.69525, 0.97610, 0.21294),
c(0.70553, 0.97255, 0.21032),
c(0.71577, 0.96875, 0.20815),
c(0.72596, 0.96470, 0.20640),
c(0.73610, 0.96043, 0.20504),
c(0.74617, 0.95593, 0.20406),
c(0.75617, 0.95121, 0.20343),
c(0.76608, 0.94627, 0.20311),
c(0.77591, 0.94113, 0.20310),
c(0.78563, 0.93579, 0.20336),
c(0.79524, 0.93025, 0.20386),
c(0.80473, 0.92452, 0.20459),
c(0.81410, 0.91861, 0.20552),
c(0.82333, 0.91253, 0.20663),
c(0.83241, 0.90627, 0.20788),
c(0.84133, 0.89986, 0.20926),
c(0.85010, 0.89328, 0.21074),
c(0.85868, 0.88655, 0.21230),
c(0.86709, 0.87968, 0.21391),
c(0.87530, 0.87267, 0.21555),
c(0.88331, 0.86553, 0.21719),
c(0.89112, 0.85826, 0.21880),
c(0.89870, 0.85087, 0.22038),
c(0.90605, 0.84337, 0.22188),
c(0.91317, 0.83576, 0.22328),
c(0.92004, 0.82806, 0.22456),
c(0.92666, 0.82025, 0.22570),
c(0.93301, 0.81236, 0.22667),
c(0.93909, 0.80439, 0.22744),
c(0.94489, 0.79634, 0.22800),
c(0.95039, 0.78823, 0.22831),
c(0.95560, 0.78005, 0.22836),
c(0.96049, 0.77181, 0.22811),
c(0.96507, 0.76352, 0.22754),
c(0.96931, 0.75519, 0.22663),
c(0.97323, 0.74682, 0.22536),
c(0.97679, 0.73842, 0.22369),
c(0.98000, 0.73000, 0.22161),
c(0.98289, 0.72140, 0.21918),
c(0.98549, 0.71250, 0.21650),
c(0.98781, 0.70330, 0.21358),
c(0.98986, 0.69382, 0.21043),
c(0.99163, 0.68408, 0.20706),
c(0.99314, 0.67408, 0.20348),
c(0.99438, 0.66386, 0.19971),
c(0.99535, 0.65341, 0.19577),
c(0.99607, 0.64277, 0.19165),
c(0.99654, 0.63193, 0.18738),
c(0.99675, 0.62093, 0.18297),
c(0.99672, 0.60977, 0.17842),
c(0.99644, 0.59846, 0.17376),
c(0.99593, 0.58703, 0.16899),
c(0.99517, 0.57549, 0.16412),
c(0.99419, 0.56386, 0.15918),
c(0.99297, 0.55214, 0.15417),
c(0.99153, 0.54036, 0.14910),
c(0.98987, 0.52854, 0.14398),
c(0.98799, 0.51667, 0.13883),
c(0.98590, 0.50479, 0.13367),
c(0.98360, 0.49291, 0.12849),
c(0.98108, 0.48104, 0.12332),
c(0.97837, 0.46920, 0.11817),
c(0.97545, 0.45740, 0.11305),
c(0.97234, 0.44565, 0.10797),
c(0.96904, 0.43399, 0.10294),
c(0.96555, 0.42241, 0.09798),
c(0.96187, 0.41093, 0.09310),
c(0.95801, 0.39958, 0.08831),
c(0.95398, 0.38836, 0.08362),
c(0.94977, 0.37729, 0.07905),
c(0.94538, 0.36638, 0.07461),
c(0.94084, 0.35566, 0.07031),
c(0.93612, 0.34513, 0.06616),
c(0.93125, 0.33482, 0.06218),
c(0.92623, 0.32473, 0.05837),
c(0.92105, 0.31489, 0.05475),
c(0.91572, 0.30530, 0.05134),
c(0.91024, 0.29599, 0.04814),
c(0.90463, 0.28696, 0.04516),
c(0.89888, 0.27824, 0.04243),
c(0.89298, 0.26981, 0.03993),
c(0.88691, 0.26152, 0.03753),
c(0.88066, 0.25334, 0.03521),
c(0.87422, 0.24526, 0.03297),
c(0.86760, 0.23730, 0.03082),
c(0.86079, 0.22945, 0.02875),
c(0.85380, 0.22170, 0.02677),
c(0.84662, 0.21407, 0.02487),
c(0.83926, 0.20654, 0.02305),
c(0.83172, 0.19912, 0.02131),
c(0.82399, 0.19182, 0.01966),
c(0.81608, 0.18462, 0.01809),
c(0.80799, 0.17753, 0.01660),
c(0.79971, 0.17055, 0.01520),
c(0.79125, 0.16368, 0.01387),
c(0.78260, 0.15693, 0.01264),
c(0.77377, 0.15028, 0.01148),
c(0.76476, 0.14374, 0.01041),
c(0.75556, 0.13731, 0.00942),
c(0.74617, 0.13098, 0.00851),
c(0.73661, 0.12477, 0.00769),
c(0.72686, 0.11867, 0.00695),
c(0.71692, 0.11268, 0.00629),
c(0.70680, 0.10680, 0.00571),
c(0.69650, 0.10102, 0.00522),
c(0.68602, 0.09536, 0.00481),
c(0.67535, 0.08980, 0.00449),
c(0.66449, 0.08436, 0.00424),
c(0.65345, 0.07902, 0.00408),
c(0.64223, 0.07380, 0.00401),
c(0.63082, 0.06868, 0.00401),
c(0.61923, 0.06367, 0.00410),
c(0.60746, 0.05878, 0.00427),
c(0.59550, 0.05399, 0.00453),
c(0.58336, 0.04931, 0.00486),
c(0.57103, 0.04474, 0.00529),
c(0.55852, 0.04028, 0.00579),
c(0.54583, 0.03593, 0.00638),
c(0.53295, 0.03169, 0.00705),
c(0.51989, 0.02756, 0.00780),
c(0.50664, 0.02354, 0.00863),
c(0.49321, 0.01963, 0.00955),
c(0.47960, 0.01583, 0.01055)
),
ncol = 3,
byrow = TRUE
)
# interpolate(turbo_colormap_data, 0) -> c(0.18995, 0.07176. 0.23217)
# interpolate(turbo_colormap_data, 0.5) -> c(0.638425, 0.990970, 0.236465)
# interpolate(turbo_colormap_data, 1) -> c(0.47960, 0.01583, 0.01055)
interpolate <- function(colormap, x) {
x <- max(0.0, min(1.0, x))
a <- floor(x * 255.0)
b <- min(255, a + 1)
f <- x * 255.0 - a
a <- a + 1
b <- b + 1
return(c(
colormap[a, 1] + (colormap[b, 1] - colormap[a, 1]) * f,
colormap[a, 2] + (colormap[b, 2] - colormap[a, 2]) * f,
colormap[a, 3] + (colormap[b, 3] - colormap[a, 3]) * f
))
}
interpolate_or_clip <- function(colormap, x) {
if (x < 0.0) {
return(c(0.0, 0.0, 0.0))
}
else if (x > 1.0) {
return(c(1.0, 1.0, 1.0))
}
else {
return(interpolate(colormap, x))
}
}
# use this like e.g. grDevices::rainbow
# pie(rep(1, 12), col = rainbow(12), main = "RGB/HSV")
# pie(rep(1, 12), col = turbo(12), main = "turbo")
#
# install.packages("colorspace")
# colorspace::demoplot(grDevices::rainbow(64), type = "heatmap")
# colorspace::demoplot(turbo(64), type = "heatmap")
# turbo goes in the reverse direction to rainbow, but you get the general idea
turbo <- function(n, start = 0, end = 1) {
xs <- seq.int(from = start, to = end, length.out = n)
sapply(xs, function(x) {
do.call(grDevices::rgb, as.list(interpolate(turbo_colormap_data, x)))
})
}
# Better, shorter, more idiomatic, vectorized versions of the interpolate and turbo functions
# thanks to @onesandzeroes
interpolate_vec <- function(colormap, x) {
x <- pmax(0.0, pmin(1.0, x))
a <- floor(x * 255.0)
b <- pmin(255, a + 1)
f <- x * 255.0 - a
a <- a + 1
b <- b + 1
colormap[a, ] + (colormap[b, ] - colormap[a, ]) * f
}
turbo_vec <- function(n, start = 0, end = 1) {
xs <- seq.int(from = start, to = end, length.out = n)
grDevices::rgb(interpolate_vec(turbo_colormap_data, xs))
}
@statibk
Copy link

statibk commented Aug 22, 2019

Thanks for posting this, very useful for trying it out. I just played around whether I could get a HCL-based approximation a la http://colorspace.R-Forge.R-project.org/articles/approximations.html. As the turbo palette uses this hump-shaped luminance pattern, it is actually more of a diverging palette. Hence I use divergingx_hcl() here:

turbo_hcl <- function(n) colorspace::divergingx_hcl(n,
  h1 = 295, h2 = 115, h3 = 3,
  c1 = 20, c2 = 110, c3 = 100, cmax1 = 130, cmax2 = 170,
  l1 = 10, l2 = 90, l3 = 20,
  p1 = 3.5, p2 = 1.7, p3 = 2, p4 = 1.7
)
colorspace::specplot(turbo(11), turbo_hcl(11))

Hue and luminance can be captured alright but the somewhat erratic chroma pattern is hard to mimic. Hence, the palettes look slightly different. I just wanted to post the code here in case someone else wonders about the same...

@kgreger
Copy link

kgreger commented Aug 22, 2019

I borrowed heavily on your code to generate a custom palette (Preferences.tps) for Tableau: https://gist.github.com/kgreger/50edb16656df58ba9f56590a3b9a8dbe

@onesandzeroes
Copy link

onesandzeroes commented Aug 23, 2019

Thanks for this, I might look into getting this added to one of the ggplot theme packages like ggthemes. Since it's R we're talking about, you can also vectorize the interpolate function pretty easily (which might save you from needing sapply):

interpolate_vec = function(colormap, x) {
    x = pmax(0.0, pmin(1.0, x))
    a = floor(x * 255.0)
    b = pmin(255, a + 1)
    f = x * 255.0 - a
    a = a + 1
    b = b + 1
    
    colormap[a, ] + (colormap[b, ] - colormap[a, ]) * f
}

(think this gives the results transposed relative to how you're using them in the turbo() function but that's an easy fix)

@jlmelville
Copy link
Author

Thanks for the suggestion @onesandzeros. I have updated the gist to add your improved functions (they seem to give the same output as the originals).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment