Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
Package: painbow
Type: Package
Title: Use XKCD's "Painbow" Colormap and Dataset in ggplot2
Version: 1.0.1
Title: Use XKCD's "Painbow" Colormap and Dataset in Base and ggplot2 Graphics
Version: 1.1.0
Author: Steve Haroz
Maintainer: Steve Haroz <painbow@steveharoz.com>
Description: XKCD described a supposedly "bad" colormap that it called a "Painbow" (see <https://xkcd.com/2537/>). 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 <https://xkcd.com/2537/>). 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
Expand Down
24 changes: 23 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -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"
)
27 changes: 27 additions & 0 deletions R/painbow.R
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
52 changes: 44 additions & 8 deletions man/painbow.Rd
Original file line number Diff line number Diff line change
@@ -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
}