library(shiny)
library(magrittr)
show_browser <- TRUE
# for accessing data from spex upload location
data_location <- "/data/private/shiny_scripts/spex_upload/inst/extdata/"
#data_location <- "inst/extdata/"
folders <- basename(list.dirs(data_location))
available_datasets <- folders[folders != "extdata"]
sample_names <- "sample_name"
bab_light_blue <- "#00aeef"
bab_dark_blue <- "#1d305f"
appCSS <- "
#loading-content {
position: absolute;
background: #000000;
opacity: 0.9;
z-index: 100;
left: 0;
right: 0;
height: 100%;
text-align: center;
color: #FFFFFF;
}
"
# UI ----
ui <- tagList(
#bootstrapDep,
fluidPage(
shinyFeedback::useShinyFeedback(),
shinyjs::useShinyjs(),
shinyjs::inlineCSS(appCSS),
tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "styles.css"),
HTML('<link rel="icon" type="image/jpg" href = "images/spex_logo_rotated.png"/>'),
#tags$script(src = "script.js"),
tags$script(
# "var exploreText = document.getElementById('explore');
# exploreText.style.backgroundColor = 'red';"
"$(document).on('shiny:connected', function() {
Shiny.setInputValue('pre_chosen_dataset', document.location.hash, {priority: 'event'});
})"
)
),
theme = bslib::bs_theme(
bg = bab_dark_blue,
fg = "white",
primary = bab_light_blue,
secondary = bab_light_blue
),
titlePanel(
tags$img(
src = "images/BI_logo_grey.png",
style="margin-top: -10px; padding-right:10px; padding-bottom:10px",
width = "80",
height = "85",
align = "right"
),
windowTitle="spex"
),
br(),
tabsetPanel(
id = "main_panels",
## info panel ----
tabPanel(
"info",
br(),
div(
id = "loading-content",
h2("Loading...")
),
shinyjs::hidden(
div(
id = "app-content",
sidebarLayout(
sidebarPanel(
width = 3,
selectInput(
inputId = "choose_dataset",
label = NULL,
choices = c("choose dataset", available_datasets)
),
actionButton(inputId = "load_data", label = "load dataset"),
br(),
br(),
p(id="explore", "Explore your chosen dataset by using the tabs above."),
p(id="explore2", "Sample names and experimental conditions are shown in the metadata section."),
p(id="explore3","The data tab shows the whole dataset, which can be downloaded if required."),
p(id="explore4","A range of plots can be viewed and downloaded to explore different aspects of the dataset.")
),
mainPanel(
br(),
h1(textOutput(outputId = "dataset_name"), align = "center"),
br(),
h5(textOutput(outputId = "dataset_info")),
br(),br(),br(),
br(),br(),br(),br(),br(),br(),br(),
h6("For more information about work carried out at the Babraham Institute
visit the", a(href= "https://www.babraham.ac.uk/", "website")),
br(),br(),br(),br()
)
)
)
)
),
## metadata panel ----
tabPanel(
"metadata",
br(),
fluidRow(
column(
width = 6,
wellPanel(align = "center",
h3("Dataset summary", align = "center", style="margin: 10px;"),
textOutput("meta_info1"),
textOutput("meta_info2"),
h6("Number of categories in each condition:"),
tableOutput("meta_info3"),
checkboxInput("show_meta_summary", "show more information on conditions"),
conditionalPanel(
condition = "input.show_meta_summary == 1",
fluidRow(
column(
width = 4,
selectInput(
"selected_condition",
"select condition",
choices = ""
),
),
column(width = 8, tableOutput("meta_summary"))
)
),
checkboxInput("show_meta", "show all metadata"),
conditionalPanel(
condition = "input.show_meta == 1",
DT::dataTableOutput("meta_table")
),
if(show_browser) actionButton("browser", "browser")
)
),
column(
width = 6,
wellPanel(align = "center",
h3("Sets of interest", align = "center", style="margin: 10px;"),
textOutput("set_info1"),
h6("Number in each set:"),
tableOutput("set_info2"),
checkboxInput("show_sets", "show items in set"),
conditionalPanel(
condition = "input.show_sets == 1",
fluidRow(
column(
width = 4,
selectInput(
"selected_set",
"select set",
choices = ""
)
),
column(width = 8, tableOutput("set_summary"))
)
)
)
)
),
br(),
br()
),
## data panel ----
tabPanel(
"data",
br(),
wellPanel(
DT::dataTableOutput("data_table"),
downloadButton("download_csv", "download csv")
)
),
## plot panel ----
tabPanel(
"plot",
br(),
navlistPanel(
"plot type",
tabPanel("histogram", mod_histogramUI("hist")),
tabPanel("scatterplot", mod_scatterplot_ui("scatter")),
tabPanel("heatmap", mod_heatmap_ui("heatmap")),
tabPanel("violinplot", mod_violinplot_ui("violinplot")),
widths = c(3,9)
)
),
## filter panel ----
tabPanel(
"filter",
br(),
mod_name_filter_ui("name_filter")
)
),
## footers ----
br(),
fluidRow(
column(
width = 3,
tags$img(src = "images/bioinformatics_logo_small_grey.png",
width = "200", height = "71")
),
column(
width = 6,
offset = 3,
br(),
br(),
p("Any problems please email laura.biggins@babraham.ac.uk",
style = "font-size:12px", align = "right")
)
),
br()
),
# tags$script(
# "var exploreText = document.getElementById('explore');
# exploreText.style.backgroundColor = 'red';"
# ),
tags$script(src = "script.js")
)
# server ----
server <- function(input, output, session ) {
## reactive values ----
data_loaded <- reactiveVal(FALSE)
#chosen_dataset <- eventReactive(input$load_data, input$choose_dataset)
chosen_dataset <- reactiveVal("choose dataset")
rv <- reactiveValues(
dataset = NULL, # the currently loaded dataset
long_data_tib = NULL, # tidied long version of dataset
measure_names = NULL, # all the row (gene) names
measures_of_interest = NULL, # sets of ids of interest
metadata = NULL # list of accompanying metadata
)
observeEvent(input$load_data, {
chosen_dataset(input$choose_dataset)
})
observeEvent(input$pre_chosen_dataset, {
req(input$pre_chosen_dataset)
print("from pre_chosen_dataset")
cleaned_choice <- substring(input$pre_chosen_dataset, 2) # remove hash
if(cleaned_choice %in% available_datasets){
chosen_dataset(cleaned_choice)
updateSelectInput(
inputId = "choose_dataset",
choices = c("choose dataset", available_datasets),
selected = cleaned_choice
)
}
})
## load data ----
#observeEvent(input$load_data, {
observeEvent(chosen_dataset(), {
if(chosen_dataset() != "choose dataset") {
# need checks here that the locations exist
data_folder <- paste0(data_location, chosen_dataset(), "/")
#if(file.exists(paste0(data_folder, "dataset.feather"))){
# dataset <- feather::read_feather(paste0(data_folder, "dataset.feather"))
# } else {
dataset <- readRDS(paste0(data_folder, "dataset.rds"))
# }
metadata_processed <- readRDS(paste0(data_folder, "metadata.rds"))
if(file.exists(paste0(data_folder, "of_interest.rds"))){
of_interest <- readRDS(paste0(data_folder, "of_interest.rds"))
} else of_interest <- NULL
if(file.exists(paste0(data_folder, "info.rds"))){
info <- readRDS(paste0(data_folder, "info.rds"))
} else info <- list(summary_info = "populate with info file")
rv$dataset <- dataset
rv$metadata <- metadata_processed
rv$measure_names <- rownames(dataset)
rv$measures_of_interest <- of_interest
rv$info <- info
meta_factors <- metadata_processed$meta_all %>%
dplyr::mutate_if(is.character, factor) %>%
dplyr::mutate_if(is.double, factor) %>%
dplyr::mutate_if(is.integer, factor)
tib <- tibble::as_tibble(dataset, rownames = "row_attribute")
long_data_tibble <- tib %>%
tidyr::pivot_longer(cols = -row_attribute, names_to = sample_names) %>%
tidyr::drop_na() %>%
dplyr::left_join(meta_factors)
rv$long_data_tib <- long_data_tibble
updateSelectInput(
inputId = "selected_condition",
label = "select condition",
choices = names(rv$metadata$meta_summary)
)
}
})
## info tab ----
output$dataset_name <- renderText({
chosen_dataset()
})
output$dataset_info <- renderText({
if(chosen_dataset() == "choose dataset") {
"Choose a dataset from the dropdown on the left"
} else {
#"populate this with an info file"
rv$info$summary_info
}
})
## metadata tab ----
### dataset summary ----
#### info that's always present if data is loaded ----
output$meta_info1 <- renderText({
req(rv$metadata)
req(rv$dataset)
paste0(
"The dataset contains ",
nrow(rv$metadata$meta_summary[[sample_names]]),
" samples and ",
nrow(rv$dataset),
" measures."
)
})
output$meta_info2 <- renderText({
req(rv$metadata)
met <- rv$metadata
paste0(
"Conditions are: ",
paste0(
names(met$meta_summary)[!names(met$meta_summary) %in% met$sample_name],
collapse = ", "
),
"."
)
})
output$meta_info3 <- renderTable({
req(rv$metadata)
tibble::enframe(sapply(rv$metadata$meta_summary, nrow))
}, colnames = FALSE)
#### info in conditional panels ----
output$meta_table <- DT::renderDataTable({
req(rv$metadata)
dt_setup(rv$metadata$meta_all, n_rows = 20)
})
output$meta_summary <- renderTable({
req(input$selected_condition)
req(rv$metadata$meta_summary)
rv$metadata$meta_summary[[input$selected_condition]]
})
### Sets of interest ----
output$set_info1 <- renderText({
req(rv$measures_of_interest)
n_sets <- length(rv$measures_of_interest)
if(n_sets == 1) text <- " set available"
else text <- " sets available"
paste0(n_sets, text, ". To add more, use the filter tab.")
})
output$set_info2 <- renderTable({
req(rv$measures_of_interest)
tibble::enframe(sapply(rv$measures_of_interest, nrow))
}, colnames = FALSE)
#### table in conditional panel ----
output$set_summary <- renderTable({
req(input$selected_set)
req(rv$measures_of_interest)
rv$measures_of_interest[[input$selected_set]]
})
## data tab ----
output$data_table <- DT::renderDataTable({
req(rv$dataset)
#dt_setup(rv$dataset, n_rows = 20, dom_opt = "ftlip", show_rownames = TRUE)
DT::datatable(
rv$dataset,
options = list(
dom = "ftlip",
scrollX = TRUE,
autoWidth = FALSE
)
) %>%
DT::formatStyle(0, target = 'row', `font-size` = '90%', lineHeight = '80%') %>%
DT::formatRound(columns = 1:ncol(rv$dataset), digits = 2)
})
output$download_csv <- downloadHandler(
filename = function() {
paste(chosen_dataset(), ".csv", sep = "")
},
content = function(file) {
write.csv(x = rv$dataset, file)
}
)
## plot tab ----
### histogram module ----
mod_histogramServer(
"hist",
data_to_plot = reactive(rv$long_data_tib),
meta = reactive(rv$metadata),
chosen_dataset
)
### heatmap module ----
mod_heatmap_server(
"heatmap",
dataset = reactive(rv$dataset),
metadata = reactive(rv$metadata),
sample_name_col = sample_names,
of_interest = reactive(rv$measures_of_interest),
chosen_dataset = chosen_dataset
)
### scatterplot module ----
mod_scatterplot_server(
"scatter",
data_to_plot = reactive(rv$long_data_tib),
metadata = reactive(rv$metadata),
sample_name_col = sample_names,
sets_of_interest = reactive(rv$measures_of_interest),
chosen_dataset = chosen_dataset
)
### violinplot module ----
mod_violinplot_server(
"violinplot",
long_data_tib = reactive(rv$long_data_tib),
chosen_dataset = chosen_dataset,
metadata = reactive(rv$metadata),
sample_name_col = sample_names
)
## filter tab
### filter module ----
filter_results <- mod_name_filter_server(
"name_filter",
reactive(rv$measure_names),
of_interest = reactive(rv$measures_of_interest),
chosen_dataset = chosen_dataset
)
### filter results - observeEvent
observeEvent(filter_results(), {
rv$measures_of_interest <- filter_results()
print("filter results updated")
updateSelectInput(inputId = "selected_set", choices = names(rv$measures_of_interest))
})
observeEvent(input$browser, browser())
shinyjs::hide(id = "loading-content", anim = TRUE, animType = "fade")
shinyjs::show("app-content")
}
shinyApp(ui = ui, server = server)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.