Skip to content

Commit

Permalink
DEG analysis included but not finished
Browse files Browse the repository at this point in the history
  • Loading branch information
fentouxungui committed May 17, 2024
1 parent fd226fb commit 830d559
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 18 deletions.
27 changes: 27 additions & 0 deletions R/functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,30 @@ ReviseGene <- function(Agene, GeneLibrary){
return(NA)
}
}


# 检查差异分析时所需要的R包依赖
check_dependency <- function(test){
if (test == "wilcox") { # 检查所需要的R包,暂时这样吧,其它几个test先不测试了
if(!require(devtools, quietly = TRUE)){
install.packages("devtools")
}
if(!require(presto)){
devtools::install_github('immunogenomics/presto')
}
}else if(test == "DESeq2"){
if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
if (!require("DESeq2", quietly = TRUE)) {
BiocManager::install("DESeq2")
}
} else if(test == "MAST"){
if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
if (!require("DESeq2", quietly = TRUE)) {
BiocManager::install("MAST")
}
}
}


153 changes: 151 additions & 2 deletions R/server.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ server <- function(input, output, session) {
shiny::req(input$dataset_file) # req: Check for required values; dataset_file is a data.frame
ext = tools::file_ext(input$dataset_file$datapath) # file_ext: returns the file (name) extensions
validate(need(expr = ext == "rds", message = "Please upload a .rds file")) # validate + need:检查后缀是否为rds,否则抛出错误
data$obj <- prepare_seurat_object(obj = Seurat::UpdateSeuratObject(readRDS(file = input$dataset_file$datapath)))
data$obj <- SeuratObject::JoinLayers(prepare_seurat_object(obj = Seurat::UpdateSeuratObject(readRDS(file = input$dataset_file$datapath))))
data$reduction_options <- prepare_reduction_options(obj = data$obj, keyword = c("umap","tsne"))
data$cluster_options <- prepare_cluster_options(df = data$obj@meta.data)
data$split_options <- prepare_split_options(df = data$obj@meta.data, max.level = 6)
Expand Down Expand Up @@ -239,7 +239,7 @@ server <- function(input, output, session) {
updateCheckboxInput(session, "VlnSplitPlot", value = FALSE)
updateCheckboxInput(session, "VlnStackPlot", value = FALSE)
updateCheckboxInput(session, "VlnFlipPlot", value = FALSE)
updateSelectInput(session, "VlnFillBy", selected = 1)
updateSelectInput(session, "VlnFillBy", selected = "feature")
})

# shiny related bug
Expand Down Expand Up @@ -458,6 +458,155 @@ server <- function(input, output, session) {
}
}, height = function(){session$clientData$output_ridgeplot_width * input$RidgeplotHWRatio}) # box plot: height = width default

################################ DEGs analysis
# Warning
output$degs_warning = renderText({
paste0('Differential Expression testing is computationally intensive and may take some time. 注意,请在点击"Analyze"之前,保存好先前的分析结果!')
})

DEGs <- reactiveValues(degs = NULL, degs_ready = FALSE)

output$DEGs_ready <- reactive({
return(DEGs$degs_ready)
})

# Disable suspend for output$file_loaded, 当被隐藏时,禁用暂停,conditionalpanel所需要要的参数
outputOptions(output, 'DEGs_ready', suspendWhenHidden=FALSE)

# Part-1: ClusterMarkers

# define Cluster Annotation choice
output$ClusterMarkersClusterResolution.UI <- renderUI({
selectInput("ClusterMarkersClusterResolution","Choose A Cluster Resolution:", choices = data$cluster_options)
})

observeEvent(input$DEGsClusterMarkersAnalysis, {
showModal(modalDialog(title = "Calculating Cluster Markers...", "Please wait for a few minutes!", footer= NULL, size = "l"))
isolate(cds <- data$obj)
Seurat::Idents(cds) <- input$ClusterMarkersClusterResolution
check_dependency(test = input$testuse)
cluster.markers <- Seurat::FindAllMarkers(cds, test.use = input$testuse, logfc.threshold = input$logfcthreshold,
min.pct = input$minpct, min.diff.pct = ifelse(input$mindiffpct, input$mindiffpct, -Inf), only.pos = TRUE)
removeModal()
DEGs$degs <<- cluster.markers #修改全局变量,需不需要改为 <<-
DEGs$degs_ready <<- TRUE
})


