---
title: "'graphicsutils', an overview"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{Overview}
abstract: "The package graphicsutils is a set of miscellaneous functions to be used with the graphics library."
author: Kevin Cazelles
---



The "graphicsutils" package includes a set of functions built on the top of the
`graphics` package. This vignette is basically a guided tour of the package,
a cook book that exemplifies the functions implemented.

```{r setup, echo = FALSE}
knitr::opts_chunk$set(
  fig.align = "center",
  comment = "#> ",
  fig.height = 6,
  fig.width = 6
)
library(graphicsutils)
```

An important aspect of `graphicsutils` is that functions have been written in a layer-oriented perspective meaning that the default behavior of the functions provides functions that are rather minimalist and the user should call other functions (such as `axis`, `box2`, etc.) or change the default parameters values in order to customize his plot. Even though that this takes more command lines, we think that this approach makes it easier to get very personalized figures and we hope the functions we provide will help users
making beautiful figures.



# Empty your plot with plot0()

In the layer-oriented approach we are using, it is very convenient to start with an empty plot of a given dimension, just like a canevas. To help creating such canevas, we wrote `plot0()`. Note that by default x and y ranges are `c(-1, 1)`. Moreover the argument `fill` color the plot region (it is equivalent to calling the `plotAreaColor()`).

```{r plotv0, fig.cap = "plot0() and plotAreaColor()"}
par(mar = c(1, 1, 1, 1), mfrow = c(2, 2))
#
plot0()
text(0, 0, "plot0")
#
plot0(fill = "#8eb5e3")
#
plot0()
plotAreaColor(col = "#8eb5e3")
#
plot0()
plotAreaColor(col = "#8eb5e3", border = "grey20", lty = 2, lwd = 4)
```

The `fill` and `grid.col` make the customization of the background fairly
easy:

```{r plot0v2}
plot0(c(-10, 10), fill = "grey90", grid.col = 'white')
```

Another parameter `text` that adds a text in the middle of the plot area
which makes `plot0()` a helpful function to add piece of legend :

```{r plot0v3}
plot0(c(-10, 10), asp = 1, fill = 8, text = 'cool', srt = 45, cex = 4, col = 2)
```



# Add plot components

## box2()

The `box2()` function allows the user to add any axes around the plot. A
limitation of the `box()` function is does not allowed all the combination of
axes. `box2()` proposes a simple way to select the sides to be added on the plot:
1 = bottom; 2 = left; 3 = top; 4 = right.

```{r box2}
par(mar = rep(2, 4))
plot0()
box2(which = "figure", lwd = 2, fill = "grey30")
box2(side = 12, lwd = 2, fill = "grey80")
axis(1)
axis(2)
```


## Add text with a box around


### First example

```{r textBox1}
plot(1, type = "n", ann = FALSE, las = 1)
coords <- textBox(x = 1, y = 1, labels = "AqA")
str(coords)

rect(coords$box[1], coords$box[2], coords$box[3], coords$box[4], border = 3)
text(x = coords$x, y = coords$y, labels = coords$labels, col = "red")
```

### Padding

```{r textBox2}
plot(1, type = "n", ann = FALSE, las = 1)
# all borders
textBox(x = 1, y = 1.2, labels = "Hello World (1)", padding = 0.05)
# bottom/top and left/right
textBox(x = 1, y = 1.0, labels = "Hello World (2)", padding = c(0.05, 0.20))
# bottom, left, top, right
textBox(x = 1, y = 0.8, labels = "Hello World (3)",
  padding = c(0.05, 0.05, 0.05, 0.35))
```

### Colors & box type

```{r textBox3}
plot(1, type = "n", ann = FALSE, las = 1)
textBox(x = 1, y = 1.2, labels = "Hello World (1)", padding = 0.05,
  col = "yellow", border = "green", fill = "red")
textBox(x = 1, y = 1.0, labels = "Hello World (2)", padding = 0.05, lwd = 3,
  lty = 3)
textBox(x = 1, y = 0.8, labels = "Hello World (3)", padding = 0.05,
  density = 30, angle = 45, fill = "gray")
```

### Text fonts

```{r textBox4}
plot(1, type = "n", ann = FALSE, las = 1)
textBox(x = 1, y = 1.2, labels = "Hello World (1)", padding = 0.05,
  family = "mono")
textBox(x = 1, y = 1.0, labels = "Hello World (2)", padding = 0.05,
  family = "serif")
textBox(x = 1, y = 0.8, labels = "Hello World (3)", padding = 0.05,
  family = "serif", font = 3, cex = 3)
```


### Text alignment

