---
title: "Introduction to coloRify"
author: "Maurits Unkel"
date: "10-15-2025"
output: 
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 4
    highlight: tango
vignette: >
  %\VignetteIndexEntry{Introduction to coloRify}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

<div style="
  display:flex;
  justify-content:center;
  margin:2rem 0;
">
  <img src="logo.png"
       style="height:180px;max-width:100%;margin:0;">
</div>

```{r options, include = FALSE, echo = FALSE, results = 'asis'}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")

# Increase default figure size for all plots in this vignette
knitr::opts_chunk$set(
  fig.width = 7,   # default is 4.9
  fig.height = 5,  # default is 3.5
  dpi = 96         # better for screen readability
)

# BiocStyle::markdown() # for Bioconductor package 
```

# Introduction

🌈 Colorify makes color creation and modification intuitive and effortless. Colorify is lightweight and dependency-free yet combines functionality of popular color and visualization packages, including:

* viridis palettes, that are perceptually uniform and colorblind-friendly: Viridis, Turbo, Inferno, Cividis, Plasma, Rocket & Mako.
* Rcolorbrewer palettes and inspired palette visualization.
* ggplot2 easy-to-use integration of scale_color_* and scale_fill_* bindings.
* base R (grDevices) palettes: Rainbow, Heat, Terrain, Topo, Cm & all hcl/pal palettes.
* Okabe-Ito palette, for a highly distinct and colorblind-safe scheme.

## Why use coloRify?

Colorify is dependency-free, yet offers access to all popular palettes and color functionality described above! 

If you are, like me, tired of errors complaining *you need more colors than your palette contains*? No problem!
Colorify generates maximally different colors alongside custom palettes based on how many colors are requested.  

Colorify enables effortless palette/color modification, based on the intuitive RGB and HSL color spaces. 

## How coloRify works 

See the examples below for the following functionality:

* colorify(): the main function offers call parameters for most-in-one color/palette creation and modification tools, the other functions are in support of this, as will be shown in the examples and documentation below. 

  * colorify_pal(): colorify() wrapper to return a color palette generator function  

* display_palettes(): view coloRify palettes that are used with colorify(colors = ...)  

* ggplot2 bindings: scale_fill_colorify() & scale_color_colorify

* utilities for color space conversion: hex2rgba() & hsv2rgb()

* colortistry(): #Rtistry creative fun

# Examples

To run coloRify, simply install the package from CRAN...
```{r install_CRAN, eval=FALSE, message=FALSE, warning=FALSE}
install.packages('colorify')
```

...or the development version from GitHub
```{r install_GitHub, eval=FALSE, message=FALSE, warning=FALSE}
pak::pkg_install('colorify', dependencies = TRUE, upgrade = TRUE)
```

Then load the library.
```{r library, eval=TRUE, message=FALSE, warning=FALSE}
library(colorify)
```

Note that coloRify uses hexcolors (e.g.: '#FF0000FF') and includes base R colors (e.g.: 'red') from grDevices:
```{r base_colors, eval=FALSE, message=FALSE, warning=FALSE}
grDevices::colors()
```

## colorify()
### basic
A basic call with just n(=10) colors requested. n takes an integer > 0. 
```{r colorify_basic, eval=TRUE, message=FALSE, warning=FALSE}
colorify(n = 10, plot = TRUE)
```

See in the output above that coloRify returns a hexcolor vector.

### seed
To show that a different seed yields different generated colors. Pass seed as an integer.
```{r colorify_basic_seed, eval=TRUE, message=FALSE, warning=FALSE}
c <- colorify(10, plot = TRUE, seed = 1337)
```

### custom colors

You can give custom colors and generate the rest, *always* have enough colors for plotting calls! 
```{r colorify_custom_colors, eval=TRUE, message=FALSE, warning=FALSE}
c <- colorify(colors = c("red", "white", "blue"), n = 5, plot = TRUE)
```

### naming

Set names to the output hexcolor vector. colors_names takes a character vector of names the length of the amount of requested colors. 
```{r colorify_named_colors, eval=TRUE, message=FALSE, warning=FALSE}
c <- colorify(colors = c("red", "white", "blue"), n = 5, colors_names = paste0('name', rep(1:5)), plot = TRUE)
```

### ordering

Order the hexcolor output. Integer given as starting point for ordering, may be negative. 
```{r colorify_order_colors, eval=TRUE, message=FALSE, warning=FALSE}
# set integer for the ordering starting position
c <- colorify(colors = c("red", "white", "blue"), n = 5, order = 2, plot = TRUE)
c <- colorify(colors = c("red", "white", "blue"), n = 5, order = 3, plot = TRUE)
# negative integer inverses the order 
c <- colorify(colors = c("red", "white", "blue"), n = 5, order = -1, plot = TRUE)
```

### transparency

Set transparency of colors. alpha takes a float ranging between [0-1].
```{r colorify_colors_transparency, eval=TRUE, message=FALSE, warning=FALSE}
c <- colorify(colors = c("red", "white", "blue"), n = 5, alpha = .25, plot = TRUE)
```