# Part-2: InterClusterDEGs

# define Cluster Annotation choice
output$InterClusterDEGsClusterResolution.UI <- renderUI({
selectInput("InterClusterDEGsClusterResolution","Choose A Cluster Resolution:", choices = data$cluster_options)
})

# define the idents used
output$InterClusterDEGsGroupCase.UI <- renderUI({
req(input$InterClusterDEGsClusterResolution)
selectInput("InterClusterDEGsGroupCase","Choose Case Clusters:", choices = levels(data$obj@meta.data[,input$InterClusterDEGsClusterResolution]), multiple = TRUE)
})

# define the idents used
output$InterClusterDEGsGroupControl.UI <- renderUI({
req(input$InterClusterDEGsClusterResolution)
req(input$InterClusterDEGsGroupCase)
selectInput("InterClusterDEGsGroupControl","Choose control Clusters:", multiple = TRUE,
choices = setdiff(levels(data$obj@meta.data[,input$InterClusterDEGsClusterResolution]),input$InterClusterDEGsGroupCase))
})


observeEvent(input$InterClusterDEGsAnalysis, {
if (any(is.null(input$InterClusterDEGsGroupCase), is.null(input$InterClusterDEGsGroupControl))) {
showModal(modalDialog(title = "Error:","Please specify the case and control clusters. Press ESC to close.",easyClose = TRUE,footer = NULL))
}else{
showModal(modalDialog(title = "Calculating Cluster Markers...", "Please wait for a few minutes!", footer= NULL, size = "l"))
isolate(cds <- data$obj)
Seurat::Idents(cds) <- input$InterClusterDEGsClusterResolution
check_dependency(test = input$testuse)
cluster.markers <- Seurat::FindMarkers(cds, ident.1 = input$InterClusterDEGsGroupCase, ident.2 = input$InterClusterDEGsGroupControl,
test.use = input$testuse, logfc.threshold = input$logfcthreshold,
min.pct = input$minpct, min.diff.pct = ifelse(input$mindiffpct, input$mindiffpct, -Inf))
removeModal()
DEGs$degs <<- cluster.markers #修改全局变量,需不需要改为 <<-
DEGs$degs_ready <<- TRUE
}
})


# Part-3: IntraClusterDEGs


# define Cluster Annotation choice
output$IntraClusterDEGsCustomizedGroups.UI <- renderUI({
selectInput("IntraClusterDEGsCustomizedGroups","Group samples by:", choices = data$cluster_options)
})

# define the idents used
output$IntraClusterDEGsCustomizedGroupsCase.UI <- renderUI({
req(input$IntraClusterDEGsCustomizedGroups)
selectInput("IntraClusterDEGsCustomizedGroupsCase","Choose Case Samples:", choices = levels(data$obj@meta.data[,input$IntraClusterDEGsCustomizedGroups]), multiple = TRUE)
})

# define the idents used
output$IntraClusterDEGsCustomizedGroupsControl.UI <- renderUI({
req(input$IntraClusterDEGsCustomizedGroups)
req(input$IntraClusterDEGsCustomizedGroupsCase)
selectInput("IntraClusterDEGsCustomizedGroupsControl","Choose control Samples:", multiple = TRUE,
choices = setdiff(levels(data$obj@meta.data[,input$IntraClusterDEGsCustomizedGroups]),input$IntraClusterDEGsCustomizedGroupsCase))
})

# define Cluster Annotation choice
output$IntraClusterDEGsSubsetCells.UI <- renderUI({
req(input$IntraClusterDEGsCustomizedGroups)
selectInput("IntraClusterDEGsSubsetCells","Subset Cells By:", choices = setdiff(data$cluster_options, input$IntraClusterDEGsCustomizedGroups))
})

