#' Place a plot that has been previously created but not drawn
#'
#' @usage pagePlotPlace(
#' plot,
#' x = NULL,
#' y = NULL,
#' width = NULL,
#' height = NULL,
#' just = c("left", "top"),
#' default.units = "inches",
#' draw = TRUE,
#' params = NULL
#' )
#'
#' @param plot Plot object to be placed, defined by the
#' output of a plotgardener plotting function.
#' @param x A numeric or unit object specifying plot x-location.
#' @param y A numeric, unit object, or character containing a "b" combined
#' with a numeric value specifying plot y-location.
#' The character value will place the plot y relative to the bottom
#' of the most recently plotted plot according to the units
#' of the plotgardener page.
#' @param width A numeric or unit object specifying plot width.
#' @param height A numeric or unit object specifying plot height.
#' @param just Justification of plot relative to its (x, y) location.
#' If there are two values, the first value specifies horizontal
#' justification and the second value specifies vertical justification.
#' Possible string values are: \code{"left"}, \code{"right"},
#' \code{"centre"}, \code{"center"}, \code{"bottom"}, and \code{"top"}.
#' Default value is \code{just = c("left", "top")}.
#' @param default.units A string indicating the default units to use
#' if \code{x}, \code{y}, \code{width}, or \code{height} are only
#' given as numerics. Default value is \code{default.units = "inches"}.
#' @param draw A logical value indicating whether graphics output
#' should be produced. Default value is \code{draw = TRUE}.
#' @param params An optional \link[plotgardener]{pgParams} object
#' containing relevant function parameters.
#'
#' @return Function will update dimensions of an input plot and
#' return an updated plot object.
#'
#' @examples
#' ## Load Hi-C data
#' library(plotgardenerData)
#' data("IMR90_HiC_10kb")
#'
#' ## Create, but do not plot, square Hi-C plot
#' hicPlot <- plotHicSquare(
#' data = IMR90_HiC_10kb, resolution = 10000,
#' zrange = c(0, 70),
#' chrom = "chr21",
#' chromstart = 28000000, chromend = 30300000,
#' draw = FALSE
#' )
#'
#' ## Create page
#' pageCreate(width = 3.75, height = 3.5, default.units = "inches")
#'
#' ## Place Hi-C plot on page
#' pagePlotPlace(
#' plot = hicPlot,
#' x = 0.25, y = 0.25, width = 3, height = 3,
#' just = c("left", "top"),
#' default.units = "inches", draw = TRUE
#' )
#'
#' ## Annotate heatmap legend
#' annoHeatmapLegend(
#' plot = hicPlot,
#' x = 3.4, y = 0.25, width = 0.12, height = 1.2,
#' just = c("left", "top"), default.units = "inches"
#' )
#'
#' ## Hide page guides
#' pageGuideHide()
#' @export
pagePlotPlace <- function(plot, x = NULL, y = NULL, width = NULL,
height = NULL, just = c("left", "top"),
default.units = "inches",
draw = TRUE, params = NULL) {
# =========================================================================
# FUNCTIONS
# =========================================================================
set_x <- function(object, val) {
if (is.null(val)) {
object["x"] <- list(NULL)
} else {
object$x <- val
}
return(object)
}
set_y <- function(object, val) {
if (is.null(val)) {
object["y"] <- list(NULL)
} else {
object$y <- val
}
return(object)
}
set_width <- function(object, val) {
if (is.null(val)) {
object["width"] <- list(NULL)
} else {
object$width <- val
}
return(object)
}
set_height <- function(object, val) {
if (is.null(val)) {
object["height"] <- list(NULL)
} else {
object$height <- val
}
return(object)
}
set_values <- function(object, x, y, width, height) {
object <- set_x(object = object, val = x)
object <- set_y(object = object, val = y)
object <- set_width(object = object, val = width)
object <- set_height(object = object, val = height)
return(object)
}
replace_value <- function(val, new) {
return(new[val])
}
## Define a function to parse coordinates
parse_coordinates <- function(inputPlot, outputPlot) {
## Make sublists of the dimensions/coords of the input/output plots
inputCoords <- list(
x = inputPlot$x, y = inputPlot$y,
width = inputPlot$width, height = inputPlot$height,
just = inputPlot$just
)
outputCoords <- list(
x = outputPlot$x, y = outputPlot$y,
width = outputPlot$width,
height = outputPlot$height, just = outputPlot$just
)
## Determine which values in the output plot are NULL
to_replace <- names(outputCoords[vapply(
outputCoords,
is.null, logical(1)
)])
not_replace <- outputCoords[!vapply(
outputCoords,
is.null, logical(1)
)]
## Get corresponding values for those that are NULL from the input plot
replaced <- unlist(lapply(to_replace, replace_value,
new = inputCoords
),
recursive = FALSE
)
## Recombine values that weren't replaced and those that were
new_coords <- c(not_replace, replaced)
outputPlot <- set_values(
object = outputPlot, x = new_coords$x,
y = new_coords$y, width = new_coords$width,
height = new_coords$height
)
outputPlot$just <- new_coords$just
## Return object
return(outputPlot)
}
## Define a function that renames grobs and copies to a new gtree
copy_grobs <- function(grob) {
new_name <- grobName(grob)
grob$name <- new_name
assign("new_gtree",
addGrob(
gTree = get("new_gtree", envir = pgEnv),
child = grob
),
envir = pgEnv
)
}
# =========================================================================
# PARSE PARAMETERS
# =========================================================================
place <- parseParams(params = params,
defaultArgs = formals(eval(match.call()[[1]])),
declaredArgs = lapply(match.call()[-1], eval.parent,
n = 2),
class = "place")
## Justification
place$just <- justConversion(place$just)
# =========================================================================
# ERRORS
# =========================================================================
if (is.null(place$plot)) stop("argument \"plot\" is missing, ",
"with no default.", call. = FALSE)
# =========================================================================
# INITIALIZE PLOT OBJECT COPY
# =========================================================================
object <- place$plot
# =========================================================================
# PARSE UNITS FOR INPUTS
# =========================================================================
if (!is.null(place$x)) {
place$x <- misc_defaultUnits(value = place$x,
name = "x",
default.units = place$default.units)
}
if (!is.null(place$y)) {
place$y <- misc_defaultUnits(value = place$y,
name = "y",
default.units = place$default.units)
}
if (!is.null(place$width)) {
place$width <- misc_defaultUnits(value = place$width,
name = "width",
default.units = place$default.units)
}
if (!is.null(place$height)) {
place$height <- misc_defaultUnits(value = place$height,
name = "height",
default.units =
place$default.units)
}
# =========================================================================
# UPDATE DIMENSIONS AND COORDINATES OF PLOT OBJECT BASED ON INPUTS
# =========================================================================
object <- set_values(
object = object, x = place$x, y = place$y,
width = place$width, height = place$height
)
object$just <- place$just
attr(x = object, which = "plotted") <- place$draw
# =========================================================================
# INHERIT DIMENSIONS/COOORDINATES WHERE NULL
# =========================================================================
object <- parse_coordinates(
inputPlot = place$plot,
outputPlot = object
)
# =========================================================================
# CALL ERRORS
# =========================================================================
check_placement(object = object)
# =========================================================================
# DEFINE A NEW VIEWPORT
# =========================================================================
## Get viewport name
currentViewports <- current_viewports()
num <-
length(grep(
pattern = gsub(
pattern = "[0-9]",
replacement = "",
x = object$grobs$vp$name
),
x = currentViewports
)) + 1
vp_name <- gsub("[0-9]", replacement = num, x = object$grobs$vp$name)
## If full placing information isn't provided but plot == TRUE,
## set up it's own viewport separate from bb_makepage
## Not translating into page_coordinates
if (is.null(object$x) | is.null(object$y) |
is.null(object$width) | is.null(object$height)) {
new_vp <- viewport(
height = unit(1, "snpc"), width = unit(1, "snpc"),
x = unit(0.5, "npc"), y = unit(0.5, "npc"),
clip = "on",
xscale = object$grobs$vp$xscale,
yscale = object$grobs$vp$yscale,
just = "center",
name = vp_name
)
if (place$draw == TRUE) {
grid.newpage()
warning("Plot placement will only fill up the graphical device.",
call. = FALSE
)
}
} else {
addViewport(vp_name)
## Convert coordinates into same units as page
page_coords <- convert_page(object = object)
## Make viewport
new_vp <- viewport(
height = page_coords$height, width = page_coords$width,
x = page_coords$x, y = page_coords$y,
clip = "on",
xscale = object$grobs$vp$xscale,
yscale = object$grobs$vp$yscale,
just = place$just,
name = vp_name
)
}
# =========================================================================
# RENAME GROBS
# =========================================================================
assign("new_gtree", gTree(vp = new_vp), envir = pgEnv)
invisible(lapply(object$grobs$children, copy_grobs))
# =========================================================================
# ASSIGN NEW GROBS TO OBJECT
# =========================================================================
object$grobs <- get("new_gtree", envir = pgEnv)
# =========================================================================
# IF DRAW == TRUE, DRAW GROBS
# =========================================================================
if (place$draw == TRUE) {
grid.draw(object$grobs)
}
# =========================================================================
# RETURN UPDATED OBJECT
# =========================================================================
message(gsub(
pattern = "[0-9]",
replacement = "",
x = vp_name
), "[", vp_name, "]")
invisible(object)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.