diff --git a/R/makeShinyCodes.R b/R/makeShinyCodes.R
index f0b22d8..4a073ed 100644
--- a/R/makeShinyCodes.R
+++ b/R/makeShinyCodes.R
@@ -122,6 +122,7 @@ makeShinyCodes <- function(
readr::write_file(wrSVmainB1(i), file = fname, append = TRUE)
readr::write_file(wrSVmainB2(i), file = fname, append = TRUE)
readr::write_file(wrSVmainB3(i), file = fname, append = TRUE)
+ readr::write_file(wrSVmainMOD(i), file = fname, append = TRUE)
}
readr::write_file(wrSVpost(), file = fname, append = TRUE)
@@ -156,6 +157,7 @@ makeShinyCodes <- function(
readr::write_file(wrUImainB1(shiny.prefix, defPtSiz[1]), file = fname, append = TRUE)
readr::write_file(wrUImainB2(shiny.prefix), file = fname, append = TRUE)
readr::write_file(wrUImainB3(shiny.prefix), file = fname, append = TRUE)
+ readr::write_file(wrUImainMOD(shiny.prefix), file = fname, append = TRUE)
readr::write_file(glue::glue(', \n'), append = TRUE, file = fname)
} else {
for (i in seq_along(shiny.prefix)) {
@@ -223,6 +225,11 @@ makeShinyCodes <- function(
file = fname,
append = TRUE
)
+ readr::write_file(
+ wrUImainMOD(shiny.prefix[i]),
+ file = fname,
+ append = TRUE
+ )
readr::write_file(glue::glue('), \n\n\n'), append = TRUE, file = fname)
}
}
diff --git a/R/writer0.R b/R/writer0.R
index daa52ba..f9e67b7 100644
--- a/R/writer0.R
+++ b/R/writer0.R
@@ -1293,7 +1293,27 @@ wrShFunc <- function() {
' }}\n',
' return(ggOut)\n',
'}}\n',
- '\n',
+ '\n',
+ '\n',
+ '\n',
+ '## Module score helper function \n',
+ 'scModuleScore <- function(inpGene, inpH5, geneList, seed = 42) {{\n',
+ ' valid <- geneList[present == TRUE]$gene\n',
+ ' bgPool <- setdiff(names(inpGene), valid)\n',
+ ' set.seed(seed)\n',
+ ' bgGenes <- sample(bgPool, min(length(valid), length(bgPool)))\n',
+ ' h5file <- H5File$new(inpH5, mode = "r")\n',
+ ' h5data <- h5file[["grp"]][["data"]]\n',
+ ' readRows <- function(genes) {{\n',
+ ' do.call(rbind, lapply(genes, function(g)\n',
+ ' pmax(h5data$read(args = list(inpGene[g], quote(expr=))), 0)))\n',
+ ' }}\n',
+ ' targetMat <- readRows(valid)\n',
+ ' bgMat <- readRows(bgGenes)\n',
+ ' h5file$close_all()\n',
+ ' colMeans(targetMat) - colMeans(bgMat)\n',
+ '}}\n',
+ '\n',
'\n',
'\n'
)
diff --git a/R/writer1.R b/R/writer1.R
index 02f58e0..eb32a8d 100644
--- a/R/writer1.R
+++ b/R/writer1.R
@@ -1519,6 +1519,174 @@ wrSVmainT1 <- function(prefix) {
)
}
+#' Write code for server.R - Module Score tab
+#'
+#' @rdname wrSVmainMOD
+#' @export wrSVmainMOD
+#'
+wrSVmainMOD <- function(prefix) {
+ glue::glue(
+ ' ### Functions for Module Score tab \n',
+ ' output${prefix}comb_sub1.ui <- renderUI({{ \n',
+ ' sub = strsplit({prefix}conf[UI == input${prefix}comb_sub1]$fID, "\\\\|")[[1]] \n',
+ ' checkboxGroupInput("{prefix}comb_sub2", "Select which cells to show", inline = TRUE, \n',
+ ' choices = sub, selected = sub) \n',
+ ' }}) \n',
+ ' observeEvent(input${prefix}comb_sub1non, {{ \n',
+ ' sub = strsplit({prefix}conf[UI == input${prefix}comb_sub1]$fID, "\\\\|")[[1]] \n',
+ ' updateCheckboxGroupInput(session, inputId = "{prefix}comb_sub2", \n',
+ ' choices = sub, selected = NULL, inline = TRUE) \n',
+ ' }}) \n',
+ ' observeEvent(input${prefix}comb_sub1all, {{ \n',
+ ' sub = strsplit({prefix}conf[UI == input${prefix}comb_sub1]$fID, "\\\\|")[[1]] \n',
+ ' updateCheckboxGroupInput(session, inputId = "{prefix}comb_sub2", \n',
+ ' choices = sub, selected = sub, inline = TRUE) \n',
+ ' }}) \n',
+ '\n',
+ ' output${prefix}comb_mod_geneTxt <- renderUI({{ \n',
+ ' geneList <- scGeneList(input${prefix}comb_mod_inp, {prefix}gene[[input${prefix}comb_mod_ass]]) \n',
+ ' if (nrow(geneList) > 50) {{ \n',
+ ' HTML("More than 50 genes! Please reduce the list.") \n',
+ ' }} else {{ \n',
+ ' ok <- nrow(geneList[present == TRUE]) \n',
+ ' bad <- nrow(geneList[present == FALSE]) \n',
+ ' oup <- paste0(ok, " genes found and will be used for scoring") \n',
+ ' if (bad > 0) \n',
+ ' oup <- paste0(oup, "
", bad, " not found: ", \n',
+ ' paste0(geneList[present == FALSE]$gene, collapse = ", "), "") \n',
+ ' HTML(oup) \n',
+ ' }} \n',
+ ' }}) \n',
+ '\n',
+ ' {prefix}comb_mod_score <- reactive({{ \n',
+ ' geneList <- scGeneList(input${prefix}comb_mod_inp, {prefix}gene[[input${prefix}comb_mod_ass]]) \n',
+ ' shiny::validate( \n',
+ ' need(nrow(geneList[present == TRUE]) >= 2, \n',
+ ' "Please provide at least 2 valid genes."), \n',
+ ' need(nrow(geneList) <= 50, \n',
+ ' "More than 50 genes - please reduce the list.") \n',
+ ' ) \n',
+ ' inpH5 <- paste0("{prefix}assay_", input${prefix}comb_mod_ass, ".h5") \n',
+ ' scModuleScore({prefix}gene[[input${prefix}comb_mod_ass]], inpH5, geneList, \n',
+ ' seed = 42) \n',
+ ' }}) \n',
+ '\n',
+ ' {prefix}comb_mod_dr_oup <- reactive({{ \n',
+ ' score <- {prefix}comb_mod_score() \n',
+ ' inpdr <- input${prefix}comb_mod_dr \n',
+ ' ggData <- data.table({prefix}dimr[[inpdr]]); colnames(ggData) <- c("X","Y") \n',
+ ' rat <- (max(ggData$X) - min(ggData$X)) / (max(ggData$Y) - min(ggData$Y)) \n',
+ ' sub1 <- if (is.null(input${prefix}comb_sub1)) {prefix}conf$UI[1] else input${prefix}comb_sub1 \n',
+ ' ggData$sub <- {prefix}meta[, {prefix}conf[UI == sub1]$ID, with = FALSE][[1]] \n',
+ ' ggData$val <- score \n',
+ ' bgCells <- FALSE \n',
+ ' if (length(input${prefix}comb_sub2) != 0 && \n',
+ ' length(input${prefix}comb_sub2) != nlevels(ggData$sub)) {{ \n',
+ ' bgCells <- TRUE \n',
+ ' ggData2 <- ggData[!sub %in% input${prefix}comb_sub2] \n',
+ ' ggData <- ggData[sub %in% input${prefix}comb_sub2] \n',
+ ' }} \n',
+ ' if (input${prefix}comb_mod_ord == "Max-1st") {{ \n',
+ ' ggData <- ggData[order(val)] \n',
+ ' }} else if (input${prefix}comb_mod_ord == "Min-1st") {{ \n',
+ ' ggData <- ggData[order(-val)] \n',
+ ' }} else if (input${prefix}comb_mod_ord == "Random") {{ \n',
+ ' ggData <- ggData[sample(nrow(ggData))] \n',
+ ' }} \n',
+ ' inpfsz <- sList[input${prefix}comb_mod_fsz] \n',
+ ' inpcol <- cList[[input${prefix}comb_mod_col]] \n',
+ ' ggOut <- ggplot(ggData, aes(X, Y, color = val)) \n',
+ ' if (bgCells) \n',
+ ' ggOut <- ggOut + geom_point(data = ggData2, color = "snow2", \n',
+ ' size = input${prefix}comb_mod_siz / 2, shape = 16) \n',
+ ' ggOut <- ggOut + \n',
+ ' geom_point(size = input${prefix}comb_mod_siz, shape = 16) + \n',
+ ' xlab(paste0(inpdr,"1")) + ylab(paste0(inpdr,"2")) + \n',
+ ' sctheme(base_size = inpfsz, XYval = input${prefix}comb_mod_txt) + \n',
+ ' scale_color_gradientn("Module Score ", colours = inpcol) + \n',
+ ' guides(color = guide_colorbar(barwidth = 15)) \n',
+ ' asp <- input${prefix}comb_mod_asp \n',
+ ' if (asp == "Square") ggOut <- ggOut + coord_fixed(ratio = 1) \n',
+ ' else if (asp == "Fixed") ggOut <- ggOut + coord_fixed(ratio = rat) \n',
+ ' ggOut \n',
+ ' }}) \n',
+ ' output${prefix}comb_mod_dr_oup.ui <- renderUI({{ \n',
+ ' plotOutput("{prefix}comb_mod_dr_oup", height = pList[input${prefix}comb_mod_psz]) \n',
+ ' }}) \n',
+ ' output${prefix}comb_mod_dr_oup <- renderPlot({{ \n',
+ ' {prefix}comb_mod_dr_oup() + theme(legend.position = "none") \n',
+ ' }}) \n',
+ ' output${prefix}comb_mod_leg_oup.ui <- renderUI({{ \n',
+ ' plotOutput("{prefix}comb_mod_leg_oup", \n',
+ ' height = 72 * convertHeight( \n',
+ ' grobHeight(g_legend({prefix}comb_mod_dr_oup())), \n',
+ ' unitTo = "in", valueOnly = TRUE) + 50) \n',
+ ' }}) \n',
+ ' output${prefix}comb_mod_leg_oup <- renderPlot({{ \n',
+ ' grid.newpage(); grid.draw(g_legend({prefix}comb_mod_dr_oup())) \n',
+ ' }}) \n',
+ ' output${prefix}comb_mod_dr_oup.dl <- downloadHandler( \n',
+ ' filename = function() {{ \n',
+ ' paste0("{prefix}modscore_dimred_", input${prefix}comb_mod_dr, \n',
+ ' ".", input${prefix}comb_mod_dr_oup.f) \n',
+ ' }}, \n',
+ ' content = function(file) {{ \n',
+ ' p <- {prefix}comb_mod_dr_oup() + theme(legend.position = "none") \n',
+ ' ggsav(file, height = input${prefix}comb_mod_dr_oup.h, \n',
+ ' width = input${prefix}comb_mod_dr_oup.w, plot = p) \n',
+ ' }} \n',
+ ' ) \n',
+ '\n',
+ ' {prefix}comb_mod_vln_oup <- reactive({{ \n',
+ ' score <- {prefix}comb_mod_score() \n',
+ ' sub1 <- if (is.null(input${prefix}comb_sub1)) {prefix}conf$UI[1] else input${prefix}comb_sub1 \n',
+ ' ggData <- data.table( \n',
+ ' X = {prefix}meta[, {prefix}conf[UI == input${prefix}comb_grp]$ID, with = FALSE][[1]], \n',
+ ' sub = {prefix}meta[, {prefix}conf[UI == sub1]$ID, with = FALSE][[1]], \n',
+ ' val = score \n',
+ ' ) \n',
+ ' if (length(input${prefix}comb_sub2) != 0 && \n',
+ ' length(input${prefix}comb_sub2) != nlevels(ggData$sub)) \n',
+ ' ggData <- ggData[sub %in% input${prefix}comb_sub2] \n',
+ ' ggCol <- strsplit({prefix}conf[UI == input${prefix}comb_grp]$fCL, "\\\\|")[[1]] \n',
+ ' names(ggCol) <- levels(ggData$X) \n',
+ ' ggLvl <- levels(ggData$X)[levels(ggData$X) %in% unique(ggData$X)] \n',
+ ' ggData$X <- factor(ggData$X, levels = ggLvl) \n',
+ ' ggCol <- ggCol[ggLvl] \n',
+ ' inpfsz <- sList[input${prefix}comb_mod_fsz] \n',
+ ' if (input${prefix}comb_mod_vln_typ == "violin") {{ \n',
+ ' ggOut <- ggplot(ggData, aes(X, val, fill = X)) + geom_violin(scale = "width") \n',
+ ' }} else {{ \n',
+ ' ggOut <- ggplot(ggData, aes(X, val, fill = X)) + geom_boxplot() \n',
+ ' }} \n',
+ ' if (input${prefix}comb_mod_vln_pts) \n',
+ ' ggOut <- ggOut + geom_jitter(size = input${prefix}comb_mod_siz, shape = 16) \n',
+ ' ggOut + \n',
+ ' xlab(input${prefix}comb_grp) + ylab("Module Score") + \n',
+ ' sctheme(base_size = inpfsz, Xang = 45, XjusH = 1) + \n',
+ ' scale_fill_manual("", values = ggCol) + \n',
+ ' theme(legend.position = "none") \n',
+ ' }}) \n',
+ ' output${prefix}comb_mod_vln_oup.ui <- renderUI({{ \n',
+ ' plotOutput("{prefix}comb_mod_vln_oup", height = pList2[input${prefix}comb_mod_psz]) \n',
+ ' }}) \n',
+ ' output${prefix}comb_mod_vln_oup <- renderPlot({{{prefix}comb_mod_vln_oup()}}) \n',
+ ' output${prefix}comb_mod_vln_oup.dl <- downloadHandler( \n',
+ ' filename = function() {{ \n',
+ ' paste0("{prefix}modscore_violin_", input${prefix}comb_grp, \n',
+ ' ".", input${prefix}comb_mod_vln_oup.f) \n',
+ ' }}, \n',
+ ' content = function(file) {{ \n',
+ ' ggsav(file, height = input${prefix}comb_mod_vln_oup.h, \n',
+ ' width = input${prefix}comb_mod_vln_oup.w, plot = {prefix}comb_mod_vln_oup()) \n',
+ ' }} \n',
+ ' ) \n',
+ '\n',
+ '\n',
+ '\n'
+ )
+}
+
#' Write code for server.R
#'
#' @rdname wrSVpost
diff --git a/R/writer2.R b/R/writer2.R
index 784b169..fcc4f94 100644
--- a/R/writer2.R
+++ b/R/writer2.R
@@ -1076,6 +1076,128 @@ wrUImainB3 <- function(prefix) {
)
}
+#' Write code for ui.R - Module Score tab
+#'
+#' @rdname wrUImainMOD
+#' @export wrUImainMOD
+#'
+wrUImainMOD <- function(prefix) {
+ glue::glue(
+ ' ### Tab: Module scoring \n',
+ ' tabPanel( \n',
+ ' HTML("Module scoring"), \n',
+ ' h4("Gene Module Score: Violin + Dimred"), \n',
+ ' "Compute a per-cell module score (mean expression of a gene list minus the mean of ", \n',
+ ' "a random background gene set of equal size), then visualise across cell groups ", \n',
+ ' "and on a reduced-dimension plot.", \n',
+ ' br(), br(), \n',
+ ' fluidRow( \n',
+ ' column( \n',
+ ' 4, \n',
+ ' selectInput("{prefix}comb_grp", "Group by:", \n',
+ ' choices = {prefix}conf[grp == TRUE]$UI, \n',
+ ' selected = {prefix}def$grp1) \n',
+ ' ), \n',
+ ' column( \n',
+ ' 4, \n',
+ ' actionButton("{prefix}comb_togL", "Toggle to subset cells"), \n',
+ ' conditionalPanel( \n',
+ ' condition = "input.{prefix}comb_togL % 2 == 1", \n',
+ ' selectInput("{prefix}comb_sub1", "Cell information to subset:", \n',
+ ' choices = {prefix}conf[grp == TRUE]$UI, \n',
+ ' selected = {prefix}def$grp1), \n',
+ ' uiOutput("{prefix}comb_sub1.ui"), \n',
+ ' actionButton("{prefix}comb_sub1all", "Select all groups", class = "btn btn-primary"), \n',
+ ' actionButton("{prefix}comb_sub1non", "Deselect all groups", class = "btn btn-primary") \n',
+ ' ) \n',
+ ' ) \n',
+ ' ), \n',
+ ' fluidRow( \n',
+ ' column( \n',
+ ' 3, style = "border-right: 2px solid black", \n',
+ ' textAreaInput("{prefix}comb_mod_inp", \n',
+ ' HTML("Gene list for module score
(max 50, separated by , ; or newline):"), \n',
+ ' height = "200px", \n',
+ ' value = paste0({prefix}def$genes[[1]], collapse = ", ")) %>% \n',
+ ' helper(type = "inline", size = "m", fade = TRUE, \n',
+ ' title = "Genes for module score", \n',
+ ' content = c("Input target genes to score per cell", \n',
+ ' "- Score = mean(target genes) - mean(random background genes)", \n',
+ ' "- Background pool size equals the target gene list size", \n',
+ ' "- Separate genes by comma, semicolon, or newline")), \n',
+ ' selectInput("{prefix}comb_mod_ass", "Assay:", \n',
+ ' choices = {prefix}def$assay, \n',
+ ' selected = {prefix}def$assay[1]), \n',
+ ' h4(htmlOutput("{prefix}comb_mod_geneTxt")), \n',
+ ' br(), \n',
+ ' actionButton("{prefix}comb_mod_tog", "Toggle graphics controls"), \n',
+ ' conditionalPanel( \n',
+ ' condition = "input.{prefix}comb_mod_tog % 2 == 1", \n',
+ ' sliderInput("{prefix}comb_mod_siz", "Point size:", \n',
+ ' min = 0, max = 4, value = 1.25, step = 0.25), \n',
+ ' radioButtons("{prefix}comb_mod_psz", "Plot size:", \n',
+ ' choices = c("Small", "Medium", "Large"), \n',
+ ' selected = "Medium", inline = TRUE), \n',
+ ' radioButtons("{prefix}comb_mod_fsz", "Font size:", \n',
+ ' choices = c("Small", "Medium", "Large"), \n',
+ ' selected = "Medium", inline = TRUE), \n',
+ ' radioButtons("{prefix}comb_mod_col", "Dimred colour palette:", \n',
+ ' choices = c("White-Red", "Blue-Yellow-Red", "Yellow-Green-Purple"), \n',
+ ' selected = "Blue-Yellow-Red"), \n',
+ ' radioButtons("{prefix}comb_mod_dr", "Reduction:", \n',
+ ' choices = {prefix}def$dimrd, \n',
+ ' selected = {prefix}def$dimrd[1]), \n',
+ ' radioButtons("{prefix}comb_mod_asp", "Aspect ratio:", \n',
+ ' choices = c("Square", "Fixed", "Free"), \n',
+ ' selected = "Square", inline = TRUE), \n',
+ ' checkboxInput("{prefix}comb_mod_txt", "Show axis text on dimred", value = FALSE), \n',
+ ' radioButtons("{prefix}comb_mod_ord", "Dimred plot order:", \n',
+ ' choices = c("Max-1st", "Min-1st", "Original", "Random"), \n',
+ ' selected = "Max-1st", inline = TRUE), \n',
+ ' radioButtons("{prefix}comb_mod_vln_typ", "Violin/boxplot type:", \n',
+ ' choices = c("violin", "boxplot"), \n',
+ ' selected = "violin", inline = TRUE), \n',
+ ' checkboxInput("{prefix}comb_mod_vln_pts", "Show data points on violin", value = FALSE) \n',
+ ' ) \n',
+ ' ), \n',
+ ' column( \n',
+ ' 5, style = "border-right: 2px solid black", \n',
+ ' h4("Module score on reduced dimensions"), \n',
+ ' uiOutput("{prefix}comb_mod_dr_oup.ui"), \n',
+ ' fluidRow(column(6, uiOutput("{prefix}comb_mod_leg_oup.ui"))), \n',
+ ' fluidRow( \n',
+ ' column(3, downloadButton("{prefix}comb_mod_dr_oup.dl", "Download")), \n',
+ ' column(3, radioButtons("{prefix}comb_mod_dr_oup.f", "Format:", \n',
+ ' choices = c("png", "pdf"), selected = "png", inline = TRUE)), \n',
+ ' column(3, numericInput("{prefix}comb_mod_dr_oup.h", "Height:", \n',
+ ' min = 4, max = 20, value = 8, step = 0.5)), \n',
+ ' column(3, numericInput("{prefix}comb_mod_dr_oup.w", "Width:", \n',
+ ' min = 4, max = 20, value = 8, step = 0.5)) \n',
+ ' ), \n',
+ ' br() \n',
+ ' ), \n',
+ ' column( \n',
+ ' 4, \n',
+ ' h4("Module score violin / boxplot"), \n',
+ ' uiOutput("{prefix}comb_mod_vln_oup.ui"), \n',
+ ' fluidRow( \n',
+ ' column(3, downloadButton("{prefix}comb_mod_vln_oup.dl", "Download")), \n',
+ ' column(3, radioButtons("{prefix}comb_mod_vln_oup.f", "Format:", \n',
+ ' choices = c("png", "pdf"), selected = "png", inline = TRUE)), \n',
+ ' column(3, numericInput("{prefix}comb_mod_vln_oup.h", "Height:", \n',
+ ' min = 4, max = 20, value = 8, step = 0.5)), \n',
+ ' column(3, numericInput("{prefix}comb_mod_vln_oup.w", "Width:", \n',
+ ' min = 4, max = 20, value = 8, step = 0.5)) \n',
+ ' ), \n',
+ ' br() \n',
+ ' ) \n',
+ ' ) # End of fluidRow (4 space) \n',
+ ' ) # End of tab (2 space) \n',
+ ' , \n',
+ ' \n'
+ )
+}
+
#' Write code for ui.R
#'
#' @rdname wrUImainS1