# define Cluster Annotation choice
output$IntraClusterDEGsSubsetCellsSelectedClusters.UI <- renderUI({
req(input$IntraClusterDEGsCustomizedGroups)
req(input$IntraClusterDEGsSubsetCells)
shinyWidgets::pickerInput(inputId = "IntraClusterDEGsSubsetCellsSelectedClusters", label = "Select Clusters:",
choices = levels(data$obj@meta.data[,input$IntraClusterDEGsSubsetCells]), selected = levels(data$obj@meta.data[,input$IntraClusterDEGsSubsetCells]),
options = shinyWidgets::pickerOptions(actionsBox = TRUE, size = 10, selectedTextFormat = "count > 3"), multiple = TRUE)
})

# 计算自定义分组的差异基因,支持subset clusters - 这里需要改!下周再说吧!!! 2024.05.17
observeEvent(input$IntraClusterDEGssAnalysis, {
# if (any(is.null(input$InterClusterDEGsGroupCase), is.null(input$InterClusterDEGsGroupControl))) {
# showModal(modalDialog(title = "Error:","Please specify the case and control clusters. Press ESC to close.",easyClose = TRUE,footer = NULL))
# }else{
# showModal(modalDialog(title = "Calculating Cluster Markers...", "Please wait for a few minutes!", footer= NULL, size = "l"))
# isolate(cds <- data$obj)
# Seurat::Idents(cds) <- input$InterClusterDEGsClusterResolution
# check_dependency(test = input$testuse)
# cluster.markers <- Seurat::FindMarkers(cds, ident.1 = input$InterClusterDEGsGroupCase, ident.2 = input$InterClusterDEGsGroupControl,
# test.use = input$testuse, logfc.threshold = input$logfcthreshold,
# min.pct = input$minpct, min.diff.pct = ifelse(input$mindiffpct, input$mindiffpct, -Inf))
# removeModal()
# DEGs$degs <<- cluster.markers #修改全局变量,需不需要改为 <<-
# DEGs$degs_ready <<- TRUE
# }
})

# part-4: 重置参数
observeEvent(input$SetDefault, {
updateSelectInput(session = session, inputId = "testuse", selected = "wilcox")
updateSliderInput(session, "logfcthreshold", value = 0.1 )
updateSliderInput(session, "minpct", value = 0.01 )
updateSliderInput(session, "mindiffpct", value = 0 )
})

# part-5: 输出结果
# output$dataset_degs <- reactive({ DEGs$degs })
output$dataset_degs <- DT::renderDT(server=FALSE,{
req(DEGs$degs)
# Show data
DT::datatable(DEGs$degs, extensions = 'Buttons',
options = list(scrollX=TRUE, lengthMenu = c(5,10,15),
paging = TRUE, searching = TRUE,
fixedColumns = TRUE, autoWidth = TRUE,
ordering = TRUE, dom = 'Bfrtip',
buttons = c('copy', 'csv', 'excel')))
})

}
59 changes: 43 additions & 16 deletions R/ui.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ ui <- function(){
box(fileInput("dataset_file", "Choose A Seurat .rds file:", accept = '.rds'), status = "primary", width = 12),
conditionalPanel(
condition = "output.file_loaded",
box(title = "Cell Meta Info", collapsible = TRUE,
shinycssloaders::withSpinner(DT::dataTableOutput('dataset_meta')), status = "primary", width = 12)
box(title = "Cell Meta Info", collapsible = TRUE, status = "primary", width = 12,
shinycssloaders::withSpinner(DT::dataTableOutput('dataset_meta')))
)
)

Expand Down Expand Up @@ -161,13 +161,6 @@ ui <- function(){
sliderInput("HeatmapLineWidth", label = "Line Width:", min = 1, max = 10, value = 1),
sliderInput("HeatmapFeatureTextSize", label = "Feature Text Size:", min = 0, max = 20, value = 10),
sliderInput("HeatmapPlotHWRatio", label = "Adjust Height/Width Ratio:", min = 0.1, max = 2, value = 0.9) # adjust the Ratio of width and height of plot.

# downloadButton('DownloadPlot', label = 'Download Scater Plot - Not Recommmended'),
# textInput("Group1","Group 1:", value = "1"),
# textInput("Group2","Group 2:", value = "2"),
# actionButton("CalculateDEG", "Calculate DEGs!"),
# textInput("Cluster", "Cluster:", value = "0"),
# actionButton("CalculateDEGWithin", "Calculate DEGs Within A Cluster"),
)
)
)
Expand Down Expand Up @@ -196,17 +189,51 @@ ui <- function(){
sliderInput("RidgeplotXlabelSize", label = "x Axis Label Size:", min = 0, max = 20, value = 14),
sliderInput("RidgeplotYlabelSize", label = "Y Axis Label Size:", min = 0, max = 20, value = 10),
sliderInput("RidgeplotHWRatio", label = "Adjust Height/Width Ratio:", min = 0.1, max = 2, value = 0.9) # adjust the Ratio of width and height of plot.

# downloadButton('DownloadPlot', label = 'Download Scater Plot - Not Recommmended'),
# textInput("Group1","Group 1:", value = "1"),
# textInput("Group2","Group 2:", value = "2"),
# actionButton("CalculateDEG", "Calculate DEGs!"),
# textInput("Cluster", "Cluster:", value = "0"),
# actionButton("CalculateDEGWithin", "Calculate DEGs Within A Cluster"),
)
)
)

