R/cividis-colormap.R

#' Original 'cividis' color map
#'
#' A dataset containing the original RGB values of the default Matplotlib color
#'  map ('cividis'). Source: \url{https://github.com/pnnl/cmaputil/blob/master/colormaps/cividis.txt}.
#'
#' @format A data frame with 1024 rows and 4 variables:
#' \itemize{
#'   \item R: Red value
#'   \item G: Green value
#'   \item B: Blue value
#' }
"cividis.map"

#' 'cividis' color map
#'
#' This function creates a vector of \code{n} equally spaced colors along the
#' \code{cividis} color map created by \href{https://github.com/jamienunez}{Jamie R. Nuez}
#' and \href{https://github.com/smcolby}{Sean M. Colby}. This so-called "cividis" colormap
#' is generated by optimizing the ["viridis" colormap](https://bids.github.io/colormap/) and is
#' optimal for viewing by those with or without color vision deficiency (CVD), a different visual
#' perception of colors that affects 8.5% of the human population. This colormap was developed as a
#' [Python module called "cmaputil"](https://github.com/pnnl/cmaputil). Thus, it is designed to be
#' perfectly perceptually-uniform, both in regular form and also when converted to
#' black-and-white, and can be perceived by readers with all forms of color blindness.
#'
#' @param n The number of colors (\eqn{\ge 1}) to be in the palette.
#'
#' @param alpha	The alpha transparency, a number in [0,1], see argument alpha in
#' \code{\link[grDevices]{hsv}}.
#'
#' @param begin The (corrected) hue in [0,1] at which the cividis colormap begins.
#'
#' @param end The (corrected) hue in [0,1] at which the cividis colormap ends.
#'
#' @param direction Sets the order of colors in the scale. If 1, the default, colors
#' are ordered from darkest to lightest. If -1, the order of colors is reversed.
#'
#' @param option A character string indicating the colormap option to use. So far, there is only one
#' option called "cividis" (or "V").
#'
#' @return \code{cividis} returns a character vector, \code{cv}, of color hex
#' codes. This can be used either to create a user-defined color palette for
#' subsequent graphics by \code{palette(cv)}, a \code{col =} specification in
#' graphics functions or in \code{par}.
#'
#' @examples
#' library(ggplot2)
#' library(hexbin)
#'
#' dat <- data.frame(x = rnorm(10000), y = rnorm(10000))
#'
#' ggplot(dat, aes(x = x, y = y)) +
#'   geom_hex() + coord_fixed() +
#'   scale_fill_gradientn(colours = cividis(256))
#'
#' # using code from RColorBrewer to demo the palette
#' n = 200
#' image(
#'   1:n, 1, as.matrix(1:n),
#'   col = cividis(n = n, begin = 0, end = 1),
#'   xlab = "cividis n", ylab = "", xaxt = "n", yaxt = "n", bty = "n"
#' )
#' @export
#'
cividis <-
  function(n,
           alpha = 1,
           begin = 0,
           end = 1,
           direction = 1,
           option = "V") {
    if (begin < 0 | begin > 1 | end < 0 | end > 1) {
      stop("begin and end must be in [0,1]")
    }
    if (abs(direction) != 1) {
      stop("direction must be 1 or -1")
    }

    if (direction == -1) {
      tmp <- begin
      begin <- end
      end <- tmp
    }

    option <- switch(option,
                     V = "V", cividis = "V",
                     {
                       warning(paste0("Option '", option, "' does not exist. Defaulting to 'cividis'.")); "V"})

    map <-
      cividis::cividis.map[cividis::cividis.map$opt == option,]
    map_cols <- grDevices::rgb(map$R, map$G, map$B)
    fn_cols <-
      grDevices::colorRamp(map_cols, space = "Lab", interpolate = "spline")
    cols <- fn_cols(seq(begin, end, length.out = n)) / 255
    grDevices::rgb(cols[, 1], cols[, 2], cols[, 3], alpha = alpha)
  }


#' @rdname cividis
#'
#' @return  \code{cividisMap} returns a \code{n} lines data frame containing the
#' red (\code{R}), green (\code{G}), blue (\code{B}) and alpha (\code{alpha})
#' channels of \code{n} equally spaced colors along the 'cividis' color map.
#' \code{n = 256} by default, which corresponds to the data from the original
#' 'cividis' color map in Matplotlib.
#'
cividisMap <- function(n = 256,
                       alpha = 1,
                       begin = 0,
                       end = 1,
                       direction = 1,
                       option = "V") { # nocov start
  if (begin < 0 | begin > 1 | end < 0 | end > 1) {
    stop("begin and end must be in [0,1]")
  }

  if (abs(direction) != 1) {
    stop("direction must be 1 or -1")
  }

  if (direction == -1) {
    tmp <- begin
    begin <- end
    end <- tmp
  }

  option <- switch(option,
                   V = "V", cividis = "V",
                   {warning(paste0("Option '", option, "' does not exist. Defaulting to 'cividis'.")); "V"})

  map <- cividis::cividis.map[cividis::cividis.map$opt == option, ]
  map_cols <- grDevices::rgb(map$R, map$G, map$B)
  fn_cols <- grDevices::colorRamp(map_cols, space = "Lab", interpolate = "spline")
  cols <- fn_cols(seq(begin, end, length.out = n)) / 255
  data.frame(R = cols[, 1], G = cols[, 2], B = cols[, 3], alpha = alpha)
} # nocov end
marcosci/cividis documentation built on May 27, 2019, 1:08 p.m.