--- 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) ```