diff --git a/NEWS.md b/NEWS.md index 2b9985d55..9111fba71 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,9 +14,13 @@ Notable changes include: * removal of `PMS2Munsell()` and support data * deprecation of `coordinates()<-` and `proj4string()<-` in favor of `initSpatial()<-` * removal of `rruff.sample` example XRD patterns - * `plotSPC()` now uses `electroStatics_1D()` for fixing horizon depth label overlap, solutions are deterministic and almost always better - # `plotSPC()` depth axis adjustments via new argument (logical or list) `depth.axis` - * deprecation of `plotSPC()` arguments: + +Major changes to `plotSPC()`: + * The maximum depth range of the figure is now based on `max.depth` or `max(x)`. This means that sketches generated with aqp 2.x will generally have less white space at the bottom of the figure. Make more room for additional annotation or visual effect by setting the desired depth range with the `max.depth` argument. + * now uses `electroStatics_1D()` for fixing horizon depth label overlap, solutions are deterministic and almost always better + * better depth axis interval heuristics (if not specified), varying based on figure depth range + * depth axis adjustments via new argument `depth.axis`, logical or list + * deprecation of arguments: - `plot.depth.axis`: set via `depth.axis = TRUE`, `depth.axis = FALSE`, or customize `depth.axis = list(...)` - `cex.depth.axis`: set via `depth.axis = list(cex = 1)` - `axis.line.offset`: set via `depth.axis = list(line = -2)` diff --git a/R/aqp-label-placement-solvers.R b/R/aqp-label-placement-solvers.R index 65c1dd1c2..a77b4e462 100644 --- a/R/aqp-label-placement-solvers.R +++ b/R/aqp-label-placement-solvers.R @@ -802,7 +802,7 @@ SANN_1D <- function(x, thresh = 0.6, adj = thresh * 2/3, min.x = min(x) - 0.2, m #' hz.depths = TRUE, #' name.style = 'center-center', #' cex.names = 1.5, -#' plot.depth.axis = FALSE, +#' depth.axis = FALSE, #' name = NA, #' color = 'z', #' show.legend = FALSE, diff --git a/R/data-documentation.R b/R/data-documentation.R index 053a3bfc0..623b907b0 100644 --- a/R/data-documentation.R +++ b/R/data-documentation.R @@ -64,13 +64,13 @@ #' group.name.offset = -15, label = 'biome', #' name.style = 'center-center', color = 'CIA', #' cex.names = 0.66, cex.id = 0.66, width = 0.3, -#' plot.depth.axis = FALSE, hz.depths = TRUE) +#' depth.axis = FALSE, hz.depths = TRUE) #' #' groupedProfilePlot(wilson2022, groups = 'biome', #' group.name.offset = -15, label = 'pm', #' name.style = 'center-center', color = 'Fet', #' cex.names = 0.66, cex.id = 0.66, width = 0.3, -#' plot.depth.axis = FALSE, hz.depths = TRUE) +#' depth.axis = FALSE, hz.depths = TRUE) #' "wilson2022" diff --git a/R/plotMultipleSPC.R b/R/plotMultipleSPC.R index c330a753b..f03c374d7 100644 --- a/R/plotMultipleSPC.R +++ b/R/plotMultipleSPC.R @@ -49,27 +49,29 @@ #' #' # plot 2 SoilProfileCollection objects on the same axis #' par(mar=c(1,1,1,1)) -#' plot(sp3, n=n.pedons) -#' plot(sp4, add=TRUE, x.idx.offset=group.ends[1], plot.depth.axis=FALSE, id.style='side') +#' plot(sp3, n = n.pedons) +#' plot(sp4, add = TRUE, x.idx.offset = group.ends[1], +#' depth.axis = FALSE, id.style = 'side') +#' #' # annotate groups -#' profileGroupLabels(x0=group.starts, x1=group.ends, +#' profileGroupLabels(x0 = group.starts, x1 = group.ends, #' labels=c('Collection 1', 'Collection 2'), y0=120, y1=tick.heights) #' profileGroupLabels <- function(x0, x1, labels, y0=100, y1=98, label.offset=2, label.cex=0.75) { - + # sanity check: start / stop / label lengths should be equal if(! all.equal(length(x0), length(x1), length(labels)) ) stop('start positions, stop positions, and number of labels must be equal', call. = FALSE) - + # pre-compute some elements n.groups <- length(x0) label.centers <- (x0 + x1) / 2 - + # add group base lines segments(x0=x0, x1=x1, y0=y0, y1=y0) # add arrows to first / last group members arrows(x0=c(x0, x1), x1=c(x0, x1), y0=c(y0, y0), y1=y1, length=0.1) - + # annotate with group names text(x=label.centers, y=y0 + label.offset, labels=labels, cex=label.cex) } @@ -242,14 +244,14 @@ profileGroupLabels <- function(x0, x1, labels, y0=100, y1=98, label.offset=2, la #' depth.axis = list(line = 0) #' ) plotMultipleSPC <- function(spc.list, group.labels, args = rep(list(NA), times = length(spc.list)), merged.legend = NULL, merged.colors = c("#5E4FA2", "#3288BD", "#66C2A5","#ABDDA4", "#E6F598", "#FEE08B","#FDAE61", "#F46D43", "#D53E4F","#9E0142"), merged.legend.title = merged.legend, arrow.offset = 2, bracket.base.depth = 95, label.offset = 2, label.cex = 0.75, ...) { - + # compute group stats n.groups <- length(spc.list) spc.lengths <- sapply(spc.list, length) n.pedons <- sum(spc.lengths) group.starts <- c(1, 1 + cumsum(spc.lengths[-n.groups])) group.ends <- cumsum(spc.lengths) - + # get depths + offset to start / end profiles yy <- unlist(sapply(spc.list, function(i) profileApply(i, max))) tick.heights <- yy[c(group.starts, group.ends)] + arrow.offset @@ -364,7 +366,7 @@ plotMultipleSPC <- function(spc.list, group.labels, args = rep(list(NA), times = } - + # setup plot with first SPC in list do.call( what = plotSPC, @@ -373,8 +375,8 @@ plotMultipleSPC <- function(spc.list, group.labels, args = rep(list(NA), times = n = n.pedons, na.omit(args[[1]]), ...) - ) - + ) + # iterate over remaining SPC objs if(n.groups > 1) { for(i in 2:n.groups) { @@ -383,12 +385,18 @@ plotMultipleSPC <- function(spc.list, group.labels, args = rep(list(NA), times = suppressMessages( do.call( what = plotSPC, - args = c(x=this.obj, x.idx.offset=group.ends[i-1], add=TRUE, plot.depth.axis=FALSE, this.args) + args = c( + x = this.obj, + x.idx.offset = group.ends[i-1], + add = TRUE, + depth.axis = FALSE, + this.args + ) ) ) } } - + # annotate groups with brackets profileGroupLabels( x0 = group.starts, @@ -398,7 +406,7 @@ plotMultipleSPC <- function(spc.list, group.labels, args = rep(list(NA), times = y1 = tick.heights, label.offset = label.offset, label.cex = label.cex - ) + ) # add merged legend if(! is.null(merged.legend)) { diff --git a/R/plotSPC.R b/R/plotSPC.R index e93e5d159..96d3c6d68 100644 --- a/R/plotSPC.R +++ b/R/plotSPC.R @@ -26,7 +26,7 @@ #' #' @param label quoted column name of the (site-level) attribute used to identify profile sketches #' -#' @param raggedBottom quoted column name of the (site-level) attribute (logical) used to mark profiles with a truncated lower boundary +#' @param raggedBottom either quoted column name of the (site-level) attribute (logical) used to mark profiles with a truncated lower boundary, or `FALSE` suppress ragged bottom depths when `max.depth < max(x)` #' #' @param hz.depths logical, annotate horizon top depths to the right of each sketch (`FALSE`) #' @@ -529,13 +529,17 @@ plotSPC <- function( # ragged bottom flag if(!missing(raggedBottom)) { + + # valid type + if(! inherits(raggedBottom, c('logical', 'character'))) { + stop('`raggedBottom` must be logical or character', call. = FALSE) + } + # valid name - if(! raggedBottom %in% siteNames(x)) + if((is.character(raggedBottom)) & ! raggedBottom %in% siteNames(x)) { stop('invalid `raggedBottom` column name', call. = FALSE) + } - # must be logical - if(! is.logical(x[[raggedBottom]])) - stop('`raggedBottom` must be logical', call. = FALSE) } # length of y.offset must length(x) or 1 diff --git a/R/quickSPC.R b/R/quickSPC.R index 163ec9569..61be69e61 100644 --- a/R/quickSPC.R +++ b/R/quickSPC.R @@ -108,14 +108,14 @@ #' # each horizon label is '10' depth-units (default) #' s <- quickSPC(x) #' plotSPC(s, name.style = 'center-center', -#' cex.names = 1, plot.depth.axis = FALSE, +#' cex.names = 1, depth.axis = FALSE, #' hz.depths = TRUE #' ) #' #' # each horizon label is '5' depth-units #' s <- quickSPC(x, interval = 5) #' plotSPC(s, name.style = 'center-center', -#' cex.names = 1, plot.depth.axis = FALSE, +#' cex.names = 1, depth.axis = FALSE, #' hz.depths = TRUE #' ) #' @@ -128,7 +128,7 @@ #' #' s <- quickSPC(x) #' plotSPC(s, name.style = 'center-center', -#' cex.names = 1, plot.depth.axis = FALSE, +#' cex.names = 1, depth.axis = FALSE, #' hz.depths = TRUE #' ) #' @@ -139,7 +139,7 @@ #' x <- 'NODATA,150,NA-' #' s <- quickSPC(x) #' plotSPC(s, name.style = 'center-center', -#' cex.names = 1, plot.depth.axis = FALSE, +#' cex.names = 1, depth.axis = FALSE, #' hz.depths = TRUE) #' #' diff --git a/man/SoilProfileCollection-plotting-methods.Rd b/man/SoilProfileCollection-plotting-methods.Rd index 9765f6ab7..9ef798f66 100644 --- a/man/SoilProfileCollection-plotting-methods.Rd +++ b/man/SoilProfileCollection-plotting-methods.Rd @@ -19,7 +19,7 @@ plotSPC( hz.depths = FALSE, hz.depths.offset = ifelse(fixLabelCollisions, 0.03, 0), hz.depths.lines = fixLabelCollisions, - depth.axis = list(style = "compact", cex = cex.names, line = -2.5), + depth.axis = list(style = "compact", cex = cex.names * 1.15), alt.label = NULL, alt.label.col = "black", cex.names = 0.5, @@ -80,7 +80,7 @@ plotSPC( \item{label}{quoted column name of the (site-level) attribute used to identify profile sketches} -\item{raggedBottom}{quoted column name of the (site-level) attribute (logical) used to mark profiles with a truncated lower boundary} +\item{raggedBottom}{either quoted column name of the (site-level) attribute (logical) used to mark profiles with a truncated lower boundary, or \code{FALSE} suppress ragged bottom depths when \code{max.depth < max(x)}} \item{hz.depths}{logical, annotate horizon top depths to the right of each sketch (\code{FALSE})} @@ -90,9 +90,10 @@ plotSPC( \item{depth.axis}{logical or list. Use a logical to suppress (\code{FALSE}) or add depth axis using defaults (\code{TRUE}). Use a list to specify one or more of: \itemize{ -\item \code{style} ('compact', 'traditional') -\item \code{line} (numeric, negative values move axis to the left) -\item \code{cex} (scaling applied to entire depth axis) +\item \code{style}: 'compact', 'traditional' +\item \code{line}: numeric, negative values move axis to the left +\item \code{cex}: scaling applied to entire depth axis +\item \code{interval}: axis interval See examples. }} @@ -126,7 +127,7 @@ See examples. \item{n}{integer describing amount of space along x-axis to allocate, defaults to \code{length(x)}} -\item{max.depth}{suggested lower depth boundary of plot, profiles are also truncated at this depth} +\item{max.depth}{numeric. The lower depth for all sketches, deeper profiles are truncated at this depth. Use larger values to arbitrarily extend the vertical dimension, convenient for leaving extract space for annotation.} \item{n.depth.ticks}{suggested number of ticks in depth scale} diff --git a/man/fixOverlap.Rd b/man/fixOverlap.Rd index 30b263b2b..990921a61 100644 --- a/man/fixOverlap.Rd +++ b/man/fixOverlap.Rd @@ -51,7 +51,7 @@ x$z <- as.numeric(x$hzID) hz.depths = TRUE, name.style = 'center-center', cex.names = 1.5, - plot.depth.axis = FALSE, + depth.axis = FALSE, name = NA, color = 'z', show.legend = FALSE, diff --git a/man/harden.melanization.Rd b/man/harden.melanization.Rd index 653271421..761b785b9 100644 --- a/man/harden.melanization.Rd +++ b/man/harden.melanization.Rd @@ -60,12 +60,20 @@ jacobs2000$melanorder <- order(jacobs2000$melan) # Plot in order of increasing Melanization index -plotSPC(jacobs2000, axis.line.offset = -1, +plotSPC(jacobs2000, color = "matrix_color", label = "melan", - plot.order = jacobs2000$melanorder) - -abline(h = c(0,100,150,200), lty = 2) + plot.order = jacobs2000$melanorder, + max.depth = 250 + ) + +segments( + x0 = 0.5, + x1 = length(jacobs2000) + 0.5, + y0 = c(0,100,150,200), + y1 = c(0,100,150,200), + lty = 2 +) # Add [estimated] parent material color swatches lapply(seq_along(jacobs2000$c_horizon_color), function(i) { diff --git a/man/harden.rubification.Rd b/man/harden.rubification.Rd index d3cf6edc7..7f81aa71e 100644 --- a/man/harden.rubification.Rd +++ b/man/harden.rubification.Rd @@ -69,12 +69,20 @@ jacobs2000$rubiforder <- order(jacobs2000$rubif) # Plot in order of increasing Rubification index -plotSPC(jacobs2000, axis.line.offset = -1, - color = "matrix_color", - label = "rubif", - plot.order = jacobs2000$rubiforder) - -abline(h = c(0,100,150,200), lty = 2) +plotSPC(jacobs2000, +color = "matrix_color", +label = "rubif", +plot.order = jacobs2000$rubiforder, +max.depth = 250 +) + +segments( + x0 = 0.5, + x1 = length(jacobs2000) + 0.5, + y0 = c(0,100,150,200), + y1 = c(0,100,150,200), + lty = 2 +) # Add [estimated] parent material color swatches trash <- sapply(seq_along(jacobs2000$c_horizon_color), function(i) { diff --git a/man/plotMultipleSPC.Rd b/man/plotMultipleSPC.Rd index b1e3192b4..99089367a 100644 --- a/man/plotMultipleSPC.Rd +++ b/man/plotMultipleSPC.Rd @@ -174,7 +174,7 @@ plotMultipleSPC( label.offset = 3, args = arg.list, merged.legend = 'clay', merged.legend.title = 'Clay (\%)', - axis.line.offset = 0 + depth.axis = list(line = 0) ) } \seealso{ diff --git a/man/profileGroupLabels.Rd b/man/profileGroupLabels.Rd index c4031d6e0..e6e5a6ec2 100644 --- a/man/profileGroupLabels.Rd +++ b/man/profileGroupLabels.Rd @@ -70,10 +70,12 @@ tick.heights <- yy[c(group.starts, group.ends)] + 2 # plot 2 SoilProfileCollection objects on the same axis par(mar=c(1,1,1,1)) -plot(sp3, n=n.pedons) -plot(sp4, add=TRUE, x.idx.offset=group.ends[1], plot.depth.axis=FALSE, id.style='side') +plot(sp3, n = n.pedons) +plot(sp4, add = TRUE, x.idx.offset = group.ends[1], +depth.axis = FALSE, id.style = 'side') + # annotate groups -profileGroupLabels(x0=group.starts, x1=group.ends, +profileGroupLabels(x0 = group.starts, x1 = group.ends, labels=c('Collection 1', 'Collection 2'), y0=120, y1=tick.heights) } diff --git a/man/quickSPC.Rd b/man/quickSPC.Rd index 64e1e4d8c..d8ebbed71 100644 --- a/man/quickSPC.Rd +++ b/man/quickSPC.Rd @@ -130,14 +130,14 @@ x <- c( # each horizon label is '10' depth-units (default) s <- quickSPC(x) plotSPC(s, name.style = 'center-center', - cex.names = 1, plot.depth.axis = FALSE, + cex.names = 1, depth.axis = FALSE, hz.depths = TRUE ) # each horizon label is '5' depth-units s <- quickSPC(x, interval = 5) plotSPC(s, name.style = 'center-center', - cex.names = 1, plot.depth.axis = FALSE, + cex.names = 1, depth.axis = FALSE, hz.depths = TRUE ) @@ -150,7 +150,7 @@ x <- c( s <- quickSPC(x) plotSPC(s, name.style = 'center-center', - cex.names = 1, plot.depth.axis = FALSE, + cex.names = 1, depth.axis = FALSE, hz.depths = TRUE ) @@ -161,7 +161,7 @@ plotSPC(s, name.style = 'center-center', x <- 'NODATA,150,NA-' s <- quickSPC(x) plotSPC(s, name.style = 'center-center', - cex.names = 1, plot.depth.axis = FALSE, + cex.names = 1, depth.axis = FALSE, hz.depths = TRUE) diff --git a/man/wilson2022.Rd b/man/wilson2022.Rd index f6e7598f4..84e1ff240 100644 --- a/man/wilson2022.Rd +++ b/man/wilson2022.Rd @@ -60,13 +60,13 @@ groupedProfilePlot(wilson2022, groups = 'pm', group.name.offset = -15, label = 'biome', name.style = 'center-center', color = 'CIA', cex.names = 0.66, cex.id = 0.66, width = 0.3, -plot.depth.axis = FALSE, hz.depths = TRUE) +depth.axis = FALSE, hz.depths = TRUE) groupedProfilePlot(wilson2022, groups = 'biome', group.name.offset = -15, label = 'pm', name.style = 'center-center', color = 'Fet', cex.names = 0.66, cex.id = 0.66, width = 0.3, -plot.depth.axis = FALSE, hz.depths = TRUE) +depth.axis = FALSE, hz.depths = TRUE) } \references{