#' Define the plot UI
#'
#' Define the \code{\link{plotOutput}} object for a given panel containing a single plot.
#'
#' @param plot_name String containing the name of the plot.
#' @param height Integer scalar specifying the height of the plot in pixels.
#' @param brush_direction String specifying the direction of brushing, i.e., \code{"x"}, \code{"y"} or \code{"xy"}.
#' @param brush_fill String containing a color to use for the fill of the brush.
#' @param brush_stroke String containing a color to use for the stroke of the brush.
#'
#' @return The output of \code{\link{plotOutput}} with relevant parametrization.
#'
#' @author Aaron Lun
#'
#' @rdname INTERNAL_define_plot_ui
#' @importFrom shinyWidgets addSpinner
#' @importFrom shiny brushOpts plotOutput uiOutput tagList hoverOpts
.define_plot_ui <- function(plot_name, height, brush_direction, brush_fill, brush_stroke) {
.input_FUN <- function(field) { paste0(plot_name, "_", field) }
brush.opts <- brushOpts(.input_FUN(.brushField), resetOnNew=TRUE, delay=2000,
direction=brush_direction, fill=brush_fill, stroke=brush_stroke,
opacity=.brushFillOpacity)
hoveropt <- hoverOpts(.input_FUN(.hoverTooltip), delay=100)
dblclick <- .input_FUN(.zoomClick)
clickopt <- .input_FUN(.lassoClick)
panel_height <- paste0(height, "px")
addSpinner(
plotOutput(plot_name, brush=brush.opts, dblclick=dblclick, click=clickopt, hover=hoveropt, height=panel_height),
color=brush_fill
)
}
#' Add extra aesthetic columns
#'
#' This is a simple utility that is broken out of \code{\link{.generateOutput,DotPlot-method}}.
#' It purely serves to run all of the non-exposed generics that modify \code{plot.data}
#' (e.g., \code{\link{.addDotPlotDataColor}}) and accumulate the resulting commands and labels.
#'
#' @param x An instance of a \linkS4class{DotPlot} class.
#' @param envir An environment containing \code{plot.data}.
#'
#' @return A list containing \code{commands}, a list of character vectors with R commands;
#' and \code{labels}, a list of strings containing various labels to use in legends.
#'
#' @author Aaron Lun, Kevin Rue-Albrecht
#'
#' @rdname INTERNAL_add_extra_aesthetic_columns
.add_extra_aesthetic_columns <- function(x, envir) {
collected <- list()
labels <- list()
# Add commands coercing X and Y to appropriate type
collected$coerce <- .coerce_dataframe_columns(envir,
fields=c("X", "Y"), df="plot.data",
max_levels=.get_factor_maxlevels()
)
# Add commands adding optional columns to plot.data
out_color <- .addDotPlotDataColor(x, envir)
collected$color <- out_color$commands
labels <- c(labels, out_color$labels)
if (!is.null(envir$plot.data$ColorBy)) {
collected$color <- c(collected$color,
.coerce_dataframe_columns(envir,
fields="ColorBy", df="plot.data",
max_levels=.get_color_maxlevels()
)
)
}
out_shape <- .addDotPlotDataShape(x, envir)
collected$shape <- out_shape$commands
labels <- c(labels, out_shape$labels)
out_size <- .addDotPlotDataSize(x, envir)
collected$size <- out_size$commands
labels <- c(labels, out_size$labels)
out_facets <- .addDotPlotDataFacets(x, envir)
collected$facets <- out_facets$commands
labels <- c(labels, out_facets$labels)
list(commands=collected, labels=labels)
}
#' Add a \code{SelectBy} column
#'
#' This is another simple utility to just add a \code{SelectBy} column to \code{plot.data},
#' indicating whether each row was included in a multiple selection transmitted from another panel.
#' If \code{x} restricts its multiple selections, \code{plot.data} will be subsetted to only those rows with \code{SelectBy=TRUE}.
#'
#' @param x An instance of a \linkS4class{DotPlot} class.
#' @param envir An environment containing \code{plot.data}.
#'
#' @return A list of character vectors containing commands necessary to add \code{SelectBy} and,
#' if necessary, perform the subsetting.
#'
#' @author Aaron Lun
#'
#' @rdname INTERNAL_add_selectby_column
.add_selectby_column <- function(x, envir) {
collected <- list()
plot.data <- envir$plot.data
# Removing NAs in axes aesthetics as they mess up .process_selectby_choice.
clean_select_fields <- c("X", "Y", intersect(c("FacetRow", "FacetColumn"), colnames(plot.data)))
clean_affected <- vapply(clean_select_fields, function(i) any(is.na(plot.data[[i]])), TRUE)
if (any(clean_affected)) {
clean_expression <- paste(sprintf("!is.na(%s)", clean_select_fields[clean_affected]), collapse=" & ")
collected$na.rm <- sprintf("plot.data <- subset(plot.data, %s);", clean_expression)
.textEval(collected$na.rm, envir)
}
collected$select.effect <- .addDotPlotDataSelected(x, envir)
collected
}
#' Coerce \code{plot.data} columns
#'
#' Coerce key columns of \code{plot.data} to factors if they are categorical,
#' otherwise make them numeric by any means possible.
#' This ensures that downstream code only has to deal with factors or numbers.
#'
#' @param envir An environment containing the \code{df} data.frame.
#' @param fields A character vector of column names to coerce.
#' @param df Name of the data.frame in \code{envir}.
#' @inheritParams .coerce_type
#'
#' @return
#' The specified \code{plot.data} columns are coerced to factors or numeric values.
#' A character vector is returned containing the commands to do so.
#'
#' @seealso
#' \code{\link{.coerce_type}}, which generates the commands to do the coercion.
#' @author Aaron Lun, Kevin Rue-Albrecht
#' @rdname INTERNAL_coerce_dataframe_columns
.coerce_dataframe_columns <- function(envir, fields, df="plot.data", max_levels=Inf) {
coerce_cmds <- NULL
for (f in fields) {
v <- get(df, envir = envir)[[f]]
coerce_cmds <- c(coerce_cmds, .coerce_type(v, f, max_levels=max_levels, df=df))
}
.textEval(coerce_cmds, envir)
coerce_cmds
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.