tab_list[["degs"]] = tabItem(tabName = "degs",
fluidRow(
box(textOutput("degs_warning"), title = "WARNING:", background = "orange", width = 12),
tabBox(
title = "Find Markers or DEGs",
id = "tabset_degs", width = 12, # height = "250px",
tabPanel("ClusterMarkers", strong(h3("Find Markers for All Clusters")),
shinycssloaders::withSpinner(uiOutput("ClusterMarkersClusterResolution.UI"), proxy.height = "10px"),
actionButton("DEGsClusterMarkersAnalysis", "Analyze")),
tabPanel("InterClusterDEGs", strong(h3("Find DEGs Between two Cluster Groups")),
shinycssloaders::withSpinner(uiOutput("InterClusterDEGsClusterResolution.UI"), proxy.height = "10px"),
shinycssloaders::withSpinner(uiOutput("InterClusterDEGsGroupCase.UI"), proxy.height = "10px"),
shinycssloaders::withSpinner(uiOutput("InterClusterDEGsGroupControl.UI"), proxy.height = "10px"),
actionButton("InterClusterDEGsAnalysis", "Analyze")),
tabPanel("IntraClusterDEGs", strong(h3("Find DEGs by Customized Groups Within Selected Clusters")),
shinycssloaders::withSpinner(uiOutput("IntraClusterDEGsCustomizedGroups.UI"), proxy.height = "10px"),
shinycssloaders::withSpinner(uiOutput("IntraClusterDEGsCustomizedGroupsCase.UI"), proxy.height = "10px"),
shinycssloaders::withSpinner(uiOutput("IntraClusterDEGsCustomizedGroupsControl.UI"), proxy.height = "10px"),
tags$hr(style="border: none; border-top: 1px dashed #ccc;"),
shinycssloaders::withSpinner(uiOutput("IntraClusterDEGsSubsetCells.UI"), proxy.height = "10px"),
shinycssloaders::withSpinner(uiOutput("IntraClusterDEGsSubsetCellsSelectedClusters.UI"), proxy.height = "10px"),
tags$hr(style="border: none; border-top: 1px dashed #ccc;"),
actionButton("IntraClusterDEGssAnalysis", "Analyze")),
tabPanel("Parameters", strong(h3("Set Parameters")),
sliderInput("logfcthreshold", label = "Logfc Threshold:", min = 0, max = 1, value = 0.1),
selectInput("testuse","Test use:", choices = c(wilcox = "wilcox", wilcox_limma = "wilcox_limma",
T_test = "t", negbinom = "negbinom", poisson = "poisson",
LR = "LR", MAST = "MAST", DESeq2 = "DESeq2")),
sliderInput("minpct", label = "Minimum Expression Percentage:", min = 0, max = 1, value = 0.01),
sliderInput("mindiffpct", label = "Minimum Expression Percentage Difference:", min = 0, max = 1, value = 0),
actionButton("SetDefault", "Set As Default"))

),
conditionalPanel(
condition = "output.DEGs_ready",
box(title = "Analysis Results:", collapsible = TRUE, status = "primary", width = 12,
shinycssloaders::withSpinner(DT::dataTableOutput('dataset_degs')))
)
)
)

body = dashboardBody(
div(class= "tab-content", tab_list)
)
Expand Down

0 comments on commit 830d559

Please sign in to comment.