### custom palettes

You can supply an available palette in colors, that will be expanded up to requested n. 
```{r colorify_available_palette, eval=TRUE, message=FALSE, warning=FALSE}
c <- colorify(colors = c("Okabe-Ito"), plot = TRUE)
# note the 10th color is generated
c <- colorify(colors = c("Okabe-Ito"), plot = TRUE, n = 10)
# note that blue and yellow are cut, as only 10 colors are requested. 
c <- colorify(colors = c("Okabe-Ito", "red", "blue", "yellow"), plot = TRUE, n = 10)
```

### gradients

Easy color gradients using the 'nn' parameter, also with custom and available palettes.
```{r colorify_color_gradients, eval=TRUE, message=FALSE, warning=FALSE}
g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 100, plot = TRUE)
g2 <- colorify(colors = c("pastel2"), nn = 100, plot = TRUE)
```

### plotting

Plot options, default is circular output, plot = include 'i' for image and 'l' to plot color index as labels. 
```{r colorify_plotting, eval=TRUE, message=FALSE, warning=FALSE}
g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 15, plot = 'l')
g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 15, plot = 'i')
g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 15, plot = 'il')
```

### values and factors

Values and factors, let's say you want your palette to be more or less RGB (red, green, blue)/HSL (hue, saturation, lightness), you can simply tweak their specific channels! 
Values are intuitively ranged between [0-100] (instead of 0-255). Factors are multiplicative. 

The order in which values and factors are called matters, play around with combinations to obtain your ideal custom palettes.

Note that a gradient is made from the 'n' parameter here, as some palettes are actually called as functions internally. 

```{r colorify_values_and_factors, eval=TRUE, message=FALSE, warning=FALSE}
g3 <- colorify(100, colors = c("viridis"), plot = T)
# r = red, f = factor: rf = 2 to multiply all red values 
g4 <- colorify(100, colors = c("viridis"), rf = 2, plot = T)
# v = value: rv = 50 to increase all red values by 50, on a scale between 0-100
g5 <- colorify(100, colors = c("viridis"), rv = 50, plot = T)
# first, multiply red values by 2, then increase red values by 50
g6 <- colorify(100, colors = c("viridis"), rf = 2, rv = 50, plot = T)
# first, increase red values by 50, then multiply red values by 2
g7 <- colorify(100, colors = c("viridis"), rv = 50, rf = 2, plot = T)
# float factor decrease values by multiplication
g8 <- colorify(100, colors = c("viridis"), bf = .5, plot = T)
# negative values work to decrease values 
g9 <- colorify(100, colors = c("viridis"), bv = -100, gv = -50, plot = T)
```

### minimum and maximum values

When value and factor adjustments are made, the .min and .max parameters are used to set minimum and maximum RGB/HSL values.
```{r colorify_min_and_max, eval=TRUE, message=FALSE, warning=FALSE}
g3 <- colorify(100, colors = c("viridis"), plot = T)
g8 <- colorify(100, colors = c("viridis"), bf = .5, plot = T)
# same factor decrease, yet limited by minimum value
g10 <- colorify(100, colors = c("viridis"), bf = .5, bmin = 40, plot = T)
# need factor/value change to use min/max value 
g11 <- colorify(100, colors = c("viridis"), bf = 1, bmax = 40, plot = T)
# can use them in combination
g12 <- colorify(100, colors = c("viridis"), bf = 1, bmin = 40, bmax = 40,  plot = T)
```

### locking

The colors_lock can be used by locking specific colors by numerical index, starting from 1. 
colors_lock can also be used by patterning, as long as the nn % length of the boolean character == 0. 
colors_lock can be inversed by putting a ! in front of the given vector. 
```{r colorify_color_locking, eval=TRUE, message=FALSE, warning=FALSE}
c <- colorify(colors = c("pastel2"), nn = 30, plot = TRUE)
# lock by index
c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = c(4,5,6, 10,11,12), lf = .5, plot = T)
# inverse lock by index
c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = -c(4:12), lf = .5, plot = T)
# lock by patterns
c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = c(TRUE, FALSE), lf = .5, plot = T)
c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = c(TRUE, FALSE, FALSE), lf = .5, plot = T)
```

### mapping

colors_map takes a vector of values matching the vector of (generated) colors, returning a color_map function which can then be used to generate colors based on supplied values to it. 
```{r colorify_paired_gradients, eval=TRUE, message=FALSE, warning=FALSE}
color_map <- colorify(colors = c('red', 'white', 'blue'), colors_map = c(0, 500, 1000))
# note the map is then given values to map back to the given color ranges from colors_map
m1 <- colorify(colors = color_map(0:1000), plot = T)
```

## display_palettes()

### all palettes

The base use of display_palettes() shows all available palettes in coloRify, that can be used with colorify(colors = c(...)).
```{r display_basic, eval=TRUE, message=FALSE, warning=FALSE}
display_palettes()
```

### n palettes

The n parameter here is used to show the amount of colors per palette. 

