diff --git a/.travis.yml b/.travis.yml index f85aa8b..ea188ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,10 @@ language: r ## no tests, coverage ## check as CRAN +before_install: + - sudo apt-get update -y + - sudo apt-get -y install libglu1-mesa-dev libharfbuzz-dev libfribidi-dev + script: - R CMD build . --compact-vignettes=gs+qpdf - - R CMD check *tar.gz --as-cran + - R CMD check *tar.gz ## without CRAN check, --as-cran diff --git a/CHANGELOG.md b/CHANGELOG.md index 011dafb..4ae8225 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.2.2] - 2021-02-10 +* Add global option for `dpi` using `options(ggrastr.default.dpi=N)`. PR found here: https://github.com/VPetukhov/ggrastr/pull/21 +* Vignettes edited accordingly +* Use both html and markdown for vignettes, link to README + + +## [0.2.1] - 2020-09-14 +* Changes to be in sync with ggrastr version 0.2.1 on CRAN: https://cran.rstudio.com/src/contrib/ggrastr_0.2.1.tar.gz +* Aesthetic revisions to the github README +* Otherwise, this version mirrors https://github.com/VPetukhov/ggrastr/releases/tag/v0.2.0 + + ## [0.2.0] - 2020-08 * Refactor code to use rasterise() * Added `geom_violin_rast()` as a feature request diff --git a/DESCRIPTION b/DESCRIPTION index 7908bab..399ffb6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,28 +1,28 @@ -Package: ggrastr -Type: Package -Title: Raster Layers for 'ggplot2' -Version: 0.2.2 -Authors@R: c(person("Viktor", "Petukhov", email = "viktor.s.petukhov@ya.ru", role = c("aut", "cph")), person("Teun", "van den Brand", email = "t.vd.brand@nki.nl", role=c("aut")), person("Evan", "Biederstedt", email = "evan.biederstedt@gmail.com", role=c("cre", "aut"))) -Description: Provides a set of geoms to rasterize only specific layers of the plot while simultaneously keeping all labels and text in vector format. This allows users to keep plots within the reasonable size limit without loosing vector properties of the scale-sensitive information. -License: MIT + file LICENSE -Encoding: UTF-8 -LazyData: true -Imports: - ggplot2 (>= 2.1.0), - Cairo (>= 1.5.9), - ggbeeswarm, - grid, - ragg, - png -Depends: - R (>= 3.2.2) -RoxygenNote: 7.1.1 -Suggests: - rmarkdown, - knitr -VignetteBuilder: knitr -URL: https://github.com/VPetukhov/ggrastr -BugReports: https://github.com/VPetukhov/ggrastr/issues -NeedsCompilation: no -Author: Viktor Petukhov [aut, cph], Teun van den Brand [aut], Evan Biederstedt [cre, aut] -Maintainer: Evan Biederstedt +Package: ggrastr +Type: Package +Title: Raster Layers for 'ggplot2' +Version: 0.2.2 +Authors@R: c(person("Viktor", "Petukhov", email = "viktor.s.petukhov@ya.ru", role = c("aut", "cph")), person("Teun", "van den Brand", email = "t.vd.brand@nki.nl", role=c("aut")), person("Evan", "Biederstedt", email = "evan.biederstedt@gmail.com", role=c("cre", "aut"))) +Description: Provides a set of geoms to rasterize only specific layers of the plot while simultaneously keeping all labels and text in vector format. This allows users to keep plots within the reasonable size limit without loosing vector properties of the scale-sensitive information. +License: MIT + file LICENSE +Encoding: UTF-8 +LazyData: true +Imports: + ggplot2 (>= 2.1.0), + Cairo (>= 1.5.9), + ggbeeswarm, + grid, + ragg, + png +Depends: + R (>= 3.2.2) +RoxygenNote: 7.1.1 +Suggests: + rmarkdown, + knitr +VignetteBuilder: knitr +URL: https://github.com/VPetukhov/ggrastr +BugReports: https://github.com/VPetukhov/ggrastr/issues +NeedsCompilation: no +Author: Viktor Petukhov [aut, cph], Teun van den Brand [aut], Evan Biederstedt [cre, aut] +Maintainer: Evan Biederstedt diff --git a/R/geom-beeswarm-rast.R b/R/geom-beeswarm-rast.R index e8e3207..3f141bc 100644 --- a/R/geom-beeswarm-rast.R +++ b/R/geom-beeswarm-rast.R @@ -6,7 +6,7 @@ #' @import ggbeeswarm #' @param priority Method used to perform point layout (see ggbeeswarm::position_beeswarm) #' @param cex Scaling for adjusting point spacing (see ggbeeswarm::position_beeswarm) -#' @param groupOnX Should jitter be added to the x axis if TRUE or y axis if FALSE (the default NULL causes the function to guess which axis is the categorical one based on the number of unique entries in each) Refer to see ggbeeswarm::position_beeswarm +#' @param groupOnX Should jitter be added to the x axis if TRUE or y axis if FALSE (the default NULL causes the function to guess which axis is the categorical one based on the number of unique entries in each) Refer to see ggbeeswarm::position_beeswarm #' @param dodge.width Amount by which points from different aesthetic groups will be dodged. This requires that one of the aesthetics is a factor. (see ggbeeswarm::position_beeswarm) #' @param raster.dpi An integer of length one setting the desired resolution in dots per inch. (default=300) #' @param dev A character specifying a device. Can be one of: \code{"cairo"}, \code{"ragg"} or \code{"ragg_png"}. (default="cairo") @@ -19,7 +19,7 @@ #' ggplot(mtcars) + geom_beeswarm_rast(aes(x = factor(cyl), y = mpg), raster.dpi = 600, cex = 1.5) #' #' @export -geom_beeswarm_rast <- function(..., priority= c("ascending", "descending", "density", "random", "none"), cex = 1, groupOnX = NULL, dodge.width = 0, raster.dpi = 300, dev="cairo") { +geom_beeswarm_rast <- function(..., priority= c("ascending", "descending", "density", "random", "none"), cex = 1, groupOnX = NULL, dodge.width = 0, raster.dpi = getOption("ggrastr.default.dpi", 300), dev="cairo") { rasterise(ggbeeswarm::geom_beeswarm(..., priority=priority, cex=cex, groupOnX=groupOnX, dodge.width=dodge.width), dpi=raster.dpi, dev=dev) } diff --git a/R/geom-boxplot-jitter.R b/R/geom-boxplot-jitter.R index 90daa37..3df4ad4 100644 --- a/R/geom-boxplot-jitter.R +++ b/R/geom-boxplot-jitter.R @@ -20,7 +20,7 @@ DrawGeomBoxplotJitter <- function(data, panel_params, coord, dev="cairo", ..., outlier.size = 1.5, outlier.stroke = 0.5, outlier.alpha = NULL, - raster=FALSE, raster.dpi=300, + raster=FALSE, raster.dpi=getOption("ggrastr.default.dpi", 300), raster.width=NULL, raster.height=NULL ) { boxplot_grob <- ggplot2::GeomBoxplot$draw_group(data, panel_params, coord, ...) @@ -76,7 +76,7 @@ GeomBoxplotJitter <- ggplot2::ggproto("GeomBoxplotJitter", #' @param outlier.jitter.height Amount of horizontal jitter. The jitter is added in both positive and negative directions, #' so the total spread is twice the value specified here (default=0) #' @param raster.dpi Resolution of the rastered image (default=300). Ignored if \code{raster == FALSE}. -#' @param dev A character specifying a device (default="cairo"). Can be one of: \code{"cairo"}, \code{"ragg"} or \code{"ragg_png"}. +#' @param dev A character specifying a device (default="cairo"). Can be one of: \code{"cairo"}, \code{"ragg"} or \code{"ragg_png"}. #' @return geom_boxplot plot with rasterized layer #' #' @examples @@ -94,7 +94,7 @@ geom_boxplot_jitter <- function(mapping = NULL, data = NULL, dev = "cairo", inherit.aes = TRUE, ..., outlier.jitter.width=NULL, outlier.jitter.height=0, - raster.dpi=300 + raster.dpi=getOption("ggrastr.default.dpi", 300) ) { ggplot2::layer( geom = GeomBoxplotJitter, mapping = mapping, data = data, stat = stat, @@ -103,4 +103,4 @@ geom_boxplot_jitter <- function(mapping = NULL, data = NULL, dev = "cairo", outlier.jitter.width=outlier.jitter.width, outlier.jitter.height=outlier.jitter.height, raster.dpi=raster.dpi, dev=dev, ...)) -} \ No newline at end of file +} diff --git a/R/geom-jitter-rast.R b/R/geom-jitter-rast.R index 092839d..d167b63 100644 --- a/R/geom-jitter-rast.R +++ b/R/geom-jitter-rast.R @@ -14,6 +14,6 @@ #' ggplot(mpg) + geom_jitter_rast(aes(x = factor(cyl), y = hwy), raster.dpi = 600) #' #' @export -geom_jitter_rast <- function(..., raster.dpi = 300, dev="cairo"){ +geom_jitter_rast <- function(..., raster.dpi = getOption("ggrastr.default.dpi", 300), dev="cairo"){ rasterise(geom_jitter(...), dpi=raster.dpi, dev=dev) -} \ No newline at end of file +} diff --git a/R/geom-point-rast.R b/R/geom-point-rast.R index 5d2cbe6..92832b4 100644 --- a/R/geom-point-rast.R +++ b/R/geom-point-rast.R @@ -15,6 +15,6 @@ #' ggplot() + geom_point_rast(aes(x=rnorm(1000), y=rnorm(1000)), raster.dpi=600) #' #' @export -geom_point_rast <- function(..., raster.dpi=300, dev="cairo") { +geom_point_rast <- function(..., raster.dpi=getOption("ggrastr.default.dpi", 300), dev="cairo") { rasterise(geom_point(...), dpi=raster.dpi, dev=dev) } diff --git a/R/geom-quasirandom-rast.R b/R/geom-quasirandom-rast.R index f3a6a0a..cdd8401 100644 --- a/R/geom-quasirandom-rast.R +++ b/R/geom-quasirandom-rast.R @@ -14,6 +14,6 @@ #' ggplot(mtcars) + geom_quasirandom_rast(aes(x = factor(cyl), y = mpg), raster.dpi = 600) #' #' @export -geom_quasirandom_rast <- function(..., width = NULL, varwidth = FALSE, bandwidth = 0.5, nbins = NULL, method = "quasirandom", groupOnX = NULL, dodge.width = 0, raster.dpi = 300, dev="cairo") { +geom_quasirandom_rast <- function(..., width = NULL, varwidth = FALSE, bandwidth = 0.5, nbins = NULL, method = "quasirandom", groupOnX = NULL, dodge.width = 0, raster.dpi = getOption("ggrastr.default.dpi", 300), dev="cairo") { rasterise(ggbeeswarm::geom_quasirandom(..., width = width, varwidth = varwidth, bandwidth = bandwidth, nbins = nbins, method = method, groupOnX = groupOnX, dodge.width = dodge.width), dpi=raster.dpi, dev=dev) } diff --git a/R/geom-tile-rast.R b/R/geom-tile-rast.R index 1dd1279..fe04ebf 100644 --- a/R/geom-tile-rast.R +++ b/R/geom-tile-rast.R @@ -16,6 +16,6 @@ #' ggplot(coords) + geom_tile_rast(aes(x=Var1, y=Var2, fill=Value)) #' #' @export -geom_tile_rast <- function(..., raster.dpi=300, dev="cairo") { +geom_tile_rast <- function(..., raster.dpi=getOption("ggrastr.default.dpi", 300), dev="cairo") { rasterise(geom_tile(...), dpi=raster.dpi, dev=dev) -} \ No newline at end of file +} diff --git a/R/geom-violin-rast.R b/R/geom-violin-rast.R index 1de9793..db80f92 100644 --- a/R/geom-violin-rast.R +++ b/R/geom-violin-rast.R @@ -14,6 +14,6 @@ #' ggplot(mpg) + geom_violin_rast(aes(x = factor(cyl), y = hwy), raster.dpi = 600) #' #' @export -geom_violin_rast = function(..., raster.dpi=300, dev="cairo"){ +geom_violin_rast = function(..., raster.dpi=getOption("ggrastr.default.dpi", 300), dev="cairo"){ rasterise(geom_violin(...), dpi=raster.dpi, dev=dev) -} \ No newline at end of file +} diff --git a/R/rasterise.R b/R/rasterise.R index 8d23181..3511d61 100644 --- a/R/rasterise.R +++ b/R/rasterise.R @@ -1,146 +1,146 @@ -#' Rasterise ggplot layers -#' Takes a ggplot layer as input and renders their graphical output as a raster. -#' -#' @author Teun van den Brand -#' @param layer A \code{Layer} object, typically constructed with a call to a -#' \code{geom_*()} or \code{stat_*()} function. -#' @param dpi An integer of length one setting the desired resolution in dots per inch. (default=NULL) -#' @param dev A character specifying a device. Can be one of: \code{"cairo"}, \code{"ragg"} or \code{"ragg_png"}. (default="cairo") -#' -#' @return A modified \code{Layer} object. -#' @examples -#' require(ggplot2) -#' # `rasterise()` is used to wrap layers -#' ggplot(pressure, aes(temperature, pressure)) + -#' rasterise(geom_line()) -#' -#' # The `dpi` argument controls resolution -#' ggplot(faithful, aes(eruptions, waiting)) + -#' rasterise(geom_point(), dpi = 5) -#' -#' # The `dev` argument offers a few options for devices -#' require(ragg) -#' ggplot(diamonds, aes(carat, depth, z = price)) + -#' rasterise(stat_summary_hex(), dev = "ragg") -#' -#' @export -rasterise <- function(layer, dpi = NULL, dev = "cairo") { - dev <- match.arg(dev, c("cairo", "ragg", "ragg_png")) - - if (!inherits(layer, "Layer")) { - stop("Cannot rasterise an object of class `", class(layer)[1], "`. Must be either 'cairo', 'ragg', or 'ragg_png'.", call. = FALSE) - } - - # Take geom from input layer - old_geom <- layer$geom - # Reconstruct input layer - ggproto( - NULL, layer, - # Let the new geom inherit from the old geom - geom = ggproto( - NULL, old_geom, - # draw_panel draws like old geom, but appends info to graphical object - draw_panel = function(...) { - grob <- old_geom$draw_panel(...) - class(grob) <- c("rasteriser", class(grob)) - grob$dpi <- dpi - grob$dev <- dev - return(grob) - } - ) - ) -} - -#' @rdname rasterise -#' @export -rasterize <- rasterise - -#' @export -#' @noRd -#' @importFrom grid makeContext -#' @method makeContext rasteriser -makeContext.rasteriser <- function(x) { - # Grab viewport information - vp <- if(is.null(x$vp)) grid::viewport() else x$vp - width <- grid::convertWidth(unit(1, "npc"), "inch", valueOnly = TRUE) - height <- grid::convertHeight(unit(1, "npc"), "inch", valueOnly = TRUE) - - # Grab grob metadata - dpi <- x$dpi - if (is.null(dpi)) { - # If missing, take current DPI - dpi <- grid::convertWidth(unit(1, "inch"), "pt", valueOnly = TRUE) - } - dev <- x$dev - - # Clean up grob - x$dev <- NULL - x$dpi <- NULL - class(x) <- setdiff(class(x), "rasteriser") - - # Track current device - dev_cur <- grDevices::dev.cur() - # Reset current device upon function exit - on.exit(grDevices::dev.set(dev_cur), add = TRUE) - - # Setup temporary device for capture - if (dev == "cairo") { - dev_id <- Cairo::Cairo( - type = 'raster', - width = width, height = height, - units = "in", dpi = dpi, bg = NA - )[1] - } else if (dev == "ragg") { - dev_id <- ragg::agg_capture( - width = width, height = height, - units = "in", res = dpi, - background = NA - ) - } else { - # Temporarily make a file to write png to - file <- tempfile(fileext = ".png") - # Destroy temporary file upon function exit - on.exit(unlink(file), add = TRUE) - ragg::agg_png( - file, - width = width, height = height, - units = "in", res = dpi, - background = NA - ) - } - - # Render layer - grid::pushViewport(vp) - grid::grid.draw(x) - grid::popViewport() - - # Capture raster - if (dev != "ragg_png") { - cap <- grid::grid.cap() - } - grDevices::dev.off() - - if (dev == "ragg_png") { - # Read in the png file - cap <- png::readPNG(file, native = FALSE) - dim <- dim(cap) - cap <- matrix( - grDevices::rgb( - red = as.vector(cap[, , 1]), - green = as.vector(cap[, , 2]), - blue = as.vector(cap[, , 3]), - alpha = as.vector(cap[, , 4]) - ), - dim[1], dim[2] - ) - } - - # Forward raster grob - grid::rasterGrob( - cap, x = 0.5, y = 0.5, - height = unit(height, "inch"), - width = unit(width, "inch"), - default.units = "npc", - just = "center" - ) -} +#' Rasterise ggplot layers +#' Takes a ggplot layer as input and renders their graphical output as a raster. +#' +#' @author Teun van den Brand +#' @param layer A \code{Layer} object, typically constructed with a call to a +#' \code{geom_*()} or \code{stat_*()} function. +#' @param dpi An integer of length one setting the desired resolution in dots per inch. (default=NULL) +#' @param dev A character specifying a device. Can be one of: \code{"cairo"}, \code{"ragg"} or \code{"ragg_png"}. (default="cairo") +#' @details The default \code{dpi} (\code{NULL} (= let device decide)) can conveniently be controlled by setting the option \code{"ggrastr.default.dpi"} (e.g. \code{option("ggrastr.default.dpi", 30)} for drafting). +#' @return A modified \code{Layer} object. +#' @examples +#' require(ggplot2) +#' # `rasterise()` is used to wrap layers +#' ggplot(pressure, aes(temperature, pressure)) + +#' rasterise(geom_line()) +#' +#' # The `dpi` argument controls resolution +#' ggplot(faithful, aes(eruptions, waiting)) + +#' rasterise(geom_point(), dpi = 5) +#' +#' # The `dev` argument offers a few options for devices +#' require(ragg) +#' ggplot(diamonds, aes(carat, depth, z = price)) + +#' rasterise(stat_summary_hex(), dev = "ragg") +#' +#' @export +rasterise <- function(layer, dpi = getOption("ggrastr.default.dpi"), dev = "cairo") { + dev <- match.arg(dev, c("cairo", "ragg", "ragg_png")) + + if (!inherits(layer, "Layer")) { + stop("Cannot rasterise an object of class `", class(layer)[1], "`. Must be either 'cairo', 'ragg', or 'ragg_png'.", call. = FALSE) + } + + # Take geom from input layer + old_geom <- layer$geom + # Reconstruct input layer + ggproto( + NULL, layer, + # Let the new geom inherit from the old geom + geom = ggproto( + NULL, old_geom, + # draw_panel draws like old geom, but appends info to graphical object + draw_panel = function(...) { + grob <- old_geom$draw_panel(...) + class(grob) <- c("rasteriser", class(grob)) + grob$dpi <- dpi + grob$dev <- dev + return(grob) + } + ) + ) +} + +#' @rdname rasterise +#' @export +rasterize <- rasterise + +#' @export +#' @noRd +#' @importFrom grid makeContext +#' @method makeContext rasteriser +makeContext.rasteriser <- function(x) { + # Grab viewport information + vp <- if(is.null(x$vp)) grid::viewport() else x$vp + width <- grid::convertWidth(unit(1, "npc"), "inch", valueOnly = TRUE) + height <- grid::convertHeight(unit(1, "npc"), "inch", valueOnly = TRUE) + + # Grab grob metadata + dpi <- x$dpi + if (is.null(dpi)) { + # If missing, take current DPI + dpi <- grid::convertWidth(unit(1, "inch"), "pt", valueOnly = TRUE) + } + dev <- x$dev + + # Clean up grob + x$dev <- NULL + x$dpi <- NULL + class(x) <- setdiff(class(x), "rasteriser") + + # Track current device + dev_cur <- grDevices::dev.cur() + # Reset current device upon function exit + on.exit(grDevices::dev.set(dev_cur), add = TRUE) + + # Setup temporary device for capture + if (dev == "cairo") { + dev_id <- Cairo::Cairo( + type = 'raster', + width = width, height = height, + units = "in", dpi = dpi, bg = NA + )[1] + } else if (dev == "ragg") { + dev_id <- ragg::agg_capture( + width = width, height = height, + units = "in", res = dpi, + background = NA + ) + } else { + # Temporarily make a file to write png to + file <- tempfile(fileext = ".png") + # Destroy temporary file upon function exit + on.exit(unlink(file), add = TRUE) + ragg::agg_png( + file, + width = width, height = height, + units = "in", res = dpi, + background = NA + ) + } + + # Render layer + grid::pushViewport(vp) + grid::grid.draw(x) + grid::popViewport() + + # Capture raster + if (dev != "ragg_png") { + cap <- grid::grid.cap() + } + grDevices::dev.off() + + if (dev == "ragg_png") { + # Read in the png file + cap <- png::readPNG(file, native = FALSE) + dim <- dim(cap) + cap <- matrix( + grDevices::rgb( + red = as.vector(cap[, , 1]), + green = as.vector(cap[, , 2]), + blue = as.vector(cap[, , 3]), + alpha = as.vector(cap[, , 4]) + ), + dim[1], dim[2] + ) + } + + # Forward raster grob + grid::rasterGrob( + cap, x = 0.5, y = 0.5, + height = unit(height, "inch"), + width = unit(width, "inch"), + default.units = "npc", + just = "center" + ) +} diff --git a/README.md b/README.md index 75e9796..94b5f83 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # ggrastr -Provides a set of ggplot2 [geoms](https://ggplot2.tidyverse.org/reference/#section-geoms) to rasterize only specific layers of the plot (e.g. large scatterplots with many points), while keeping all labels and text in vector format. This allows users to keep plots within a reasonable size limit without losing the vector properties of scale-sensitive information. +Provides a set of ggplot2 [geoms](https://ggplot2.tidyverse.org/reference/#section-geoms) to rasterize only specific layers of the plot (e.g. large scatter plots with many points), while keeping all labels and text in vector format. This allows users to keep plots within a reasonable size limit without losing the vector properties of scale-sensitive information. ## Installation @@ -23,20 +23,26 @@ devtools::install_github('VPetukhov/ggrastr', build_vignettes = TRUE) ## Rasterize any ggplot2 layer -Note that with ggrastr version 0.2.0, any ggplot2 geom provided by the user can be rasterized with the function `rasterise()`. Furthermore, when the aspect ratio is distorted, points are rendered without distortion. +Note that with `ggrastr` version 0.2.0, any ggplot2 geom provided by the user can be rasterized with the function `rasterise()`. Furthermore, when the aspect ratio is distorted, points are rendered without distortion. -For more details and examples, see the [vignettes](https://htmlpreview.github.io/?https://raw.githubusercontent.com/VPetukhov/ggrastr/master/doc/Raster_geoms.html). +For more details and examples, see the **vignettes:** +* [HTML version](https://htmlpreview.github.io/?https://raw.githubusercontent.com/VPetukhov/ggrastr/master/doc/Raster_geoms.html) +* [Markdown version](https://github.com/VPetukhov/ggrastr/blob/master/vignettes/Raster_geoms.md) -## Geoms provided: -* `geom_point_rast`: raster scatterplots -* `geom_jitter_rast`: raster jittered scatterplots +## Geoms provided + +We alo provide wrappers for several geoms to guarantee compatibility with an older version of `ggrastr`. However, we encourage users to use the `rasterise()` function instead. + +* `geom_point_rast`: raster scatter plots +* `geom_jitter_rast`: raster jittered scatter plots * `geom_boxplot_jitter`: boxplots that allows to jitter and rasterize outlier points * `geom_tile_rast`: raster heatmap * `geom_beeswarm_rast`: raster [bee swarm plots](https://github.com/eclarke/ggbeeswarm#geom_beeswarm) -* `geom_quasirandom_rast`: raster [quasirandom scatterplot](https://github.com/eclarke/ggbeeswarm#geom_quasirandom) +* `geom_quasirandom_rast`: raster [quasirandom scatter plot](https://github.com/eclarke/ggbeeswarm#geom_quasirandom) ## Troubleshooting + If your R session crashes when you try to render a rasterized plot, it's probably the case that your version of Cairo was built for another version of R (see [Upgrading to a new version of R](https://shiny.rstudio.com/articles/upgrade-R.html)). To check if you are using a proper version, run the command below and ensure that the "Built" version is the same as your R version. @@ -48,10 +54,11 @@ pkgs[pkgs$Package == 'Cairo', c("Package", "LibPath", "Version", "Built")] To ensure that Cairo works, try running `Cairo::Cairo(type='raster'); dev.off()` and check if it crashes your R session. ## Citation + If you find `ggrastr` useful for your publication, please cite: ``` Viktor Petukhov, Teun van den Brand and Evan Biederstedt (2021). ggrastr: Raster Layers for 'ggplot2'. R package version 0.2.2. https://CRAN.R-project.org/package=ggrastr -``` \ No newline at end of file +``` diff --git a/ggrastr.Rproj b/ggrastr.Rproj index 497f8bf..270314b 100644 --- a/ggrastr.Rproj +++ b/ggrastr.Rproj @@ -18,3 +18,4 @@ StripTrailingWhitespace: Yes BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd,collate,namespace diff --git a/man/geom_beeswarm_rast.Rd b/man/geom_beeswarm_rast.Rd index 7f075e1..93d1397 100644 --- a/man/geom_beeswarm_rast.Rd +++ b/man/geom_beeswarm_rast.Rd @@ -10,7 +10,7 @@ geom_beeswarm_rast( cex = 1, groupOnX = NULL, dodge.width = 0, - raster.dpi = 300, + raster.dpi = getOption("ggrastr.default.dpi", 300), dev = "cairo" ) } diff --git a/man/geom_boxplot_jitter.Rd b/man/geom_boxplot_jitter.Rd index 20f2d2d..984951d 100644 --- a/man/geom_boxplot_jitter.Rd +++ b/man/geom_boxplot_jitter.Rd @@ -16,7 +16,7 @@ geom_boxplot_jitter( ..., outlier.jitter.width = NULL, outlier.jitter.height = 0, - raster.dpi = 300 + raster.dpi = getOption("ggrastr.default.dpi", 300) ) } \arguments{ diff --git a/man/geom_jitter_rast.Rd b/man/geom_jitter_rast.Rd index 2d62c60..e24902e 100644 --- a/man/geom_jitter_rast.Rd +++ b/man/geom_jitter_rast.Rd @@ -4,7 +4,11 @@ \alias{geom_jitter_rast} \title{This geom is similar to \code{\link[ggplot2]{geom_jitter}}, but creates a raster layer} \usage{ -geom_jitter_rast(..., raster.dpi = 300, dev = "cairo") +geom_jitter_rast( + ..., + raster.dpi = getOption("ggrastr.default.dpi", 300), + dev = "cairo" +) } \arguments{ \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}. These are diff --git a/man/geom_point_rast.Rd b/man/geom_point_rast.Rd index f170cd4..ade8636 100644 --- a/man/geom_point_rast.Rd +++ b/man/geom_point_rast.Rd @@ -4,7 +4,11 @@ \alias{geom_point_rast} \title{This geom is similar to \code{\link[ggplot2]{geom_point}}, but creates a raster layer} \usage{ -geom_point_rast(..., raster.dpi = 300, dev = "cairo") +geom_point_rast( + ..., + raster.dpi = getOption("ggrastr.default.dpi", 300), + dev = "cairo" +) } \arguments{ \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}. These are diff --git a/man/geom_quasirandom_rast.Rd b/man/geom_quasirandom_rast.Rd index abd9de5..6d3f209 100644 --- a/man/geom_quasirandom_rast.Rd +++ b/man/geom_quasirandom_rast.Rd @@ -13,7 +13,7 @@ geom_quasirandom_rast( method = "quasirandom", groupOnX = NULL, dodge.width = 0, - raster.dpi = 300, + raster.dpi = getOption("ggrastr.default.dpi", 300), dev = "cairo" ) } diff --git a/man/geom_tile_rast.Rd b/man/geom_tile_rast.Rd index 07d52bc..a4c3fa6 100644 --- a/man/geom_tile_rast.Rd +++ b/man/geom_tile_rast.Rd @@ -4,7 +4,11 @@ \alias{geom_tile_rast} \title{This geom is similar to \code{\link[ggplot2]{geom_tile}}, but creates a raster layer} \usage{ -geom_tile_rast(..., raster.dpi = 300, dev = "cairo") +geom_tile_rast( + ..., + raster.dpi = getOption("ggrastr.default.dpi", 300), + dev = "cairo" +) } \arguments{ \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}. These are diff --git a/man/geom_violin_rast.Rd b/man/geom_violin_rast.Rd index 6264582..23a32fd 100644 --- a/man/geom_violin_rast.Rd +++ b/man/geom_violin_rast.Rd @@ -4,7 +4,11 @@ \alias{geom_violin_rast} \title{This geom is similar to \code{\link[ggplot2]{geom_violin}}, but creates a raster layer} \usage{ -geom_violin_rast(..., raster.dpi = 300, dev = "cairo") +geom_violin_rast( + ..., + raster.dpi = getOption("ggrastr.default.dpi", 300), + dev = "cairo" +) } \arguments{ \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}. These are diff --git a/man/rasterise.Rd b/man/rasterise.Rd index d6e6e62..8650e32 100644 --- a/man/rasterise.Rd +++ b/man/rasterise.Rd @@ -6,9 +6,9 @@ \title{Rasterise ggplot layers Takes a ggplot layer as input and renders their graphical output as a raster.} \usage{ -rasterise(layer, dpi = NULL, dev = "cairo") +rasterise(layer, dpi = getOption("ggrastr.default.dpi"), dev = "cairo") -rasterize(layer, dpi = NULL, dev = "cairo") +rasterize(layer, dpi = getOption("ggrastr.default.dpi"), dev = "cairo") } \arguments{ \item{layer}{A \code{Layer} object, typically constructed with a call to a @@ -25,6 +25,9 @@ A modified \code{Layer} object. Rasterise ggplot layers Takes a ggplot layer as input and renders their graphical output as a raster. } +\details{ +The default \code{dpi} (\code{NULL} (= let device decide)) can conveniently be controlled by setting the option \code{"ggrastr.default.dpi"} (e.g. \code{option("ggrastr.default.dpi", 30)} for drafting). +} \examples{ require(ggplot2) # `rasterise()` is used to wrap layers diff --git a/vignettes/Raster_geoms.Rmd b/vignettes/Raster_geoms.Rmd index 2e1241b..1681b11 100644 --- a/vignettes/Raster_geoms.Rmd +++ b/vignettes/Raster_geoms.Rmd @@ -60,6 +60,22 @@ plot + rasterise(geom_point(), dpi = 5, dev = "ragg_png") ``` +### Set the parameter 'dpi' globally with options(ggrastr.default.dpi=N) + +The parameter `dpi` is an integer which sets the desired resolution in dots per inch. With ggrastr versions `>=0.2.2`, users can set this parameter globally, using [options()](https://stat.ethz.ch/R-manual/R-devel/library/base/html/options.html). In the following example, plots will be rendered with `dpi=750` after the user sets this with `options(ggrastr.default.dpi=750)`: + +```{r} +## set ggrastr.default.dpi with options() +options(ggrastr.default.dpi=750) + +plot <- ggplot(diamonds, aes(carat, price, colour = cut)) +new_plot = plot + rasterise(geom_point()) + theme(aspect.ratio = 1) +print(new_plot) + +## set back to default 300 +options(ggrastr.default.dpi=300) +``` + ### Raserized plots with facet_wrap() Facets are rendered correctly without users having to adjust the width/height settings. @@ -73,7 +89,7 @@ plot + rasterise(geom_point(), dpi = 300) + facet_wrap(~ sample(1:3, nrow(diamon -### Points: Rasterize scatterplots with geom_point_rast() +### Points: Rasterize scatter plots with geom_point_rast() Sometimes you need to publish a figure in a vector format: ```{r, fig.width=4, fig.height=4} library(ggplot2) @@ -124,9 +140,9 @@ PrintFileSize(gg_rast, 'Raster') PrintFileSize(gg_vec, 'Vector') ``` -### Jitter: Rasterize jittered scatterplots with geom_jitter_rast() +### Jitter: Rasterize jittered scatter plots with geom_jitter_rast() -Just like the example above with`geom_point_rast()`, users may also opt to create rasterized scatterplots with jitter. The geom `geom_jitter_rast()` is similar to `ggplot2::geom_jitter()`, but it creates a rasterized layer: +Just like the example above with`geom_point_rast()`, users may also opt to create rasterized scatter plots with jitter. The geom `geom_jitter_rast()` is similar to `ggplot2::geom_jitter()`, but it creates a rasterized layer: ```{r, fig.width=4, fig.height=4} diff --git a/vignettes/Raster_geoms.md b/vignettes/Raster_geoms.md new file mode 100644 index 0000000..9473e74 --- /dev/null +++ b/vignettes/Raster_geoms.md @@ -0,0 +1,365 @@ +--- +title: "Raster geoms" +output: + rmarkdown::html_vignette: + toc: true +vignette: > + %\VignetteIndexEntry{"Raster geoms"} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + + + +## ggrastr + +### Convert any ggplot2 layer into a rasterized output + +Using the function `rasterize()`, users can rasterize any ggplot2 layer: + + + +```r +library(ggplot2) +library(ggrastr) + +plot <- ggplot(diamonds, aes(carat, price, colour = cut)) + +plot + rasterise(geom_point(), dpi = 72) + theme(aspect.ratio = 1) +``` + +![plot of chunk unnamed-chunk-1](figure/unnamed-chunk-1-1.png) + +Note that with ggrastr changes in version 0.2.0, when the aspect ratio is distorted, points are still rendered without distortion, i.e. the points are still circles: + + +```r +# Points remain round across different aspect ratios +plot + rasterise(geom_point(), dpi = 72) + theme(aspect.ratio = 0.2) +``` + +![plot of chunk unnamed-chunk-2](figure/unnamed-chunk-2-1.png) + +By default, plots are rendered with [cairo](https://CRAN.R-project.org/package=Cairo). However, users now have the option to render plots with the [ragg](https://github.com/r-lib/ragg) device. The motivation for using `ragg` is that `ragg` can be faster and has better anti-aliasing. That being said, the default ragg device also has some alpha blending quirks. Because of these quirks, users are recommended to use the `ragg_png` option to work around the alpha blending. + +The differences in devices are best seen at lower resolution: + + +```r +# The default 'cairo' at dpi=5 +plot + rasterise(geom_point(), dpi = 5, dev = "cairo") +``` + +![plot of chunk unnamed-chunk-3](figure/unnamed-chunk-3-1.png) + + +```r +# Using 'ragg' gives better anti-aliasing but has unexpected alpha blending +plot + rasterise(geom_point(), dpi = 5, dev = "ragg") +``` + +![plot of chunk unnamed-chunk-4](figure/unnamed-chunk-4-1.png) + + + +```r +# Using 'ragg_png' solves the alpha blend, but requires writing a temporary file to disk +plot + rasterise(geom_point(), dpi = 5, dev = "ragg_png") +``` + +![plot of chunk unnamed-chunk-5](figure/unnamed-chunk-5-1.png) + + +### Set the parameter 'dpi' globally with options(ggrastr.default.dpi=N) + +The parameter `dpi` is an integer which sets the desired resolution in dots per inch. With ggrastr versions `>=0.2.2`, users can set this parameter globally, using [options()](https://stat.ethz.ch/R-manual/R-devel/library/base/html/options.html). In the following example, plots will be rendered with `dpi=750` after the user sets this with `options(ggrastr.default.dpi=750)`: + + +```r +## set ggrastr.default.dpi with options() +options(ggrastr.default.dpi=750) + +plot <- ggplot(diamonds, aes(carat, price, colour = cut)) +new_plot = plot + rasterise(geom_point()) + theme(aspect.ratio = 1) +print(new_plot) +``` + +![plot of chunk unnamed-chunk-6](figure/unnamed-chunk-6-1.png) + +```r + +## set back to default 300 +options(ggrastr.default.dpi=300) +``` + +### Raserized plots with facet_wrap() + +Facets are rendered correctly without users having to adjust the width/height settings. + + +```r +# Facets won't warp points +set.seed(123) +plot + rasterise(geom_point(), dpi = 300) + facet_wrap(~ sample(1:3, nrow(diamonds), 2)) +``` + +![plot of chunk unnamed-chunk-7](figure/unnamed-chunk-7-1.png) + + + + +### Points: Rasterize scatter plots with geom_point_rast() +Sometimes you need to publish a figure in a vector format: + +```r +library(ggplot2) +library(ggrastr) + +points_num <- 10000 +df <- data.frame(x=rnorm(points_num), y=rnorm(points_num), c=as.factor(1:points_num %% 2)) +gg <- ggplot(df, aes(x=x, y=y, color=c)) + scale_color_discrete(guide=FALSE) + +gg_vec <- gg + geom_point(size=0.5) +print(gg_vec) +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +``` + +![plot of chunk unnamed-chunk-8](figure/unnamed-chunk-8-1.png) + +But in other cases, your figure contains thousands of points, e.g. try `points_num <- 500000` in the example above, and you will notice the performance issues---it takes significantly longer to render the plot: + +![gg_vec_plot_500000](ggvec_50000_plot.png) + + +In this case, a reasonable solution would be to rasterize the plot. But the problem is that all text becomes rasterized as well. +Raster layers with `ggrastr` were developed to prevent such a situation, here using `geom_point_rast()`: + +```r +gg_rast <- gg + geom_point_rast(size=0.5) +print(gg_rast) +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +``` + +![plot of chunk unnamed-chunk-9](figure/unnamed-chunk-9-1.png) + +The plots look the same, but the difference in size can be seen when they are exported to pdfs. Unfortunately, there is a longer rendering time to produce such plots: + +```r +PrintFileSize <- function(gg, name) { + invisible(ggsave('tmp.pdf', gg, width=4, height=4)) + cat(name, ': ', file.info('tmp.pdf')$size / 1024, ' Kb.\n', sep = '') + unlink('tmp.pdf') +} + +PrintFileSize(gg_rast, 'Raster') +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +#> Raster: 312.8662 Kb. +PrintFileSize(gg_vec, 'Vector') +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +#> Vector: 556.8867 Kb. +``` + +As expected, the difference becomes larger with growth of number of points: + +```r +points_num <- 1000000 +df <- data.frame(x=rnorm(points_num), y=rnorm(points_num), c=as.factor(1:points_num %% 2)) +gg <- ggplot(df, aes(x=x, y=y, color=c)) + scale_color_discrete(guide=FALSE) + +gg_vec <- gg + geom_point(size=0.5) +gg_rast <- gg + geom_point_rast(size=0.5) + +PrintFileSize(gg_rast, 'Raster') +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +#> Raster: 400.4473 Kb. +PrintFileSize(gg_vec, 'Vector') +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +#> Vector: 54862.49 Kb. +``` + +### Jitter: Rasterize jittered scatter plots with geom_jitter_rast() + +Just like the example above with`geom_point_rast()`, users may also opt to create rasterized scatter plots with jitter. The geom `geom_jitter_rast()` is similar to `ggplot2::geom_jitter()`, but it creates a rasterized layer: + + + +```r +library(ggplot2) +library(ggrastr) + +points_num <- 5000 +df <- data.frame(x=rnorm(points_num), y=rnorm(points_num), c=as.factor(1:points_num %% 2)) +gg <- ggplot(df, aes(x=x, y=y, color=c)) + scale_color_discrete(guide=FALSE) + +gg_jitter_rast <- gg + geom_jitter_rast(raster.dpi=600) +print(gg_jitter_rast) +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +``` + +![plot of chunk unnamed-chunk-12](figure/unnamed-chunk-12-1.png) + + + +### Tiles: Rasterize heatmaps with geom_tile_rast() + +Heatmaps also have similar issues with the default vectorized formats: + + + +```r +library(ggplot2) +library(ggrastr) + +coords <- expand.grid(1:500, 1:500) +coords$Value <- 1 / apply(as.matrix(coords), 1, function(x) sum((x - c(50, 50))^2)^0.01) +gg_tile_vec <- ggplot(coords) + geom_tile(aes(x=Var1, y=Var2, fill=Value)) +gg_tile_rast <- ggplot(coords) + geom_tile_rast(aes(x=Var1, y=Var2, fill=Value)) +print(gg_tile_rast) +``` + +![plot of chunk unnamed-chunk-13](figure/unnamed-chunk-13-1.png) + +We can see that the rasterized plots using `ggrastr` are lighter in size when rendered to pdf: + + +```r +PrintFileSize(gg_tile_rast, 'Raster') +#> Raster: 46.77637 Kb. +PrintFileSize(gg_tile_vec, 'Vector') +#> Vector: 817.8398 Kb. +``` + + + +### Violinplots: Rasterize violin plots with geom_violin_rast() + +One can see a similar effect with violin plots: + + +```r +library(ggplot2) +library(ggrastr) + +gg_violin_vec <- ggplot(mtcars, aes(factor(cyl), mpg)) + geom_violin() +gg_violin_rast <- ggplot(mtcars) + geom_violin_rast(aes(factor(cyl), mpg)) +print(gg_violin_rast) +``` + +![plot of chunk unnamed-chunk-15](figure/unnamed-chunk-15-1.png) + + +```r +## difference in size shown +PrintFileSize(gg_tile_rast, 'Raster') +#> Raster: 46.77637 Kb. +PrintFileSize(gg_tile_vec, 'Vector') +#> Vector: 817.8398 Kb. +``` + + + +### Boxplots: Jitter outliers and rasterize boxplots with geom_boxplot_jitter + +Another type of plots with a potentially large number of small objects is geom_boxplot: + +```r +library(ggplot2) +library(ggrastr) + +points_num <- 5000 +df <- data.frame(x=as.factor(1:points_num %% 2), y=log(abs(rcauchy(points_num)))) +gg <- ggplot(df, aes(x=x, y=y)) + scale_color_discrete(guide=FALSE) + +boxplot <- gg + geom_boxplot() +print(boxplot) +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +``` + +![plot of chunk unnamed-chunk-17](figure/unnamed-chunk-17-1.png) + +With a large number of objects, outlier points become noninformative. For example, here is the rendered plot with `points_num <- 1000000`: + +![boxplot_1000000](boxplot_1000000.png) + + +For such a large number of points, it would be better to jitter them using `geom_boxplot_jitter()`: + +```r +library(ggplot2) +library(ggrastr) +points_num <- 500000 +df <- data.frame(x=as.factor(1:points_num %% 2), y=log(abs(rcauchy(points_num)))) +gg <- ggplot(df, aes(x=x, y=y)) + scale_color_discrete(guide=FALSE) + +gg_box_vec <- gg + geom_boxplot_jitter(outlier.size=0.1, outlier.jitter.width=0.3, outlier.alpha=0.5) +print(gg_box_vec) +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +``` + +![plot of chunk unnamed-chunk-18](figure/unnamed-chunk-18-1.png) + +And this geom can be rasterized as well: + +```r +gg_box_rast <- gg + geom_boxplot_jitter(outlier.size=0.1, outlier.jitter.width=0.3, outlier.alpha=0.5, raster.dpi=200) +print(gg_box_rast) +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +``` + +![plot of chunk unnamed-chunk-19](figure/unnamed-chunk-19-1.png) + + + +```r +PrintFileSize(gg_box_rast, 'Raster') +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +#> Raster: 120.4609 Kb. +PrintFileSize(gg_box_vec, 'Vector') +#> Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please +#> use `guide = "none"` instead. +#> Vector: 226.7207 Kb. +``` + + +### Beeswarm-style plots: geom_beeswarm_rast and geom_quasirandom + +ggrastr also allows users to create rasterized beeswarm plots. As described in the README for [ggbeeswarm](https://github.com/eclarke/ggbeeswarm), + +> Beeswarm plots (aka column scatter plots or violin scatter plots) are a way of plotting points that would ordinarily overlap so that they fall next to each other instead. In addition to reducing overplotting, it helps visualize the density of the data at each point (similar to a violin plot), while still showing each data point individually. + +The ggrastr geom `geom_beeswarm_rast` is similar to `ggbeeswarm::geom_beeswarm()`, but it provides a rasterized layer: + + +```r +library(ggplot2) +library(ggrastr) + +ggplot(mtcars) + geom_beeswarm_rast(aes(x = factor(cyl), y=mpg), raster.dpi=600, cex=1.5) +``` + +![plot of chunk unnamed-chunk-21](figure/unnamed-chunk-21-1.png) + +Analogously, `geom_quasirandom_rast` is much like `ggbeeswarm::geom_quasirandom()`, but with a rasterized layer: + + +```r +library(ggplot2) +library(ggrastr) + +ggplot(mtcars) + geom_quasirandom_rast(aes(x = factor(cyl), y=mpg), raster.dpi=600) +``` + +![plot of chunk unnamed-chunk-22](figure/unnamed-chunk-22-1.png) + +We encourage users to visit both https://CRAN.R-project.org/package=ggbeeswarm and the github repo at https://github.com/eclarke/ggbeeswarm for more details. diff --git a/vignettes/figure/unnamed-chunk-1-1.png b/vignettes/figure/unnamed-chunk-1-1.png new file mode 100644 index 0000000..aaaa551 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-1-1.png differ diff --git a/vignettes/figure/unnamed-chunk-12-1.png b/vignettes/figure/unnamed-chunk-12-1.png new file mode 100644 index 0000000..5828922 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-12-1.png differ diff --git a/vignettes/figure/unnamed-chunk-13-1.png b/vignettes/figure/unnamed-chunk-13-1.png new file mode 100644 index 0000000..85e62c7 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-13-1.png differ diff --git a/vignettes/figure/unnamed-chunk-15-1.png b/vignettes/figure/unnamed-chunk-15-1.png new file mode 100644 index 0000000..c1ac594 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-15-1.png differ diff --git a/vignettes/figure/unnamed-chunk-17-1.png b/vignettes/figure/unnamed-chunk-17-1.png new file mode 100644 index 0000000..aa4732d Binary files /dev/null and b/vignettes/figure/unnamed-chunk-17-1.png differ diff --git a/vignettes/figure/unnamed-chunk-18-1.png b/vignettes/figure/unnamed-chunk-18-1.png new file mode 100644 index 0000000..0877fa1 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-18-1.png differ diff --git a/vignettes/figure/unnamed-chunk-19-1.png b/vignettes/figure/unnamed-chunk-19-1.png new file mode 100644 index 0000000..6cea7d8 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-19-1.png differ diff --git a/vignettes/figure/unnamed-chunk-2-1.png b/vignettes/figure/unnamed-chunk-2-1.png new file mode 100644 index 0000000..5821ce4 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-2-1.png differ diff --git a/vignettes/figure/unnamed-chunk-21-1.png b/vignettes/figure/unnamed-chunk-21-1.png new file mode 100644 index 0000000..e410743 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-21-1.png differ diff --git a/vignettes/figure/unnamed-chunk-22-1.png b/vignettes/figure/unnamed-chunk-22-1.png new file mode 100644 index 0000000..2a5d5d8 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-22-1.png differ diff --git a/vignettes/figure/unnamed-chunk-3-1.png b/vignettes/figure/unnamed-chunk-3-1.png new file mode 100644 index 0000000..37056f6 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-3-1.png differ diff --git a/vignettes/figure/unnamed-chunk-4-1.png b/vignettes/figure/unnamed-chunk-4-1.png new file mode 100644 index 0000000..dda8c7e Binary files /dev/null and b/vignettes/figure/unnamed-chunk-4-1.png differ diff --git a/vignettes/figure/unnamed-chunk-5-1.png b/vignettes/figure/unnamed-chunk-5-1.png new file mode 100644 index 0000000..c78d28d Binary files /dev/null and b/vignettes/figure/unnamed-chunk-5-1.png differ diff --git a/vignettes/figure/unnamed-chunk-6-1.png b/vignettes/figure/unnamed-chunk-6-1.png new file mode 100644 index 0000000..72efe1a Binary files /dev/null and b/vignettes/figure/unnamed-chunk-6-1.png differ diff --git a/vignettes/figure/unnamed-chunk-7-1.png b/vignettes/figure/unnamed-chunk-7-1.png new file mode 100644 index 0000000..60e9f67 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-7-1.png differ diff --git a/vignettes/figure/unnamed-chunk-8-1.png b/vignettes/figure/unnamed-chunk-8-1.png new file mode 100644 index 0000000..e882452 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-8-1.png differ diff --git a/vignettes/figure/unnamed-chunk-9-1.png b/vignettes/figure/unnamed-chunk-9-1.png new file mode 100644 index 0000000..8772071 Binary files /dev/null and b/vignettes/figure/unnamed-chunk-9-1.png differ