```{r textBox5}
text <- "Hello World!\nHow beautiful you are!"
plot(1, type = "n", ann = FALSE, las = 1)
textBox(x = 1, y = 1.2, labels = text, padding = 0.05, align = "l")
textBox(x = 1, y = 1.0, labels = text, padding = 0.05, align = "c")
textBox(x = 1, y = 0.8, labels = text, padding = 0.05, align = "r")

plot(1, type = "n", ann = FALSE, las = 1)
textBox(x = 1, y = 1.2, labels = text, padding = 0.05, align = "l", lheight = 0)
textBox(x = 1, y = 1.0, labels = text, padding = 0.05, align = "l", lheight = 1)
textBox(x = 1, y = 0.8, labels = text, padding = 0.05, align = "l", lheight = 2)

plot(1, type = "n", ann = FALSE, las = 1)
textBox(x = 1, y = 1.2, labels = text, align = "l",
  padding = c(0.05, 0.05, 0.05, 0.35))
textBox(x = 1, y = 1.0, labels = text, align = "c",
  padding = c(0.05, 0.05, 0.05, 0.35))
textBox(x = 1, y = 0.8, labels = text, align = "r",
  padding = c(0.05, 0.05, 0.05, 0.35))
```


### Removing box and/or text

```{r textBox6}
plot(1, type = "n", ann = FALSE, las = 1)
textBox(x = 1, y = 1.2, labels = text, col = "transparent")
textBox(x = 1, y = 1.0, labels = text, lwd = 0)
textBox(x = 1, y = 0.8, labels = text, lwd = 0, col = "transparent")
```


## shadowText()


```{r shadowText}
plot(1, type = "n", ann = FALSE, las = 1)
shadowText(x = 0.7, y = 1.3, labels = "This is a\nshadow text")
shadowText(x = 1.0, y = 1.3, labels = "This is a\nshadow text",
           family = "serif")
shadowText(x = 1.3, y = 1.3, labels = "This is a\nshadow text",
           family = "mono")
shadowText(x = 1.0, y = 1.0, labels = "This is a shadow text",
           family = "serif", cex = 3, col = "yellow", bg = "red")
shadowText(x = 0.7, y = 0.7, labels = "This is a\nshadow text",
           family = "serif", srt = 45)
shadowText(x = 1.0, y = 0.7, labels = "This is a\nshadow text",
           family = "serif", srt = 180)
shadowText(x = 1.3, y = 0.7, labels = "This is a\nshadow text",
           family = "serif", srt = -45)
```




## Add circles

A function that creates circles.

```{r circles}
par(mar = c(1, 1, 1, 1), mfrow = c(2, 2))
plot0()
circles(0, 0, 1)
plot0()
circles(0, 0, seq(0, 1, 0.2))
plot0()
circles(0, 0, seq(0, 1, 0.2), lty = 2, lwd = 1.4)
plot0()
circles(0, 0 ,seq(0, 1, 0.2), from = pi, col = "#BBBBFF88", lty = 2, lwd = 1.4)
```


## Add ellipses

```{r ellispes}
plot0(c(-2, 2), c(-2, 2), asp = 1)
ellipse(c(-1, 1), c(1, 1, -1, -1), from = pi*seq(0.25, 1, by = 0.25),
  to = 1.25*pi, col = 2, border = 4, lwd = 3)
```


## Add images on plot

The `pchImage()` function eases the uses of `rasterImage()` to add images
(including `.png` and `.jpeg` files) on a graphic. It allows to change the color of the whole image.

```{r pchImage}
pathLogo <- system.file("img", "Rlogo.png", package = "png")
par(mar = c(4, 1, 4, 1), mfrow = c(1, 2))
plot0()
pchImage(0, 0, file = pathLogo, cex.x = 4.5, cex.y = 4)
plot0()
pchImage(0, 0, file = pathLogo, cex.x = 4.5, cex.y = 4, col = "grey25", angle = 25)
```


## Add a frame to your plot

### frameIt()

Default frame.

```{r frameIt}
plot0()
frameIt()
```

A custom one.

```{r frameIt2}
plot0()
frameIt(cex.x = 1.5, col = c(2, 3), border = 1)
```

#### addFrame()

```{r frame3}
addFrame()
addFrame(grid = TRUE)
addFrame(grid = TRUE, lwd = 0.25, lty = 3)
addFrame(at_x = seq(-1, 1, by = 0.1))
## Frame width
addFrame(width = 0.25)
addFrame(at_x = seq(-1, 1, by = 0.01), width = 1.00)
## Colors
addFrame(col = 1:6)
addFrame(col = "lightgray", border = "darkgray")
## Adding to a plot
maps::map()
addFrame(grid = TRUE, add = TRUE, width = 5)
maps::map.axes()
## Other graphical parameters
addFrame(bg = "darkgray", xaxs = "i", yaxs = "i")
```

## Add an envelop

