#' @name tP_PCAUI
#'
#' @title Tab panel UI for tab panel 'PCA'
#'
#' @description
#' The module defines the UI in the tab panel 'PCA'.
#'
#' @details
#' \code{tP_PCAUI} returns the HTML code for the tab-pane 'PCA'.
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#'
#' @return
#' \code{shiny.tag} with HTML content
#'
#' @author Thomas Naake
#'
#' @examples
#' tP_PCAUI("test")
#'
#' @importFrom shiny NS tabPanel fluidRow column downloadButton
#' @importFrom shiny checkboxInput plotOutput
#' @importFrom shinydashboard box
#' @importFrom shinyhelper helper
#' @importFrom plotly plotlyOutput
#'
#' @noRd
tP_PCAUI <- function(id) {
ns <- shiny::NS(id)
tabPanel(title = "PCA", value = "PCA",
shiny::fluidRow(
shiny::column(width = 12,
plotly::plotlyOutput(outputId = ns("plot"), height = "auto") |>
shinyhelper::helper(content = "tabPanel_PCA"),
shiny::downloadButton(outputId = ns("downloadPlot"), ""))
),
shiny::fluidRow(
shinydashboard::box(title = "Parameters", width = 6,
collapsible = TRUE,
shiny::fluidRow(
shiny::column(width = 6,
shiny::selectInput(inputId = ns("x"),
label = "x-axis", choices = "PC1",
selected = "PC1")),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("y"),
label = "y-axis", choices = "PC2",
selected = "PC2"))
),
shiny::fluidRow(
shiny::column(3,
shiny::checkboxInput(inputId = ns("scale"),
label = "scale", value = TRUE)),
shiny::column(3,
shiny::checkboxInput(inputId = ns("center"),
label = "center", value = TRUE)),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("color"),
label = "Color", choices = "none"))
),
shiny::fluidRow(
shiny::column(width = 6),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("size"),
label = "Size", choices = "none"))
)
),
shiny::column(width = 6,
shinydashboard::box(title = "Scree plot", width = 12,
collapsible = TRUE, collapsed = TRUE,
shiny::plotOutput(outputId = ns("PCAVarplot"))),
shinydashboard::box(title = "Loadings plot", width = 12,
collapsible = TRUE, collapsed = TRUE,
plotly::plotlyOutput(outputId = ns("PCALoadings")))
)
)
)
}
#' @name tP_PCoAUI
#'
#' @title Tab panel UI for tab panel 'PCoA'
#'
#' @description
#' The module defines the UI in the tab panel 'PCoA'.
#'
#' @details
#' \code{tP_PCoAUI} returns the HTML code for the tab-pane 'PCoA'.
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#'
#' @return
#' \code{shiny.tag} with HTML content
#'
#' @author Thomas Naake
#'
#' @examples
#' tP_PCoAUI("test")
#'
#' @importFrom shiny NS tabPanel fluidRow column uiOutput selectInput
#' @importFrom shinydashboard box
#' @importFrom shinyhelper helper
#'
#' @noRd
tP_PCoAUI <- function(id) {
ns <- shiny::NS(id)
shiny::tabPanel(title = "PCoA",
shiny::fluidRow(
shiny::column(width = 12,
plotly::plotlyOutput(outputId = ns("plot"),
height = "auto") |>
shinyhelper::helper(content = "tabPanel_PCoA"),
shiny::downloadButton(outputId = ns("downloadPlot"), ""))
),
shiny::fluidRow(
shinydashboard::box(title = "Parameters", width = 6,
collapsible = TRUE,
shiny::fluidRow(
shiny::column(width = 6,
shiny::selectInput(inputId = ns("x"),
label = "x-axis", choices = "Axis.1",
selected = "Axis.1")),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("y"),
label = "y-axis", choices = "Axis.2",
selected = "Axis.2"))
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::selectInput(inputId = ns("dist"),
label = "Distance measure",
choices = c("euclidean", "maximum",
"manhattan", "canberra", "minkowski"),
selected = "euclidean")),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("color"),
label = "Color", choices = "none"))
),
shiny::fluidRow(
shiny::column(width = 6),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("size"),
label = "Size", choices = "none"))
)
)
)
)
}
#' @name tP_NMDSUI
#'
#' @title Tab panel UI for tab panel 'NMDS'
#'
#' @description
#' The module defines the UI in the tab panel 'NMDS'.
#'
#' @details
#' \code{tP_NMDSUI} returns the HTML code for the tab-pane 'NMDS'.
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#'
#' @return
#' \code{shiny.tag} with HTML content
#'
#' @author Thomas Naake
#'
#' @examples
#' tP_NMDSUI("test")
#'
#' @importFrom shiny NS tabPanel fluidRow column downloadButton
#' @importFrom shiny uiOutput selectInput
#' @importFrom shinydashboard box
#' @importFrom shinyhelper helper
#' @importFrom plotly plotlyOutput
#'
#' @noRd
tP_NMDSUI <- function(id) {
ns <- shiny::NS(id)
shiny::tabPanel(title = "NMDS",
shiny::fluidRow(
shiny::column(width = 12,
plotly::plotlyOutput(outputId = ns("plot"), height = "auto") |>
shinyhelper::helper(content = "tabPanel_NMDS"),
shiny::downloadButton(outputId = ns("downloadPlot"), ""))),
shiny::fluidRow(
shinydashboard::box(title = "Parameters", width = 6,
collapsible = TRUE,
shiny::fluidRow(
shiny::column(width = 6,
shiny::selectInput(inputId = ns("x"),
label = "x-axis", choices = "MDS1",
selected = "MDS1")),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("y"),
label = "y-axis", choices = "MDS2",
selected = "MDS2"))
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::selectInput(inputId = ns("dist"),
label = "Distance measure",
choices = c("euclidean", "maximum",
"manhattan", "canberra", "minkowski"),
selected = "euclidean")),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("color"),
label = "Color", choices = "none"))
),
shiny::fluidRow(
shiny::column(width = 6),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("size"),
label = "Size", choices = "none"))
)
)
)
)
}
#' @name tP_tSNEUI
#'
#' @title Tab panel UI for tab panel 'tSNE'
#'
#' @description
#' The module defines the UI in the tab panel 'tSNE'.
#'
#' @details
#' \code{tP_tSNEUI} returns the HTML code for the tab-pane 'tSNE'.
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#'
#' @return
#' \code{shiny.tag} with HTML content
#'
#' @author Thomas Naake
#'
#' @examples
#' tP_tSNEUI("test")
#'
#' @importFrom shiny NS tabPanel fluidRow column downloadButton
#' @importFrom shiny uiOutput selectInput plotOutput sliderInput checkboxInput
#' @importFrom shinydashboard box
#' @importFrom shinyhelper helper
#' @importFrom plotly plotlyOutput
#'
#' @noRd
tP_tSNEUI <- function(id) {
ns <- shiny::NS(id)
shiny::tabPanel(title = "tSNE",
shiny::fluidRow(
shiny::column(width = 12,
plotly::plotlyOutput(outputId = ns("plot"), height = "auto") |>
shinyhelper::helper(content = "tabPanel_tSNE"),
shiny::downloadButton(outputId = ns("downloadPlot"), ""))),
shiny::fluidRow(
shinydashboard::box(
title = "Principal components", status = "primary", width = 12,
collapsible = TRUE, collapsed = TRUE,
shiny::fluidRow(
shiny::column(width = 6,
shiny::plotOutput(outputId = ns("PCAVarplotPerm"))),
shiny::column(width = 6,
shiny::plotOutput(outputId = ns("PCAVarPvalueplot")))
)
)
),
shiny::fluidRow(
shinydashboard::box(title = "Parameters", width = 6,
collapsible = TRUE,
shiny::fluidRow(
shiny::column(width = 6,
shiny::selectInput(inputId = ns("x"), label = "x-axis",
choices = "X1", selected = "X1")),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("y"), label = "y-axis",
choices = "X2", selected = "X2"))
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::sliderInput(inputId = ns("perplexity"),
label = "Perplexity", min = 1, max = 5, value = 2,
step = 1)),
shiny::column(width = 6,
shiny::sliderInput(inputId = ns("maxIter"),
label = "Number of iterations",
min = 100, max = 10000, value = 1000))
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::sliderInput(inputId = ns("initialDims"),
label = "Number of retained dimensions in initial PCA",
min = 1, max = 5, value = 3, step = 1)),
shiny::column(width = 6,
shiny::sliderInput(inputId = ns("dims"),
label = "Output dimensionality",
min = 2, max = 3, value = 3, step = 1))
),
shiny::fluidRow(
shiny::column(3,
shiny::checkboxInput(inputId = ns("scale"),
label = "scale", value = TRUE)),
shiny::column(3,
shiny::checkboxInput(inputId = ns("center"),
label = "center", value = TRUE)),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("color"),
label = "Color", choices = "none"))
),
fluidRow(
shiny::column(width = 6),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("size"),
label = "Size", choices = "none"))
)
)
)
)
}
#' @name tSNEUIServer
#'
#' @title Server for UI for tSNE
#'
#' @description
#' The module defines the UI in the tab panel 'tSNE'.
#'
#' @details
#' \code{tP_sSNEUIServer} defines the UI for the tab-pane 'tSNE' from the
#' server-side. Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#' @param sample_n \code{numeric(1)} and \code{reactive} value, number of
#' samples
#'
#' @author Thomas Naake
#'
#' @return
#' \code{shiny.render.function}
#'
#' @importFrom shiny NS moduleServer updateSliderInput
#' @importFrom plotly plotlyOutput
#'
#' @noRd
tSNEUIServer <- function(id, sample_n) {
ns <- shiny::NS(id)
shiny::moduleServer(
id,
function(input, output, session) {
shiny::observe({
shiny::updateSliderInput(session = session,
inputId = "perplexity",
max = ceiling((sample_n() - 1) / 3),
value = ceiling(sample_n()^0.5))
})
shiny::observe({
shiny::updateSliderInput(session = session,
inputId = "initialDims", max = sample_n())
})
}
)
}
#' @name tP_umapUI
#'
#' @title Tab panel UI for tab panel 'UMAP'
#'
#' @description
#' The module defines the UI in the tab panel 'UMAP'.
#'
#' @details
#' \code{tP_umapUI} returns the HTML code for the tab-pane 'UMAP'.
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#' @param se \code{SummarizedExperiment} object
#'
#' @return
#' \code{shiny.tag} with HTML content
#'
#' @author Thomas Naake
#'
#' @importFrom shiny NS tabPanel fluidRow column downloadButton
#' @importFrom shiny uiOutput selectInput
#' @importFrom shinydashboard box
#' @importFrom shinyhelper helper
#' @importFrom plotly plotlyOutput
#'
#' @examples
#' tP_UMAPUI("test")
#'
#' @noRd
tP_umapUI <- function(id) {
ns <- shiny::NS(id)
shiny::tabPanel(title = "UMAP",
shiny::fluidRow(
shiny::column(width = 12,
plotly::plotlyOutput(outputId = ns("plot"),
height = "auto") |>
shinyhelper::helper(content = "tabPanel_UMAP"),
shiny::downloadButton(outputId = ns("downloadPlot"), ""))),
shiny::fluidRow(
shinydashboard::box(title = "Parameters", width = 6,
collapsible = TRUE,
shiny::fluidRow(
shiny::column(width = 6,
shiny::selectInput(inputId = ns("x"), label = "x-axis",
choices = "X1", selected = "X1")),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("y"), label = "y-axis",
choices = "X2", selected = "X2"))
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::sliderInput(
inputId = ns("minDist"),
label = "Minimum distance", min = 0.01,
max = 10, value = 0.1)),
shiny::column(width = 6,
shiny::sliderInput(inputId = ns("nNeighbors"),
label = "Number of neighbors", min = 2,
max = 10, value = 10, step = 1))
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::sliderInput(
inputId = ns("spread"),
label = "Spread", min = 0.01, max = 10, value = 1)),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("color"),
label = "Color", choices = "none"))
),
shiny::fluidRow(
shiny::column(width = 6),
shiny::column(width = 6,
shiny::selectInput(inputId = ns("size"),
label = "Size", choices = "none"))
)
)
)
)
}
#' @name umapUIServer
#'
#' @title Server for UI for UMAP
#'
#' @description
#' The module defines the UI in the tab panel 'UMAP'.
#'
#' @details
#' \code{umapUIServer} defines the UI for the tab-pane 'UMAP' from the
#' server-side. Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#' @param sample_n \code{numeric(1)} and \code{reactive} value, number of
#' samples
#'
#' @author Thomas Naake
#'
#' @return
#' \code{shiny.render.function}
#'
#' @importFrom shiny moduleServer updateSliderInput
#' @importFrom SummarizedExperiment colData
#'
#' @noRd
umapUIServer <- function(id, sample_n) {
shiny::moduleServer(
id,
function(input, output, session) {
shiny::observe({
shiny::updateSliderInput(session = session,
inputId = "nNeighbors", max = sample_n)
})
}
)
}
#' @name dimRedServer
#'
#' @title Module for server expressions of tab panel 'Dimension reduction'
#'
#' @description
#' The module defines the server expressions in the tab panel
#' 'Dimension reduction'.
#'
#' @details
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#' @param assay \code{matrix} and \code{reactive} value, obtained from
#' \code{assay(SummarizedExperiment)}
#' @param type \code{character}
#' @param label \code{character}
#' @param params \code{reactiveValues}
#' @param innerWidth \code{numeric} and \code{reactive} value, specifying the
#' width of the window size
#' @param selectedTab \code{character} and \code{reactive} value, specifying
#' the selected tab panel, e.g. \code{"PCA"}
#'
#' @return
#' \code{shiny.render.function} expression
#'
#' @author Thomas Naake
#'
#' @importFrom shiny moduleServer reactive fluidRow column updateSelectInput
#' @importFrom shiny reactiveValuesToList downloadHandler req bindCache
#' @importFrom plotly renderPlotly
#' @importFrom htmlwidgets saveWidget
#' @importFrom SummarizedExperiment colData
#'
#' @noRd
#'
dimRedServer <- function(id, se, assay, type = "PCA", label = "PC", params,
innerWidth, selectedTab) {
shiny::moduleServer(
id,
function(input, output, session) {
## create reactiveValues to store results from dimensionReduction,
## only update/calculate when the user has selected the tab
## (selectedTab() == id) and if the values were not previously
## calcuated (rv$run), update also if there are changes to the
## parameters
rv <- reactiveValues(
run = FALSE, dimensionReduction_list = NULL, coordinates = NULL,
explainedVar = NULL, innerWidth = "600px")
observeEvent({reactiveValuesToList(params()); se(); assay()}, {
rv$run <- FALSE
})
observeEvent({selectedTab(); rv$run}, {
if (selectedTab() == id & !rv$run) {
rv$dimensionReduction_list <- dimensionReduction(
x = assay(), type = type,
params = reactiveValuesToList(params()))
rv$coordinates <- rv$dimensionReduction_list[[1]]
if (id %in% c("PCA", "PCoA")) {
rv$explainedVar <- explVar(
d = rv$dimensionReduction_list[[2]], type = id)
}
rv$run <- TRUE
}
})
observeEvent(innerWidth(), {
rv$innerWidth <- innerWidth() * 3 / 5
})
## create an expression that retrieves information on the columns of
## dimensionReduction tbl (from PCA, PCoA, or NMDS), i.e. the
## principal components or axis (remove the last column = namesDf)
shiny::observe({
if (!is.null(rv$coordinates)) {
cn <- colnames(rv$coordinates)
cn <- cn[-length(cn)]
shiny::updateSelectInput(session = session, inputId = "x",
choices = cn, selected = cn[1])
shiny::updateSelectInput(session = session, inputId = "y",
choices = cn, selected = cn[2])
}
})
shiny::observe({
shiny::updateSelectInput(session = session,
inputId = "color",
choices = c("none", colnames(se()@colData)))
})
shiny::observe({
shiny::updateSelectInput(session = session,
inputId = "size",
choices = c("none", colnames(se()@colData)))
})
## reactive plot for dimension reduction plots
output$plot <- plotly::renderPlotly({
if (!is.null(rv$coordinates)) {
dimensionReductionPlot(rv$coordinates, se = se(),
color = input$color, size = input$size,
x_coord = input$x, y_coord = input$y,
explainedVar = rv$explainedVar,
height = rv$innerWidth)
}
})
output$downloadPlot <- shiny::downloadHandler(
filename = function() {
paste(type, "_", input$x, "_", input$y, "_",
input$color, "_", input$size, ".html", sep = "")
},
content = function(file) {
htmlwidgets::saveWidget(
dimensionReductionPlot(tbl = rv$coordinates, se = se(),
color = input$color, size = input$size,
x_coord = input$x, y_coord = input$y,
explainedVar = rv$explainedVar,
height = rv$innerWidth), file)
}
)
}
)
}
#' @name screePlotServer
#'
#' @title Module for server expressions of tab panels 'PCA' and 'tSNE'
#' (scree plot)
#'
#' @description
#' The module defines the server expressions in the tab panel
#' 'Dimension Reduction', specifically for the tab panels 'PCA' and 'tSNE'.
#'
#' @details
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#' @param assay \code{matrix} and \code{reactive} value, obtained from
#' \code{assay(SummarizedExperiment)}
#' @param center \code{logical} and \code{reactive} value
#' @param scale \code{logical} and \code{reactive} value
#'
#' @return
#' \code{shiny.render.function} expression
#'
#' @importFrom shiny moduleServer reactive renderPlot
#' @importFrom shinyhelper helper
#' @importFrom plotly plotlyOutput
#'
#' @author Thomas Naake
#'
#' @noRd
screePlotServer <- function(id, assay, center, scale) {
shiny::moduleServer(
id,
function(input, output, session) {
var_x <- shiny::reactive({
pca <- dimensionReduction(assay(),
params = list(center = center(), scale = scale()),
type = "PCA")
explVar(d = pca[[2]], type = "PCA")
})
if (id == "PCA") {
## Scree plot for PCA Panel
output$PCAVarplot <- shiny::renderPlot({
plotPCAVar(var_x(), NULL)
})
} else { ## tSNE
var_perm <- shiny::reactive({
permuteExplVar(assay(), n = 10, center = center(),
scale = scale(), sample_n = 5000)
})
## Scree plot for tSNE panel including permuted values
output$PCAVarplotPerm <- shiny::renderPlot({
plotPCAVar(var_x(), var_perm())
})
output$PCAVarPvalueplot <- shiny::renderPlot({
plotPCAVarPvalue(var_x(), var_perm())
})
}
}
)
}
#' @name loadingsPlotServer
#'
#' @title Module for server expressions of tab panel 'PCA' (loading plot)
#'
#' @description
#' The module defines the server expressions in the tab panel
#' 'Dimension Reduction', specifically for the tab panel 'PCA'. It defines
#' the loading plot server expression
#'
#' @details
#' Internal function for \code{shinyQC}.
#'
#' @param id \code{character}
#' @param assay \code{matrix} and \code{reactive} value, obtained from
#' \code{assay(SummarizedExperiment)}
#' @param center \code{logical} and \code{reactive} value
#' @param scale \code{logical} and \code{reactive} value
#'
#' @return
#' \code{shiny.render.function} expression
#'
#' @author Thomas Naake
#'
#' @importFrom shiny moduleServer reactive reactiveValuesToList
#' @importFrom plotly renderPlotly
#'
#' @noRd
loadingsPlotServer <- function(id, assay, params) {
shiny::moduleServer(
id,
function(input, output, session) {
tbl_loadings <- shiny::reactive({
tblPCALoadings(assay(), shiny::reactiveValuesToList(params()))
})
output$PCALoadings <- plotly::renderPlotly({
plotPCALoadings(tbl_loadings(),
x_coord = input$x, y_coord = input$y)
})
}
)
}
#' @name tP_dimensionReduction_all
#'
#' @title Tab panel UI for tab panel 'Dimension Reduction'
#'
#' @description
#' The module defines the UI for the tab panel 'Dimension Reduction'.
#'
#' @details
#' \code{tP_dimensionReduction_all} returns the HTML code for the tab-pane
#' 'Dimension Reduction'. Internal function for \code{shinyQC}.
#'
#' @return
#' \code{shiny.tag} with HTML content
#'
#' @author Thomas Naake
#'
#' @examples
#' tP_dimensionReduction_all()
#'
#' @importFrom shiny tabPanel
#' @importFrom shinydashboard tabBox
#'
#' @noRd
tP_dimensionReduction_all <- function() {
shiny::tabPanel("Dimension Reduction",
shinydashboard::tabBox(title = "", width = 12,
id = "dimensionReductionTab",
tP_PCAUI(id = "PCA"),
tP_PCoAUI(id = "PCoA"),
tP_NMDSUI(id = "NMDS"),
tP_tSNEUI(id = "tSNE"),
tP_umapUI(id = "UMAP")
)
)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.