Nothing
# ZetaSuite Shiny Application
# A web interface for high-throughput screening data analysis
library(shiny)
library(shinydashboard)
library(DT)
library(plotly)
library(shinyjs)
# UI Definition
ui <- dashboardPage(
dashboardHeader(
title = tags$a(href = "https://cran.r-project.org/web/packages/ZetaSuite/index.html",
"ZetaSuite",
target = "_blank",
style = "color: white; text-decoration: none;")
),
dashboardSidebar(
sidebarMenu(
menuItem("Welcome", tabName = "welcome", icon = icon("home")),
menuItem("Data Upload", tabName = "upload", icon = icon("upload")),
menuItem("Example Data", tabName = "example", icon = icon("database")),
menuItem("Quality Control", tabName = "qc", icon = icon("check-circle")),
menuItem("Z-score Analysis", tabName = "zscore", icon = icon("chart-line")),
menuItem("Event Coverage", tabName = "eventcoverage", icon = icon("layer-group")),
menuItem("Zeta Score", tabName = "zeta", icon = icon("calculator")),
menuItem("SVM Analysis", tabName = "svm", icon = icon("brain")),
menuItem("FDR Cutoff", tabName = "fdr", icon = icon("cut")),
menuItem("Single Cell QC", tabName = "singlecell", icon = icon("mobile")),
menuItem("Results", tabName = "results", icon = icon("download")),
menuItem("Help & Support", tabName = "help", icon = icon("question-circle"))
)
),
dashboardBody(
useShinyjs(),
tabItems(
# Welcome Tab
tabItem(tabName = "welcome",
fluidRow(
box(title = "Welcome to ZetaSuite", width = 12,
h3("Multi-dimensional High-throughput Data Analysis"),
p("ZetaSuite is an R package designed for analyzing multi-dimensional high-throughput screening data, particularly two-dimensional RNAi screens and single-cell RNA sequencing data."),
br(),
h4("Key Features:"),
tags$ul(
tags$li("Quality Control Analysis"),
tags$li("Z-score Normalization"),
tags$li("Event Coverage Analysis"),
tags$li("Zeta Score Calculation"),
tags$li("SVM-based Background Correction"),
tags$li("Screen Strength Analysis"),
tags$li("Single Cell Quality Control")
),
br(),
h4("Getting Started:"),
p("1. Use the 'Example Data' tab to explore the built-in dataset"),
p("2. Or upload your own data in the 'Data Upload' tab"),
p("3. Follow the analysis workflow through the tabs"),
br(),
p("For more information, see the package vignette and documentation.")
)
)
),
# Data Upload Tab
tabItem(tabName = "upload",
fluidRow(
box(title = "Upload Data Files", width = 12,
fileInput("countMat", "Upload Count Matrix (CSV)", accept = ".csv"),
fileInput("negGene", "Upload Negative Control Genes (CSV)", accept = ".csv"),
fileInput("posGene", "Upload Positive Control Genes (CSV)", accept = ".csv"),
fileInput("nonExpGene", "Upload Non-expressed Genes (CSV, optional)", accept = ".csv"),
actionButton("loadData", "Load Data", class = "btn-primary")
)
),
fluidRow(
box(title = "Data Preview", width = 12,
tabsetPanel(
tabPanel("Count Matrix", DT::dataTableOutput("countMatPreview")),
tabPanel("Negative Controls", DT::dataTableOutput("negGenePreview")),
tabPanel("Positive Controls", DT::dataTableOutput("posGenePreview"))
)
)
)
),
# Example Data Tab
tabItem(tabName = "example",
fluidRow(
box(title = "Example Dataset", width = 12,
h4("HTS2 Screening Dataset"),
p("This example dataset contains:"),
tags$ul(
tags$li("1,609 genes × 100 alternative splicing events"),
tags$li("30 negative control genes (non-specific siRNAs)"),
tags$li("20 positive control genes (PTB-targeting siRNAs)"),
tags$li("50 non-expressed genes (RPKM < 1 in HeLa cells)")
),
br(),
actionButton("loadExampleData", "Load Example Data", class = "btn-success")
)
),
fluidRow(
box(title = "Example Data Summary", width = 12,
verbatimTextOutput("exampleDataSummary")
)
)
),
# Quality Control Tab
tabItem(tabName = "qc",
fluidRow(
box(title = "Quality Control Analysis", width = 12,
actionButton("runQC", "Run Quality Control", class = "btn-success"),
br(), br(),
textOutput("qcStatus")
)
),
fluidRow(
box(title = "Score Distribution", width = 6,
plotOutput("scoreQCPlot")
),
box(title = "t-SNE Plot", width = 6,
plotOutput("tsnePlot")
)
),
fluidRow(
box(title = "Box Plots", width = 6,
plotOutput("boxPlot")
),
box(title = "SSMD Distribution", width = 6,
plotOutput("ssmdPlot")
)
)
),
# Z-score Analysis Tab
tabItem(tabName = "zscore",
fluidRow(
box(title = "Z-score Normalization", width = 12,
actionButton("runZscore", "Calculate Z-scores", class = "btn-success"),
br(), br(),
textOutput("zscoreStatus")
)
),
fluidRow(
box(title = "Z-score Matrix Preview", width = 12,
DT::dataTableOutput("zscorePreview")
)
)
),
# Event Coverage Tab
tabItem(tabName = "eventcoverage",
fluidRow(
box(title = "Event Coverage Parameters", width = 6,
numericInput("binNum", "Number of Bins", value = 100, min = 10, max = 500),
checkboxInput("combine", "Combine Directions", value = TRUE),
actionButton("runEventCoverage", "Calculate Event Coverage", class = "btn-success")
),
box(title = "Event Coverage Status", width = 6,
textOutput("eventCoverageStatus")
)
),
fluidRow(
box(title = "Decrease Direction", width = 6,
plotOutput("ecDecreasePlot")
),
box(title = "Increase Direction", width = 6,
plotOutput("ecIncreasePlot")
)
)
),
# Zeta Score Tab
tabItem(tabName = "zeta",
fluidRow(
box(title = "Zeta Score Parameters", width = 6,
checkboxInput("useSVM", "Use SVM Curves", value = FALSE),
actionButton("runZeta", "Calculate Zeta Scores", class = "btn-success")
),
box(title = "Zeta Score Status", width = 6,
textOutput("zetaStatus")
)
),
fluidRow(
box(title = "Zeta Scores Preview", width = 12,
DT::dataTableOutput("zetaPreview")
)
),
fluidRow(
box(title = "Top Hits by Zeta_D", width = 6,
DT::dataTableOutput("topDecreaseTable")
),
box(title = "Top Hits by Zeta_I", width = 6,
DT::dataTableOutput("topIncreaseTable")
)
)
),
# SVM Analysis Tab
tabItem(tabName = "svm",
fluidRow(
box(title = "SVM Analysis", width = 12,
actionButton("runSVM", "Run SVM Analysis", class = "btn-success"),
br(), br(),
textOutput("svmStatus")
)
),
fluidRow(
box(title = "SVM Results", width = 12,
tabsetPanel(
tabPanel("Decrease Direction", DT::dataTableOutput("svmDecreaseTable")),
tabPanel("Increase Direction", DT::dataTableOutput("svmIncreaseTable"))
)
)
)
),
# FDR Cutoff Tab
tabItem(tabName = "fdr",
fluidRow(
box(title = "FDR Cutoff Parameters", width = 6,
checkboxInput("combineFDR", "Combine Directions", value = FALSE),
actionButton("runFDR", "Calculate FDR Cutoffs", class = "btn-success")
),
box(title = "FDR Cutoff Status", width = 6,
textOutput("fdrStatus")
)
),
fluidRow(
box(title = "Zeta Score Distribution by Type", width = 6,
plotOutput("zetaTypePlot")
),
box(title = "Screen Strength Curves", width = 6,
plotOutput("ssCutoffPlot")
)
),
fluidRow(
box(title = "FDR Cutoff Results", width = 12,
DT::dataTableOutput("fdrTable")
)
),
fluidRow(
box(title = "Hit Selection", width = 12,
numericInput("ssThreshold", "Screen Strength Threshold", value = 0.8, min = 0, max = 1, step = 0.1),
actionButton("selectHits", "Select Hits", class = "btn-primary"),
br(), br(),
verbatimTextOutput("hitSelectionResults")
)
)
),
# Single Cell QC Tab
tabItem(tabName = "singlecell",
fluidRow(
box(title = "Single Cell Data Upload", width = 12,
fileInput("countMatSC", "Upload Single Cell Count Matrix (CSV)", accept = ".csv"),
actionButton("loadSCData", "Load Single Cell Data", class = "btn-primary")
)
),
fluidRow(
box(title = "Single Cell QC Parameters", width = 6,
numericInput("binNumSC", "Number of Bins", value = 10, min = 5, max = 100),
checkboxInput("filterSC", "Filter Low Count Cells", value = TRUE),
actionButton("runSingleCell", "Run Single Cell QC", class = "btn-success")
),
box(title = "Single Cell QC Status", width = 6,
textOutput("singleCellStatus")
)
),
fluidRow(
box(title = "Zeta Score Distribution", width = 12,
plotOutput("singleCellPlot")
)
),
fluidRow(
box(title = "Single Cell Results", width = 12,
DT::dataTableOutput("singleCellTable")
)
)
),
# Results Tab
tabItem(tabName = "results",
fluidRow(
box(title = "Download Results", width = 12,
downloadButton("downloadZscore", "Download Z-scores"),
downloadButton("downloadZeta", "Download Zeta Scores"),
downloadButton("downloadFDR", "Download FDR Results"),
downloadButton("downloadHits", "Download Selected Hits"),
downloadButton("downloadSingleCell", "Download Single Cell Results"),
downloadButton("downloadReport", "Download Analysis Report")
)
),
fluidRow(
box(title = "Analysis Summary", width = 12,
verbatimTextOutput("analysisSummary")
)
)
),
# Help & Support Tab
tabItem(tabName = "help",
fluidRow(
box(title = "Documentation & Support", width = 12,
h4("Package Documentation"),
p("For detailed documentation and examples, see the package vignette:"),
code("vignette(\"ZetaSuite\")"),
br(),
p("Official CRAN package page:"),
tags$a(href = "https://cran.r-project.org/web/packages/ZetaSuite/index.html",
"ZetaSuite on CRAN",
target = "_blank",
class = "btn btn-info"),
br(), br(),
h4("Bug Reports & Feature Requests"),
p("If you encounter any bugs or have feature requests, please report them on our GitHub issues page:"),
tags$a(href = "https://github.com/JunhuiLi1017/ZetaSuite/issues",
"Report a Bug or Request Feature",
target = "_blank",
class = "btn btn-warning"),
br(), br(),
h4("Citation"),
p("If you use ZetaSuite in your research, please cite:"),
p("Hao, Y., Zhang, S., Shao, C. et al. ZetaSuite: computational analysis of two-dimensional high-throughput data from multi-target screens and single-cell transcriptomics. Genome Biol 23, 162 (2022). https://doi.org/10.1186/s13059-022-02729-4"),
br(),
h4("Contact"),
p("For questions about the package, contact the maintainer:"),
p("Junhui Li <ljh.biostat@gmail.com>")
)
),
fluidRow(
box(title = "Troubleshooting", width = 12,
h4("Common Issues"),
tags$ul(
tags$li("Make sure all required packages are installed"),
tags$li("Check that CSV files have correct column headers and data types"),
tags$li("For large datasets, consider reducing the number of bins"),
tags$li("Ensure you have sufficient positive and negative control samples")
),
br(),
h4("Data Format Requirements"),
p("Count Matrix: Rows = Genes/siRNAs, Columns = Readouts/conditions"),
p("Control Files: First column should contain gene/siRNA identifiers"),
p("All files should be in CSV format with proper headers")
)
)
)
)
)
)
# Server Logic
server <- function(input, output, session) {
# Reactive values to store data and results
values <- reactiveValues(
countMat = NULL,
negGene = NULL,
posGene = NULL,
nonExpGene = NULL,
countMatSC = NULL,
zscoreVal = NULL,
ecData = NULL,
zetaData = NULL,
svmData = NULL,
fdrData = NULL,
singleCellData = NULL,
qcResults = NULL,
selectedHits = NULL
)
# Load example data
observeEvent(input$loadExampleData, {
tryCatch({
# Load ZetaSuite package data
library(ZetaSuite)
data(countMat)
data(negGene)
data(posGene)
data(nonExpGene)
data(ZseqList)
data(SVMcurve)
values$countMat <- countMat
values$negGene <- negGene
values$posGene <- posGene
values$nonExpGene <- nonExpGene
showNotification("Example data loaded successfully!", type = "message")
}, error = function(e) {
showNotification(paste("Error loading example data:", e$message), type = "error")
})
})
# Load main data
observeEvent(input$loadData, {
req(input$countMat, input$negGene, input$posGene)
tryCatch({
values$countMat <- read.csv(input$countMat$datapath, row.names = 1)
values$negGene <- read.csv(input$negGene$datapath)
values$posGene <- read.csv(input$posGene$datapath)
if (!is.null(input$nonExpGene)) {
values$nonExpGene <- read.csv(input$nonExpGene$datapath)
}
showNotification("Data loaded successfully!", type = "message")
}, error = function(e) {
showNotification(paste("Error loading data:", e$message), type = "error")
})
})
# Load single cell data
observeEvent(input$loadSCData, {
req(input$countMatSC)
tryCatch({
values$countMatSC <- read.csv(input$countMatSC$datapath, row.names = 1)
showNotification("Single cell data loaded successfully!", type = "message")
}, error = function(e) {
showNotification(paste("Error loading single cell data:", e$message), type = "error")
})
})
# Example data summary
output$exampleDataSummary <- renderPrint({
if (!is.null(values$countMat)) {
cat("=== Example Dataset Summary ===\n\n")
cat("Count matrix dimensions:", dim(values$countMat), "\n")
cat("Negative controls:", nrow(values$negGene), "genes\n")
cat("Positive controls:", nrow(values$posGene), "genes\n")
if (!is.null(values$nonExpGene)) {
cat("Non-expressed genes:", nrow(values$nonExpGene), "genes\n")
}
cat("\nData ready for analysis!\n")
} else {
cat("Click 'Load Example Data' to load the built-in dataset.\n")
}
})
# Data preview outputs
output$countMatPreview <- DT::renderDataTable({
req(values$countMat)
DT::datatable(head(values$countMat, 10), options = list(scrollX = TRUE))
})
output$negGenePreview <- DT::renderDataTable({
req(values$negGene)
DT::datatable(values$negGene, options = list(scrollX = TRUE))
})
output$posGenePreview <- DT::renderDataTable({
req(values$posGene)
DT::datatable(values$posGene, options = list(scrollX = TRUE))
})
# Quality Control
observeEvent(input$runQC, {
req(values$countMat, values$negGene, values$posGene)
tryCatch({
withProgress(message = "Running Quality Control...", {
values$qcResults <- QC(values$countMat, values$negGene, values$posGene)
})
output$qcStatus <- renderText("Quality Control completed successfully!")
showNotification("Quality Control completed!", type = "message")
}, error = function(e) {
output$qcStatus <- renderText(paste("Error:", e$message))
showNotification(paste("Error in Quality Control:", e$message), type = "error")
})
})
# Z-score Analysis
observeEvent(input$runZscore, {
req(values$countMat, values$negGene)
tryCatch({
withProgress(message = "Calculating Z-scores...", {
values$zscoreVal <- Zscore(values$countMat, values$negGene)
})
output$zscoreStatus <- renderText("Z-score calculation completed successfully!")
showNotification("Z-scores calculated!", type = "message")
}, error = function(e) {
output$zscoreStatus <- renderText(paste("Error:", e$message))
showNotification(paste("Error in Z-score calculation:", e$message), type = "error")
})
})
# Event Coverage
observeEvent(input$runEventCoverage, {
req(values$zscoreVal, values$negGene, values$posGene)
tryCatch({
withProgress(message = "Calculating Event Coverage...", {
values$ecData <- EventCoverage(values$zscoreVal, values$negGene, values$posGene,
input$binNum, input$combine)
})
output$eventCoverageStatus <- renderText("Event Coverage calculation completed successfully!")
showNotification("Event Coverage calculated!", type = "message")
}, error = function(e) {
output$eventCoverageStatus <- renderText(paste("Error:", e$message))
showNotification(paste("Error in Event Coverage calculation:", e$message), type = "error")
})
})
# Zeta Score
observeEvent(input$runZeta, {
req(values$zscoreVal, values$ecData)
tryCatch({
withProgress(message = "Calculating Zeta Scores...", {
if (input$useSVM && !is.null(values$svmData)) {
values$zetaData <- Zeta(values$zscoreVal, values$ecData[[1]]$ZseqList,
values$svmData, SVM = TRUE)
} else {
values$zetaData <- Zeta(values$zscoreVal, values$ecData[[1]]$ZseqList, SVM = FALSE)
}
})
output$zetaStatus <- renderText("Zeta Score calculation completed successfully!")
showNotification("Zeta Scores calculated!", type = "message")
}, error = function(e) {
output$zetaStatus <- renderText(paste("Error:", e$message))
showNotification(paste("Error in Zeta Score calculation:", e$message), type = "error")
})
})
# SVM Analysis
observeEvent(input$runSVM, {
req(values$ecData)
tryCatch({
withProgress(message = "Running SVM Analysis...", {
values$svmData <- SVM(values$ecData)
})
output$svmStatus <- renderText("SVM Analysis completed successfully!")
showNotification("SVM Analysis completed!", type = "message")
}, error = function(e) {
output$svmStatus <- renderText(paste("Error:", e$message))
showNotification(paste("Error in SVM Analysis:", e$message), type = "error")
})
})
# FDR Cutoff
observeEvent(input$runFDR, {
req(values$zetaData, values$negGene, values$posGene, values$nonExpGene)
tryCatch({
withProgress(message = "Calculating FDR Cutoffs...", {
values$fdrData <- FDRcutoff(values$zetaData, values$negGene, values$posGene,
values$nonExpGene, input$combineFDR)
})
output$fdrStatus <- renderText("FDR Cutoff calculation completed successfully!")
showNotification("FDR Cutoffs calculated!", type = "message")
}, error = function(e) {
output$fdrStatus <- renderText(paste("Error:", e$message))
showNotification(paste("Error in FDR Cutoff calculation:", e$message), type = "error")
})
})
# Hit Selection
observeEvent(input$selectHits, {
req(values$zetaData, values$fdrData)
tryCatch({
fdr_table <- values$fdrData[[1]]
selected_threshold <- fdr_table[fdr_table$SS >= input$ssThreshold, ]
if (nrow(selected_threshold) > 0) {
best_threshold <- selected_threshold[which.max(selected_threshold$SS), ]
combined_zeta <- values$zetaData$Zeta_D + values$zetaData$Zeta_I
hits <- names(combined_zeta[combined_zeta >= best_threshold$Cut_Off])
values$selectedHits <- data.frame(
Gene = hits,
Zeta_D = values$zetaData[hits, "Zeta_D"],
Zeta_I = values$zetaData[hits, "Zeta_I"],
Combined_Zeta = combined_zeta[hits],
stringsAsFactors = FALSE
)
output$hitSelectionResults <- renderPrint({
cat("=== Hit Selection Results ===\n\n")
cat("Screen Strength threshold:", input$ssThreshold, "\n")
cat("Selected threshold:", best_threshold$Cut_Off, "\n")
cat("Screen Strength:", best_threshold$SS, "\n")
cat("Total hits identified:", length(hits), "\n")
cat("Apparent FDR:", best_threshold$aFDR, "\n")
})
showNotification(paste("Selected", length(hits), "hits!"), type = "message")
} else {
output$hitSelectionResults <- renderPrint({
cat("No thresholds found with Screen Strength >=", input$ssThreshold, "\n")
cat("Try lowering the threshold or running FDR analysis with different parameters.\n")
})
}
}, error = function(e) {
output$hitSelectionResults <- renderPrint({
cat("Error in hit selection:", e$message, "\n")
})
})
})
# Single Cell QC
observeEvent(input$runSingleCell, {
req(values$countMatSC)
tryCatch({
withProgress(message = "Running Single Cell QC...", {
values$singleCellData <- ZetaSuitSC(values$countMatSC, input$binNumSC, input$filterSC)
})
output$singleCellStatus <- renderText("Single Cell QC completed successfully!")
showNotification("Single Cell QC completed!", type = "message")
}, error = function(e) {
output$singleCellStatus <- renderText(paste("Error:", e$message))
showNotification(paste("Error in Single Cell QC:", e$message), type = "error")
})
})
# Plot outputs
output$scoreQCPlot <- renderPlot({
req(values$qcResults)
tryCatch({
if (is.null(values$qcResults$score_qc)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No score QC plot available", cex = 1.2)
} else {
values$qcResults$score_qc
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$tsnePlot <- renderPlot({
req(values$qcResults)
tryCatch({
if (is.null(values$qcResults$tSNE_QC)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No t-SNE plot available", cex = 1.2)
} else {
values$qcResults$tSNE_QC
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$boxPlot <- renderPlot({
req(values$qcResults)
tryCatch({
if (is.null(values$qcResults$QC_box)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No box plot available", cex = 1.2)
} else {
values$qcResults$QC_box
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$ssmdPlot <- renderPlot({
req(values$qcResults)
tryCatch({
if (is.null(values$qcResults$QC_SSMD)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No SSMD plot available", cex = 1.2)
} else {
values$qcResults$QC_SSMD
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$ecDecreasePlot <- renderPlot({
req(values$ecData)
tryCatch({
if (is.null(values$ecData[[2]]$EC_jitter_D)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No decrease direction plot available", cex = 1.2)
} else {
values$ecData[[2]]$EC_jitter_D
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$ecIncreasePlot <- renderPlot({
req(values$ecData)
tryCatch({
if (is.null(values$ecData[[2]]$EC_jitter_I)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No increase direction plot available", cex = 1.2)
} else {
values$ecData[[2]]$EC_jitter_I
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$zetaTypePlot <- renderPlot({
req(values$fdrData)
tryCatch({
if (is.null(values$fdrData[[2]]$Zeta_type)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No zeta type plot available", cex = 1.2)
} else {
values$fdrData[[2]]$Zeta_type
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$ssCutoffPlot <- renderPlot({
req(values$fdrData)
tryCatch({
if (is.null(values$fdrData[[2]]$SS_cutOff)) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No screen strength plot available", cex = 1.2)
} else {
values$fdrData[[2]]$SS_cutOff
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
output$singleCellPlot <- renderPlot({
req(values$singleCellData)
tryCatch({
if (is.null(values$singleCellData[[2]])) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, "No single cell plot available", cex = 1.2)
} else {
values$singleCellData[[2]]
}
}, error = function(e) {
plot(1, 1, type = "n", axes = FALSE, xlab = "", ylab = "")
text(1, 1, paste("Error rendering plot:", e$message), cex = 1.2)
})
})
# Table outputs
output$zscorePreview <- DT::renderDataTable({
req(values$zscoreVal)
DT::datatable(head(values$zscoreVal, 10), options = list(scrollX = TRUE))
})
output$zetaPreview <- DT::renderDataTable({
req(values$zetaData)
DT::datatable(head(values$zetaData, 10), options = list(scrollX = TRUE))
})
output$topDecreaseTable <- DT::renderDataTable({
req(values$zetaData)
top_decrease <- head(values$zetaData[order(values$zetaData$Zeta_D, decreasing = TRUE), ], 10)
DT::datatable(top_decrease, options = list(scrollX = TRUE))
})
output$topIncreaseTable <- DT::renderDataTable({
req(values$zetaData)
top_increase <- head(values$zetaData[order(values$zetaData$Zeta_I, decreasing = TRUE), ], 10)
DT::datatable(top_increase, options = list(scrollX = TRUE))
})
output$svmDecreaseTable <- DT::renderDataTable({
req(values$svmData)
DT::datatable(values$svmData$cutOffD, options = list(scrollX = TRUE))
})
output$svmIncreaseTable <- DT::renderDataTable({
req(values$svmData)
DT::datatable(values$svmData$cutOffI, options = list(scrollX = TRUE))
})
output$fdrTable <- DT::renderDataTable({
req(values$fdrData)
DT::datatable(values$fdrData[[1]], options = list(scrollX = TRUE))
})
output$singleCellTable <- DT::renderDataTable({
req(values$singleCellData)
DT::datatable(values$singleCellData[[1]], options = list(scrollX = TRUE))
})
# Download handlers
output$downloadZscore <- downloadHandler(
filename = function() { "zscore_results.csv" },
content = function(file) {
req(values$zscoreVal)
write.csv(values$zscoreVal, file)
}
)
output$downloadZeta <- downloadHandler(
filename = function() { "zeta_scores.csv" },
content = function(file) {
req(values$zetaData)
write.csv(values$zetaData, file)
}
)
output$downloadFDR <- downloadHandler(
filename = function() { "fdr_results.csv" },
content = function(file) {
req(values$fdrData)
write.csv(values$fdrData[[1]], file)
}
)
output$downloadHits <- downloadHandler(
filename = function() { "selected_hits.csv" },
content = function(file) {
req(values$selectedHits)
write.csv(values$selectedHits, file, row.names = FALSE)
}
)
output$downloadSingleCell <- downloadHandler(
filename = function() { "single_cell_results.csv" },
content = function(file) {
req(values$singleCellData)
write.csv(values$singleCellData[[1]], file)
}
)
output$downloadReport <- downloadHandler(
filename = function() { "zetaSuite_analysis_report.txt" },
content = function(file) {
cat("=== ZetaSuite Analysis Report ===\n\n", file = file)
if (!is.null(values$countMat)) {
cat("Data Summary:\n", file = file, append = TRUE)
cat("Count matrix dimensions:", dim(values$countMat), "\n", file = file, append = TRUE)
cat("Negative controls:", nrow(values$negGene), "genes\n", file = file, append = TRUE)
cat("Positive controls:", nrow(values$posGene), "genes\n", file = file, append = TRUE)
if (!is.null(values$nonExpGene)) {
cat("Non-expressed genes:", nrow(values$nonExpGene), "genes\n", file = file, append = TRUE)
}
cat("\n", file = file, append = TRUE)
}
if (!is.null(values$zetaData)) {
cat("Zeta Score Summary:\n", file = file, append = TRUE)
cat("Number of genes:", nrow(values$zetaData), "\n", file = file, append = TRUE)
cat("Zeta_D range:", range(values$zetaData$Zeta_D), "\n", file = file, append = TRUE)
cat("Zeta_I range:", range(values$zetaData$Zeta_I), "\n", file = file, append = TRUE)
cat("\n", file = file, append = TRUE)
}
if (!is.null(values$selectedHits)) {
cat("Hit Selection Results:\n", file = file, append = TRUE)
cat("Total hits identified:", nrow(values$selectedHits), "\n", file = file, append = TRUE)
cat("\n", file = file, append = TRUE)
}
cat("Analysis completed on:", Sys.time(), "\n", file = file, append = TRUE)
}
)
# Analysis summary
output$analysisSummary <- renderPrint({
cat("=== ZetaSuite Analysis Summary ===\n\n")
if (!is.null(values$countMat)) {
cat("✓ Count matrix loaded:", nrow(values$countMat), "genes ×", ncol(values$countMat), "samples\n")
}
if (!is.null(values$zscoreVal)) {
cat("✓ Z-scores calculated\n")
}
if (!is.null(values$ecData)) {
cat("✓ Event coverage calculated\n")
}
if (!is.null(values$zetaData)) {
cat("✓ Zeta scores calculated\n")
}
if (!is.null(values$svmData)) {
cat("✓ SVM analysis completed\n")
}
if (!is.null(values$fdrData)) {
cat("✓ FDR cutoffs calculated\n")
}
if (!is.null(values$selectedHits)) {
cat("✓ Hits selected:", nrow(values$selectedHits), "genes\n")
}
if (!is.null(values$singleCellData)) {
cat("✓ Single cell QC completed\n")
}
cat("\nAnalysis ready for download!")
})
}
# Run the application
shinyApp(ui = ui, server = server)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.