What was I thinking?

I was researching the various color choices made in the Solarized color scheme, and why they worked so well in such varied circumstances. I work in numerous environments. Whether via the command line and shell or a lightweight editor or a full-fledged IDE, Solarized seems to stay consistent.

As well, in my day job we spend hours talking about color and how best to represent data via color.

Since Solarized defines a space in the spectrum of possible color schemes, its Tristimulus Colorimetry can be plotted.

What is Solarized?

From the github site

Precision colors for machines and people

solarized dualmode

Solarized is a sixteen color palette (eight monotones, eight accent colors) designed for use with terminal and gui applications. It has several unique properties. Ethan Schoonover designed this colorscheme with both precise CIELAB lightness relationships and a refined set of hues based on fixed color wheel relationships.

See the changelog for what’s new in the most recent release.

Palette

solarized palette *** solarized vim

Color Values

L*a*b* (pronounced L-star, a-star, b-star) values are canonical (White D65, Reference D50), other values are matched in sRGB space.

SOLARIZED HEX     16/8 TERMCOL  XTERM/HEX   L*A*B*     RGB         HSB
--------- ------- ---- -------  ----------- ---------- ----------- -----------
base03    #002b36  8/4 brblack  234 #1c1c1c 15 -12 -12   0  43  54 193 100  21
base02    #073642  0/4 black    235 #262626 20 -12 -12   7  54  66 192  90  26
base01    #586e75 10/7 brgreen  240 #585858 45 -07 -07  88 110 117 194  25  46
base00    #657b83 11/7 bryellow 241 #626262 50 -07 -07 101 123 131 195  23  51
base0     #839496 12/6 brblue   244 #808080 60 -06 -03 131 148 150 186  13  59
base1     #93a1a1 14/4 brcyan   245 #8a8a8a 65 -05 -02 147 161 161 180   9  63
base2     #eee8d5  7/7 white    254 #e4e4e4 92 -00  10 238 232 213  44  11  93
base3     #fdf6e3 15/7 brwhite  230 #ffffd7 97  00  10 253 246 227  44  10  99
yellow    #b58900  3/3 yellow   136 #af8700 60  10  65 181 137   0  45 100  71
orange    #cb4b16  9/3 brred    166 #d75f00 50  50  55 203  75  22  18  89  80
red       #dc322f  1/1 red      160 #d70000 50  65  45 220  50  47   1  79  86
magenta   #d33682  5/5 magenta  125 #af005f 50  65 -05 211  54 130 331  74  83
violet    #6c71c4 13/5 brmagenta 61 #5f5faf 50  15 -45 108 113 196 237  45  77
blue      #268bd2  4/4 blue      33 #0087ff 55 -10 -45  38 139 210 205  82  82
cyan      #2aa198  6/6 cyan      37 #00afaf 60 -35 -05  42 161 152 175  74  63
green     #859900  2/2 green     64 #5f8700 60 -20  65 133 153   0  68 100  60

Solarized is a color space

The L*a*b* values of Solarized define a color space, which can be plotted.

Lstar Astar Bstar
15 -12 -12
20 -12 -12
45 -07 -07
50 -07 -07
60 -06 -03
65 -05 -02
92 -00 10
97 00 10
60 10 65
50 50 55
50 65 45
50 65 -05
50 15 -45
55 -10 -45
60 -35 -05
60 -20 65

Create the Solarized data frame

Load the various libraries, and then create the Solarized data frame from a list of vectors.

library(colorspace)
library(ggplot2)
library(scatterplot3d)
Lstar = c(15, 20, 45, 50, 60, 65, 92, 97, 60, 50, 50, 50, 50, 55, 60, 60)
Astar = c(-12, -12, -7, -7, -6, -5, 0, 0, 10, 50, 65, 65, 15, -10, -35, -20)
Bstar = c(-12, -12, -7, -7, -3, -2, 10, 10, 65, 55, 45, -5, -45, -45, -5, 65)
solarized = structure(list(Lstar, Astar, Bstar), .Names = c("Lstar", "Astar", "Bstar"), row.names = c(NA,16), class = "data.frame")
head(solarized)
##   Lstar Astar Bstar
## 1    15   -12   -12
## 2    20   -12   -12
## 3    45    -7    -7
## 4    50    -7    -7
## 5    60    -6    -3
## 6    65    -5    -2

Solarized L*a*b* to LAB class

solarizedLAB = with(solarized, LAB(Lstar, Astar, Bstar))
solarizedLAB[1:6,]
##       L   A   B
## [1,] 15 -12 -12
## [2,] 20 -12 -12
## [3,] 45  -7  -7
## [4,] 50  -7  -7
## [5,] 60  -6  -3
## [6,] 65  -5  -2

Solarized L*a*b* to LUV class

solarizedLUV <- as(solarizedLAB, "LUV")
solarizedLUV[1:6,]
##       L          U          V
## [1,] 15 -12.833991 -10.503142
## [2,] 20 -14.981659 -11.895468
## [3,] 45 -12.349864  -8.599082
## [4,] 50 -12.711649  -8.802341
## [5,] 60  -9.666614  -3.357409
## [6,] 65  -7.926079  -2.091574

Solarized LAB/LUV to hex

The canonical L*a*b* or L*u*v* values can represent more colors than hex. Notice the NA result - this is a LAB value that has no corresponding RGB.

Both LAB and LUV should produce the same sRGB, and thus the same hex.

hex(solarizedLAB)
##  [1] NA        NA        "#566E76" "#637B82" "#829496" "#92A1A1" "#F0E7D5"
##  [8] "#FFF6E3" "#BB8801" "#CF4B15" "#E0332E" "#D43982" "#5C73C4" NA       
## [15] "#1FA198" NA
hex(solarizedLUV)
##  [1] NA        NA        "#566E76" "#637B82" "#829496" "#92A1A1" "#F0E7D5"
##  [8] "#FFF6E3" "#BB8801" "#CF4B15" "#E0332E" "#D43982" "#5C73C4" NA       
## [15] "#1FA198" NA

Solarized LAB/LUV to hex - with fixup

Therefore the hex needs to be fixed up to fit within the bounds of possible values. This is fitting the values to RGB.

hex(solarizedLAB, fixup = TRUE)
##  [1] "#002B36" "#003641" "#566E76" "#637B82" "#829496" "#92A1A1" "#F0E7D5"
##  [8] "#FFF6E3" "#BB8801" "#CF4B15" "#E0332E" "#D43982" "#5C73C4" "#008DD1"
## [15] "#1FA198" "#8D9800"
hex(solarizedLUV, fixup = TRUE)
##  [1] "#002B36" "#003641" "#566E76" "#637B82" "#829496" "#92A1A1" "#F0E7D5"
##  [8] "#FFF6E3" "#BB8801" "#CF4B15" "#E0332E" "#D43982" "#5C73C4" "#008DD1"
## [15] "#1FA198" "#8D9800"

Plot Solarized LAB with Base R

plot(as(solarizedLAB, "LAB"))

Plot Solarized LUV with Base R

plot(solarizedLUV, "LUV")

Plot Solarized using ggplot

ggplot(solarized, aes(x = Astar, y = Bstar)) +
  geom_point(size = 5, aes(color = hex(solarizedLAB, fixup = TRUE))) +
  scale_color_identity()

3D Scatterplot for relative luminosity

scatterplot3d(Astar, Bstar, Lstar, color = hex(solarizedLAB, fixup = TRUE), pch = 16, type = "h")