Nothing
dir.create(file.path("www", "xlsx"), showWarnings = FALSE, mode = "0777")
suppressPackageStartupMessages({
library("broom")
library("broom")
library("dplyr")
library("DT")
library("ggplot2")
library("ggpubr")
library("glue")
library("purrr")
library("readxl")
library("shiny")
library("stats")
library("tidyr")
library("utils")
})
percent <- function(x) paste(round(x * 100, digits = 0), " %")
`%>%` <- dplyr::`%>%`
ggplot2_themes <- c(
paste0("ggplot2::", grep("^theme_", ls("package:ggplot2"), value = TRUE), "()"),
paste0("ggpubr::", grep("^theme_", ls("package:ggpubr"), value = TRUE), "()")
) %>%
setdiff(paste0("ggplot2::theme_", c("get", "set", "replace", "update"), "()")) %>%
setdiff(paste0("ggpubr::theme_", c("cleveland"), "()")) %>%
purrr::set_names(., gsub(".*::theme_(.*)\\(\\)", "\\1", .)) %>%
gsub("\\(\\)", "", .)
card <- function(title, body, type = "") {
shiny::tags$div(class = paste("card", type),
shiny::tags$div(class = "card-header", align = "center", title),
shiny::tags$div(class = "card-body", align = "center", body)
)
}
plotDownloadInputUI <- function(id, label, height = "330px") {
ns <- shiny::NS(id)
card(
title = {
shiny::tags$h4(label, align = "center",
shiny::downloadButton(ns("plot_download"), label = "Download")
)
},
body = { shiny::plotOutput(ns("plot"), height = height) }
)
}
plotDownloadInput <- function(id, plot_object, width, height, dpi) {
shiny::callModule(id = id, function(input, output, session) {
output$plot <- shiny::renderPlot({ plot_object })
output$plot_download <- shiny::downloadHandler(
filename = function() { paste0(id, ".png") },
content = function(file) {
ggplot2::ggsave(
filename = file, plot = plot_object,
width = width,
height = height,
units = "cm",
dpi = dpi
)
}
)
})
}
cap_word <- function(x) {
substr(x, 1, 1) <- toupper(substr(x, 1, 1))
x
}
get_xlsx_contents <- function(files, project_name = NULL, od_outlier = 1.5, lm_outlier = 1.5) {
out_all_excel <- dplyr::tibble(file = files, filename = basename(file)) %>%
dplyr::mutate(sheet_name = purrr::map(.data[["file"]], readxl::excel_sheets)) %>%
tidyr::unnest(.data[["sheet_name"]]) %>%
dplyr::mutate(
nested_data = purrr::map2(.data[["file"]], .data[["sheet_name"]], function(.x, .y) {
tmp <- suppressMessages({readxl::read_xlsx(.x, .y)})
dplyr::mutate(tmp[, 1:max(grep("Volume \\(µl\\)|OD2", colnames(tmp)))],
re_OD = (.data[["OD2"]] - .data[["OD1"]]) / .data[["OD1"]],
mean_OD = purrr::map2_dbl(.data[["OD1"]], .data[["OD2"]], ~ mean(c(.x, .y)))
)
})
) %>%
tidyr::unnest(nested_data)
if (is.null(project_name)) project_name <- unique(out_all_excel[["Project"]])
out_excel <- out_all_excel %>%
dplyr::filter(.data[["Project"]] %in% !!project_name) %>%
dplyr::mutate(
lower_threshold = stats::quantile(.data[["re_OD"]], 0.25, na.rm = TRUE) -
!!od_outlier * stats::IQR(.data[["re_OD"]], na.rm = TRUE),
upper_threshold = stats::quantile(.data[["re_OD"]], 0.75, na.rm = TRUE) +
!!od_outlier * stats::IQR(.data[["re_OD"]], na.rm = TRUE),
is_outlier_OD = .data[["re_OD"]] < .data[["lower_threshold"]] | .data[["re_OD"]] > .data[["upper_threshold"]]
) %>%
dplyr::group_by(.data[["filename"]]) %>%
dplyr::mutate(normalised_OD = .data[["mean_OD"]] - .data[["mean_OD"]][1]) %>%
dplyr::ungroup()
out_model <- out_excel %>%
dplyr::filter(
.data[["Step"]] == "BLANK",
.data[["Concentration (mU/L)"]] != 0,
!.data[["is_outlier_OD"]]
) %>%
dplyr::group_by(.data[["filename"]]) %>%
dplyr::do({
lm = broom::tidy(
stats::lm(
formula = log10(normalised_OD) ~ log10(`Concentration (mU/L)` / 23),
data = .
)
)[, c("term", "estimate")]
}) %>%
dplyr::ungroup() %>%
dplyr::mutate(
term = c("(Intercept)" = "Intercept", "log10(`Concentration (mU/L)`/23)" = "Slope")[.data[["term"]]]
) %>%
dplyr::group_by(.data[["term"]]) %>%
dplyr::mutate(
lower_threshold = stats::quantile(.data[["estimate"]], 0.25) - !!lm_outlier * stats::IQR(.data[["estimate"]]),
upper_threshold = stats::quantile(.data[["estimate"]], 0.75) + !!lm_outlier * stats::IQR(.data[["estimate"]]),
is_outlier = .data[["estimate"]] < .data[["lower_threshold"]] | .data[["estimate"]] > .data[["upper_threshold"]]
) %>%
dplyr::ungroup() %>%
tidyr::pivot_wider(
id_cols = "filename",
names_from = "term",
values_from = c("estimate", "lower_threshold", "upper_threshold", "is_outlier")
)
out_excel_model <- dplyr::full_join(x = out_excel, y = out_model, by = "filename") %>%
dplyr::group_by(.data[["filename"]]) %>%
dplyr::mutate(
"Concentration (µg/L)" = .data[["Dilution Factor"]] *
10^((log10(.data[["normalised_OD"]]) - .data[["estimate_Intercept"]]) / .data[["estimate_Slope"]]),
"Concentration (µg/L)" = ifelse(
test = is.na(.data[["Concentration (µg/L)"]]) & .data[["Step"]] == "BLANK",
yes = .data[["Concentration (mU/L)"]] / 23,
no = .data[["Concentration (µg/L)"]]
),
"Total (ng)" = .data[["Volume (µl)"]] / 10^3 * .data[["Concentration (µg/L)"]]
) %>%
dplyr::ungroup() %>%
dplyr::group_by(.data[["filename"]], .data[["sheet_name"]], .data[["Target"]], .data[["Step"]]) %>%
dplyr::mutate(measure_id = 1:dplyr::n()) %>%
dplyr::ungroup() %>%
dplyr::mutate(
is_any_outlier = .data[["is_outlier_OD"]] |
.data[["is_outlier_Intercept"]] |
.data[["is_outlier_Slope"]]
)
out_insulin_tmp <- out_excel_model %>%
dplyr::filter(!.data[["is_any_outlier"]]) %>%
dplyr::group_by(.data[["filename"]], .data[["sheet_name"]], .data[["Target"]]) %>%
tidyr::pivot_wider(
id_cols = c("filename", "sheet_name", "Target", "measure_id"),
names_from = "Step",
values_from = "Total (ng)"
) %>%
dplyr::mutate(
ins_SUPERNATANT1 = .data[["SUPERNATANT1"]] / (.data[["LYSATE"]] + .data[["SUPERNATANT1"]] + .data[["SUPERNATANT2"]]),
ins_SUPERNATANT2 = .data[["SUPERNATANT2"]] / (.data[["LYSATE"]] + .data[["SUPERNATANT2"]])
) %>%
dplyr::ungroup() %>%
dplyr::select("filename", "sheet_name", "Target", "measure_id", dplyr::num_range("ins_SUPERNATANT", 1:2))
out_insulin <- out_insulin_tmp %>%
tidyr::pivot_longer(
cols = dplyr::num_range("ins_SUPERNATANT", 1:2),
names_to = "Step",
names_pattern = "ins_(.*)",
values_to = "Insulin Secretion (% of content)"
) %>%
tidyr::drop_na("Insulin Secretion (% of content)")
out_excel_insulin <- dplyr::full_join(
x = out_excel_model,
y = out_insulin,
by = c("filename", "sheet_name", "Step", "Target", "measure_id")
)
out_insulin_fc <- out_insulin_tmp %>%
tidyr::drop_na(dplyr::num_range("ins_SUPERNATANT", 1:2)) %>%
dplyr::group_by(.data[["filename"]], .data[["sheet_name"]], .data[["Target"]], .data[["measure_id"]]) %>%
dplyr::transmute(
"fc_SUPERNATANT2_SUPERNATANT1" = ins_SUPERNATANT2 / ins_SUPERNATANT1,
"log2_fc_SUPERNATANT2_SUPERNATANT1" = log2(ins_SUPERNATANT2 / ins_SUPERNATANT1)
) %>%
dplyr::ungroup()
dplyr::full_join(
x = out_excel_insulin,
y = out_insulin_fc,
by = c("filename", "sheet_name", "Target", "measure_id")
) %>%
dplyr::mutate(
is_any_outlier = .data[["is_outlier_OD"]] |
.data[["is_outlier_Intercept"]] |
.data[["is_outlier_Slope"]] |
(is.na(.data[["fc_SUPERNATANT2_SUPERNATANT1"]]) & !.data[["Step"]] %in% c("BLANK", "LYSATE")) |
(is.na(.data[["Insulin Secretion (% of content)"]]) & !.data[["Step"]] %in% c("BLANK", "LYSATEE")),
Sample = gsub("mM ", "mM\n", .data[["Sample"]])
) %>%
dplyr::group_by(.data[["filename"]], .data[["sheet_name"]]) %>%
dplyr::arrange(.data[["Condition"]], .data[["Sample"]]) %>%
dplyr::ungroup() %>%
dplyr::mutate(
Sample = factor(Sample, levels = unique(.data[["Sample"]])),
Type = factor(cap_word(Type), levels = c("Reference", "Control", "Target")),
) %>%
dplyr::arrange(.data[["Type"]], .data[["Target"]]) %>%
dplyr::mutate(
Type_Target = gsub("NA: NA", NA, paste0(.data[["Type"]], ": ", .data[["Target"]])),
Type_Target = factor(x = Type_Target, levels = unique(Type_Target))
)
}
get_outliers <- function(data, fold_change) {
if (!"is_reference_good" %in% colnames(data)) {
data <- dplyr::full_join(
x = data,
y = data %>%
dplyr::filter(Type %in% "Reference") %>%
dplyr::group_by(.data[["filename"]]) %>%
dplyr::summarise(
is_reference_good = mean(.data[["fc_SUPERNATANT2_SUPERNATANT1"]], na.rm = TRUE) >= fold_change,
.groups = "drop_last"
) %>%
dplyr::ungroup() %>%
dplyr::select(c("filename", "is_reference_good")),
by = "filename"
)
}
data %>%
dplyr::filter(.data[["is_any_outlier"]] | !.data[["is_reference_good"]]) %>%
dplyr::select(c(
"filename", "Target", "Condition",
"is_outlier_Intercept", "is_outlier_Slope",
"is_outlier_OD",
"is_reference_good"
)) %>%
dplyr::distinct() %>%
tidyr::replace_na(list(Target = "BLANK")) %>%
dplyr::group_by(.data[["filename"]]) %>%
dplyr::summarise(
"Blank Linearity" = any(.data[["is_outlier_Intercept"]] | .data[["is_outlier_Slope"]]),
"Technical Variability (OD)" = any(.data[["is_outlier_OD"]]),
"Not Secreting Insulin in Reference" = any(!.data[["is_reference_good"]]),
.groups = "drop_last"
)
}
# UI-side ==========================================================================================
ui <- shiny::navbarPage(
theme = "yeti-bootstrap.min.css",
title = shiny::tags$span(shiny::tags$img(src = "insane.png", height = 18), "INSANE (INsulin Secretion ANalysEr)"),
windowTitle = "INSANE (INsulin Secretion ANalysEr)",
collapsible = TRUE,
id = "main_menu",
selected = "upload-tab",
## Upload tab ------------------------------------------------------------------------------------
shiny::tabPanel("Experiments Upload & Plot Settings", icon = shiny::icon("file-upload"), value = "upload-tab",
shiny::column(width = 4,
card(title = "Plot Settings", body = {
shiny::tagList(
shiny::tags$img(src = "insane.png", height = 120),
shiny::selectInput("ggplot2_theme", "Theme",
choices = ggplot2_themes[sort(names(ggplot2_themes))],
selected = grep("light", ggplot2_themes, value = TRUE)
),
shiny::radioButtons("colour_scale", shiny::tags$span("Colour Palette", shiny::helpText('(No effect on "thresholds areas")')),
choices = c("Viridis", "Plasma", "Magma", "Inferno", "Grey"),
inline = TRUE
),
shiny::sliderInput("colour_scale_range", shiny::tags$span("Limits of the Colour Palette", shiny::helpText("(Dark to Bright)")),
min = 0, max = 1,
value = c(0, 0.85),
step = 0.05
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::numericInput("font_size", shiny::tags$span("Font Size", shiny::helpText("(pt)")),
value = 12
)
),
shiny::column(width = 6,
shiny::numericInput("point_size", shiny::tags$span("Point Size", shiny::helpText("(mm)")),
value = 2,
min = 0, max = 4, step = 0.5
)
)
),
shiny::fluidRow(
shiny::column(width = 6,
shiny::numericInput("plot_width", shiny::tags$span("Width", shiny::helpText("(cm)")),
value = 16
)
),
shiny::column(width = 6,
shiny::numericInput("plot_height", shiny::tags$span("Height", shiny::helpText("(cm)")),
value = 12
)
)
),
shiny::numericInput("plot_dpi", shiny::tags$span("Resolution", shiny::helpText("(dpi)")),
value = 120
)
)
})
),
shiny::column(width = 8, align = "center",
shiny::fluidRow(
shiny::column(width = 12, align = "center",
card(title = "Useful Files", body = {
shiny::tagList(
shiny::tags$p("The experimental protocol (docx): ", shiny::downloadLink("protocol", "download here!")),
shiny::tags$br(),
shiny::tags$p("The results template (xlsx): ", shiny::downloadLink("template", "download here!"))
)
})
)
),
shiny::fluidRow(style = "padding-top: 1em;",
shiny::column(width = 6, align = "center",
card(title = "Project", body = shiny::uiOutput("project_ui"))
),
shiny::column(width = 6, align = "center",
card(title = "Upload Experiments from Excel Files", body = {
shiny::fileInput("xlsx_files", "Choose One or Several Excel Files",
multiple = TRUE, width = "90%",
accept = c(".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
)
})
)
),
shiny::fluidRow(shiny::column(width = 12, align = "center", shiny::uiOutput("upload_ui")))
)
),
## Blank tab -------------------------------------------------------------------------------------
shiny::tabPanel("Technical Quality-Control", icon = shiny::icon("chart-line"), value = "blank-tab",
shiny::sidebarLayout(
shiny::sidebarPanel(width = 3,
shiny::tags$div(align = "center",
shiny::sliderInput("od_outlier",
shiny::tags$span("Optical Density (OD) Outliers Threshold",
shiny::helpText(
"(Higher than", shiny::tags$strong("X"),
"times the interquartile range above the 75", shiny::tags$sup("th", .noWS = "before"), "percentile",
"or",
"lower than", shiny::tags$strong("X"),
"times the interquartile range below the 25", shiny::tags$sup("th", .noWS = "before"), "percentile)"
)
),
min = 1, max = 5, value = 3, step = 0.25
),
shiny::sliderInput("lm_outlier",
shiny::tags$span("Blank Estimates Outliers Threshold",
shiny::helpText(
"(Higher than", shiny::tags$strong("X"),
"times the interquartile range above the 75", shiny::tags$sup("th", .noWS = "before"), "percentile",
"or",
"lower than", shiny::tags$strong("X"),
"times the interquartile range below the 25", shiny::tags$sup("th", .noWS = "before"), "percentile)"
)
),
min = 1, max = 3, value = 1.5, step = 0.25
)
)
),
shiny::mainPanel(width = 9,
shiny::fluidRow(
shiny::column(width = 6, align = "center",
plotDownloadInputUI("od_box_plot", "Optical Density (OD) Relative Error Outliers")
),
shiny::column(width = 6, align = "center",
plotDownloadInputUI("od_density_plot", "Optical Density (OD) Relative Error Distribution")
)
),
shiny::fluidRow(style = "padding-top: 1em;",
shiny::column(width = 6, align = "center",
plotDownloadInputUI("od_lm_box_plot", "Blank Linear Regression Outliers")
),
shiny::column(width = 6, align = "center",
plotDownloadInputUI("od_lm_line_plot", "Blank Linear Regression")
)
)
)
)
),
## Analysis tab ----------------------------------------------------------------------------------
shiny::tabPanel("Insulin Secretion Analysis", icon = shiny::icon("chart-bar"), value = "is_analysis-tab",
shiny::sidebarLayout(
shiny::sidebarPanel(width = 3,
shiny::tags$div(align = "center",
shiny::actionButton("show_issues", "Show Issues in the Selected Experiments"),
shiny::tags$hr(),
shiny::radioButtons("use_boxplot", "Insulin Secretion Plot Type",
choiceNames = list(
shiny::tags$span("Boxplot", shiny::helpText("(Boxplot with points)")),
shiny::tags$span("Histogram", shiny::helpText("(Bars with mean and sem)"))
),
choiceValues = c("Boxplot", "Histogram"),
inline = TRUE
),
shiny::numericInput("fold_change",
shiny::tags$span('Threshold to Define "Secretion"',
shiny::helpText(
"(High/low glucose threshold above which cells are allegedly secreting insulin)"
)
),
value = 1, step = 0.1
),
shiny::uiOutput("target_ui"),
shiny::uiOutput("experiment_ui")
)
),
shiny::mainPanel(width = 9,
shiny::fluidRow(
shiny::column(width = 5, align = "center",
plotDownloadInputUI("is_ratio_distribution_plot",
shiny::tags$span(
"Reference Distribution",
shiny::actionLink("about_fc", NULL, icon = shiny::icon("info-circle"), style = "text-decoration:none;")
)
)
),
shiny::column(width = 7, align = "center",
plotDownloadInputUI("is_ratio_plot",
shiny::tags$span(
"Insulin Secretion Results",
shiny::actionLink("about_lm", NULL, icon = shiny::icon("info-circle"), style = "text-decoration:none;")
)
)
)
),
shiny::fluidRow(style = "padding-top: 1em;",
shiny::column(width = 12, align = "center",
plotDownloadInputUI("is_plot", "Insulin Secretion")
)
)
)
)
),
## Outliers tab ----------------------------------------------------------------------------------
shiny::tabPanel(title = "Outliers", value = "outliers-tab",
card(title = shiny::tags$h4("Outliers List"), DT::dataTableOutput("outliers"))
)
)
# Server-side ======================================================================================
server <- function(input, output, session) {
shiny::observeEvent(input[["about_fc"]], {
shiny::showModal(shiny::modalDialog(
title = 'Threshold to Define "Secretion"',
shiny::tags$p(
'High/low glucose threshold above which cells are allegedly secreting insulin.',
shiny::tags$br(),
"For each experiments",
"(", shiny::tags$i("i.e.", .noWS = "outside"), ", an Excel spreadsheet)",
"cells are considered not secreting insulin in", shiny::tags$code("Reference"),
"(", shiny::tags$code('Type = "Reference"', .noWS = "outside"), ")",
"when the mean of the optical density measurements for a", shiny::tags$code("Condition"),
"in a", shiny::tags$code("Step"), "is strictly below the defined threshold."
),
easyClose = TRUE
))
})
shiny::observeEvent(input[["about_lm"]], {
shiny::showModal(shiny::modalDialog(
title = "Analysis Method",
shiny::tags$p(
'Comparisons have been performed using linear regression with',
shiny::tags$code("Date"),
'and',
shiny::tags$code("Operator"),
'as covariate, if needed.'
),
easyClose = TRUE
))
})
shiny::observe({
shiny::req(
input[["plot_dpi"]], input[["plot_height"]], input[["plot_dpi"]],
od_box_plot(), od_density_plot(), od_lm_box_plot(), od_lm_line_plot()
)
purrr::walk2(
.x = list(
"od_box_plot", "od_density_plot", "od_lm_box_plot", "od_lm_line_plot"
),
.y = list(
od_box_plot(), od_density_plot(), od_lm_box_plot(), od_lm_line_plot()
),
.f = function(.x, .y) {
plotDownloadInput(
id = .x, plot_object = .y,
width = input[["plot_width"]] %||% 16,
height = input[["plot_height"]] %||% 12,
dpi = input[["plot_dpi"]] %||% 120
)
}
)
})
shiny::observe({
shiny::req(
input[["targets_list"]], input[["experiments_list"]],
input[["plot_dpi"]], input[["plot_height"]], input[["plot_dpi"]],
input[["fold_change"]], input[["font_size"]],
is_ratio_distribution_plot(), is_plot(), is_ratio_plot()
)
purrr::walk2(
.x = list("is_ratio_distribution_plot", "is_plot", "is_ratio_plot"),
.y = list(is_ratio_distribution_plot(), is_plot(), is_ratio_plot()),
.f = function(.x, .y) {
plotDownloadInput(
id = .x, plot_object = .y,
width = input[["plot_width"]] %||% 16,
height = input[["plot_height"]] %||% 12,
dpi = input[["plot_dpi"]] %||% 120
)
}
)
})
shiny::observe({
if (length(xlsx_available()[["file"]]) == 0) {
purrr::map(
.x = c("blank", "is_analysis", "outliers"),
.f = ~ shiny::hideTab("main_menu", target = paste0(.x, "-tab"))
)
} else {
purrr::map(
.x = c("blank", "is_analysis"),
.f = ~ shiny::showTab("main_menu", target = paste0(.x, "-tab"))
)
if (nrow(outliers_list()) == 0) {
shiny::hideTab("main_menu", target = "outliers-tab")
} else {
shiny::showTab("main_menu", target = "outliers-tab")
}
}
})
ggplot2_theme <- shiny::reactive({
package_theme <- strsplit(input[["ggplot2_theme"]], "::")[[1]]
f <- utils::getFromNamespace(package_theme[2], package_theme[1])
f(base_size = input[["font_size"]])
})
ggplot2_colour <- shiny::reactive({
if (input[["colour_scale"]] == "Grey") {
ggplot2::scale_colour_grey(
labels = (function(x) gsub(".*: ", "", x)),
start = input[["colour_scale_range"]][1],
end = input[["colour_scale_range"]][2]
)
} else {
ggplot2::scale_colour_viridis_d(
labels = (function(x) gsub(".*: ", "", x)),
option = tolower(input[["colour_scale"]]),
begin = input[["colour_scale_range"]][1],
end = input[["colour_scale_range"]][2]
)
}
})
ggplot2_fill <- shiny::reactive({
if (input[["colour_scale"]] == "Grey") {
ggplot2::scale_fill_grey(
labels = (function(x) gsub(".*: ", "", x)),
start = input[["colour_scale_range"]][1],
end = input[["colour_scale_range"]][2]
)
} else {
ggplot2::scale_fill_viridis_d(
labels = (function(x) gsub(".*: ", "", x)),
option = tolower(input[["colour_scale"]]),
begin = input[["colour_scale_range"]][1],
end = input[["colour_scale_range"]][2]
)
}
})
## Upload tab ------------------------------------------------------------------------------------
output$template <- shiny::downloadHandler(
filename = function() "insane_results_template.xlsx",
content = function(file) file.copy(file.path("www", "template.xlsx"), file, overwrite = TRUE)
)
output$protocol <- shiny::downloadHandler(
filename = function() "insane_experimental_protocol.docx",
content = function(file) file.copy(file.path("www", "protocol.docx"), file, overwrite = TRUE)
)
xlsx_contents_summary <- shiny::reactive({
if (!is.null(input[["xlsx_files"]]) && nrow(input[["xlsx_files"]]) > 0) {
res_copy <- purrr::pmap(input[["xlsx_files"]], function(name, size, type, datapath) {
file.copy(datapath, to = file.path("www", "xlsx", name), overwrite = TRUE)
})
xlsx_size <- sum(input$xlsx_files[, "size"])
class(xlsx_size) <- "object_size"
shiny::tags$p(
"A total of", shiny::tags$strong(length(input$xlsx_files[, "name"])),
if (nrow(input$xlsx_files) > 1) {
"Excel files were succesfully uploaded,"
} else {
"Excel file was succesfully uploaded,"
},
"for a total amount of", shiny::tags$strong(format(xlsx_size, units = "Kb"), .noWS = "after"), "."
)
}
})
output$xlsx_contents_summary <- shiny::renderUI({ shiny::req(xlsx_contents_summary()) })
xlsx_available <- shiny::reactive({
uploaded_files <- xlsx_contents_summary()
dplyr::tibble(file = list.files(path = file.path("www", "xlsx"), pattern = ".xlsx$", full.names = TRUE)) %>%
dplyr::mutate(sheet_name = purrr::map(.data[["file"]], readxl::excel_sheets)) %>%
tidyr::unnest(.data[["sheet_name"]]) %>%
dplyr::mutate(
Project = purrr::map2_chr(.data[["file"]], .data[["sheet_name"]], function(.x, .y) {
suppressMessages({
unique(readxl::read_xlsx(.x, .y)[["Project"]])
})
}),
filename = basename(.data[["file"]])
) %>%
dplyr::group_by(.data[["Project"]], .data[["filename"]], .data[["file"]]) %>%
dplyr::summarise(
sheet_name = glue::glue_collapse(.data[["sheet_name"]], sep = ", ", last = " and "),
.groups = "drop_last"
) %>%
dplyr::ungroup()
})
output$xlsx_available <- DT::renderDataTable({
dplyr::select(shiny::req(xlsx_available()),
c("Project", "File" = "filename", "Sheet" = "sheet_name")
)
})
xlsx_contents <- shiny::reactive({
id <- shiny::showNotification(
ui = "Data are loading, please wait ...",
duration = NULL, closeButton = FALSE
)
on.exit(shiny::removeNotification(id), add = TRUE)
if (length(xlsx_available()[["file"]]) != 0) {
get_xlsx_contents(
files = xlsx_available()[["file"]],
od_outlier = input[["od_outlier"]] %||% 3,
lm_outlier = input[["lm_outlier"]] %||% 1.5,
project_name = input[["project_name"]] %||% NULL
)
}
})
output$project_ui <- shiny::renderUI({
shiny::selectInput("project_name", "Available Projects",
choices = unique(xlsx_available()[["Project"]]),
selected = shiny::isolate(input[["project_name"]]),
width = "90%",
selectize = FALSE,
multiple = FALSE
)
})
output$upload_ui <- shiny::renderUI({
list(
if (!is.null(input$xlsx_files)) {
list(
shiny::fluidRow(style = "padding-top: 1em;",
shiny::column(width = 12,
card(title = "Excel Files Uploaded", body = shiny::uiOutput("xlsx_contents_summary"))
)
)
)
},
shiny::fluidRow(style = "padding-top: 1em;",
shiny::column(width = 12,
card(title = "Experiments Available", body = DT::dataTableOutput("xlsx_available"))
)
)
)
})
## Blank tab -------------------------------------------------------------------------------------
od_box_plot <- shiny::reactive({
shiny::req(xlsx_contents())
ggplot2::ggplot(
data = dplyr::bind_rows(xlsx_contents(), dplyr::mutate(xlsx_contents(), Step = "ALL")),
mapping = ggplot2::aes(x = .data[["Step"]], y = .data[["re_OD"]], colour = .data[["Step"]])
) +
ggplot2_theme() +
ggplot2::geom_rect(
data = ~ .x %>%
dplyr::distinct(.data[["lower_threshold"]], .data[["upper_threshold"]]) %>%
tidyr::pivot_longer(cols = c("lower_threshold", "upper_threshold")) %>%
dplyr::mutate(
ymin = ifelse(grepl("lower", .data[["name"]]), -Inf, .data[["value"]]),
ymax = ifelse(grepl("upper", .data[["name"]]), Inf, .data[["value"]])
),
mapping = ggplot2::aes(xmin = -Inf, xmax = Inf, ymin = .data[["ymin"]], ymax = .data[["ymax"]]),
fill = "firebrick2",
alpha = 0.2,
colour = "transparent",
inherit.aes = FALSE,
linetype = 2
) +
ggplot2::geom_hline(
data = ~ .x %>%
dplyr::distinct(.data[["lower_threshold"]], .data[["upper_threshold"]]) %>%
tidyr::pivot_longer(cols = c("lower_threshold", "upper_threshold")),
mapping = ggplot2::aes(yintercept = .data[["value"]]),
colour = "firebrick2",
linetype = 2
) +
ggplot2::geom_hline(yintercept = 0, linetype = 2) +
ggplot2::geom_boxplot(outlier.shape = NA, alpha = 0.2) +
ggplot2::geom_point(
data = ~ dplyr::filter(.x, .data[["is_outlier_OD"]]),
colour = "firebrick2",
size = input[["point_size"]],
position = ggplot2::position_jitter(width = 0.6)
) +
ggplot2::geom_point(
data = ~ dplyr::filter(.x, !.data[["is_outlier_OD"]]),
shape = 1,
size = input[["point_size"]],
position = ggplot2::position_jitter(width = 0.6)
) +
ggplot2::scale_y_continuous(labels = percent) +
ggplot2_colour() +
ggplot2_fill() +
ggplot2::labs(
x = NULL,
y = bquote("Relative Error:"~frac((OD[2] - OD[1]), OD[1]))
) +
ggplot2::theme(legend.position = "none")
})
od_density_plot <- shiny::reactive({
shiny::req(xlsx_contents())
ggplot2::ggplot(
data = xlsx_contents(),
mapping = ggplot2::aes(x = .data[["re_OD"]], colour = .data[["Step"]], fill = .data[["Step"]])
) +
ggplot2_theme() +
ggplot2::geom_rect(
data = ~ .x %>%
dplyr::distinct(.data[["lower_threshold"]], .data[["upper_threshold"]]) %>%
tidyr::pivot_longer(cols = c("lower_threshold", "upper_threshold")) %>%
dplyr::mutate(
xmin = ifelse(grepl("lower", .data[["name"]]), -Inf, .data[["value"]]),
xmax = ifelse(grepl("upper", .data[["name"]]), Inf, .data[["value"]])
),
mapping = ggplot2::aes(xmin = .data[["xmin"]], xmax = .data[["xmax"]], ymin = -Inf, ymax = Inf),
fill = "firebrick2",
alpha = 0.2,
colour = "transparent",
inherit.aes = FALSE,
linetype = 2
) +
ggplot2::geom_vline(
data = ~ .x %>%
dplyr::distinct(.data[["lower_threshold"]], .data[["upper_threshold"]]) %>%
tidyr::pivot_longer(cols = c("lower_threshold", "upper_threshold")),
mapping = ggplot2::aes(xintercept = .data[["value"]]),
colour = "firebrick2",
linetype = 2
) +
ggplot2::geom_vline(xintercept = 0, linetype = 2) +
ggplot2::geom_density(alpha = 0.2) +
ggplot2::geom_density(mapping = ggplot2::aes(colour = "ALL", fill = "ALL"), alpha = 0.2) +
ggplot2::scale_x_continuous(labels = percent, expand = ggplot2::expansion(mult = c(0, 0))) +
ggplot2::scale_y_continuous(expand = ggplot2::expansion(mult = c(0, 0.05))) +
ggplot2_colour() +
ggplot2_fill() +
ggplot2::labs(
x = bquote("Relative Error:"~frac((OD[2] - OD[1]), OD[1])),
y = "Density",
colour = NULL,
fill = NULL
)
})
od_lm_box_plot <- shiny::reactive({
shiny::req(xlsx_contents())
ggplot2::ggplot(
data = xlsx_contents() %>%
dplyr::select("filename", dplyr::matches("_Intercept|_Slope")) %>%
dplyr::distinct() %>%
tidyr::pivot_longer(
cols = -c("filename"),
names_to = c(".value", "term"),
names_pattern = "(.*)_([^_]*)",
),
mapping = ggplot2::aes(x = .data[["term"]], y = .data[["estimate"]], group = .data[["term"]])
) +
ggplot2_theme() +
ggplot2::geom_rect(
data = ~ .x %>%
dplyr::distinct(.data[["term"]], .data[["lower_threshold"]], .data[["upper_threshold"]]) %>%
tidyr::pivot_longer(cols = c("lower_threshold", "upper_threshold")) %>%
dplyr::mutate(
ymin = ifelse(grepl("lower", .data[["name"]]), -Inf, .data[["value"]]),
ymax = ifelse(grepl("upper", .data[["name"]]), Inf, .data[["value"]])
),
mapping = ggplot2::aes(xmin = -Inf, xmax = Inf, ymin = .data[["ymin"]], ymax = .data[["ymax"]]),
fill = "firebrick2",
alpha = 0.2,
colour = "transparent",
inherit.aes = FALSE,
linetype = 2
) +
ggplot2::geom_hline(
data = ~ .x %>%
dplyr::distinct(.data[["term"]], .data[["lower_threshold"]], .data[["upper_threshold"]]) %>%
tidyr::pivot_longer(cols = c("lower_threshold", "upper_threshold")),
mapping = ggplot2::aes(yintercept = .data[["value"]]),
colour = "firebrick2",
linetype = 2
) +
ggplot2::geom_boxplot(outlier.shape = NA, alpha = 0.2) +
ggplot2::geom_point(
data = ~ dplyr::filter(.x, .data[["is_outlier"]]),
colour = "firebrick2",
size = input[["point_size"]],
position = ggplot2::position_jitter(width = 0.6)
) +
ggplot2::geom_point(
data = ~ dplyr::filter(.x, !.data[["is_outlier"]]),
mapping = ggplot2::aes(colour = .data[["filename"]]),
shape = 1,
size = input[["point_size"]],
position = ggplot2::position_jitter(width = 0.6)
) +
ggplot2_colour() +
ggplot2::labs(x = NULL, y = "Estimate") +
ggplot2::facet_wrap(facets = ggplot2::vars(.data[["term"]]), scales = "free") +
ggplot2::theme(axis.text.x = ggplot2::element_blank()) +
ggplot2::theme(
legend.position = "none",
panel.grid.major.x = ggplot2::element_blank(),
axis.ticks.x = ggplot2::element_blank()
)
})
od_lm_line_plot <- shiny::reactive({
shiny::req(xlsx_contents())
ggplot2::ggplot(
data = xlsx_contents() %>%
dplyr::filter(.data[["Step"]] == "BLANK" & .data[["Concentration (µg/L)"]] != 0),
mapping = ggplot2::aes(
x = .data[["Concentration (µg/L)"]],
y = .data[["normalised_OD"]],
colour = .data[["filename"]]
)
) +
ggplot2_theme() +
ggplot2::geom_point(
data = ~ dplyr::filter(.x, !(.data[["is_outlier_OD"]] | .data[["is_outlier_Intercept"]] | .data[["is_outlier_Slope"]])),
shape = 1,
size = input[["point_size"]]
) +
ggplot2::geom_smooth(
data = ~ dplyr::filter(.x, !(.data[["is_outlier_OD"]] | .data[["is_outlier_Intercept"]] | .data[["is_outlier_Slope"]])),
method = "lm", se = FALSE, formula = y ~ x
) +
ggplot2::geom_point(
data = ~ dplyr::filter(.x, (.data[["is_outlier_OD"]] | .data[["is_outlier_Intercept"]] | .data[["is_outlier_Slope"]])),
colour = "firebrick2",
size = input[["point_size"]]
) +
ggplot2::geom_smooth(
data = ~ dplyr::filter(.x, (.data[["is_outlier_OD"]] | .data[["is_outlier_Intercept"]] | .data[["is_outlier_Slope"]])),
colour = "firebrick2",
method = "lm", se = FALSE, formula = y ~ x
) +
ggplot2_colour() +
ggplot2::scale_x_log10() +
ggplot2::scale_y_log10() +
ggplot2::labs(
x = "Concentration (µg/L)",
y = "Normalised Optical Density (OD)"
) +
ggplot2::theme(legend.position = "none")
})
## Analysis tab ----------------------------------------------------------------------------------
output$target_ui <- shiny::renderUI({
xlsx_contents_subset <- dplyr::filter(shiny::req(xlsx_contents()), Step != "BLANK")
shiny::selectInput("targets_list", "Available Files",
choices = unique(xlsx_contents_subset[["filename"]]),
selected = unique(xlsx_contents_subset[["filename"]]),
width = "100%",
selectize = FALSE,
multiple = TRUE,
size = 10
)
})
output$experiment_ui <- shiny::renderUI({
experiments_list <- shiny::req(xlsx_contents()) %>%
dplyr::mutate(experiment_file = glue::glue("{Target} ({filename})")) %>%
dplyr::filter(
.data[["filename"]] %in% shiny::req(input[["targets_list"]]),
!.data[["Step"]] %in% "BLANK"
)
shiny::selectInput("experiments_list", "Available Experiments",
choices = unique(experiments_list[["experiment_file"]]),
selected = unique(experiments_list[["experiment_file"]]),
width = "100%",
selectize = FALSE,
multiple = TRUE,
size = 10
)
})
xlsx_contents_selected <- shiny::reactive({
shiny::req(xlsx_contents())
experiments_list <- xlsx_contents() %>%
dplyr::filter(
.data[["filename"]] %in% input[["targets_list"]],
!.data[["Step"]] %in% "BLANK"
)
dplyr::full_join(
x = experiments_list,
y = experiments_list %>%
dplyr::filter(Type %in% "Reference") %>%
dplyr::group_by(.data[["filename"]]) %>%
dplyr::summarise(
is_reference_good = mean(.data[["fc_SUPERNATANT2_SUPERNATANT1"]], na.rm = TRUE) >= input[["fold_change"]],
.groups = "drop_last"
) %>%
dplyr::ungroup() %>%
dplyr::select(c("filename", "is_reference_good")),
by = "filename"
) %>%
dplyr::mutate(
experiment_file = glue::glue("{Target} ({filename})"),
keep = .data[["experiment_file"]] %in% !!input[["experiments_list"]]
)
})
is_ratio_distribution_plot <- shiny::reactive({
shiny::req(xlsx_contents_selected())
shiny::req(length(intersect(input[["experiments_list"]], xlsx_contents_selected()[["experiment_file"]])) != 0)
xlsx_contents_selected <- dplyr::filter(xlsx_contents_selected(), !.data[["is_any_outlier"]])
if (nrow(xlsx_contents_selected) == 0) {
return(
ggplot2::ggplot() +
ggplot2_theme() +
ggplot2::labs(
x = NULL,
y = bquote(atop("Insulin Secretion", group("(", "High" / "Low Glucose", ")"))),
colour = NULL,
fill = NULL
) +
ggplot2::annotate(
"text", x = 0.5, y = 0.5, label = "Not available!",
angle = 30, size = 24, colour = "red", alpha = 0.25
) +
ggplot2::theme(axis.text = ggplot2::element_blank())
)
}
fc_threshold <- input[["fold_change"]]
gg_data <- xlsx_contents_selected %>%
dplyr::filter(
.data[["Type"]] %in% "Reference",
!.data[["is_any_outlier"]],
.data[["Step"]] %in% "SUPERNATANT2"
) %>%
dplyr::select(c("filename", "Type_Target", "Condition", "fc_SUPERNATANT2_SUPERNATANT1")) %>%
dplyr::distinct() %>%
dplyr::mutate(facet_file = gsub(".xlsx$", "", gsub("_", "\n", .data[["filename"]])))
ggplot2::ggplot(
data = gg_data,
mapping = ggplot2::aes(
x = .data[["Type_Target"]],
y = .data[["fc_SUPERNATANT2_SUPERNATANT1"]]
)
) +
ggplot2_theme() +
ggplot2::geom_rect(
data = dplyr::tibble(ymax = fc_threshold),
mapping = ggplot2::aes(xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = .data[["ymax"]]),
fill = "firebrick2",
alpha = 0.2,
colour = "transparent",
inherit.aes = FALSE,
linetype = 2
) +
ggplot2::geom_hline(
data = dplyr::tibble(yintercept = fc_threshold),
mapping = ggplot2::aes(yintercept = yintercept),
colour = "firebrick2",
linetype = 2
) +
ggplot2::geom_boxplot(alpha = 0.2, width = 0.5, outlier.shape = NA) +
ggplot2::geom_violin(alpha = 0.2) +
ggplot2::geom_point(
mapping = ggplot2::aes(
colour = .data[["Condition"]],
fill = .data[["Condition"]]
),
size = input[["point_size"]],
shape = 1,
position = ggplot2::position_jitter(width = 0.6)
) +
ggplot2::scale_x_discrete(labels = (function(x) gsub(".*: ", "", x))) +
ggplot2::scale_y_continuous(limits = c(0, NA), expand = ggplot2::expansion(mult = c(0, 0.05))) +
ggplot2_colour() +
ggplot2_fill() +
ggplot2::labs(
x = NULL,
y = bquote(atop("Insulin Secretion", group("(", "High" / "Low Glucose", ")"))),
colour = "Condition",
fill = "Condition",
caption = if (all(xlsx_contents_selected[["is_reference_good"]])) {
NULL
} else {
"Warning: Reference is not secreting insulin in one or several experiments!"
}
) +
ggplot2::theme(plot.caption = ggplot2::element_text(colour = "firebrick2"))
})
is_od_plot <- shiny::reactive({
shiny::req(xlsx_contents_selected())
shiny::req(length(intersect(input[["experiments_list"]], xlsx_contents_selected()[["experiment_file"]])) != 0)
xlsx_contents_selected <- dplyr::filter(xlsx_contents_selected(), .data[["keep"]] & !.data[["is_any_outlier"]])
if (nrow(xlsx_contents_selected) == 0) {
return(
ggplot2::ggplot() +
ggplot2_theme() +
ggplot2::labs(
x = NULL,
y = "Normalised Optical Density\n(OD)"
) +
ggplot2::annotate(
"text", x = 0.5, y = 0.5, label = "Not available!",
angle = 30, size = 24, colour = "red", alpha = 0.25
) +
ggplot2::theme(axis.text = ggplot2::element_blank())
)
}
ggplot2::ggplot(
data = xlsx_contents_selected %>%
dplyr::select(c("Sample", "Step", "Type_Target", "normalised_OD", "Date", "Operator")) %>%
dplyr::distinct(),
mapping = ggplot2::aes(
x = paste0(.data[["Step"]], "\n", .data[["Sample"]]),
y = .data[["normalised_OD"]],
colour = .data[["Type_Target"]],
fill = .data[["Type_Target"]]
)
) +
ggplot2_theme() +
{
if (input[["use_boxplot"]] == "Boxplot") {
list(
ggplot2::geom_boxplot(
outlier.shape = NA,
alpha = 0.2,
position = ggplot2::position_dodge(width = 0.9),
na.rm = TRUE
),
ggplot2::geom_point(
shape = 1,
size = input[["point_size"]],
position = ggplot2::position_jitterdodge(dodge.width = 0.9, jitter.width = 0.25),
na.rm = TRUE
)
)
} else {
list(
ggplot2::geom_errorbar(
stat = "summary",
fun.data = "mean_se",
position = ggplot2::position_dodge(width = 0.9),
width = 0.25,
show.legend = FALSE,
na.rm = TRUE
),
ggplot2::geom_bar(stat = "summary", fun.y = mean, position = ggplot2::position_dodge(width = 0.9)),
ggplot2::geom_label(
mapping = ggplot2::aes(group = .data[["Type_Target"]]),
stat = "summary",
fun.data = function(x) {
x <- stats::na.omit(x)
se <- sqrt(stats::var(x)/length(x))
mean <- mean(x)
data.frame(y = mean, label = length(x))
},
position = ggplot2::position_dodge(width = 0.9),
fill = "white",
colour = "black",
show.legend = FALSE,
vjust = 1.25
),
ggplot2::scale_y_continuous(expand = ggplot2::expansion(mult = c(0, 0.05)))
)
}
} +
ggplot2_colour() +
ggplot2_fill() +
ggplot2::labs(
x = NULL,
y = "Normalised Optical Density\n(OD)",
colour = NULL,
fill = NULL,
caption = if (all(xlsx_contents_selected[["is_reference_good"]])) {
NULL
} else {
"Warning: Reference is not secreting insulin in one or several experiments!"
}
) +
ggplot2::theme(plot.caption = ggplot2::element_text(colour = "firebrick2"))
})
is_percent_plot <- shiny::reactive({
shiny::req(xlsx_contents_selected())
shiny::req(length(intersect(input[["experiments_list"]], xlsx_contents_selected()[["experiment_file"]])) != 0)
xlsx_contents_selected <- dplyr::filter(xlsx_contents_selected(), .data[["keep"]] & !.data[["is_any_outlier"]])
if (nrow(xlsx_contents_selected) == 0) {
return(
ggplot2::ggplot() +
ggplot2_theme() +
ggplot2::labs(
x = NULL,
y = "Insulin Secretion\n(% of content)",
colour = NULL,
fill = NULL
) +
ggplot2::annotate(
"text", x = 0.5, y = 0.5, label = "Not available!",
angle = 30, size = 24, colour = "red", alpha = 0.25
) +
ggplot2::theme(axis.text = ggplot2::element_blank())
)
}
ggplot2::ggplot(
data = xlsx_contents_selected %>%
dplyr::filter(Step %in% c("SUPERNATANT1", "SUPERNATANT2")) %>%
dplyr::select(c("Sample", "Type_Target", "Insulin Secretion (% of content)", "Date", "Operator")) %>%
dplyr::distinct(),
mapping = ggplot2::aes(
x = .data[["Sample"]],
y = .data[["Insulin Secretion (% of content)"]],
colour = .data[["Type_Target"]],
fill = .data[["Type_Target"]]
)
) +
ggplot2_theme() +
{
if (input[["use_boxplot"]] == "Boxplot") {
list(
ggplot2::geom_boxplot(
outlier.shape = NA,
alpha = 0.2,
position = ggplot2::position_dodge(width = 0.9),
na.rm = TRUE
),
ggplot2::geom_point(
shape = 1,
size = input[["point_size"]],
position = ggplot2::position_jitterdodge(dodge.width = 0.9, jitter.width = 0.25),
na.rm = TRUE
),
ggplot2::scale_y_continuous(labels = percent)
)
} else {
list(
ggplot2::geom_errorbar(
stat = "summary",
fun.data = "mean_se",
position = ggplot2::position_dodge(width = 0.9),
width = 0.25,
show.legend = FALSE,
na.rm = TRUE
),
ggplot2::geom_bar(stat = "summary", fun.y = mean, position = ggplot2::position_dodge(width = 0.9)),
ggplot2::geom_label(
mapping = ggplot2::aes(group = .data[["Type_Target"]]),
stat = "summary",
fun.data = function(x) {
x <- stats::na.omit(x)
se <- sqrt(stats::var(x)/length(x))
mean <- mean(x)
data.frame(y = mean, label = length(x))
},
position = ggplot2::position_dodge(width = 0.9),
fill = "white",
colour = "black",
show.legend = FALSE,
vjust = 1.25
),
ggplot2::scale_y_continuous(
labels = percent,
expand = ggplot2::expansion(mult = c(0, 0.05))
)
)
}
} +
ggplot2_colour() +
ggplot2_fill() +
ggplot2::labs(
x = NULL,
y = "Insulin Secretion\n(% of content)",
colour = NULL,
fill = NULL,
caption = if (all(xlsx_contents_selected[["is_reference_good"]])) {
NULL
} else {
"Warning: Reference is not secreting insulin in one or several experiments!"
}
) +
ggplot2::theme(plot.caption = ggplot2::element_text(colour = "firebrick2"))
})
is_plot <- shiny::reactive({
patchwork::wrap_plots(
is_od_plot() + ggplot2::theme(legend.direction = "horizontal"),
is_percent_plot() + ggplot2::theme(legend.direction = "horizontal"),
nrow = 1, ncol = 2, guides = "collect"
) +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = "top"))
})
is_ratio_plot <- shiny::reactive({
shiny::req(xlsx_contents_selected())
shiny::req(length(intersect(input[["experiments_list"]], xlsx_contents_selected()[["experiment_file"]])) != 0)
xlsx_contents_selected <- dplyr::filter(xlsx_contents_selected(), .data[["keep"]] & !.data[["is_any_outlier"]])
if (nrow(xlsx_contents_selected) == 0) {
return(
ggplot2::ggplot() +
ggplot2_theme() +
ggplot2::labs(
x = NULL,
y = bquote(atop("Insulin Secretion", group("(", "High" / "Low Glucose", ")")))
) +
ggplot2::annotate(
"text", x = 0.5, y = 0.5, label = "Not available!",
angle = 30, size = 24, colour = "red", alpha = 0.25
) +
ggplot2::theme(axis.text = ggplot2::element_blank())
)
}
gg_data <- xlsx_contents_selected %>%
tidyr::drop_na(.data[["Type"]], .data[["Target"]]) %>%
dplyr::select(c("Condition", "Type_Target", "fc_SUPERNATANT2_SUPERNATANT1", "Date", "Operator")) %>%
dplyr::distinct() %>%
tidyr::drop_na(.data[["fc_SUPERNATANT2_SUPERNATANT1"]])
if (length(unique(gg_data[["Type_Target"]])) > 1) {
lm_data <- gg_data %>%
dplyr::group_by(.data[["Condition"]]) %>%
tidyr::nest() %>%
dplyr::ungroup() %>%
dplyr::mutate(
lm = purrr::map(.x = .data[["data"]], .f = function(data) {
if (length(unique(data[["Type_Target"]])) > 1) {
purrr::map2_df(
.x = utils::combn(levels(droplevels(data[["Type_Target"]])), 2, simplify = FALSE),
.y = list(data),
.f = function(x, data) {
mult <- 1.5
splitted_data <- dplyr::filter(data, .data[["Type_Target"]] %in% x)
if (input[["use_boxplot"]] == "Boxplot") {
mean_se_fc <- splitted_data %>%
dplyr::group_by(.data[["Type_Target"]]) %>%
dplyr::summarise(
mean_se = max(.data[["fc_SUPERNATANT2_SUPERNATANT1"]]),
.groups = "drop_last"
) %>%
dplyr::ungroup()
} else {
mean_se_fc <- splitted_data %>%
dplyr::group_by(.data[["Type_Target"]]) %>%
dplyr::summarise(
mean_se = mean(.data[["fc_SUPERNATANT2_SUPERNATANT1"]]) +
sqrt(stats::var(.data[["fc_SUPERNATANT2_SUPERNATANT1"]]) / length(.data[["fc_SUPERNATANT2_SUPERNATANT1"]])),
.groups = "drop_last"
) %>%
dplyr::ungroup()
}
default_formula <- fc_SUPERNATANT2_SUPERNATANT1 ~ Type_Target
if (length(unique(splitted_data[["Date"]])) > 1) {
splitted_data[["Date"]] <- as.factor(splitted_data[["Date"]])
default_formula <- stats::update.formula(default_formula, . ~ . + Date)
}
if (length(unique(splitted_data[["Operator"]])) > 1) {
splitted_data[["Operator"]] <- as.factor(splitted_data[["Operator"]])
default_formula <- stats::update.formula(default_formula, . ~ . + Operator)
}
stats::lm(default_formula, data = splitted_data) %>%
broom::tidy() %>%
dplyr::filter(grepl("Type_Target", .data[["term"]])) %>%
dplyr::mutate(
group1 = levels(droplevels(splitted_data[["Type_Target"]]))[1],
group2 = levels(droplevels(splitted_data[["Type_Target"]]))[2],
y_position = max(mean_se_fc[["mean_se"]]),
term = NULL
)
}
) %>%
dplyr::mutate(dplyr::across(
.cols = dplyr::num_range("group", 1:2),
.fns = ~ factor(.x, levels = levels(data[["Type_Target"]]))
))
}
}),
data = NULL
) %>%
tidyr::unnest("lm") %>%
dplyr::group_by(.data[["Condition"]]) %>%
dplyr::mutate(
group = 1:dplyr::n(),
y_position = max(.data[["y_position"]]),
y_position = .data[["y_position"]] + c(0.5 * .data[["group"]]),
annotations = paste("p =", format.pval(.data[["p.value"]], digits = 3))
) %>%
dplyr::ungroup() %>%
tidyr::drop_na(.data[["p.value"]])
}
ggplot2::ggplot(
data = gg_data,
mapping = ggplot2::aes(
x = .data[["Type_Target"]],
y = .data[["fc_SUPERNATANT2_SUPERNATANT1"]],
colour = .data[["Type_Target"]],
fill = .data[["Type_Target"]],
group = .data[["Type_Target"]]
)
) +
ggplot2_theme() +
{
if (input[["use_boxplot"]] == "Boxplot") {
list(
ggplot2::geom_boxplot(
outlier.shape = NA,
alpha = 0.2,
position = ggplot2::position_dodge(width = 0.9),
na.rm = TRUE
),
ggplot2::geom_point(
shape = 1,
size = input[["point_size"]],
position = ggplot2::position_jitterdodge(dodge.width = 0.9, jitter.width = 0.25),
na.rm = TRUE
)
)
} else {
list(
ggplot2::geom_errorbar(
stat = "summary",
fun.data = "mean_se",
position = ggplot2::position_dodge(width = 0.9),
width = 0.25,
show.legend = FALSE,
na.rm = TRUE
),
ggplot2::geom_bar(stat = "summary", fun.y = mean, position = ggplot2::position_dodge(width = 0.9)),
ggplot2::geom_label(
stat = "summary",
fun.data = function(x) {
x <- stats::na.omit(x)
se <- sqrt(stats::var(x)/length(x))
mean <- mean(x)
data.frame(y = mean, label = length(x))
},
position = ggplot2::position_dodge(width = 0.9),
fill = "white",
colour = "black",
show.legend = FALSE,
vjust = 1.25
),
ggplot2::scale_y_continuous(expand = ggplot2::expansion(mult = c(0, 0.05)))
)
}
} +
ggplot2_colour() +
ggplot2_fill() +
ggplot2::scale_x_discrete(labels = (function(x) gsub(".*: ", "", x))) +
ggplot2::labs(
x = NULL,
y = bquote(atop("Insulin Secretion", group("(", "High" / "Low Glucose", ")"))),
colour = NULL,
fill = NULL,
caption = if (all(xlsx_contents_selected[["is_reference_good"]])) {
NULL
} else {
"Warning: Reference is not secreting insulin in one or several experiments!"
}
) +
{
if (length(unique(gg_data[["Type_Target"]])) > 1 && nrow(lm_data) > 0) {
ggpubr::geom_signif(
data = dplyr::mutate(lm_data, group = 1:dplyr::n()),
mapping = ggplot2::aes(
y_position = .data[["y_position"]],
xmin = .data[["group1"]], xmax = .data[["group2"]],
annotations = .data[["annotations"]],
group = .data[["group"]]
),
manual = TRUE,
tip_length = 0,
inherit.aes = FALSE
)
}
} +
ggplot2::facet_grid(cols = ggplot2::vars(!!ggplot2::sym("Condition"))) +
ggplot2::theme(legend.position = "none") +
ggplot2::theme(plot.caption = ggplot2::element_text(colour = "firebrick2"))
})
shiny::observeEvent(input[["show_issues"]], {
shiny::showModal(shiny::modalDialog(size = "l", easyClose = TRUE,
title = "Issues Detected in the Selected Experiments",
{
list_issues <- get_outliers(dplyr::filter(xlsx_contents_selected(), .data[["keep"]]), input[["fold_change"]])
if (nrow(list_issues)==0) {
shiny::tags$p("No issues currently detected in the selected experiments.")
} else {
DT::renderDataTable({ list_issues })
}
}
))
})
## Outliers tab ----------------------------------------------------------------------------------
outliers_list <- shiny::reactive({
get_outliers(shiny::req(xlsx_contents()), input[["fold_change"]])
})
output$outliers <- DT::renderDataTable({ outliers_list() })
}
shiny::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.