Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: tinyplot
Type: Package
Title: Lightweight Extension of the Base R Graphics System
Version: 0.0.5.9005
Version: 0.0.5.9006
Authors@R:
c(
person(
Expand Down Expand Up @@ -41,6 +41,7 @@ Imports:
grDevices,
methods,
stats,
tools,
utils
Suggests:
altdoc (>= 0.3.0),
Expand Down
8 changes: 8 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ export(tpar)
importFrom(grDevices,adjustcolor)
importFrom(grDevices,as.raster)
importFrom(grDevices,colorRampPalette)
importFrom(grDevices,dev.list)
importFrom(grDevices,dev.new)
importFrom(grDevices,dev.off)
importFrom(grDevices,extendrange)
importFrom(grDevices,hcl.colors)
importFrom(grDevices,hcl.pals)
importFrom(grDevices,jpeg)
importFrom(grDevices,palette)
importFrom(grDevices,palette.colors)
importFrom(grDevices,palette.pals)
importFrom(grDevices,pdf)
importFrom(grDevices,png)
importFrom(grDevices,recordGraphics)
importFrom(grDevices,svg)
importFrom(grDevices,xy.coords)
importFrom(graphics,Axis)
importFrom(graphics,abline)
Expand Down Expand Up @@ -45,6 +52,7 @@ importFrom(stats,model.frame)
importFrom(stats,na.omit)
importFrom(stats,terms)
importFrom(stats,update)
importFrom(tools,file_ext)
importFrom(utils,head)
importFrom(utils,modifyList)
importFrom(utils,tail)
13 changes: 12 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# News

## 0.0.5.9005 (development version)
## 0.0.5.9006 (development version)

License:

Expand All @@ -23,6 +23,17 @@ automatically vary line widths by group. (#134 @grantmcdermott)
- `tpar()` now accepts standard `par()` arguments in addition to the
`tinyplot`-specific ones. This allows users to set or query graphical parameters
via a single convenience function, instead having to invoke `tpar` and `par` separately.
- Users can write plots directly to disk using the new `file` argument,
alongside corresponding `width` and `height` arguments for output customization
(both of which are defined in inches). For example,
`tinyplot(..., file = "~/myplot.png", width = 8, height = 5)`. This
implementation relies on a simple internal wrapper around the traditional R
external graphics devices like `png()`, `pdf()`, etc. But it may prove more
convenient, since the current global graphics parameters held in `(t)par()` are
carried over to the external device too and don't need to be reset. Note that
the appropriate device type is determined automatically by the file extension,
which must be one of ".png", ".jpg" (".jpeg"), ".pdf", or ".svg". (#143
@grantmcdermott)

Bug fixes:

Expand Down
83 changes: 82 additions & 1 deletion R/tinyplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,34 @@
#' @param add logical. If TRUE, then elements are added to the current plot rather
#' than drawing a new plot window. Note that the automatic legend for the
#' added elements will be turned off.
#' @param file character string giving the file path for writing a plot to disk.
#' If specified, the plot will not be displayed interactively, but rather sent
#' to the appropriate external graphics device (i.e.,
#' \code{\link[grDevices]{png}}, \code{\link[grDevices]{jpeg}},
#' \code{\link[grDevices]{pdf}}, or \code{\link[grDevices]{svg}}). As a point
#' of convenience, note that any global parameters held in `(t)par` are
#' automatically carried over to the external device and don't need to be
#' reset (in contrast to the conventional base R approach that requires
#' manually opening and closing the device). The device type is determined by
#' the file extension at the end of the provided path, and must be one of
#' ".png", ".jpg" (".jpeg"), ".pdf", or ".svg". (Other file types may be
#' supported in the future.) The file dimensions can be controlled by the
#' corresponding `width` and `height` arguments below, otherwise will fall
#' back to the `"file.width"` and `"file.height"` values held in
#' \code{\link[tinyplot]{tpar}} (i.e., both defaulting to 7 inches, and where
#' the default resolution for bitmap files is also specified as 300
#' DPI).
#' @param width numeric giving the plot width in inches. Together with `height`,
#' typically used in conjunction with the `file` argument above, overriding the
#' default values held in `tpar("file.width", "file.height")`. If either `width`
#' or `height` is specified, but a corresponding `file` argument is not
#' provided as well, then a new interactive graphics device dimensions will be
#' opened along the given dimensions. Note that this interactive resizing may
#' not work consistently from within an IDE like RStudio that has an integrated
#' graphics windows.
#' @param height numeric giving the plot height in inches. Same considerations as
#' `width` (above) apply, e.g. will default to `tpar("file.height")` if not
#' specified.
#' @param ... other graphical parameters. See \code{\link[graphics]{par}} or
#' the "Details" section of \code{\link[graphics]{plot}}.
#'
Expand All @@ -213,10 +241,11 @@
#' out existing `plot` calls for `tinyplot` (or its shorthand alias `plt`),
#' without causing unexpected changes to the output.
#'
#' @importFrom grDevices adjustcolor colorRampPalette extendrange palette palette.colors palette.pals hcl.colors hcl.pals xy.coords
#' @importFrom grDevices adjustcolor colorRampPalette extendrange palette palette.colors palette.pals hcl.colors hcl.pals xy.coords png jpeg pdf svg dev.off dev.new dev.list
#' @importFrom graphics abline arrows axis Axis box grconvertX grconvertY lines par plot.default plot.new plot.window points polygon segments title mtext text rect
#' @importFrom utils modifyList head tail
#' @importFrom stats na.omit
#' @importFrom tools file_ext
#'
#' @examples
#'
Expand Down Expand Up @@ -411,10 +440,58 @@ tinyplot.default = function(
ymax = NULL,
ribbon_alpha = 0.2,
add = FALSE,
file = NULL,
width = NULL,
height = NULL,
...) {

dots = list(...)

# Write plot to output file (if requested)
if (!is.null(file)) {
filepath = file
filewidth = width
fileheight = height
if (is.null(filewidth)) filewidth = .tpar[["file.width"]]
if (is.null(fileheight)) fileheight = .tpar[["file.height"]]
fileres = .tpar[["file.res"]]
# catch to close interactive device if one isn't already open
fkdev = is.null(dev.list())
# grab existing device pars to pass on to next one
dop = par(no.readonly = TRUE)
# close interactive device if not already open
if (isTRUE(fkdev)) dev.off()
exttype = file_ext(filepath)
if (exttype == "jpg") exttype = "jpeg"
switch(exttype,
png = png(filepath, width = filewidth, height = fileheight, units = "in", res = fileres),
jpeg = jpeg(filepath, width = filewidth, height = fileheight, units = "in", res = fileres),
pdf = pdf(filepath, width = filewidth, height = fileheight),
svg = svg(filepath, width = filewidth, height = fileheight),
stop("\nUnsupported file extension. Only '.png', '.jpg', '.pdf', or '.svg' are allowed.\n")
)
dop$new = FALSE # catch for some interfaces
par(dop)
on.exit(dev.off(), add = TRUE)
# else statement below for interactive plot with user-specified width/height
} else if (!is.null(width) || !is.null(height)) {
devwidth = width
devheight = height
# if one of width or height is missing, set equal to the other
if (is.null(devwidth)) devwidth = devheight
if (is.null(devheight)) devheight = devwidth
# catch to close interactive device if one isn't already open
fkdev = is.null(dev.list())
# grab existing device pars to pass on to next one
dop = par(no.readonly = TRUE)
# close interactive device if not already open
if (isTRUE(fkdev)) dev.off()
dev.new(width = devwidth, height = devheight)
dop$new = FALSE # catch for some interfaces
par(dop)
}

# Adding to the previous plot?
if (isTRUE(add)) {
legend = FALSE
# main = sub = xlab = ylab = NULL ## Rather do this later
Expand All @@ -423,6 +500,9 @@ tinyplot.default = function(
# Save current graphical parameters
opar = par(no.readonly = TRUE)
if (par_restore || !is.null(facet)) {
if (!is.null(file) || !is.null(width) || !is.null(height)) {
opar$new = FALSE # catch for some interfaces
}
on.exit(par(opar), add = TRUE)
}

Expand Down Expand Up @@ -1247,6 +1327,7 @@ tinyplot.default = function(
last_facet_par = par(no.readonly = TRUE)
set_last_facet_par(last_facet_par)
}


}

Expand Down
27 changes: 27 additions & 0 deletions R/tpar.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@
#' `facet.border` \tab\tab Character or integer specifying the facet border colour. If an integer, will correspond to the users default colour palette (see \code{\link[grDevices]{palette}}). Passed \code{\link[graphics]{rect}}. Defaults to `NA` (none).\cr
#' \tab\tab\cr
#' \tab\tab\cr
#' `file.height` \tab\tab Numeric specifying the height (in inches) of any plot that is written to disk using the `tinyplot(..., file = X)` argument. Defaults to 7.\cr
#' \tab\tab\cr
#' \tab\tab\cr
#' `file.width` \tab\tab Numeric specifying the width (in inches) of any plot that is written to disk using the `tinyplot(..., file = X)` argument. Defaults to 7.\cr
#' \tab\tab\cr
#' \tab\tab\cr
#' `file.res` \tab\tab Numeric specifying the resolution (in dots per square inch) of any plot that is written to disk in bitmap format (i.e., PNG or JPEG) using the `tinyplot(..., file = X)` argument. Defaults to 300.\cr
#' \tab\tab\cr
#' \tab\tab\cr
#' `fmar` \tab\tab A numeric vector of form `c(b,l,t,r)` for controlling the (base) margin padding, in terms of lines, between the individual facets in a faceted plot. Defaults to `c(1,1,1,1)`, i.e. a single line of padding around each facet. If more that three facets are detected, the `fmar` parameter is scaled by 0.75 (i.e., three-quarters) to reduce the excess whitespace that would otherwise arise due to the absent axes lines and labels. (An exception is made for 2x2 plots to better match the `cex` expansion logic of the base graphics system under this particular layout.) Similarly, note that an extra 0.5 lines is subtracted from each side of the facet padding for plots that aren't framed, to reduce excess whitespace.\cr
#' \tab\tab\cr
#' \tab\tab\cr
Expand Down Expand Up @@ -149,6 +158,24 @@ tpar = function(...) {
.tpar$facet.border = facet.border
}

if (length(opts$file.width)) {
file.width = as.numeric(opts$file.width)
if(!is.numeric(file.width)) stop("file.width needs to be numeric")
.tpar$file.width = file.width
}

if (length(opts$file.height)) {
file.height = as.numeric(opts$file.height)
if(!is.numeric(file.height)) stop("file.height needs to be numeric")
.tpar$file.height = file.height
}

if (length(opts$file.res)) {
file.res = as.numeric(opts$file.res)
if(!is.numeric(file.res)) stop("file.res needs to be numeric")
.tpar$file.res = file.res
}

if (length(opts$fmar)) {
fmar = as.numeric(opts$fmar)
if(!is.numeric(fmar)) stop("fmar needs to be numeric")
Expand Down
5 changes: 5 additions & 0 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
assign(".tinyplot_env", new.env(), envir = tnypltptns)
.tpar <- new.env()

# Figure output options if written to file
.tpar$file.width <- if(is.null(getOption("tinyplot_file.width"))) 7 else as.numeric(getOption("tinyplot_file.width"))
.tpar$file.height <- if(is.null(getOption("tinyplot_file.height"))) 7 else as.numeric(getOption("tinyplot_file.height"))
.tpar$file.res <- if(is.null(getOption("tinyplot_file.res"))) 300 else as.numeric(getOption("tinyplot_file.res"))

# Facet margin, i.e. gap between the individual facet windows
.tpar$fmar <- if(is.null(getOption("tinyplot_fmar"))) c(1,1,1,1) else as.numeric(getOption("tinyplot_fmar"))

Expand Down
34 changes: 34 additions & 0 deletions man/tinyplot.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions man/tpar.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.