-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.Rmd
450 lines (335 loc) · 13.1 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
---
output: github_document
editor_options:
markdown:
wrap: 80
---
```{r knitr_init, echo=FALSE}
knitr::opts_chunk$set(
collapse=TRUE,
warning=FALSE,
message=FALSE,
comment="#>",
fig.path="man/figures/README-"
);
```
# colorjam <img src="man/figures/colorjam_logo.png" width="133px" height="154px" align="right" style="padding-left:10px;background-color:white;"/>
## Why colorjam?
`colorjam` provides visually distinct categorical colors of arbitrary length,
using an optimized pattern of chroma/luminance values.
* **Scalable.** Visually distinct categorical colors of arbitrary length.
* `rainbowJam(n)`
* ggplot2 functions: `scale_color_jam()`, `scale_fill_jam()`
* **Color-blindness friendly.** Optimized for three kinds of color blindness.
<!--
* The `"dichromat"` color wheel (default) is optimized for three kinds of
color blindness, <br>
as simulated by the `dichromat` package.
-->
* **Flexible.** `"dichromat"`, `"ryb"`, `"rgb"` color wheels are available.
<!--
* `"dichromat"`: color-blindness optimized
* `"ryb"`: red-yellow-blue "rainbow", additive color blending
* `"rgb"`: red-green-blue "rainbow", default R, computer imaging
* custom color wheels can be defined
-->
* **Optimized for statistical design.** First color
<b style='color:#CDAD00'>gold</b> assigned to control groups:
<!--
* **`"dichromat2"`**: color-blindness optimized, starts with gold (default)
* `"ryb2"`: red-yellow-blue, additive color blending
* `"rgb2"`: red-green-blue, default R, computer imaging
-->
* **Interactive R-shiny app.** `launchColorjamShiny()`
## Installation
Install colorjam using the `remotes` package:
``` r
remotes::install_github("jmw86069/colorjam");
```
OR, use `pacman` to keep the package updated:
``` r
### if necessary, install pacman:
# install.packages("pacman")
library(pacman)
p_load_current_gh("jmw86069/colorjam")
```
*The `colorjam` package is being prepared for CRAN in the "near" future.*
## Command reference
The full command reference is available here:
[`colorjam` command reference](https://jmw86069.github.io/colorjam)
## Quick start with colorjam
For the examples below, two packages are loaded:
```{r, packages}
library(colorjam);
library(jamba);
```
### Categorical colors
#### dichromat (default)
Let's generate `n=5` categorical colors, displayed by
`jamba::showColors()`.
```{r, cat5, fig.width=6, fig.height=5}
showColors(rainbowJam(5));
```
Alternatively, `color_pie()` displays colors in a pie circle.
```{r, pie5, fig.width=6, fig.height=5}
color_pie(rainbowJam(5));
```
Categorical colors are scalable.
```{r, pie15, fig.width=6, fig.height=5}
color_pie(rainbowJam(15));
```
Label the colors using the 4994 `named_colors`:
```{r, named15, fig.width=6, fig.height=5}
color_pie(rainbowJam(15, nameStyle="closest_named_color"));
```
Gradually increase the number of colors, then use
`color_pie()` to plot them in concentric circles.
```{r, cat_list_dichromat}
colorList <- lapply(nameVector(c(36, 24, 12)), function(n){
rainbowJam(n, nameStyle="n");
});
color_pie(colorList,
main="preset='dichromat2' (default)");
```
##### What is "dichromat" here?
Every color system has a "color wheel" - something like
<B style='color:#CC0000'>red</B>-<B style='color:#009900'>green</B>-<B style='color:#0000EE'>blue</B> (RGB) or
<B style='color:#CC0000'>red</B>-<B style='color:#DDCC00'>yellow</B>-<B style='color:#0000EE'>blue</B> (RYB).
We defined a new color wheel `"dichromat"` to maximize the visual distinction
between color hues for people with color blindness. The process was driven
by R package `dichromat`, so we gave it that name out of respect.
The `"dichromat"` color wheel allocates approximately equal halves of the color
wheel to be visually distinct for `"deutan"`, `"protan"`, and `"tritan"`
forms of color blindness. Roughly akin to using "cool"/"warm" colors for
each half the color wheel, for each simulated color. The wheel avoids colors
which are the most difficult to distinguish in the color wheel.
It isn't perfect.
However `colorjam` does provide the first scalable method (we have seen)
to produce categorical colors optimized for the three major forms
of color-blindness.
Other excellent resources that provide color-blindness friendly colors,
which are not scalable. However to be fair, fixed colors may be the best
realistic approach, so `colorjam` may not be the ideal solution.
#### red-yellow-blue
The "full rainbow" color wheel
"<B style='color:#CC0000'>red</B>-<B style='color:#DDCC00'>yellow</B>-<B style='color:#0000EE'>blue</B>"
is recommended over default RGB to provide the best full rainbow.
It performs particularly well for color blending
(see [Color-blending](#Color-blending)) for additive paint-like mixing.
* `preset="ryb"` for red-yellow-blue
```{r, cat_list_ryb}
colorList1 <- lapply(nameVector(c(12)), function(n){
rainbowJam(n, preset="ryb");
});
color_pie(colorList1,
main="Red-Yellow-Blue\npreset='ryb' (starting at red)");
```
* `preset="ryb2"` (recommended) for yellow-red-blue, starting with yellow
```{r, cat_list_ryb2}
colorList1 <- lapply(nameVector(c(16)), function(n){
rainbowJam(n, preset="ryb2");
});
color_pie(colorList1,
main="Yellow-Red-Blue\npreset='ryb2' (starting at yellow)");
```
The reason to start with yellow is noticed when the first category in a set is
the reference or control group in a scientific experiment. It is intuitive for
the reference/control to have a neutral color, instead of being bright red.
Previous versions (\<= 0.0.23.900) of colorjam used a red-yellow-blue color
wheel starting with red.
#### red-green-blue
Similarly, the R default
"<B style='color:#CC0000'>red</B>-<B style='color:#009900'>green</B>-<B style='color:#0000EE'>blue</B>"
color wheel:
* `preset="rgb"` the R default RGB color wheel
```{r, cat_list_rgb}
color_pie(
rainbowJam(16, preset="rgb"),
main="Red-Green-Blue\npreset='rgb' (starting at red)");
```
*(Look how much of this color wheel is blue-green.
This style is not for me, haha.)*
* `preset="rgb2"` the R default RGB color wheel, starting with yellow
```{r, cat_list_rgb2}
color_pie(
rainbowJam(16, preset="rgb2"),
main="Red-Green-Blue\npreset='rgb2' (starting at yellow)");
```
#### More about color wheels
The 4994 colors provided in `named_colors` (see next section) are collated
from numerous sources, and ultimately represent colors that people
were motivated to name. Look how many named colors include red/orange/yellow
as compared to green/blue/purple! Then compare to the RGB color wheel above,
which disproportionately represents blue/green, to the detriment of red/yellow.
Here, `named_colors` are filtered for at least Chroma 40 using
`subset_colors(named_colors, C > 40)`
```{r, named_color_bias}
color_pie(unname(
subset_colors(named_colors, C > 40)))
```
Clearly people can see many more red-orange-yellow, and comparatively very few
green/blue colors. This bias is partly from lower sensitivity of colors such as
"cyan", and partly due to RGB color monitors being unable to produce high
saturation colors with that hue. Color theory is fascinating, and endlessly
complex, in part because each person is slightly different.
### Color matching / Color naming
Two functions are provided to match colors to a reference set, which is a
convenient way to assign color names.
* `closestRcolor()`
* matches colors to the 657 colors in `grDevices::colors()`,
custom reference colors can be supplied.
* `closest_named_color()`
* matches colors to **4883** `named_colors`, which adds 4447 colors from
[meodai/named-colors](https://github.com/meodai/named-colors) (amazing!)
and 436 colors not already represented from `grDevices::colors()`.
The argument `showPalette=TRUE` will plot the original colors and the
closest matched color for comparison.
```{r, color_names}
cnc <- closest_named_color(c(rainbowJam(12), "grey"),
showPalette=TRUE,
main="closest_named_color() using `named_colors`");
crc <- closestRcolor(c(rainbowJam(12), "grey"),
showPalette=TRUE,
main="closestRcolor() using `colors()`");
```
There are two underlying methods:
* `"HCL"` (default) matches color hue by angle, with custom weights to
channels H, C, and L.
* `"LUV"` matches colors using non-polar coordinates and Euclidean distance
across the channels L, U, and V.
Greyscale colors are matches separately to a subset of grayscale
reference colors, to avoid using hue in unsaturated colors.
### Color-blending
`blend_colors()` has some useful features:
* **Paint-style blending**. blue + yellow = green. (For default RGB: blue +
yellow = grey)
* **Scalable number of colors**. Able to mix more than two colors.
* **Transparency-aware**. Accounts for color transparency during mixing.
The argument `do_plot=TRUE` will plot a visual summary of the mixing results.
```{r, blend_colors1, fig.width=3, fig.height=3}
blent1 <- blend_colors(c("red", "blue"), do_plot=TRUE);
blent2 <- blend_colors(c("gold", "blue"), do_plot=TRUE);
blent3 <- blend_colors(c("gold", "red"), do_plot=TRUE);
blent8 <- blend_colors(c("red1", "red3", "blue"), do_plot=TRUE);
blent9 <- blend_colors(c("red1", "blue1", "blue4"), do_plot=TRUE);
blent10 <- blend_colors(c("red", "blue", "ivory"), do_plot=TRUE);
```
### Color-splitting
`color2gradient()` can split colors using a light-dark gradient.
```{r, color_split}
colorSet <- rainbowJam(5);
colorSet4 <- color2gradient(colorSet, n=4);
color_pie(list(
colorSet4=unname(colorSet4),
colorSet=rep(colorSet, each=4)),
main="Color split into 4 additional subsets.");
```
The intensity of the gradient is adjusted with `dex`,
"darkness expansion factor".
```{r, color_split_wt}
colorSet <- rainbowJam(5);
colorSet4a <- color2gradient(colorSet,
n=4,
dex=1/2);
colorSet4c <- color2gradient(colorSet,
n=4,
dex=3);
colorSet4b <- color2gradient(colorSet,
n=4,
dex=10);
colorSet <- rep(colorSet, each=4)
names(colorSet4c) <- names(colorSet4b) <- names(colorSet4a) <- names(colorSet4) <- "";
names(colorSet4b)[5:8] <- c(" 10", " |", " |", " v")
names(colorSet4c)[5:8] <- c(" 3", " |", " |", " v")
names(colorSet4)[5:8] <- c(" 1", " |", " |", " v")
names(colorSet4a)[5:8] <- c("1/2", " |", " |", " v")
color_pie(list(
`dex=10`=(colorSet4b),
`dex=3`=(colorSet4c),
`dex=1\n(default)`=(colorSet4),
`dex=1/2`=(colorSet4a),
colorSet=colorSet),
main=paste0("Intensity of the gradient is adjusted with 'dex'\n",
"(darkness expansion factor)"));
```
### ggplot2 functions
* `scale_color_jam()` categorical colors for ggplot2 `colour`
* `scale_fill_jam()` categorical colors for ggplot2 `fill`
```{r, ggplot_functions}
if (suppressPackageStartupMessages(require(ggplot2))) {
dsamp <- ggplot2::diamonds[sample(nrow(ggplot2::diamonds), 1000),];
d <- ggplot2::ggplot(dsamp, ggplot2::aes(carat, price)) +
ggplot2::geom_point(ggplot2::aes(colour=cut, fill=cut), size=4, shape=21);
d +
scale_color_jam() +
scale_fill_jam() +
ggplot2::ggtitle("scale_color_jam()");
}
```
Colors can be adjusted for darkness, saturation, to make interesting point
shapes:
```{r, ggplot_functions_outline}
if (suppressPackageStartupMessages(require(ggplot2))) {
d +
scale_color_jam(darkFactor=1.5) +
scale_fill_jam(darkFactor=-1.2) +
ggplot2::ggtitle("Adjustment using 'darkFactor'");
}
```
### Custom ggplot2 theme
An alternative ggplot2 theme is provided.
```{r, ggplot2_theme}
if (suppressPackageStartupMessages(require(ggplot2))) {
d +
scale_color_jam(darkFactor=1.5) +
scale_fill_jam(darkFactor=-1.2) +
ggplot2::ggtitle("theme_jam()") +
theme_jam()
}
```
This function provides some common arguments to customize:
* `base_size`: `numeric` default font size in points.
* `blankGrid`: `logical` to remove all background grid lines.
```{r, ggplot2_theme_figure}
if (suppressPackageStartupMessages(require(ggplot2))) {
d +
scale_color_jam(darkFactor=1.5) +
scale_fill_jam(darkFactor=-1.2) +
ggplot2::ggtitle("theme_jam()") +
theme_jam(base_size=24)
}
```
### Jam color gradients
* `jam_linear`: linear (sequential) gradients with white baseline color
```{r, jam_linear_1}
jamba::showColors(jam_linear)
```
* `jam_divergent`: divergent color gradients with black baseline color
```{r, jam_divergent_1}
jamba::showColors(jam_divergent)
```
The driving use case was to display genome sequence coverage heatmaps with
slightly different colors for each type of signal. We wanted linear and
divergent color gradients to use in tandem, for example `"jam_linear$firebrick"`
and `"jam_divergent$firebrick_skyblue"`.
### Color gradients
#### Two-step linear gradients
`twostep_gradient()` combines two linear gradients into one linear gradient.
Two linear gradients are combined, using orange and red:
```{r, twostep_1}
ts1 <- twostep_gradient("orange2", "firebrick", n=11, debug=TRUE)
title("orange2 + firebrick");
```
Two linear gradients are combined, using aquamarine and blue:
```{r, twostep_2}
ts2 <- twostep_gradient("aquamarine", "dodgerblue", n=11, debug=TRUE)
title("aquamarine + dodgerblue");
```
#### Custom divergent gradients
`make_jam_divergent()` combines two linear gradients.
```{r, div_1}
ts1ts2 <- make_jam_divergent(list(ts2=ts2),
list(ts1=ts1),
n=21)
jamba::showColors(ts1ts2)
```