Skip to content

Commit

Permalink
CRAN v0.1.0 submission (#151)
Browse files Browse the repository at this point in the history
* NEWS

* NEWS and version bump

* CRAN comments and .Rbuildignore update

* CRAN submission (1st time)

* Anticipatory install updates in README

* Simplify package meta docs

* Docs: Add return values and other updates per CRAN request

* Minor cleanups

* Fixes #149

* README tweak

* tweak

* More README tweaks

* Add ribbon.alpha to tpar

* document

* Add get_orig_par and supporting functions

* closes #150

* tweak

* Add get_saved_par. Closes #152.

* Easy alpha adjustment. Closes #129.

* README tweak

* fix README footnotes

- be explicit with `quarto render README.qmd --to gfm `

* typo

* typo

* prep cran submission

* submission SHA
  • Loading branch information
grantmcdermott authored Jun 20, 2024
1 parent 7218f7b commit d2f3b38
Show file tree
Hide file tree
Showing 55 changed files with 1,966 additions and 723 deletions.
3 changes: 3 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ README_files/
^_quarto$
vignettes/
^LICENSE\.md$
^cran-comments\.md$
^CRAN-SUBMISSION$
#inst/tinytest/
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,5 @@ SCRATCH
^_quarto$

_quarto

/.quarto/
3 changes: 3 additions & 0 deletions CRAN-SUBMISSION
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Version: 0.1.0
Date: 2024-06-19 18:17:25 UTC
SHA: 561b24cb0be3549f88efdc7aa527181f7e6b3327
12 changes: 6 additions & 6 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
Package: tinyplot
Type: Package
Title: Lightweight Extension of the Base R Graphics System
Version: 0.0.5.9008
Version: 0.1.0
Date: 2024-06-19
Authors@R:
c(
person(
given = "Grant",
family = "McDermott",
role = c("aut", "cre"),
email = "[email protected]"
email = "[email protected]",
comment = c(ORCID = "0000-0001-7883-8573")
),
person(
given = "Vincent",
Expand All @@ -32,7 +34,7 @@ Authors@R:
)
)
Description: Lightweight extension of the base R graphics system, with support
for automatic legends, facetting, and several other enhancements.
for automatic legends, facets, and various other enhancements.
License: Apache License (>= 2)
Depends:
R (>= 4.0)
Expand All @@ -54,8 +56,6 @@ Suggests:
knitr
Encoding: UTF-8
RoxygenNote: 7.3.1
URL: https://grantmcdermott.com/tinyplot/,
http://grantmcdermott.com/tinyplot/
URL: https://grantmcdermott.com/tinyplot/
BugReports: https://github.com/grantmcdermott/tinyplot/issues
VignetteBuilder: knitr
Roxygen: list(markdown = TRUE)
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ S3method(tinyplot,default)
S3method(tinyplot,density)
S3method(tinyplot,formula)
export(draw_legend)
export(get_saved_par)
export(plt)
export(tinyplot)
export(tpar)
Expand Down
44 changes: 41 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
# News

## 0.0.5.9008 (development version)
## 0.1.0

Our first CRAN submission! This v0.1.0 release includes the following new
features and updates:

License:

- Formally switch to Apache 2.0 license. (#141 @grantmcdermott)

Breaking changes:

- To ensure consistent "dot.case" style for all `tinyplot()` function arguments,
the following two arguments have been renamed (`old` => `new`):
- `par_restore` => `restore.par` (note the change in word order too!)
- `ribbon_alpha` => `ribbon.alpha`

We don't believe that these two arguments are much used in practice. So
hopefully it will only have a negligible effect on existing `tinyplot` code in
the wild, even though it is a breaking change. (#149 @grantmcdermott)

New features:

- Gradient legends are now supported if a continuous variable is passed to
Expand All @@ -22,7 +36,11 @@ default. Thanks to @zeileis for the suggestion. (#130 @grantmcdermott)
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.
via a single convenience function, instead having to invoke `tpar` and `par`
separately. (#140 @grantmcdermott)
- As an aside, `tpar()` has gained some additional parameters for fine-grained
control of global plot defaults, including `grid`, `ribbon.alpha`, and various
`file.*` parameters (see next bullet point).
- 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,
Expand All @@ -32,9 +50,27 @@ 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
which must be one of ".png", ".jpg" (".jpeg"), ".pdf", or ".svg".
(#143 @grantmcdermott)
- We have a shiny new `tinyplot` logo. (#148 @grantmcdermott)
- The new `get_saved_par()` function can be used to retrieve the `par` settings
from immediately before or immediately after the preceding `tinyplot` call.
This function replaces some older (non-exported) internal functions that
`tinyplot` was using to restore and control `par` environments. But it could
also prove help to end users who are looking for additional ways to restore
`par` settings after the fact. See `?get_saved_par` for some examples. (#152
@grantmcdermott)
- `tinyplot`/`plt` gaina a new `alpha = <numeric[0,1]>` convenience argument for
adding transparency to plot elements and colours. Example use:
`plt(rnorm(1e3), pch = 19, alpha = 0.3)`. (#129 @grantmcdermott)
- Similar to the preceding news item, transparency can be added to (grouped)
background fill by passing `bg` (or its alias, `fill`) a numeric in the range
`[0,1]`. This feature has the same effect as `bg = "by"` except for the added
transparency. Example use:
`plt(lat ~ long | depth, data = quakes, pch = 21, cex = 2, bg = 0.2)`. (#129
@grantmcdermott)


Bug fixes:

- Fixed bug that prevented `tpar(facet.x = ...)` args from being passed forward
Expand All @@ -56,6 +92,8 @@ CRAN's recommended 5 MB limit. Please note that local testing of the package
requires adding the `NOT_CRAN=TRUE` environment variable to your .Renviron file
(or, exporting it in your .bashrc/.zshrc/etc. dotfile if you prefer that
approach). (#145 @vincentarelbundock & @grantmcdermott)
- Update some test snapshots to match slight changes in the way that R 4.4.0
calculates `density` grid coords. (#150 @grantmcdermott)


## 0.0.5
Expand Down
13 changes: 7 additions & 6 deletions R/by_aesthetics.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
by_col = function(ngrps = 1L, col = NULL, palette = NULL, gradient = NULL, ordered = NULL) {
by_col = function(ngrps = 1L, col = NULL, palette = NULL, gradient = NULL, ordered = NULL, alpha = NULL) {

if (is.null(ordered)) ordered = FALSE
if (is.null(alpha)) alpha = 1
if (is.null(gradient)) gradient = FALSE
if (isTRUE(gradient)) {
ngrps = 100L
Expand Down Expand Up @@ -37,8 +38,8 @@ by_col = function(ngrps = 1L, col = NULL, palette = NULL, gradient = NULL, order
if (is.null(palette)) {

if (ngrps <= length(palette()) && isFALSE(ordered) && isFALSE(gradient)) {
palette_fun = function() palette() # must be function to avoid arg ambiguity
args = list()
palette_fun = function(alpha) adjustcolor(palette(), alpha) # must be function to avoid arg ambiguity
args = list(alpha = alpha)
} else {
if (ngrps <= 8 && isFALSE(ordered)) { # ngrps < 100 so we know gradient is FALSE too
palette = "R4"
Expand All @@ -58,7 +59,7 @@ by_col = function(ngrps = 1L, col = NULL, palette = NULL, gradient = NULL, order
}

}
args = list(n = ngrps, palette = palette)
args = list(n = ngrps, palette = palette, alpha = alpha)
}

} else {
Expand All @@ -71,7 +72,7 @@ by_col = function(ngrps = 1L, col = NULL, palette = NULL, gradient = NULL, order
if (pal_match < 1L) stop("'palette' is ambiguous")
palette_fun = palette.colors
if (isTRUE(gradient)) {
palette_fun2 = function(n, palette) colorRampPalette(palette.colors(palette = palette))(n)
palette_fun2 = function(n, palette, alpha) colorRampPalette(palette.colors(palette = palette, alpha = alpha))(n)
palette_fun = palette_fun2
}
} else {
Expand All @@ -87,7 +88,7 @@ by_col = function(ngrps = 1L, col = NULL, palette = NULL, gradient = NULL, order
)
}
}
args = list(n = ngrps, palette = palette)
args = list(n = ngrps, palette = palette, alpha = alpha)

} else if (class(palette) %in% c("call", "name")) {

Expand Down
31 changes: 18 additions & 13 deletions R/draw_legend.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
#' outside the plotting area) and drawing of legend.
#'
#' @md
#' @param legend Legend placement keyword or list, passed down from `tinyplot`.
#' @param legend Legend placement keyword or list, passed down from [tinyplot].
#' @param legend_args Additional legend arguments to be passed to `legend()`.
#' @param by_dep The (deparsed) "by" grouping variable name.
#' @param lgnd_labs The labels passed to `legend(legend = ...)`.
#' @param type Plotting type(s), passed down from `tinyplot`.
#' @param pch Plotting character(s), passed down from `tinyplot`.
#' @param lty Plotting linetype(s), passed down from `tinyplot`.
#' @param lwd Plotting line width(s), passed down from `tinyplot`.
#' @param col Plotting colour(s), passed down from `tinyplot`.
#' @param bg Plotting character background fill colour(s), passed down from `tinyplot`.
#' @param cex Plotting character expansion(s), passed down from `tinyplot`.
#' @param type Plotting type(s), passed down from [tinyplot].
#' @param pch Plotting character(s), passed down from [tinyplot].
#' @param lty Plotting linetype(s), passed down from [tinyplot].
#' @param lwd Plotting line width(s), passed down from [tinyplot].
#' @param col Plotting colour(s), passed down from [tinyplot].
#' @param bg Plotting character background fill colour(s), passed down from [tinyplot].
#' @param cex Plotting character expansion(s), passed down from [tinyplot].
#' @param gradient Logical indicating whether a continuous gradient swatch
#' should be used to represent the colors.
#' @param lmar Legend margins (in lines). Should be a numeric vector of the form
Expand All @@ -26,10 +26,15 @@
#' @param has_sub Logical. Does the plot have a sub-caption. Only used if
#' keyword position is "bottom!", in which case we need to bump the legend
#' margin a bit further.
#' @param new_plot Should we be calling plot.new internally?
#' @param new_plot Logical. Should we be calling plot.new internally?
#'
#' @returns No return value, called for side effect of producing a(n empty) plot
#' with a legend in the margin.
#'
#' @importFrom graphics grconvertX grconvertY rasterImage strwidth
#' @importFrom grDevices as.raster recordGraphics
#' @importFrom utils modifyList
#'
#' @examples
#'
#' oldmar = par("mar")
Expand Down Expand Up @@ -225,7 +230,7 @@ draw_legend = function(
# requires additional space
omar[2] = par("mgp")[1] + 1*par("cex.lab")
}
par(mar = omar) ## TEST
par(mar = omar)

if (isTRUE(new_plot)) plot.new()

Expand Down Expand Up @@ -292,13 +297,13 @@ draw_legend = function(
## drawn, otherwise the inset calculation---which is based in the legend
## width---will be off the first time.
if (outer_bottom) {
omar[1] = par("mgp")[1] + 1*par("cex.lab") ## TEST
if (isTRUE(has_sub)) omar[1] = omar[1] + 1*par("cex.sub") ## TEST
omar[1] = par("mgp")[1] + 1*par("cex.lab")
if (isTRUE(has_sub)) omar[1] = omar[1] + 1*par("cex.sub")
} else {
## For "top!", the logic is slightly different: We don't expand the outer
## margin b/c we need the legend to come underneath the main title. So
## we rather expand the existing inner margin.
ooma[3] = ooma[3] + topmar_epsilon ## TESTING
ooma[3] = ooma[3] + topmar_epsilon
par(oma = ooma)
}
par(mar = omar)
Expand Down
116 changes: 116 additions & 0 deletions R/get_saved_par.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#' @title Retrieve the saved graphical parameters
#'
#' @description Convenience function for retrieving the graphical parameters
#' (i.e., the full list of `tag = value` pairs held in
#' \code{\link[graphics]{par}}) from either immediately before or
#' immediately after the most recent [tinyplot] call.
#'
#' @param when character. From when should the saved parameters be retrieved?
#' Either "before" (the default) or "after" the preceding `tinyplot` call.
#'
#' @details A potential side-effect of [tinyplot] is that it can change a user's
#' \code{\link[graphics]{par}} settings. For example, it may adjust the inner
#' and outer plot margins to make space for an automatic legend; see
#' [draw_legend]. While it is possible to immediately restore the original
#' \code{\link[graphics]{par}} settings upon exit via the
#' `tinyplot(..., restore.par = TRUE)` argument, this is not the default
#' behaviour. The reason being that we need to preserve the adjusted parameter
#' settings in case users want to add further graphical annotations to their
#' plot (e.g., \code{\link[graphics]{abline}}, \code{\link[graphics]{text}},
#' etc.) Nevertheless, it may still prove desirable to recall and reset these
#' original graphical parameters after the fact (e.g., once all these extra
#' annotations have been added). That is the purpose of this [get_saved_par]
#' function.
#'
#' Of course, users may prefer to manually capture and reset graphical
#' parameters, as per the standard method described in the
#' \code{\link[graphics]{par}} documentation. For example:
#'
#' ```
#' op = par(no.readonly = TRUE) # save current par settings
#' # <do lots of (tiny)plotting>
#' par(op) # reset original pars
#' ```
#'
#' This standard manual approach may be safer than [get_saved_par] because it
#' offers more precise control. Specifically, the value of [get_saved_par]
#' itself will be reset after ever new [tinyplot] call; i.e. it may inherit an
#' already-changed set of parameters. Users should bear these trade-offs in
#' mind when deciding which approach to use. As a general rule,
#' [get_saved_par] offers the convenience of resetting the original
#' \code{\link[graphics]{par}} settings even if a user forgot to save them
#' beforehand. But one should avoid invoking it after a series of consecutive
#' [tinyplot] calls.
#'
#' Finally, note that users can always call \code{\link[grDevices]{dev.off}}
#' to reset all \code{\link[graphics]{par}} settings to their defaults.
#'
#' @returns A list of \code{\link[graphics]{par}} settings.
#'
#' @examples
#' #
#' # Contrived example where we draw a grouped scatterplot with a legend and
#' # manually add corresponding best fit lines for each group...
#' #
#'
#' # First draw the grouped scatterplot
#' tinyplot(Sepal.Length ~ Petal.Length | Species, iris)
#'
#' # Preserving adjusted par settings is good for adding elements to our plot
#' for (s in levels(iris$Species)) {
#' abline(
#' lm(Sepal.Length ~ Petal.Length, iris, subset = Species==s),
#' col = which(levels(iris$Species)==s)
#' )
#' }
#'
#' # Get saved par from before the preceding tinyplot call (but don't use yet)
#' sp = get_saved_par("before")
#'
#' # Note the changed margins will affect regular plots too, which is probably
#' # not desirable
#' plot(1:10)
#'
#' # Reset the original parameters (could use `par(sp)` here)
#' tpar(sp)
#' # Redraw our simple plot with our corrected right margin
#' plot(1:10)
#'
#' #
#' # Quick example going the other way, "correcting" for par.restore = TRUE...
#' #
#'
#' tinyplot(Sepal.Length ~ Petal.Length | Species, iris, restore.par = TRUE)
#' # Our added best lines will be wrong b/c of misaligned par
#' for (s in levels(iris$Species)) {
#' abline(
#' lm(Sepal.Length ~ Petal.Length, iris, subset = Species==s),
#' col = which(levels(iris$Species)==s), lty = 2
#' )
#' }
#' # grab the par settings from the _end_ of the preceding tinyplot call to fix
#' tpar(get_saved_par("after"))
#' # now the best lines are correct
#' for (s in levels(iris$Species)) {
#' abline(
#' lm(Sepal.Length ~ Petal.Length, iris, subset = Species==s),
#' col = which(levels(iris$Species)==s)
#' )
#' }
#'
#' # reset again to original saved par settings before exit
#' tpar(sp)
#'
#' @export
get_saved_par <- function(when = c("before", "after")) {
when = match.arg(when)
par_env_name = paste0(".saved_par_", when)
return(get(par_env_name, envir = get(".tinyplot_env", envir = parent.env(environment()))))
}

# (non-exported) companion function(s) for setting the original pars
set_saved_par <- function(when = c("before", "after"), value) {
when = match.arg(when)
par_env_name = paste0(".saved_par_", when)
assign(par_env_name, value, envir = get(".tinyplot_env", envir = parent.env(environment())))
}
Loading

0 comments on commit d2f3b38

Please sign in to comment.