From 933b91f16eec5722c9a08ab881d0552622a3e622 Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Fri, 12 Nov 2021 17:03:39 +0100 Subject: [PATCH 1/4] add painbow.colors() palette function, especially for base graphics --- R/painbow.R | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/R/painbow.R b/R/painbow.R index f58842f..24b7601 100644 --- a/R/painbow.R +++ b/R/painbow.R @@ -7,6 +7,33 @@ painbow_colors = c( '#FFFFFF', '#FEFEFF', '#FAFAFC', '#F4F4F7', '#EBECF1', '#E4E4EC', '#DBDAE6', '#D1D1DE', '#C7C7D5', '#BBBDCB', '#AFB3C3', '#A4A7BA', '#999CB0', '#8F91A6', '#87899D', '#7E8193', '#747788', '#6A6D7C', '#626170', '#575765', '#4C4C57', '#41424B', '#37373E', '#2D2C32', '#242328', '#1B1A1E', '#131313', '#0C0C0A', '#060606', '#010102', '#000000', '#000003', '#00000C', '#000219', '#03092A', '#091239', '#111B49', '#162150', '#1C2756', '#222D5C', '#2A3463', '#333B6A', '#3A4370', '#424B77', '#4A527D', '#515A82', '#576085', '#5D6689', '#606C8B', '#60718C', '#5F758A', '#577985', '#4A7E80', '#407D7B', '#367C72', '#287C69', '#1C7C60', '#147C58', '#0C7D50', '#037D47', '#1E7941', '#247139', '#356632', '#54562B', '#714524', '#8D361D', '#AD2516', '#C91610', '#DF0F0C', '#F20605', '#FD0004', '#FE0302', '#FD0400', '#FD0200', '#FC0401', '#FC0202', '#FA0401', '#F80601', '#F80400', '#F50800', '#F30B01', '#F10A01', '#ED0F00', '#E91101', '#E71302', '#E31401', '#E01400', '#DC1900', '#D91D00', '#D41E00', '#D12001', '#CD2200', '#C52A00', '#C32A00', '#C02B01', '#B83201', '#B53301', '#AF3601', '#AA3A01', '#A63D02', '#A04002', '#9A4502', '#964702', '#914A01', '#8B4F01', '#865202', '#825503', '#7D5904', '#775C03', '#716003', '#6D6304', '#666704', '#606B06', '#5D6F07', '#587207', '#527607', '#4E7908', '#4B7C08', '#467F08', '#418309', '#3E860A', '#38890C', '#348D0C', '#2F900C', '#2E930E', '#2A960E', '#269A0E', '#239D0E', '#1FA00F', '#1CA211', '#1EA411', '#1EA712', '#1CA912', '#1BAC14', '#18AE15', '#13B015', '#0DB216', '#0EB417', '#09B715', '#14BA18', '#13BD1B', '#09C11C', '#0FC41E', '#14C721', '#13CA22', '#1CCC25', '#21CF27', '#27D129', '#2CD32A', '#31D62C', '#37D72F', '#41D932', '#47DB35', '#50DD37', '#57DF3A', '#5CE13D', '#65E23F', '#6BE341', '#76E343', '#80E547', '#85E749', '#8BE84D', '#91E950', '#98EB53', '#A1EB56', '#A7ED58', '#ABEE5B', '#B2EE5E', '#BAEE61', '#BEF064', '#C0F167', '#C5F26A', '#CAF26D', '#CFF173', '#D4F17A', '#D6F181', '#D9F186', '#DBF38B', '#DDF293', '#DEF399', '#E0F29F', '#E2F2A8', '#E3F1AF', '#E3F0B5', '#E4EFBC', '#E4EEC1', '#E5EDC8', '#E5ECCD', '#E6EBD2', '#E6EAD8', '#E7E9DD', '#E7E9E1' ) +## base graphics palette +painbow.colors = function(n, alpha = FALSE, rev = FALSE) { + ## n: number of colors + n = as.integer(n[1L]) + if (n < 1L) return(character()) + + ## alpha: logical or numeric alpha transparency (vector) in [0, 1] + if (identical(alpha, FALSE)) alpha = NULL + if (!is.null(alpha)) alpha = pmin(pmax(as.numeric(alpha), 0), 1) * 255 + + ## interpolate painbow RGB coordinates + pain = grDevices::col2rgb(painbow_colors) + x = seq.int(0, 1, length.out = length(painbow_colors)) + xout = seq.int(0, 1, length.out = n) + pain = grDevices::rgb( + red = stats::approx(x, pain[1L, ], xout = xout)$y, + green = stats::approx(x, pain[2L, ], xout = xout)$y, + blue = stats::approx(x, pain[3L, ], xout = xout)$y, + alpha = alpha, + maxColorValue = 255) + + ## rev: reverse order? + if (rev) rev(pain) else pain +} + + +## ggplot2 scales scale_fill_painbow = function(...) { ggplot2::scale_fill_gradientn( colors = painbow_colors, From 9db38f3b15972f993d8ae5cf8013788ed9c1f20d Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Fri, 12 Nov 2021 17:04:55 +0100 Subject: [PATCH 2/4] add base graphics to Title/Description, add grDevices and stats in Imports, graphics in Depends, increase minor version to reflect new functionality --- DESCRIPTION | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f1185c3..afafff3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,22 +1,22 @@ Package: painbow Type: Package -Title: Use XKCD's "Painbow" Colormap in ggplot2 -Version: 1.0.1 +Title: Use XKCD's "Painbow" Colormap in Base and ggplot2 Graphics +Version: 1.1.0 Author: Steve Haroz Maintainer: Steve Haroz -Description: XKCD described a supposedly "bad" colormap that it called a "Painbow" (see ). But simple tests demonstrate that under some circumstances, the colormap can perform very well, and people can find information that is difficult to detect with the ggplot2 default and even supposedly "good" colormaps like viridis. This library let's you use the Painbow in your own ggplot graphs. +Description: XKCD described a supposedly "bad" colormap that it called a "Painbow" (see ). But simple tests demonstrate that under some circumstances, the colormap can perform very well, and people can find information that is difficult to detect with the ggplot2 default and even supposedly "good" colormaps like viridis. This package lets you use the Painbow in your own base and ggplot2 graphics. License: MIT + file LICENSE Encoding: UTF-8 LazyData: true Imports: - ggplot2 + grDevices, stats, ggplot2 Suggests: knitr, patchwork, spelling, rmarkdown Depends: - R (>= 2.10) + R (>= 2.10), graphics RoxygenNote: 7.1.2 Language: en-US BugReports: https://github.com/steveharoz/painbow/issues/new From 2442fe11e25c2a3f948d114727f0c5671a54a7c7 Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Fri, 12 Nov 2021 17:05:17 +0100 Subject: [PATCH 3/4] explicitly import and export functionality --- NAMESPACE | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index d75f824..734dabd 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1 +1,23 @@ -exportPattern("^[[:alpha:]]+") +importFrom("grDevices", + "col2rgb", + "rgb") + +importFrom("stats", + "approx") + +importFrom("ggplot2", + "scale_fill_gradientn", + "scale_color_gradientn") + +export( + ## color vector + "painbow_colors", + + ## base palette + "painbow.colors", + + ## ggplot2 scales + "scale_fill_painbow", + "scale_color_painbow", + "scale_colour_painbow" +) From e8194bc4f797479457a05aff2db52b5a7a6762fa Mon Sep 17 00:00:00 2001 From: Achim Zeileis Date: Fri, 12 Nov 2021 17:06:01 +0100 Subject: [PATCH 4/4] document new painbow.colors() function, add base examples, add some further details --- man/painbow.Rd | 52 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/man/painbow.Rd b/man/painbow.Rd index 5ce61a4..863d087 100644 --- a/man/painbow.Rd +++ b/man/painbow.Rd @@ -1,37 +1,73 @@ -\name{scale_colour_painbow} +\name{painbow} + +\alias{painbow.colors} \alias{scale_color_painbow} \alias{scale_colour_painbow} \alias{scale_fill_painbow} -\title{Painbow colormap} +\title{XKCD Painbow Colormap} -\description{Use XKCD's "Painbow" colormap} +\description{Use XKCD's "Painbow" colormap in base and ggplot2 graphics.} \usage{ +painbow.colors(n, alpha = FALSE, rev = FALSE) + scale_color_painbow(...) scale_colour_painbow(...) scale_fill_painbow(...) } \arguments{ + \item{n}{integer. The number of colors (\eqn{\ge 1}) in the palette.} + \item{alpha}{logical or numeric. Specification of an alpha-transparency (vector) + in the range from 0 (transparent) to 1 (opaque). If \code{FALSE} no alpha + level is added. If \code{TRUE} full opacity (1) is used for all colors.} + \item{rev}{logical. Should the ordering of the colors be reversed?} \item{...}{ Any arguments are passed to \code{\link[ggplot2:scale_fill_gradientn]{ggplot2:scale_fill_gradientn()}} } } -\details{The colors were extracted directly from the colorscale in XKCD's image (https://xkcd.com/2537/).} +\details{ + The 192 colors in the palette were extracted directly from the colormap in XKCD's image + (\url{https://xkcd.com/2537/}). -\author{Steve Haroz} + The \code{palette.colors} function extracts \code{n} colors along the 192 colors + by linear interpolation of the underlying RGB (red-green-blue) coordinates. + + The \code{scale_*_painbow} functions provide scales for ggplot2 graphics. +} -%% ~Make other sections like Warning with \section{Warning }{....} ~ +\author{Steve Haroz} \seealso{ See \code{\link[ggplot2:scale_fill_gradientn]{ggplot2:scale_fill_gradientn()}} for additional arguments. } \examples{ -# You can use it for continuous data -library(ggplot2) +## recreate painbow heatmap for continuous data +data("painbow_data", package = "painbow") + +## ggplot2 graphics +library("ggplot2") +ggplot(painbow_data) + + aes(x, y, fill = value) + + geom_tile() + + scale_fill_painbow() + +## base graphics +pd <- matrix(painbow_data$value, ncol = 205, byrow = TRUE)[, 205:1] +filled.contour(pd, color.palette = painbow.colors) +filled.contour(pd, color.palette = painbow.colors, nlevels = 100) + +# Old Faithful data +data("faithfuld", package = "ggplot2") ggplot(faithfuld) + aes(waiting, eruptions, fill = density) + geom_tile() + scale_fill_painbow() + +## illustrate usage of base palette +painbow.colors(5) ## original order +painbow.colors(5, rev = TRUE) ## reversed order +painbow.colors(5, alpha = TRUE) ## with explicit full opacity +painbow.colors(5, alpha = 0:4/4) ## with decreasing transparency }