```{r envelop}
plot0(c(0, 10), c(0, 10))
sz <- 100
seqx <- seq(0, 10, length.out = sz)
seqy1 <- 0.2 * seqx * runif(sz, 0, 1)
seqy2 <- 4 + 0.25 * seqx * runif(sz, 0, 1)
seqy3 <- 8 + 0.25 * seqx * runif(sz, 0, 1)
envelop(seqx, seqy1, seqy2, col = 'grey85', border = NA)
envelop(seqx, seqy2, seqy3, col = 'grey25', border = NA)
```

## Encircle points

```{r encircle}
coords <- cbind(runif(10), runif(10))
plot0(coords)
points(coords, bg = "grey25", pch = 21)
encircle(coords, border = "#7b11a1", lwd = 2)
```




# Charts


## boxplot2()

```{r boxplot2}
par(mar = rep(2, 4))
dfa <- data.frame(name = rep(LETTERS[1:4], 25), val = runif(100))
plot0(c(0, 5), c(0, 1))
boxplot2(val ~ name, data = dfa, add = TRUE, vc_cex = c(4, 40, 2))
```


## plotMeans()

```{r plotMeans, fig.height = 3, fig.width = 6}
dataset <- data.frame(dat = c(rnorm(50, 10, 2), rnorm(50, 20, 2)) , grp = rep(c('A', 'D'), each = 50))
graphics::par(mfrow = c(1, 3))
plotMeans(dat ~ grp, data = dataset, pch = 19)
##
plotMeans(dat ~ grp, data = dataset, FUN_err= function(x) sd(x)*2, pch = 15,
 ylim = c(-5, 30), yaxs = 'i', connect = TRUE, args_con = list(lwd = 2, lty = 2, col = 'grey35'))
##
ser <- function(x) sd(x)/sqrt(length(x))
plot0(c(0, 4), c(0, 30))
plotMeans(dat~grp, data = dataset, FUN_err = ser, pch = 15,
draw_axis = FALSE, add = TRUE, seqx = c(.5, 3.5), mar = c(6, 6, 1, 1), cex = 1.4)
graphics::axis(2)
```


## polarPlot()

```{r}
polarPlot(1:40, stats::runif(40), to = 1.9 * pi, col = 'grey30', border = 'grey80')
```






## plotImage

```{r plotImage2}
img <- png::readPNG(system.file('img', 'Rlogo.png', package = 'png'), native = TRUE)
op <- graphics::par(no.readonly = TRUE)
graphics::par(mfrow = c(2, 2), mar = rep(1, 4))
for (i in 1:4) plotImage(img)
graphics::par(op)
```

Another example:

```{r pchImage2}
img<-png::readPNG(system.file('img', 'Rlogo.png', package = 'png'), native = TRUE)
n<-15
plot0(c(0, 1),c(0, 1))
pchImage(0.1 + 0.8*stats::runif(n), 0.1 + 0.8 * stats::runif(n), 
  cex.x = 0.2 + 1.6 * stats::runif(n),
obj = img, angle = 360*runif(n), col = 2)
```



## Image 2

This function is designed for small matrices so the matrix is translated into
a colored image without any rotation of the axes.

```{r image2}
image2(matrix(1:9, 3))
image2(matrix(1:27, 3), from = 2, border = 2, lwd = 2)
```




# Colors manipulations

## Creating shades of colors

The `darken()` and `lighten()` functions ease the creation of shades of a given
color. For any color palette, use the `showPalette()` to display them!


```{r darken}
someblue <- darken("blue", 10 * 1:9)
showPalette(someblue)
```

```{r lighten}
somered <- lighten("red", 10 * 1:9)
showPalette(somered)
```

```{r showpal}
showPalette(ramp("blue", "red", 10 * 3:7))
showPalette(blendColors(c("blue", "purple")))
showPalette(rainbow(81))
```

`darken()` and `lighten()` functions are convenient way to produce consistent
set of shaded colors with minimal effort; also use
`showPalette()` to display your palette.


```{r darken2}
someblue <- darken("blue", 10*1:9)
showPalette(someblue)
```

```{r lighten2}
somered <- lighten("red", 10*1:9)
showPalette(somered, add_codecolor = TRUE)
```

Since version 1.1-2 a set of color palettes has been added, see `gpuPalette()`.
By default, `gpuPalette()` displays the color palettes available:


```{r gpuPalette}
gpuPalette()
```

In order to use one of the palette, use its names:

```{r insileco}
showPalette(gpuPalette("insileco"), add_codecolor = TRUE)
showPalette(gpuPalette("insileco", 25), add_codecolor = TRUE)
```


# Color scale


