# Module for co-visualization.
scell_server <- function(id, tab, upl.mod.lis, shm.mod.lis, lis.url, parent, session) {
moduleServer(id, function(input, output, session) {
cat('Module scell_server ... \n')
ns <- session$ns;
# Apply to switching from sce of bulk+cell to sce of cell alone.
sce.upl <- reactiveValues()
observeEvent(upl.mod.lis$sce$val, {
library(Matrix)
sce.all <- upl.mod.lis$sce$val
if (is.null(sce.all)) { # Erase previous datasets to avoid unexpected downstream computation.
sce.upl$bulk <- sce.upl$cell <- NULL
}
reducedDim(sce.all, 'PCA') <- reducedDim(sce.all, 'UMAP') <- reducedDim(sce.all, 'TSNE') <- NULL
rowData(sce.all) <- link_dat(rowData(sce.all), link.only=FALSE)
df.meta <- metadata(sce.all)$df.meta
if (!is.null(df.meta)) {
if (ncol(data.frame(df.meta))<2) {
lgc.mt <- FALSE; msg <- 'The "df.meta" in the "metadata" slot should be a "data.frame" with at least two columns!'
if (!lgc.mt) showModal(modal(msg = msg)); req(!lgc.mt)
} else {
metadata(sce.all)$df.meta <- link_dat(df.meta, link.only=FALSE)
}
}
# save(sce.all, file='sce.all')
if (!is.null(sce.all)) {
assay.na <- assayNames(sce.all)
lgc.ct <- 'counts' %in% assay.na
if (!lgc.ct) showModal(modal(msg = '"counts" not detected in "assayNames(<SingleCellExperiment>)"!')); req(lgc.ct)
if ('logcounts' %in% assay.na) logcounts(sce.all) <- as(logcounts(sce.all), 'dgCMatrix')
if ('count' %in% assay.na) assays(sce.all)$count <- as(assays(sce.all)$count, 'dgCMatrix')
if ('counts' %in% assay.na) assays(sce.all)$counts <- as(assays(sce.all)$counts, 'dgCMatrix')
}
sce.upl$cell <- sce.all; if (!is.null(sce.all)) {
cdat <- colData(sce.all); dat.all <- assay(sce.all)
int <- all(round(dat.all)==dat.all)
if (!int) sce.upl$cell <- NULL
if (!int) showModal(modal(msg='In co-visualization, raw count data are needed !'))
validate(need(int, '')); sce.upl$method <- 'manual'
if ('bulkCell' %in% colnames(cdat)) {
blk.cell.uni <- unique(cdat$bulkCell)
if (all(c('bulk', 'cell') %in% blk.cell.uni)) {
updateSelectInput(session, 'methCovis', choices=c('Annotation (or other) labels'='man', 'Co-clustering labels'='auto'), selected='auto')
cdat.na <- colnames(cdat)
lab.na <- grep('^label$|^label\\d+', cdat.na, value=TRUE)
if (length(lab.na)==0) {
show_mod(length(lab.na)>0, msg='At least one label column in "colData" slot is required, such as "label", "label1", "label2", ...')
}; validate(need(length(lab.na) > 0, ''))
sce.upl$method <- 'both'
bulk <- subset(sce.all, , bulkCell=='bulk')
# Bulk data are aggregated.
bulk <- aggr_rep(data=bulk, sam.factor=lab.na[1], aggr='mean')
# bulk$spFeature <- NULL
assay(bulk) <- round(assay(bulk)); sce.upl$bulk <- bulk
sce.upl$cell <- subset(sce.all, , bulkCell=='cell')
}
} else {
updateSelectInput(session, 'methCovis', choices=c('Annotation (or other) labels'='man'), selected='man')
}
}
})
# observeEvent(sce.upl$cell, {
# output$methCovis <- renderUI({
# method <- sce.upl$method
# if(is.null(sce.upl$cell) | is.null(method)) return()
# ns <- session$ns; sel <- 'auto'
# cho <- c('Annotation/manual'='man', 'Automatic'='auto')
# if (method=='manual') {
# cho <- c('Annotation/manual'='man'); sel <- 'man'
# }
# selectInput(ns('methCovis'), label='Methods', choices=cho, selected=sel)
# })
#output$direc <- renderUI({
# method <- sce.upl$method; if(is.null(method)) return()
# ns <- session$ns; sel <- 'toBulk'
# cho <- c('Cell2tissue'='toBulk', 'Tissue2cell'='toCell')
# if (method=='manual') {
# cho <- c('Cell2tissue'='toBulk'); sel <- 'toBulk'
# }
# selectInput(ns('direc'), label='Mapping direction', choices=cho, selected=sel)
#})
#})
# Initiate three reactive values in the same line can cause problems, since covisGrp slots can be assigned to covis.auto if the former have slots while the latter has no slots.
# covis.man <- covis.auto <- covisGrp <- reactiveValues()
covisGrp <- reactiveValues()
covis.man <- reactiveValues(); covis.auto <- reactiveValues(con.na=FALSE)
observe({
meth.covis <- input$methCovis; direc <- input$direc
cell <- sce.upl$cell; covis.type <- NULL
if (is.null(meth.covis)|is.null(direc)|is.null(cell)) return()
if ('man' %in% meth.covis) {
if (direc=='toBulk') covis.type <- 'toBulk'
if (direc=='toCell') covis.type <- 'toCell'
}
if (meth.covis=='auto' & direc=='toBulk') covis.type <- 'toBulkAuto'
if (meth.covis=='auto' & direc=='toCell') covis.type <- 'toCellAuto'
sce.upl$method <- ifelse('man' %in% meth.covis, 'man', 'auto')
sce.upl$covis.type <- covis.type
if ('man' %in% sce.upl$method) {
showElement('covisMan'); hideElement('covisAuto')
} else if ('auto' %in% sce.upl$method) {
showElement('covisAuto'); hideElement('covisMan')
}
})
observeEvent(sce.upl$method, {
method <- sce.upl$method; cell <- sce.upl$cell
if (is.null(method)|is.null(cell)) return()
# 1) if condition then x <- covis_man_server(arg1=reactiveValue1, ...): server is like a function that returns a value, 2) if condition then covis_man_server(arg1=reactiveValue1, ...): the condition is useless, since reactiveValue1 can cause execution on inner code of covis_man_server regardless of the condition.
if ('man' %in% method & is.null(covis.man$dimred)) {
covis_man_server('covisMan', sce.upl=sce.upl, upl.mod.lis=upl.mod.lis, shm.mod.lis=shm.mod.lis, tab=tab, covis.man=covis.man, lis.url=lis.url, parent=parent, session)
} else if ('auto' %in% method & is.null(covis.auto$res)) {
covis_auto_server('covisAuto', sce.upl=sce.upl, upl.mod.lis=upl.mod.lis, shm.mod.lis=shm.mod.lis, tab=tab, covis.auto=covis.auto, lis.url=lis.url, parent=parent, session)
}
})
# Erase value from previous session.
observeEvent(sce.upl$covis.type, { covisGrp$val <- NULL })
# "covisGrp" from scell section, passed to SHM page.
observe({
covis.type <- sce.upl$covis.type
if (is.null(covis.man$covisGrp) & is.null(covis.auto$covisGrp)) return()
if (is.null(covis.type)) return()
if (any(c('toCell', 'toBulk') %in% covis.type)) {
covisGrp$val <- covis.man$covisGrp
} else if (any(c('toBulkAuto', 'toCellAuto') %in% covis.type)) {
covisGrp$val <- covis.auto$covisGrp
}
})
sce.res <- reactive({
cat('Single cell: aggregating cells ... \n')
if (!grepl(na.sgl, upl.mod.lis$ipt$fileIn)) return()
covis.type <- sce.upl$covis.type; method <- sce.upl$method
if (is.null(covis.type)|is.null(method)) return()
sce.shm <- NULL
if (covis.type %in% 'toBulk') sce.shm <- covis.man$dimred
if (covis.type %in% 'toCell') sce.shm <- covis.man$bulk
if (covis.type %in% 'toCellAuto') {
if (is.null(covis.auto$res)) return()
sce.shm <- subset(covis.auto$res, , bulkCell=='bulk')
covisGrp$val <- 'sample'
}
if (covis.type %in% 'toBulkAuto') {
if (is.null(covis.auto$res)) return()
sce.shm <- subset(covis.auto$res, , bulkCell=='cell')
covisGrp$val <- 'assignedBulk'
}
if (is.null(sce.shm)) return()
df.rep <- assay(sce.shm)
# Column names: sp.ft, exp.var.
sp.ft <- covisGrp$val; if (is.null(sp.ft)) return()
cdat <- colData(sce.shm)
if (!sp.ft %in% colnames(cdat)) return()
# Auto-formed clusters should not be combined with variable, since all cells under variable are clustered. The cell labels are defined by users under control and condition independently.
if ('variable' %in% colnames(cdat) & 'man' %in% method) colnames(df.rep) <- paste0(cdat[, sp.ft], '__', cdat[, 'variable']) else { colnames(df.rep) <- cdat[, sp.ft] }
withProgress(message="Covis: ", value=0, {
incProgress(0.3, detail="aggregating cells or bulk ...")
sce.lis <- fread_df(cbind(as(df.rep, 'matrix'), rowData(sce.shm)), rep.aggr='mean')
incProgress(0.3, detail="aggregating cells or bulk ...")
})
lis <- list(sce.lis=sce.lis, covisGrp=sp.ft)
# save(lis, file='lis')
cat('Done! \n'); return(lis)
})
cat('Module scell_server done! \n')
onBookmark(function(state) { state })
return(list(sce.upl=sce.upl, sce.res=sce.res, covis.man=covis.man, covis.auto=covis.auto, input=input))
})}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.