#
# All of the plots.
#
#' Shiny component to describe the output of a call to vst.
#'
#' @param y Transformed matrix.
#'
#' @param counts Counts matrix to transform.
#'
#' @param sample_labels Sample labels.
#'
#' @param prefix Prefix for variables in environment for composable shiny app.
#'
#' @export
shiny_vst <- function(y=NULL, counts=NULL, sample_labels=NULL, prefix="") {
ns <- shiny::NS(prefix)
y <- ensure_reactable(y)
counts <- ensure_reactable(counts)
sample_labels <- ensure_reactable(sample_labels)
ui <- function(request) shiny::div(
shiny::h3("Transformation"),
shiny::uiOutput(ns("report"))
)
server <- function(env) {
env[[ns("y")]] <- shiny::reactive({
y_val <- y(env)
counts_val <- counts(env)
if (is.null(y_val))
y_val <- vst(counts_val)
y_val
})
env$output[[ns("report")]] <- shiny::renderUI({
y <- env[[ns("y")]]()
sample_labels_val <- sample_labels(env)
if (is.null(sample_labels_val))
sample_labels_val <- colnames(y)
if (is.null(sample_labels_val))
sample_labels_val <- as.character(seq_len(ncol(y)))
if (!is.null(attr(y,"method"))) {
dispersion <- attr(y,"dispersion")
description <- vst_methods[[attr(y,"method")]]$description
units <- vst_methods[[attr(y,"method")]]$units
cpm <- attr(y,"cpm")
if (cpm)
units <- paste0("Units for transformed counts are ",units,
" Reads Per Million.")
else
units <- paste0("Units for transformed counts are ",units," read count.")
libs <- data.frame(
Sample = sample_labels_val,
"True library size" = attr(y,"true.lib.size"),
"Adjusted library size" = attr(y,"lib.size"),
check.names=F
)
advice <- vst_advice(y)
colnames(advice) <- c("Count","Transformed count","2-fold step")
advice_html <- list(
shiny::p(description),
shiny::p(units),
shiny::p(sprintf("Estimated dispersion is %.4f.", dispersion)),
shiny::h4("Library sizes"),
shiny::renderTable(libs, include.rownames=F, digits=c(0,0,0,0)),
shiny::p(paste0("Library size adjustment method: ",
attr(y,"lib.size.method"))),
shiny::h4("Transformation"),
shiny::renderTable(advice, include.rownames=F, digits=c(0,0,2,2)),
shiny::p(
"The column \"2-fold step\" shows the difference in transformed ",
"count from the previous row. If a simple log2 transformation were ",
" used this would be uniformly 1, however a variance stabilizing ",
"transformation makes this smaller for counts close to zero."
),
shiny::p(
"Note that values shown are for a sample with average adjusted library size sample."
),
parenthetically(
"Variance stabilizing transformation is performed ",
"by varistran::vst. ",
"Transformed values table produced ",
"by varistran::vst_advice."
)
)
} else {
advice_html <- list(
shiny::p("Any transformation not by Varistran, details unknown.")
)
}
do.call(shiny::div, advice_html)
})
}
composable_shiny_app(ui, server)
}
#' Shiny component to filter rows and columns a matrix.
#'
#' @param y Transformed matrix.
#'
#' @param counts Original count matrix if available.
#'
#' @param sample_labels Sample labels.
#'
#' @param feature_labels Feature labels.
#'
#' @param prefix Prefix for variables in environment for composable shiny app.
#'
#' @export
shiny_filter <- function(y, counts=NULL, sample_labels=NULL, feature_labels=NULL, prefix="") {
ns <- shiny::NS(prefix)
y <- ensure_reactable(y)
counts <- ensure_reactable(counts)
sample_labels <- ensure_reactable(sample_labels)
feature_labels <- ensure_reactable(feature_labels)
ui <- function(request) shiny::uiOutput(ns("ui"))
server <- function(env) {
env[[ns("vars")]] <- shiny::reactive(shiny::withProgress(message="Loading", {
y_val <- y(env)
counts_val <- counts(env)
sample_labels_val <- sample_labels(env)
choices <- seq_len(ncol(y_val))
if (!is.null(sample_labels_val))
names(choices) <- sample_labels_val
else if (!is.null(colnames(y_val)))
names(choices) <- colnames(y_val)
default_min_count <- 5
default_min_expression <- min(y_val, 0.0)
default_samples <- choices
if (is.null(counts_val)) {
counts_input <- ""
what <- "expression level"
} else {
counts_input <- shiny::numericInput(ns("min_count"), "Minimum mean count", default_min_count)
what <- "transformed count"
}
ui <- shiny::tags$div(
shiny::tags$h3("Select samples"),
shiny::selectInput(ns("samples"), "Select samples",
selected=default_samples, choices=choices, multiple=TRUE),
shiny::tags$h3("Filter features"),
counts_input,
shiny::numericInput(ns("min_expression"),
paste0("Minimum mean ",what), default_min_expression),
shiny::textOutput(ns("report"))
)
list(
ui=ui,
y=y_val,
counts=counts_val,
default_samples=default_samples,
default_min_count=default_min_count,
default_min_expression=default_min_expression
)
}))
env$output[[ns("ui")]] <- shiny::renderUI({ env[[ns("vars")]]()$ui })
env[[ns("filtered")]] <- shiny::reactive({
vars <- env[[ns("vars")]]()
y_val <- vars$y
counts_val <- vars$counts
# Might not exist if tab hasn't been viewed :-(
samples_val <- env$input[[ns("samples")]]
if (is.null(samples_val))
samples_val <- vars$default_samples
min_expression_val <- env$input[[ns("min_expression")]]
if (is.null(min_expression_val))
min_expression_val <- vars$default_min_expression
min_count_val <- env$input[[ns("min_count")]]
if (is.null(min_count_val))
min_count_val <- vars$default_min_count
sample_select <- as.numeric(samples_val)
feature_select <- which(
rowMeans(y_val[,sample_select,drop=FALSE]) >= min_expression_val
)
if (!is.null(counts_val)) {
feature_select <- intersect(feature_select,which(
rowMeans(counts_val[,sample_select,drop=FALSE]) >= min_count_val
))
}
list(
sample_select=sample_select,
feature_select=feature_select,
y=y_val[feature_select,sample_select,drop=FALSE],
counts=counts_val[feature_select,sample_select,drop=FALSE],
sample_labels=sample_labels(env)[sample_select],
feature_labels=feature_labels(env)[feature_select]
)
})
env$output[[ns("report")]] <- shiny::renderText({
filtered <- env[[ns("filtered")]]()
sprintf("%d of %d features will be used.",
length(filtered$feature_select),
nrow(y(env))
)
})
}
composable_shiny_app(ui, server)
}
#' Shiny report
#'
#' Produce an interactive Shiny report showing diagnostic plots of transformed counts.
#'
#' @param y A matrix of exprssion levels, such as a transformed counts matrix.
#'
#' @param counts Original counts.
#'
#' @param sample_labels Optional. Sample names.
#'
#' @param feature_labels Optional. Feature names.
#'
#' @param prefix Optional, to facilitate use as a component of a larger Shiny app. Inputs and outputs are given this prefix.
#'
#' @return A shiny.appobj.
#'
#' Either y or counts or both must be given.
#'
#' Used interactively, the shiny report runs immediately. Otherwise it can be launched by print()-ing it. A call to this function can also be the last line in an app.R file in a Shiny app directory.
#'
#' @author Paul Harrison
#'
#' @examples
#'
#' # Generate some random data.
#' means <- runif(100,min=0,max=1000)
#' counts <- matrix(rnbinom(1000, size=1/0.01, mu=rep(means,10)), ncol=10)
#'
#' y <- varistran::vst(counts)
#' if (interactive())
#' varistran::shiny_report(y, counts)
#'
#' @export
shiny_report <- function(y=NULL, counts=NULL, sample_labels=NULL, feature_labels=NULL, prefix="") {
ns <- shiny::NS(prefix)
y <- ensure_reactable(y)
counts <- ensure_reactable(counts)
sample_labels <- ensure_reactable(sample_labels)
feature_labels <- ensure_reactable(feature_labels)
transform <- shiny_vst(y, counts, sample_labels, prefix=ns("transform"))
ty <- function(env) env[[ns("transform-y")]]()
filter <- shiny_filter(ty, counts, sample_labels, feature_labels, prefix=ns("filter"))
fy <- function(env) env[[ns("filter-filtered")]]()$y
fcounts <- function(env) env[[ns("filter-filtered")]]()$counts
fsample_labels <- function(env) env[[ns("filter-filtered")]]()$sample_labels
ffeature_labels <- function(env) env[[ns("filter-filtered")]]()$feature_labels
stability <- shiny_stability(fy, fcounts, prefix=ns("stability"))
mds_plot <- shiny_mds_plot(fy, sample_labels=fsample_labels, prefix=ns("mds"))
biplot <- shiny_biplot(fy, sample_labels=fsample_labels, feature_labels=ffeature_labels, prefix=ns("biplot"))
heatmap <- shiny_heatmap(fy, sample_labels=fsample_labels, feature_labels=ffeature_labels, prefix=ns("heatmap"))
panels <- list(
function(request) shiny::tabPanel("Transform", transform$component_ui(request)),
function(request) shiny::tabPanel("Select and filter", filter$component_ui(request)),
function(request) shiny::tabPanel("Stability", stability$component_ui(request)),
function(request) shiny::tabPanel("MDS plot", mds_plot$component_ui(request)),
function(request) shiny::tabPanel("Biplot", biplot$component_ui(request)),
function(request) shiny::tabPanel("Heatmap", heatmap$component_ui(request))
)
ui <- function(request) shiny::div(
shiny::div(
style="font-size: 150%; color: #bbbbbb; text-align: right; letter-spacing: 0.25em;",
"Varistran"
),
do.call(shiny::navlistPanel,
c(list(widths=c(2,10),well=FALSE),
lapply(panels, call_ui, request)
))
)
server <- function(env) {
e <- function(name) env[[ns(name)]]()
transform$component_server(env)
filter$component_server(env)
stability$component_server(env)
mds_plot$component_server(env)
biplot$component_server(env)
heatmap$component_server(env)
env[[ns("columns")]] <- shiny::reactive({
e("filter-filtered")$sample_select
})
env[[ns("rows")]] <- shiny::reactive({
e("filter-filtered")$feature_select
})
env[[ns("rows-selected")]] <- shiny::reactive({
e("rows")[ e("heatmap-selected") ]
})
}
app <- composable_shiny_app(ui, server)
app$component_panels <- panels
app
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.