```{r colorscale}
par(mar = c(0, 0, 0, 0))
plot0(c(0, 10), c(0, 10))
colorScale(1, 8, gpuPalette("cisl", 10))
colorScale(1, 1, gpuPalette("cisl", 10), horiz = FALSE, labels.cex = 0.7)
colorScale(7, 8, gpuPalette("cisl", 10), at = 1:5*2, labels = LETTERS[1:5])
lab <- LETTERS[1:10]
lab[c(1, 3, 5, 7, 9)] <- ""
colorScale(7, 1, gpuPalette("cisl", 10), horiz = FALSE, labels = lab, title = "color scale", labels.cex = 1.1, title.cex = 1.6)
```


```{r colorscale2}
par(mar = c(0, 0, 0, 0))
plot0(c(0, 10), c(0, 10))
colorScale(2, 7, gpuPalette("cisl", 100), percx = 0.6, at = c(5, 25, 50, 75, 95), title = "adj = 0")
colorScale(2, 3, gpuPalette("cisl", 100), percx = 0.6, at = c(5, 25, 50, 75, 95), adj = 1, title = "adj = 1")
```




# Stacked areas chart

## A simple stacked areas


```{r envelop2,  fig.width = 6,  fig.height = 6}
plot0(c(0, 10), c(0, 10))
sz <- 100
seqx <- seq(0, 10, length.out = sz)
seqy1 <- 0.2 * seqx * runif(sz, 0, 1)
seqy2 <- 4 + 0.25 * seqx * runif(sz, 0, 1)
seqy3 <- 8 + 0.25 * seqx * runif(sz, 0, 1)
envelop(seqx, seqy1, seqy2, col = "grey85", border = NA)
```

## A complete stacked areas

```{r stackedArea,  fig.width = 6,  fig.height = 6}
x <- data.frame(matrix(runif(200, 2, 10), 8, 25))
stackedAreas(x)
```






## Interactive functions

Some functions are interactive and fairly understandable, give them a try.


### Chose a color

```r
# NB: not run
pickColors()
```

### Build a layout matrix interactively

```r
# NB: not run
layout2()
```




# Miscellaneous

## Gantt chart

```{r gantt, fig.width = 9}
dfGantt
par(lwd = 2)
palette(gpuPalette(6)[c(2, 4)])
ganttChart(dfGantt, mstone_lwd = 4, mstone_spacing = 0.6, lighten_done = 80)
palette(gpuPalette(6)[c(3, 6)])
ganttChart(dfGantt, task_order = FALSE, mstone_add = TRUE, lighten_done = -40)
# restore default palette
palette("default")
```


## Are these points within this polygon?

```{r ptinpol}
mat <- matrix(10 * runif(100), 50)
res <- pointsInPolygon(mat, cbind(c(4, 8, 8, 4), c(4, 4, 8, 8)))
# Visual assessment
plot0(c(0, 10), c(0, 10))
graphics::polygon(c(4, 8, 8, 4),c(4, 4, 8, 8))
graphics::points(mat[,1], mat[,2], col = res+1)
```


## compassRose

```{r compassRose}
par(mfrow = c(2, 2), mar = rep(1, 4))
##
plot0(c(-1, 1), asp = 1)
compassRose(0, 0)
##
plot0(c(-1, 1), asp = 1)
compassRose(0.5, 0.5)
##
plot0(c(-1, 1), asp = 1)
compassRose(0, 0, cex.cr = 2)
##
plot0(c(-1, 1), asp = 1)
compassRose(0, 0, rot = 0.75*pi, cex.cr = 2, cex.let = 1.5, offset = -1.25)
```

also,

```{R compassRose2}
compassRose(0, rot = 25, cex.cr = 2, col.let =2, add = FALSE)
```



# Vector fields

```{r vectorfields}
systLin <- function(X, beta){
    Y <- matrix(0,ncol = 2)
    Y[1L] <- beta[1, 1] * X[1L] + beta[1, 2] * X[2L]
    Y[2L] <- beta[2, 1] * X[1L] + beta[2, 2] * X[2L]
    return(Y)
}
seqx <- seq(-2, 2, 0.31)
seqy <- seq(-2, 2, 0.31)
beta1 <- matrix(c(0, -1, 1, 0), 2)
# Plot 1:
vecfield2d(coords = expand.grid(seqx, seqy), FUN = systLin, args = list(beta = beta1))
# Plot 2:
graphics::par(mar = c(2, 2, 2, 2))
vecfield2d(coords = expand.grid(seqx, seqy), FUN = systLin,
   args = list(beta = beta1), cex.x = 0.35, cex.arr = 0.25,
   border = NA, cex.hh = 1, cex.shr = 0.6, col = 8)
graphics::abline(v = 0, h = 0)
```


## Manipulation of figure dimensions

### Get pretty ranges

```{r prettyRange}
vec <- stats::runif(20)
range(vec)
prettyRange(vec)
prettyRange(c(3.849, 3.88245))
```

### How many row and columns?

This helper function returns suggested numbers of row and column for a given
number of panels passed as an argument.

```{r howManyRC}
howManyRC(10)
howManyRC(16)
```