```{r display_basic_n, eval=TRUE, message=FALSE, warning=FALSE}
p1 <- display_palettes(10)
# display 100 colors per palette
p2 <- display_palettes(100)
```

### palettes by index 

The i_palettes parameter can also be passed numeric integers to get a more clear palette view. 
```{r display_zoomed_view, eval=TRUE, message=FALSE, warning=FALSE}
# display palettes by index
display_palettes(i_palettes = 50:75)
display_palettes(i_palettes = c(1,5,10,20,40,100,119))
```

### popular palettes

Popular palettes from commonly used color packages are available. 
```{r display_common, eval=TRUE, message=FALSE, warning=FALSE}
display_palettes(10, 'rcolorbrewer')
display_palettes(10, 'viridis')
display_palettes(10, 'rainbow') # grDevices palettes 
```

### bordered palettes

Visualize palettes with borders around individual colors.
```{r display_border, eval=TRUE, message=FALSE, warning=FALSE}
display_palettes(n = 10, i_palettes = 1:10, border = TRUE)
```

## ggplot2 bindings

These functions are bindings similar to the ggplot2 scale_* functions, to use them ggplot2 has to be installed and loaded.

```{r scale_colorify_ggplot2_setup, eval=FALSE, message=FALSE, warning=FALSE}
install.packages('ggplot2')
library(ggplot2)
```

### scale_color_colorify()

#### non-discrete

```{r scale_colorify_ggplot2_color_non_discrete, eval=TRUE, message=FALSE, warning=FALSE}
dsub <- subset(ggplot2::diamonds, x > 5 & x < 6 & y > 5 & y < 6)
dsub$diff <- with(dsub, sqrt(abs(x - y)) * sign(x - y))

ggplot2::ggplot(dsub, ggplot2::aes(x, y, colour = diff)) + 
  ggplot2::geom_point() + 
  scale_color_colorify(n = 4, colors = 'viridis') + 
  ggplot2::theme_bw()
```

#### discrete

```{r scale_colorify_ggplot2_color_discrete, eval=TRUE, message=FALSE, warning=FALSE}
p <- ggplot2::ggplot(mtcars, ggplot2::aes(wt, mpg))

p + ggplot2::geom_point(size = 4, ggplot2::aes(colour = factor(cyl))) +
  ggplot2::theme_bw() + 
  scale_color_colorify(discrete = TRUE, colors = c('red', 'blue', 'yellow'))
```

###  scale_fill_colorify()

#### non-discrete

```{r scale_colorify_ggplot2_fill_non_discrete, eval=TRUE, message=FALSE, warning=FALSE}
dat <- data.frame(x = rnorm(10000), y = rnorm(10000))

ggplot2::ggplot(dat, ggplot2::aes(x = x, y = y)) +
  ggplot2::geom_hex() + ggplot2::coord_fixed() +
  scale_fill_colorify(colors = 'viridis', n = 4) + ggplot2::theme_bw()
```

#### discrete

```{r scale_colorify_ggplot2_fill_discrete, eval=TRUE, message=FALSE, warning=FALSE}
df <- data.frame(category = c("A", "B", "C", "D"), value = c(10, 23, 15, 8))

ggplot2::ggplot(df, ggplot2::aes(x = category, y = value, fill = category)) +
  ggplot2::geom_bar(stat = "identity") + 
  scale_fill_colorify(discrete = TRUE, colors = 'viridis')

```

## colortistry()

My colorful monstrosity I contribute to the #Rtistry community! I heartily welcome creative contributions using coloRify <3 

```{r colortistry, eval=TRUE, message=FALSE, warning=FALSE}
colors_list <- list()
for (i in seq(100)) {
  colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(T,F,F,F,F), 20), hf = 25/i, lf = i/20)
  if (i %% 3) colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(F,F,T,F,F), 20), hf = 30/i, lf = i/20)
  if (i %% 4) colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(F,F,F,T,F), 20), hf = 50/i, lf = i/40)
  if (i %% 5) colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(F,T,F,F,F), 20), hf = 50/i, sf = i/50)
}
colortistry(colors_list)
# and with borders
colortistry(colors_list, border_color = 'black')
```


# Information

A thank you for your time and effort in using coloRify, I hope it may aid you in *COOLORing* your visualizations! 

## Contact 

Colorify was developed by Maurits Unkel at the Erasmus Medical Center in the department of Psychiatry.
Source code is available through GitHub: https://github.com/mauritsunkel/colorify
Questions regarding coloRify can be sent to: mauritsunkel@gmail.com

## License

Colorify is licensed under Apache 2.0.

## Issues and contributions

For issues and contributions, please find the coloRify Github page: https://github.com/mauritsunkel/colorify/issues

## FAQ

Q: How can I easily test my coloRify palettes on actual visualizations?

* A: I advise you to use colorspace::demoplot(colorify(5), type = "heatmap"), switching up type for specific plot types and replacing the colorify() call with your own. 


## Session info

```{r session_info}
sessionInfo()
```
