Nothing
devtools::install_github("mirzaghaderi/rtpcr")
#if (!requireNamespace("rtpcr", quietly = TRUE)) install.packages("multcompView")
#if (!requireNamespace("markdown", quietly = TRUE)) install.packages("markdown")
library(multcompView)
library(rtpcr)
library(shiny)
library(dplyr)
library(ggplot2)
library(emmeans)
library(multcomp)
library(lme4)
library(lmerTest)
library(markdown)
# UI
ui <- fluidPage(
# JavaScript to trigger the specific button on 'Enter' based on active tab
tags$script(HTML("
$(document).on('keyup', function(e) {
if (e.which == 13) {
var activeTab = $('#func_tabs .active a').attr('data-value');
var btnId = '';
if (activeTab === 'ANOVA_DCt') btnId = '#run_dc';
if (activeTab === 'ANOVA_DDCt') btnId = '#run_ddct';
if (activeTab === 'Efficiency') btnId = '#run_eff';
if (activeTab === 'TTEST_DDCt') btnId = '#run_tt';
if (activeTab === 'WILCOX_DDCt') btnId = '#run_wx';
if (activeTab === 'plotFactor') btnId = '#run_pf';
if (btnId !== '') {
$(btnId).click();
}
}
});
")),
titlePanel('rtpcr: qPCR Data Analysis & Plotting'),
fluidRow(
column(12,
div(style = "margin-bottom: 20px; color: #333; line-height: 1.6;",
p("rtpcr uses dCt and ddCt methods, including t-tests and ANOVA, repeated-measures models, and publication-ready visualizations. The package implements a general calculation method adopted from Ganger et al. (2017) and Taylor et al. (2019), covering both the Livak and Pfaffl methods. The rtpcr package gets efficiency (E) from the Ct values of genes and performs different analyses using the following functions.")
)
)
),
br(),
sidebarLayout(
sidebarPanel(
tabsetPanel(id = "func_tabs",
tabPanel("Home", value = "Home", helpText("Welcome! Please select an analysis tool from these tabs.")),
tabPanel("ANOVA_DCt", value = "ANOVA_DCt",
radioButtons("src_dc", "Data Source", choices = c("Upload CSV" = "user", "Sample Data" = "sample"), selected = "user"),
conditionalPanel("input.src_dc == 'user'", fileInput("file_dc", "Upload CSV", accept = ".csv")),
numericInput("numFactors_dc", "Number of factors", 1, min = 1),
numericInput("numRefGenes_dc", "Number of reference genes", 1, min = 1),
textInput("block_dc", "Block column (optional)", ""),
textInput("model_dc", "model (optional)", ""),
checkboxInput("set40_dc", "Set missing Ct to 40", FALSE),
checkboxInput("setModelse_dc", "Model_based se", TRUE),
selectInput("pAdj_dc", "p-value adjustment", choices = c("none","holm","bonferroni","fdr")),
actionButton("run_dc", "Run ANOVA_DCt (Enter)")
),
tabPanel("ANOVA_DDCt", value = "ANOVA_DDCt",
radioButtons("src_ddct", "Data Source", choices = c("Upload CSV" = "user", "Sample Data" = "sample"), selected = "user"),
conditionalPanel("input.src_ddct == 'user'", fileInput("file_ddct", "Upload CSV", accept = ".csv")),
numericInput("numFactors_ddct", "Number of factors", 1, min = 1),
numericInput("numRefGenes_ddct", "Number of reference genes", 1, min = 1),
textInput("specs_ddct", "Specs (e.g., Concentration or Concentration | Type)", ""),
textInput("block_ddct", "Block column (optional)", ""),
textInput("calibrator_ddct", "Calibrator Level (NULL or single level; needs character!)", ""),
selectInput("seType_ddct", "SE type", choices = c("single.group", "two.group", "paired.group")),
textInput("model_ddct", "model (optional)", ""),
selectInput("pAdj_ddct", "p-value adjustment", choices = c("none","holm","bonferroni","fdr")),
checkboxInput("set40_ddct", "Set missing Ct to 40", FALSE),
checkboxInput("setModelse_ddct", "Model_based se", TRUE),
actionButton("run_ddct", "Run ANOVA_DDCt (Enter)")
),
tabPanel("Efficiency", value = "Efficiency",
radioButtons("src_eff", "Data Source",choices = c("Upload CSV" = "user", "Sample Data" = "sample"), selected = "user"),
conditionalPanel("input.src_eff == 'user'", fileInput("file_eff", "Upload CSV", accept = ".csv")),
numericInput("baseSize_eff", "Base font size", 12, min = 6),
textInput("extra_eff", "Further adjustments (e.g. + theme_bw() + labs(...))", ""),
hr(),
h4("Save Settings"),
fluidRow(
column(6, numericInput("eff_w", "Width (in)", 8, min = 1)),
column(6, numericInput("eff_h", "Height (in)", 6, min = 1))
),
actionButton("run_eff", "Run Efficiency (Enter)")
),
tabPanel("TTEST_DDCt", value = "TTEST_DDCt",
radioButtons("src_tt", "Data Source", choices = c("Upload CSV" = "user", "Sample Data" = "sample"), selected = "user"),
conditionalPanel("input.src_tt == 'user'", fileInput("file_tt", "Upload CSV", accept = ".csv")),
numericInput("numRefGenes_tt", "Number of reference genes", 1),
textInput("factorLevels_tt", "Factor levels (comma separated)", ""),
checkboxInput("paired_tt", "Paired test", FALSE),
checkboxInput("equalVar_tt", "Equal variance", TRUE),
selectInput("pAdj_tt", "p-value adjustment", choices = c("none","holm","bonferroni","fdr")),
checkboxInput("set40_tt", "Set missing Ct to 40", FALSE),
actionButton("run_tt", "Run TTEST_DDCt (Enter)")
),
tabPanel("WILCOX_DDCt", value = "WILCOX_DDCt",
radioButtons("src_wx", "Data Source", choices = c("Upload CSV" = "user", "Sample Data" = "sample"), selected = "user"),
conditionalPanel("input.src_wx == 'user'", fileInput("file_wx", "Upload CSV", accept = ".csv")),
numericInput("numRefGenes_wx", "Number of reference genes", 1),
textInput("factorLevels_wx", "Factor levels (comma separated)", ""),
checkboxInput("paired_wx", "Paired test", FALSE),
selectInput("pAdj_wx", "p-value adjustment", choices = c("none","holm","bonferroni","fdr")),
checkboxInput("set40_wx", "Set missing Ct to 40", FALSE),
actionButton("run_wx", "Run WILCOX_DDCt (Enter)")
),
tabPanel("plotFactor", value = "plotFactor",
radioButtons("src_pf", "Data Source",
choices = c("Upload CSV" = "user",
"Sample Data" = "sample",
"Result: ANOVA_DCt" = "res_dc",
"Result: ANOVA_DDCt" = "res_ddct",
"Result: TTEST_DDCt" = "res_tt",
"Result: WILCOX_DDCt" = "res_wx"),
selected = "user"),
conditionalPanel("input.src_pf == 'user'", fileInput("file_pf", "Upload CSV for Plotting", accept = ".csv")),
selectInput("pf_x", "X Axis Column", choices = NULL),
selectInput("pf_y", "Y Axis Column", choices = NULL),
selectInput("pf_low", "Lower Error Column", choices = NULL),
selectInput("pf_up", "Upper Error Column", choices = NULL),
selectInput("pf_group", "Group (Fill) Column", choices = c("None" = "")),
selectInput("pf_facet", "Facet Column", choices = c("None" = "")),
selectInput("pf_letters", "Letters Column (Optional)", choices = c("None" = "")),
hr(),
h4("Data Cleaning"),
checkboxInput("pf_removeRows", "Remove Calibrator Cols (Single words)", FALSE),
checkboxInput("pf_removeText", "Remove Calibrator Text (Keep first word)", FALSE),
hr(),
numericInput("pf_letters_d", "Letters vertical offset", 0.2, step = 0.05),
numericInput("pf_col_width", "Column width", 0.8, step = 0.05),
numericInput("pf_err_width", "Error bar width", 0.15, step = 0.05),
numericInput("pf_dodge_width", "Dodge width", 0.8, step = 0.05),
textInput("pf_fill_colors", "Fill colors (comma separated, optional)", ""),
textInput("pf_color", "Outline color", "black"),
sliderInput("pf_alpha", "Transparency (alpha)", min = 0, max = 1, value = 1, step = 0.05),
numericInput("pf_base_size", "Base font size", 12, min = 6),
checkboxInput("pf_legend_none", "Hide legend", FALSE),
fluidRow(column(6, numericInput("pf_legend_x", "Legend X position", 1, min = 0, max = 1, step = 0.05) ),
column(6, numericInput("pf_legend_y", "Legend Y position", 1,min = 0, max = 1, step = 0.05) ) ),
textInput("extra_pf", "Further adjustments (e.g. + theme_classic() + labs(...))", ""),
hr(),
h4("Save Settings"),
fluidRow(
column(6, numericInput("pf_w", "Width (in)", 8, min = 1)),
column(6, numericInput("pf_h", "Height (in)", 6, min = 1))
),
actionButton("run_pf", "Run plotFactor (Enter)")
)
)
),
mainPanel(
tabsetPanel(id = "output_tabs",
tabPanel("Introduction", value = "Introduction",
div(style = "padding: 15px;",
includeMarkdown("README.md")
)
),
tabPanel("ANOVA_DCt", value = "ANOVA_DCt",
selectInput("gene_dc", "Select gene:", choices = character(0)),
tabsetPanel(id = "sub_dc",
tabPanel("Input data", tableOutput("preview_dc")),
tabPanel("Relative Expression", br(), downloadButton("download_dc","Download"), br(), tableOutput("table_dc")),
tabPanel("Per-Gene Results",
tabsetPanel(
tabPanel("ANOVA Table", verbatimTextOutput("anova_dc")),
tabPanel("LM Object", downloadButton("download_lm_dc", "Download LM object (.rds)")),
tabPanel("LM Formula", verbatimTextOutput("formula_dc")),
tabPanel("Final table", br(), downloadButton("download_final_dc", "Download Final Table"), br(), tableOutput("final_data_dc"))
)
)
)
),
tabPanel("ANOVA_DDCt", value = "ANOVA_DDCt",
selectInput("gene_ddct", "Select gene:", choices = character(0)),
tabsetPanel(id = "sub_ddct",
tabPanel("Input data", tableOutput("preview_ddct")),
tabPanel("Relative Expression", br(), downloadButton("download_ddct", "Download"), br(), tableOutput("table_ddct")),
tabPanel("Per-Gene Results",
tabsetPanel(
tabPanel("ANOVA Table", verbatimTextOutput("anova_ddct")),
tabPanel("LM Object", downloadButton("download_lm_ddct", "Download LM object (.rds)")),
tabPanel("LM Formula", verbatimTextOutput("formula_ddct")),
tabPanel("Final table", br(), downloadButton("download_final_ddct", "Download Final Table"), br(), tableOutput("final_data_ddct"))
)
)
)
),
tabPanel("Efficiency", value = "Efficiency",
tabsetPanel(id = "sub_eff",
tabPanel("Input data", tableOutput("preview_eff")),
tabPanel("Table", br(), downloadButton("download_eff", "Download CSV"), br(), tableOutput("table_eff")),
tabPanel("Plot",
br(),
fluidRow(
column(12,
downloadButton("download_eff_png", "Download PNG"),
downloadButton("download_eff_pdf", "Download PDF")
)
),
hr(),
plotOutput("plot_eff")
)
)
),
tabPanel("TTEST_DDCt", value = "TTEST_DDCt",
tabsetPanel(id = "sub_tt",
tabPanel("Input Data", tableOutput("preview_tt")),
tabPanel("Results", br(), downloadButton("download_tt", "Download CSV"), br(), tableOutput("table_tt"))
)
),
tabPanel("WILCOX_DDCt", value = "WILCOX_DDCt",
tabsetPanel(id = "sub_wx",
tabPanel("Input Data", tableOutput("preview_wx") ),
tabPanel("Results", br(), downloadButton("download_wx", "Download CSV"), br(), tableOutput("table_wx"))
)
),
tabPanel("plotFactor", value = "plotFactor",
tabsetPanel(id = "sub_pf",
tabPanel("Input Data", tableOutput("preview_pf")),
tabPanel("Plot",
br(),
fluidRow(
column(12,
downloadButton("download_pf_plot", "Download PNG"),
downloadButton("download_pf_pdf", "Download PDF")
)
),
hr(),
plotOutput("plot_pf_main")
)
)
)
)
)
)
)
# SERVER
server <- function(input, output, session) {
observeEvent(input$src_dc, {
if (input$src_dc == "sample") {
updateNumericInput(session, "numFactors_dc", value = 3)
updateNumericInput(session, "numRefGenes_dc", value = 1)
}
})
observeEvent(input$src_ddct, {
if (input$src_ddct == "sample") {
updateNumericInput(session, "numFactors_ddct", value = 2)
updateNumericInput(session, "numRefGenes_ddct", value = 3)
updateTextInput(session, "specs_ddct", value = "Concentration")
updateTextInput(session, "block_ddct", value = "block")
}
})
observeEvent(input$src_pf, {
if (input$src_pf == "sample") {
updateSelectInput(session, "pf_group", selected = "gene")
updateSelectInput(session, "pf_facet", selected = "gene")
updateSelectInput(session, "pf_letters", selected = "sig")
}
})
get_data <- function(src_input, file_input, sample_path) {
if (src_input == "sample") {
return(read.csv(sample_path))
} else {
req(file_input)
return(read.csv(file_input$datapath))
}
}
data_dc <- reactive({ get_data(input$src_dc, input$file_dc, "exp/data_3factor.csv") })
data_ddct <- reactive({ get_data(input$src_ddct, input$file_ddct, "exp/data_2factorBlock3ref.csv") })
data_eff <- reactive({ get_data(input$src_eff, input$file_eff, "eff/data_efficiency1.csv") })
data_tt <- reactive({ get_data(input$src_tt, input$file_tt, "exp/data_ttest18genes.csv") })
data_wx <- reactive({ get_data(input$src_wx, input$file_wx, "exp/data_ttest18genes.csv") })
df_pf <- reactive({
if (input$src_pf == "user") {
req(input$file_pf)
read.csv(input$file_pf$datapath)
} else if (input$src_pf == "sample") {
read.csv("plot/out_ANOVA_DDCt.csv")
} else if (input$src_pf == "res_dc") {
req(res_dc())
res_dc()$relativeExpression
} else if (input$src_pf == "res_ddct") {
req(res_ddct())
res_ddct()$relativeExpression
} else if (input$src_pf == "res_tt") {
req(res_tt())
res_tt()
} else if (input$src_pf == "res_wx") {
req(res_wx())
res_wx()
}
})
output$preview_dc <- renderTable({ req(data_dc()); head(data_dc(), 50) })
output$preview_ddct <- renderTable({ req(data_ddct()); head(data_ddct(), 50) })
output$preview_eff <- renderTable({ req(data_eff()); head(data_eff(), 50) })
output$preview_tt <- renderTable({ req(data_tt()); head(data_tt(), 50) })
output$preview_wx <- renderTable({ req(data_wx()); head(data_wx(), 50) })
output$preview_pf <- renderTable({ req(df_pf()); head(df_pf(), 50) })
observeEvent(input$func_tabs, {
tab_mapping <- c("ANOVA_DCt" = "ANOVA_DCt", "ANOVA_DDCt" = "ANOVA_DDCt",
"Efficiency" = "Efficiency", "TTEST_DDCt" = "TTEST_DDCt",
"WILCOX_DDCt" = "WILCOX_DDCt", "plotFactor" = "plotFactor")
if (input$func_tabs %in% names(tab_mapping)) {
updateTabsetPanel(session, "output_tabs", selected = tab_mapping[[input$func_tabs]])
} else if (input$func_tabs == "Home") {
updateTabsetPanel(session, "output_tabs", selected = "Introduction")
}
})
observeEvent(input$run_dc, { updateTabsetPanel(session, "sub_dc", selected = "Relative Expression") })
observeEvent(input$run_ddct, { updateTabsetPanel(session, "sub_ddct", selected = "Relative Expression") })
observeEvent(input$run_eff, { updateTabsetPanel(session, "sub_eff", selected = "Table") })
observeEvent(input$run_tt, { updateTabsetPanel(session, "sub_tt", selected = "Results") })
observeEvent(input$run_wx, { updateTabsetPanel(session, "sub_wx", selected = "Results") })
observeEvent(input$run_pf, { updateTabsetPanel(session, "sub_pf", selected = "Plot") })
res_eff <- eventReactive(input$run_eff, {
res <- efficiency(data_eff(), base_size = input$baseSize_eff)
if (nzchar(trimws(input$extra_eff))) {
tryCatch({
res$plot <- eval(parse(text = paste0("res$plot", input$extra_eff)))
}, error = function(e) {
showNotification(paste("Plot adjustment error:", e$message), type = "error")
})
}
res
})
output$table_eff <- renderTable({ res_eff()$Efficiency })
output$plot_eff <- renderPlot({
res_eff()$plot
}, width = function() input$eff_w * 72, height = function() input$eff_h * 72)
res_tt <- eventReactive(input$run_tt, {
TTEST_DDCt(data_tt(), numberOfrefGenes = input$numRefGenes_tt,
Factor.level.order = if(input$factorLevels_tt == "") NULL else trimws(unlist(strsplit(input$factorLevels_tt, ","))),
paired = input$paired_tt, var.equal = input$equalVar_tt, p.adj = input$pAdj_tt,
set_missing_target_Ct_to_40 = input$set40_tt)
})
output$table_tt <- renderTable({ res_tt() })
res_wx <- eventReactive(input$run_wx, {
tryCatch({ WILCOX_DDCt(data_wx(), numberOfrefGenes = input$numRefGenes_wx,
Factor.level.order = if (input$factorLevels_wx == "") NULL else trimws(unlist(strsplit(input$factorLevels_wx, ","))),
paired = input$paired_wx, p.adj = input$pAdj_wx, set_missing_target_Ct_to_40 = input$set40_wx)
}, error = function(e) { showNotification(e$message, type = "error"); NULL })
})
output$table_wx <- renderTable({ res_wx() })
observeEvent(df_pf(), {
cols <- colnames(df_pf())
pick_col <- function(i) cols[min(i, length(cols))]
updateSelectInput(session, "pf_x", choices = cols, selected = pick_col(2))
updateSelectInput(session, "pf_y", choices = cols, selected = pick_col(4))
updateSelectInput(session, "pf_low", choices = cols, selected = pick_col(9))
updateSelectInput(session, "pf_up", choices = cols, selected = pick_col(10))
updateSelectInput(session, "pf_group", choices = c("None" = "", cols),
selected = if(input$src_pf == "sample") "gene" else "")
updateSelectInput(session, "pf_facet", choices = c("None" = "", cols),
selected = if(input$src_pf == "sample") "gene" else "")
updateSelectInput(session, "pf_letters", choices = c("None" = "", cols),
selected = if(input$src_pf == "sample") "sig" else "")
})
pf_plot_obj <- eventReactive(input$run_pf, {
p <- plotFactor(data = df_pf(), x_col = input$pf_x, y_col = input$pf_y, Lower.se_col = input$pf_low,
Upper.se_col = input$pf_up, group_col = if(input$pf_group == "") NULL else input$pf_group,
facet_col = if(input$pf_facet == "") NULL else input$pf_facet,
letters_col = if(input$pf_letters == "") NULL else input$pf_letters,
letters_d = input$pf_letters_d, col_width = input$pf_col_width, err_width = input$pf_err_width,
dodge_width = input$pf_dodge_width, fill_colors = if (input$pf_fill_colors == "") NULL else trimws(unlist(strsplit(input$pf_fill_colors, ","))),
color = input$pf_color, alpha = input$pf_alpha, base_size = input$pf_base_size,
legend_position = if (input$pf_legend_none) "none" else c(input$pf_legend_x, input$pf_legend_y),
removeCalibratorCols = input$pf_removeRows,
removeCalibratorText = input$pf_removeText)
if (nzchar(trimws(input$extra_pf))) {
tryCatch({
p <- eval(parse(text = paste0("p", input$extra_pf)))
}, error = function(e) {
showNotification(paste("Plot adjustment error:", e$message), type = "error")
})
}
p
})
output$plot_pf_main <- renderPlot({
req(pf_plot_obj())
pf_plot_obj()
}, width = function() input$pf_w * 72, height = function() input$pf_h * 72)
res_dc <- eventReactive(input$run_dc, {
tryCatch({ ANOVA_DCt(data_dc(), numOfFactors = input$numFactors_dc, numberOfrefGenes = input$numRefGenes_dc,
block = if(input$block_dc == "") NULL else input$block_dc,
model = if(input$model_dc == "") NULL else input$model_dc,
p.adj = input$pAdj_dc,
set_missing_target_Ct_to_40 = input$set40_dc,
modelBased_se = input$setModelse_dc)
}, error = function(e) { showNotification(e$message, type="error"); NULL })
})
observe({
genes <- if(!is.null(res_dc()$perGene)) names(res_dc()$perGene) else character(0)
updateSelectInput(session, "gene_dc", choices = genes)
})
output$table_dc <- renderTable({ res_dc()$relativeExpression })
output$anova_dc <- renderPrint({ req(res_dc(), input$gene_dc); res_dc()$perGene[[input$gene_dc]]$ANOVA_table })
output$formula_dc <- renderPrint({ req(res_dc(), input$gene_dc); res_dc()$perGene[[input$gene_dc]]$lm_formula })
output$final_data_dc <- renderTable({ req(res_dc(), input$gene_dc); res_dc()$perGene[[input$gene_dc]]$Final_data })
res_ddct <- eventReactive(input$run_ddct, {
tryCatch({ ANOVA_DDCt(data_ddct(), numOfFactors = input$numFactors_ddct, numberOfrefGenes = input$numRefGenes_ddct,
specs = input$specs_ddct, block = if(input$block_ddct == "") NULL else input$block_ddct,
model = if(input$model_ddct == "") NULL else input$model_ddct,
calibratorLevel = if(input$calibrator_ddct == "") NULL else input$calibrator_ddct,
p.adj = input$pAdj_ddct, set_missing_target_Ct_to_40 = input$set40_ddct, se.type = input$seType_ddct,
modelBased_se = input$setModelse_ddct)
}, error = function(e) { showNotification(e$message, type="error"); NULL })
})
observe({
genes <- if(!is.null(res_ddct()$perGene)) names(res_ddct()$perGene) else character(0)
updateSelectInput(session, "gene_ddct", choices = genes)
})
output$table_ddct <- renderTable({ res_ddct()$relativeExpression })
output$anova_ddct <- renderPrint({ req(res_ddct(), input$gene_ddct); res_ddct()$perGene[[input$gene_ddct]]$ANOVA_table })
output$formula_ddct <- renderPrint({ req(res_ddct(), input$gene_ddct); res_ddct()$perGene[[input$gene_ddct]]$lm_formula })
output$final_data_ddct <- renderTable({ req(res_ddct(), input$gene_ddct); res_ddct()$perGene[[input$gene_ddct]]$Final_data })
output$download_dc <- downloadHandler(filename = "ANOVA_DCt.csv", content = function(f) write.csv(res_dc()$relativeExpression, f, row.names = FALSE))
output$download_ddct <- downloadHandler(filename = "ANOVA_DDCt.csv", content = function(f) write.csv(res_ddct()$relativeExpression, f, row.names=F))
output$download_eff <- downloadHandler(filename = "Efficiency.csv", content = function(f) write.csv(res_eff()$Efficiency, f, row.names=F))
output$download_tt <- downloadHandler(filename = "TTEST.csv", content = function(f) write.csv(res_tt(), f, row.names=F))
output$download_wx <- downloadHandler(filename = "WILCOX_DDCt.csv", content = function(f) write.csv(res_wx(), f, row.names = FALSE))
output$download_final_dc <- downloadHandler(
filename = function() { paste0("Final_Table_DCt_", input$gene_dc, ".csv") },
content = function(file) { write.csv(res_dc()$perGene[[input$gene_dc]]$Final_data, file, row.names = FALSE) }
)
output$download_final_ddct <- downloadHandler(
filename = function() { paste0("Final_Table_DDCt_", input$gene_ddct, ".csv") },
content = function(file) { write.csv(res_ddct()$perGene[[input$gene_ddct]]$Final_data, file, row.names = FALSE) }
)
output$download_eff_png <- downloadHandler(
filename = "Efficiency_Plot.png",
content = function(file) ggsave(file, plot = res_eff()$plot, device = "png", width = input$eff_w, height = input$eff_h)
)
output$download_eff_pdf <- downloadHandler(
filename = "Efficiency_Plot.pdf",
content = function(file) ggsave(file, plot = res_eff()$plot, device = "pdf", width = input$eff_w, height = input$eff_h)
)
output$download_pf_plot <- downloadHandler(
filename = "qPCR_Plot.png",
content = function(file) ggsave(file, plot = pf_plot_obj(), device = "png", width = input$pf_w, height = input$pf_h)
)
output$download_pf_pdf <- downloadHandler(
filename = "qPCR_Plot.pdf",
content = function(file) ggsave(file, plot = pf_plot_obj(), device = "pdf", width = input$pf_w, height = input$pf_h)
)
output$download_lm_dc <- downloadHandler(filename = function() paste0("LM_", input$gene_dc, ".rds"), content = function(file) saveRDS(res_dc()$perGene[[input$gene_dc]]$lm, file))
output$download_lm_ddct <- downloadHandler(filename = function() paste0("LM_", input$gene_ddct, ".rds"), content = function(file) saveRDS(res_ddct()$perGene[[input$gene_ddct]]$lm, file))
}
shinyApp(ui, 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.