From c002ffa235cb990050ebd2cea25d6fef388f188b Mon Sep 17 00:00:00 2001 From: zitoa Date: Thu, 7 Aug 2025 16:31:32 +0200 Subject: [PATCH 01/23] wip --- .../R/upload_module_preview_counts.R | 8 +- components/board.upload/R/upload_server.R | 92 ++++++++++++-- components/board.upload/R/upload_ui.R | 116 +++++++++++++----- 3 files changed, 169 insertions(+), 47 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index e94c5b38e..4a097cd14 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -27,7 +27,8 @@ upload_table_preview_counts_server <- function( info.text, caption, upload_datatype, - is.olink + is.olink, + public_dataset_id ) { moduleServer(id, function(input, output, session) { @@ -486,6 +487,11 @@ upload_table_preview_counts_server <- function( } }) + observeEvent(input$counts_csv, { + dbg("-------MNT.K1: uploaded$counts.csv: ", dim(uploaded$counts.csv)) + dbg("-------MNT.K2: uploaded$samples.csv: ", dim(uploaded$samples.csv)) + }) + # pass counts to uploaded when uploaded observeEvent(input$counts_csv, { # check if counts is csv (necessary due to drag and drop of any file) diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 536727c61..6713cf1dc 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -124,7 +124,39 @@ UploadBoard <- function(id, return(FALSE) } }) - + + observeEvent(input$start_search, { + if (input$dataset_identifier != "") { + ID <- input$dataset_identifier + is.valid.ID <- playbase::is.GEO.id.valid(ID) + if (!is.valid.ID) { + msg <- paste0(ID, " seems not a valid ID. Please use a valid dataset ID.") + shinyalert::shinyalert(text = msg, type = "error") + } else { + msg <- paste0("Searching ", ID, " in GEO and ReCount databases...") + shiny::withProgress(message = msg, value = 0.5, { + GEO <- tryCatch({ playbase::pgx.getGEOseries(id = ID, get.info = FALSE)}, + error = function(w) { NULL } ) + }) + if (!is.null(GEO)) { + cm <- intersect(colnames(GEO[["counts"]]), rownames(GEO[["samples"]])) + uploaded$counts.csv <- GEO[["counts"]][, cm, drop = FALSE] + uploaded$samples.csv <- GEO[["samples"]][cm, , drop = FALSE] + msg <- paste0("Success! ", ID, " found in ", GEO[["source"]]) + shinyalert::shinyalert(text = msg, type = "success") + rm(GEO) + new_upload(new_upload() + 1) + } else { + msg <- paste0(ID, " not found in ReCount and GEO. Please try a different ID.") + shinyalert::shinyalert(text = msg, type = "error") + } + } + } else { + msg <- paste0("Please add a dataset ID") + shinyalert::shinyalert(text = msg, type = "warning") + } + }) + ## ============================================================================ ## ================== NEW DATA UPLOAD ========================================= ## ============================================================================ @@ -134,10 +166,10 @@ UploadBoard <- function(id, uploaded_method <- NA shiny::observeEvent(input$upload_files_btn, - { - shinyjs::click(id = "upload_files") - }, - ignoreNULL = TRUE + { + shinyjs::click(id = "upload_files") + }, + ignoreNULL = TRUE ) shiny::observeEvent(uploaded_pgx(), { @@ -248,6 +280,8 @@ UploadBoard <- function(id, ## -------------------------------------------------------- df0 <- uploaded$counts.csv if (is.null(df0)) return(NULL) + + dbg("-------------------MNT1: dim(df0)=", dim(df0)) checked_for_log(FALSE) res <- playbase::pgx.checkINPUT(df0, "COUNTS") @@ -277,7 +311,7 @@ UploadBoard <- function(id, } return(list(res = res, olink = olink)) - + } ) @@ -291,7 +325,10 @@ UploadBoard <- function(id, res <- uploaded_counts()$res olink <- uploaded_counts()$olink if (is.null(res)) { return(list(status = "Missing counts.csv", matrix = NULL)) } - + + dbg("-------------------MNT2: is.null(res)=", is.null(res)) + dbg("-------------------MNT3: dim(res$df)=", dim(res$df)) + ## wait for dialog finished shiny::req(checked_for_log()) @@ -341,6 +378,10 @@ UploadBoard <- function(id, status <- "ERROR: incorrect counts matrix" } + ## HACK AZ + checked <- res$df + status <- "OK" + ## -------------------------------------------------------- ## check files: maximum samples allowed ## -------------------------------------------------------- @@ -367,7 +408,13 @@ UploadBoard <- function(id, if (is.null(checked)) { uploaded[["last_uploaded"]] <- setdiff(uploaded[["last_uploaded"]], "counts.csv") } - + + dbg("-------------------MNT4: is.null(status)=", is.null(status)) + dbg("-------------------MNT5: status=", status) + dbg("-------------------MNT6: is.null(checked)=", is.null(checked)) + dbg("-------------------MNT7: class(checked)=", class(checked)) + dbg("-------------------MNT8: dim(checked)=", dim(checked)) + if (check.e29) { if (isConfirmed) isConfirmed = TRUE if (is.null(isConfirmed)) isConfirmed = FALSE @@ -392,6 +439,9 @@ UploadBoard <- function(id, df0 <- uploaded$samples.csv if (is.null(df0)) { return(list(status = "Missing samples.csv", matrix = NULL)) } + dbg("---------MNT9: dim(checked_counts()$matrix) = ", dim(checked_counts()$matrix)) + dbg("---------MNT10: dim(uploaded$samples.csv)=", dim(uploaded$samples.csv)) + ## Single matrix counts check res <- playbase::pgx.checkINPUT(df0, "SAMPLES") @@ -449,6 +499,9 @@ UploadBoard <- function(id, uploaded[["contrasts.csv"]] <<- NULL } + dbg("-------------------MNT11: dim(res_counts) = ", dim(res_counts)) + dbg("-------------------MNT12: dim(res_samples) = ", dim(res_samples)) + list(status = status, SAMPLES = res_samples, COUNTS = res_counts) } ) @@ -464,9 +517,7 @@ UploadBoard <- function(id, { ## get uploaded counts df0 <- uploaded$contrasts.csv - if (is.null(df0)) { - return(list(status = "Missing contrasts.csv", matrix = NULL)) - } + if (is.null(df0)) return(list(status = "Missing contrasts.csv", matrix = NULL)) ## --------- Single matrix counts check---------- res <- playbase::pgx.checkINPUT(df0, "CONTRASTS") @@ -484,6 +535,18 @@ UploadBoard <- function(id, ## Check if samples.csv exists before uploading contrast.csv cc <- checked_samples_counts() + dbg("-------------------MNT13: is.null(cc$COUNTS) = ", is.null(cc$COUNTS)) + dbg("-------------------MNT14: class(cc$COUNTS) = ", class(cc$COUNTS)) + dbg("-------------------MNT15: dim(cc$COUNTS) = ", dim(cc$COUNTS)) + + dbg("-------------------MNT16: is.null(cc$SAMPLES) = ", is.null(cc$SAMPLES)) + dbg("-------------------MNT17: class(cc$SAMPLES) = ", class(cc$SAMPLES)) + dbg("-------------------MNT18: dim(cc$SAMPLES) = ", dim(cc$SAMPLES)) + + dbg("-------------------MNT19: is.null(checked) = ", is.null(checked)) + dbg("-------------------MNT20: class(checked) = ", class(checked)) + dbg("-------------------MNT21: dim(checked) = ", dim(checked)) + ## -------------- max contrast check ------------------ MAXCONTRASTS <- as.integer(auth$options$MAX_COMPARISONS) if (!is.null(checked)) { @@ -499,6 +562,10 @@ UploadBoard <- function(id, } } + dbg("-------------------MNT22: is.null(checked) = ", is.null(checked)) + dbg("-------------------MNT23: class(checked) = ", class(checked)) + dbg("-------------------MNT24: dim(checked) = ", dim(checked)) + ## -------------- cross-check with samples ------------------ if (!is.null(checked) && !is.null(cc$SAMPLES)) { cross_check <- playbase::pgx.crosscheckINPUT( @@ -1184,7 +1251,8 @@ UploadBoard <- function(id, info.text = "This is the uploaded counts data.", caption = "This is the uploaded counts data.", upload_datatype = upload_datatype, - is.olink = is.olink + is.olink = is.olink, + public_dataset_id = input$dataset_identifier ) upload_table_preview_samples_server( diff --git a/components/board.upload/R/upload_ui.R b/components/board.upload/R/upload_ui.R index 6047bba23..055dbae19 100644 --- a/components/board.upload/R/upload_ui.R +++ b/components/board.upload/R/upload_ui.R @@ -12,47 +12,93 @@ UploadUI <- function(id) { bslib::layout_columns( fill = TRUE, div( - style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", + style = "display: flex; flex-direction: column; align-items: flex-start; gap: 20px; margin-bottom: 150px; margin-top: 250px;", + div( - style = "width: 60%;", - bs_alert("To upload your own data, you should prepare at least two CSV files: an counts.csv file (containing your experiment data) and a samples.csv file (containing your sample information). A third contrasts.csv file (describing your comparisons) is optional. Read more about data preparation here.", closable = FALSE, translate = TRUE, html = TRUE) + style = "display: flex; flex-direction: row; align-items: center; gap: 20px;", + shiny::conditionalPanel( + condition = sprintf("input['%s'] <= 0", ns("public_data_opts")), + shiny::actionButton(ns("show_upload_opts"), "Upload your data", class = "btn-primary upload-btn-large") + ), + shiny::conditionalPanel( + condition = sprintf("input['%s'] <= 0", ns("show_upload_opts")), + shiny::actionButton(ns("public_data_opts"), "Retrieve public data", class = "btn-primary upload-btn-large") + ) ), br(), - div( - p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - ns("selected_datatype"), NULL, - choices = c( - "RNA-seq", - "mRNA microarray", - "proteomics", - "scRNA-seq", - "metabolomics (beta)" = "metabolomics", - "multi-omics (beta)" = "multi-omics" + + tags$style(HTML(" + .upload-btn-large { + font-size: 1.6em; + padding: 20px 45px; + min-width: 260px; + border-radius: 8px; + margin-left: 20vw; + display: block; + box-shadow: 0 2px 16px rgba(0,0,0,0.13); + } + .upload-btn-wrapper { + width: 100%; + display: flex; + justify-content: flex-start; + margin: 60px 5vw 0 0; + } + ")), + + shiny::conditionalPanel( + condition = sprintf("input['%s'] > 0", ns("show_upload_opts")), + div( + style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", + div( + style = "width: 60%;", + bs_alert("To upload your own data, you should prepare at least two CSV files: an counts.csv file (containing your experiment data) and a samples.csv file (containing your sample information). A third contrasts.csv file (describing your comparisons) is optional. Read more about data preparation here.", + closable = FALSE, translate = TRUE, html = TRUE) ), - selected = DEFAULTS$datatype, - width = "400px" - ), - shiny::uiOutput(ns("proteomics_subtype_ui")) - ), - div( - p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - inputId = ns("selected_organism"), - label = NULL, - choices = NULL, - multiple = FALSE, - width = "400px" + br(), + div( + p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + ns("selected_datatype"), NULL, + choices = c("RNA-seq", "mRNA microarray", "proteomics", "scRNA-seq", + "metabolomics (beta)" = "metabolomics", "multi-omics (beta)" = "multi-omics"), + selected = DEFAULTS$datatype, + width = "400px" + ) + ), + div( + p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + inputId = ns("selected_organism"), label = NULL, + choices = NULL, multiple = FALSE, width = "400px" + ) + ), + br(), + shiny::actionButton(ns("start_upload"), "Start upload", class = "btn-primary"), + br() ) ), - br(), - shiny::actionButton( - ns("start_upload"), - "Start upload", - class = "btn-primary" + + shiny::conditionalPanel( + condition = sprintf("input['%s'] > 0", ns("public_data_opts")), + div( + style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", + div( + style = "width: 60%;", + bs_alert("The 'Retrieve public data' functionality in OPG allows to query large repositories of publically available data to retrieve a specific dataset. You will need the dataset's unique identifier, such as the GEO ID. At the moment, GEO, ReCount, and ArrayExpress repositories are queried.", + closable = FALSE, translate = TRUE, html = TRUE) + ), + br(), + div( + p("Dataset identifier:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::textInput(ns("dataset_identifier"), label = NULL, width = "400px") + ), + br(), + shiny::actionButton(ns("start_search"), "Start search & download", class = "btn-primary"), + br() + ) ), - br() - ) + + ) ) ) @@ -61,5 +107,7 @@ UploadUI <- function(id) { uiOutput(ns("upload_wizard")), body ) + return(ui) + } From f066a2171d6d173ca89322837b080ba37b54ceb8 Mon Sep 17 00:00:00 2001 From: zitoa Date: Fri, 8 Aug 2025 09:36:24 +0200 Subject: [PATCH 02/23] wip --- components/board.upload/R/upload_module_preview_counts.R | 3 +++ components/board.upload/R/upload_server.R | 7 ++++--- components/board.upload/R/upload_ui.R | 4 ++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 4a097cd14..3230c7fa1 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -37,6 +37,7 @@ upload_table_preview_counts_server <- function( table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$counts.csv)) dt <- uploaded$counts.csv + dbg("-----------MNT1: public_dataset_id=",public_dataset_id) nrow0 <- nrow(dt) ncol0 <- ncol(dt) MAXROW <- 1000 @@ -533,6 +534,8 @@ upload_table_preview_counts_server <- function( ) } + dbg("-----------public_dataset_id = ", public_dataset_id) + ##---counts---## sel <- grep("count|expression|abundance|concentration", tolower(input$counts_csv$name)) if (length(sel)) { diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 6713cf1dc..95af817b6 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -101,7 +101,8 @@ UploadBoard <- function(id, names(all_species)[all_species=="No organism"] <- "" shiny::updateSelectizeInput(session, "selected_organism", choices = all_species, server = TRUE) }) - + + ## AZ: 7/8/2025: disappeared!!!! Tell Xavier. output$proteomics_subtype_ui <- shiny::renderUI({ if (upload_datatype() == "proteomics") { shiny::selectInput( @@ -132,6 +133,8 @@ UploadBoard <- function(id, if (!is.valid.ID) { msg <- paste0(ID, " seems not a valid ID. Please use a valid dataset ID.") shinyalert::shinyalert(text = msg, type = "error") + ID <- "" + dbg("-----------------ID=",ID) } else { msg <- paste0("Searching ", ID, " in GEO and ReCount databases...") shiny::withProgress(message = msg, value = 0.5, { @@ -506,7 +509,6 @@ UploadBoard <- function(id, } ) - ## -------------------------------------------------------- ## Check contrast matrix ## -------------------------------------------------------- @@ -1231,7 +1233,6 @@ UploadBoard <- function(id, } ) - ## ===================================================================== ## ======================== MODULES SERVERS ============================ ## ===================================================================== diff --git a/components/board.upload/R/upload_ui.R b/components/board.upload/R/upload_ui.R index 055dbae19..31f12f561 100644 --- a/components/board.upload/R/upload_ui.R +++ b/components/board.upload/R/upload_ui.R @@ -17,10 +17,12 @@ UploadUI <- function(id) { div( style = "display: flex; flex-direction: row; align-items: center; gap: 20px;", shiny::conditionalPanel( + #condition = sprintf("input.%s <= 0", ns("public_data_opts")), condition = sprintf("input['%s'] <= 0", ns("public_data_opts")), shiny::actionButton(ns("show_upload_opts"), "Upload your data", class = "btn-primary upload-btn-large") ), shiny::conditionalPanel( + #condition = sprintf("input.%s <= 0", ns("show_upload_opts")), condition = sprintf("input['%s'] <= 0", ns("show_upload_opts")), shiny::actionButton(ns("public_data_opts"), "Retrieve public data", class = "btn-primary upload-btn-large") ) @@ -46,6 +48,7 @@ UploadUI <- function(id) { ")), shiny::conditionalPanel( + #condition = sprintf("input.%s > 0", ns("show_upload_opts")), condition = sprintf("input['%s'] > 0", ns("show_upload_opts")), div( style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", @@ -79,6 +82,7 @@ UploadUI <- function(id) { ), shiny::conditionalPanel( + #condition = sprintf("input.%s > 0", ns("public_data_opts")), condition = sprintf("input['%s'] > 0", ns("public_data_opts")), div( style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", From 9049df948375edac61276296755599de98f07a0c Mon Sep 17 00:00:00 2001 From: zitoa Date: Fri, 8 Aug 2025 10:12:23 +0200 Subject: [PATCH 03/23] improve upload UI --- components/board.upload/R/upload_ui.R | 37 +++++++++++++++++++-------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/components/board.upload/R/upload_ui.R b/components/board.upload/R/upload_ui.R index 31f12f561..4f8d46ce0 100644 --- a/components/board.upload/R/upload_ui.R +++ b/components/board.upload/R/upload_ui.R @@ -17,13 +17,8 @@ UploadUI <- function(id) { div( style = "display: flex; flex-direction: row; align-items: center; gap: 20px;", shiny::conditionalPanel( - #condition = sprintf("input.%s <= 0", ns("public_data_opts")), - condition = sprintf("input['%s'] <= 0", ns("public_data_opts")), - shiny::actionButton(ns("show_upload_opts"), "Upload your data", class = "btn-primary upload-btn-large") - ), - shiny::conditionalPanel( - #condition = sprintf("input.%s <= 0", ns("show_upload_opts")), - condition = sprintf("input['%s'] <= 0", ns("show_upload_opts")), + condition = sprintf("input['%s'] == 0 && input['%s'] == 0", ns("public_data_opts"), ns("show_upload_opts")), + shiny::actionButton(ns("show_upload_opts"), "Upload your data", class = "btn-primary upload-btn-large"), shiny::actionButton(ns("public_data_opts"), "Retrieve public data", class = "btn-primary upload-btn-large") ) ), @@ -48,7 +43,6 @@ UploadUI <- function(id) { ")), shiny::conditionalPanel( - #condition = sprintf("input.%s > 0", ns("show_upload_opts")), condition = sprintf("input['%s'] > 0", ns("show_upload_opts")), div( style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", @@ -58,16 +52,17 @@ UploadUI <- function(id) { closable = FALSE, translate = TRUE, html = TRUE) ), br(), + div( p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), shiny::selectInput( ns("selected_datatype"), NULL, choices = c("RNA-seq", "mRNA microarray", "proteomics", "scRNA-seq", "metabolomics (beta)" = "metabolomics", "multi-omics (beta)" = "multi-omics"), - selected = DEFAULTS$datatype, - width = "400px" + selected = DEFAULTS$datatype, width = "400px" ) ), + div( p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), shiny::selectInput( @@ -76,13 +71,13 @@ UploadUI <- function(id) { ) ), br(), + shiny::actionButton(ns("start_upload"), "Start upload", class = "btn-primary"), br() ) ), shiny::conditionalPanel( - #condition = sprintf("input.%s > 0", ns("public_data_opts")), condition = sprintf("input['%s'] > 0", ns("public_data_opts")), div( style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", @@ -91,11 +86,31 @@ UploadUI <- function(id) { bs_alert("The 'Retrieve public data' functionality in OPG allows to query large repositories of publically available data to retrieve a specific dataset. You will need the dataset's unique identifier, such as the GEO ID. At the moment, GEO, ReCount, and ArrayExpress repositories are queried.", closable = FALSE, translate = TRUE, html = TRUE) ), + br(), + + div( + p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + ns("selected_datatype"), NULL, + choices = c("Transcriptomics", "Proteomics"), + selected = "Transcriptomics", width = "400px" + ) + ), + + div( + p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + inputId = ns("selected_organism"), label = NULL, + choices = playbase::SPECIES_TABLE$species_name, multiple = FALSE, width = "400px" + ) + ), + br(), div( p("Dataset identifier:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), shiny::textInput(ns("dataset_identifier"), label = NULL, width = "400px") ), + br(), shiny::actionButton(ns("start_search"), "Start search & download", class = "btn-primary"), br() From 0e69c2403ea78b1e88bfd4027dd1769dfb4cba5a Mon Sep 17 00:00:00 2001 From: zitoa Date: Tue, 12 Aug 2025 09:26:05 +0200 Subject: [PATCH 04/23] refactoring and polishing --- .../R/upload_module_preview_counts.R | 359 ++++++++++++------ components/board.upload/R/upload_server.R | 104 ++--- 2 files changed, 270 insertions(+), 193 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 3230c7fa1..b0c3a14cf 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -13,31 +13,98 @@ upload_table_preview_counts_ui <- function(id) { } upload_table_preview_counts_server <- function( - id, - create_raw_dir, - auth, - uploaded, - checked_matrix, - is_logscale, - checklist, - scrollY, - width, - height, - title, - info.text, - caption, - upload_datatype, - is.olink, - public_dataset_id - ) { + id, + create_raw_dir, + auth, + uploaded, + checked_matrix, + is_logscale, + checklist, + scrollY, + width, + height, + title, + info.text, + caption, + upload_datatype, + is.olink, + public_dataset_id + ) { moduleServer(id, function(input, output, session) { + ns <- session$ns + GEO_alert_shown <- reactiveVal(FALSE) + + shiny::insertUI( + selector = "head", + where = "beforeEnd", + ui = list( + tags$style(HTML(" + #custom-progress-modal { + position: fixed; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%); + background-color: #ffffff; + color: black; + padding: 30px 50px; + font-size: 20px; + font-weight: bold; + border-radius: 10px; + z-index: 1050; + text-align: center; + } + #custom-progress-bar { + height: 15px; + background-color: #007bff; + width: 40%; + transition: width 0.3s ease; + color: white; + font-weight: bold; + line-height: 25px; + animation: pulse-blue 2s infinite; + transform-origin: center; + } + @keyframes pulse-blue { + 0% { box-shadow: 0 0 8px 2px #007bff; + transform: scale(1.2); } + 50% { box-shadow: 0 0 18px 8px #3399ff; + transform: scale(1.4); } + 100% { box-shadow: 0 0 8px 2px #007bff; + transform: scale(1); } + } + #custom-progress-container { + width: 100%; + background-color: #e9ecef; + border-radius: 0.25rem; + overflow: hidden; + margin-top: 15px; + } + .shiny-notification{ display: none !important; } + ")), + tags$script(HTML(" + Shiny.addCustomMessageHandler('updateProgressBar', function(message) { + var val = message.value; + var pb = document.getElementById('custom-progress-bar'); + if(pb) { + pb.style.width = val + '%'; + pb.textContent = val + '%'; + } + }); + ")) + ) + ) + table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$counts.csv)) - dt <- uploaded$counts.csv - dbg("-----------MNT1: public_dataset_id=",public_dataset_id) + dt <- uploaded$counts.csv + + dbg("---------class(public_dataset_id) = ", class(public_dataset_id)) + dbg("---------public_dataset_id = ", public_dataset_id()) + dbg("---------class(upload_datatype) = ", class(upload_datatype)) + nrow0 <- nrow(dt) ncol0 <- ncol(dt) MAXROW <- 1000 @@ -60,10 +127,8 @@ upload_table_preview_counts_server <- function( table.RENDER <- function() { dt <- table_data() req(!is.null(dt)) - is.integer <- is.integer(dt) || all(round(dt) == dt, na.rm = TRUE) digits <- ifelse(is.integer, 0, 2) - DT::datatable(dt, class = "compact hover", rownames = TRUE, @@ -84,6 +149,7 @@ upload_table_preview_counts_server <- function( } output$table_counts <- shiny::renderUI({ + action_buttons <- div( style = "display: flex; justify-content: left; margin: 8px;", if (is.null(uploaded$counts.csv)) { @@ -117,95 +183,31 @@ upload_table_preview_counts_server <- function( ) ) - div( - bslib::as_fill_carrier(), - style = "width: 100%; display: flex; ", - if (is.null(uploaded$counts.csv)) { - if (upload_datatype() == "proteomics") { - msg <- "The counts file (counts.csv) contains the gene counts for all samples. For proteomics data types other than Olink NPX, the file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample. For Olink NPX, the uploaded file needs to be the standard Olink format." - } else { - msg <- "The counts file (counts.csv) contains the gene counts for all samples. The file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample." + if (public_dataset_id() != "") { + + ID <- public_dataset_id() + msg <- paste0("Retrieving ", ID, " from GEO or ReCount databases...") + showModal(modalDialog( + div(id = "custom-progress-modal", msg, + div(id = "custom-progress-container", + div(id = "custom-progress-bar"))), + footer = NULL, fade = FALSE)) + progress <- shiny::Progress$new(session, min = 0, max = 100) + GEO <- tryCatch({ playbase::pgx.getGEOseries(id = ID, get.info = FALSE)}, + error = function(w) { NULL }) + removeModal() + + if (!is.null(GEO)) { + if (!GEO_alert_shown()) { + msg <- paste0("Success! ", ID, " found in ", GEO[["source"]]) + shinyalert::shinyalert(text = msg, type = "success") + GEO_alert_shown(TRUE) } - bslib::layout_columns( - col_widths = c(-3, 6, -3), - row_heights = list("auto", 8, 1, 2), - gap = "0.5rem", - bslib::as_fill_carrier(bs_alert(tspan(msg), closable = FALSE, translate_js = FALSE)), - bslib::card( - if (upload_datatype() == "multi-omics") { - shiny::radioButtons( - ns("data_source"), - label = "Select input files from:", - choices = c("multi-csv", "pgx", "single-csv"), - selected = "multi-csv", - inline = TRUE - ) - }, - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'pgx'", ns("data_source")), - div( - div( - style = "margin-bottom: 15px;", - shiny::radioButtons( - ns("data_processing"), - label = "Select data processing level:", - choices = c("Raw" = "raw", "Normalized (also batch corrected if selected on computation)" = "normalized"), - selected = "raw", - inline = TRUE - ) - ), - div( - style = "display: flex; align-items: center; gap: 10px; margin-bottom: 10px;", - span("Selected:", style = "font-weight: bold;"), - textOutput(ns("selected_rows_text")), - ), - div( - style = "height: 350px; overflow-y: auto;", - DT::DTOutput(ns("available_data_table")) - ), - style = "width: 100%; max-height: 400px; overflow-y: auto;" - ), - selection = "multiple", - options = list(pageLength = 5, dom = "tp", scrollY = TRUE) - ) - }, - - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'multi-csv'", ns("data_source")), - shiny::uiOutput(ns("dynamic_file_inputs"))#, - ) - }, - - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'single-csv'", ns("data_source")), - fileInputArea( - ns("counts_csv"), - shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), - multiple = FALSE, - accept = c(".csv"), - width = "100%" - ) - ) - }, - - if (upload_datatype() != "multi-omics") { - fileInputArea( - ns("counts_csv"), - shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), - multiple = FALSE, - accept = c(".csv"), - width = "100%" - ) - }, - style = "background-color: aliceblue; border: 0.07rem dashed steelblue;" - ), - action_buttons, - br() - ) - }, + uploaded$counts.csv <- GEO[["counts"]] + uploaded$samples.csv <- GEO[["samples"]] + GEO <- NULL + } + if (!is.null(uploaded$counts.csv)) { bslib::layout_columns( col_widths = 12, @@ -229,8 +231,129 @@ upload_table_preview_counts_server <- function( ), bslib::layout_columns(action_buttons, br(), uiOutput(ns("error_summary"))) ) - } ## end of if-else - ) ## end of div + } else { + div("No counts data available for this public dataset.") + } + + } else { + + div( + bslib::as_fill_carrier(), + style = "width: 100%; display: flex; ", + if (is.null(uploaded$counts.csv)) { + if (upload_datatype() == "proteomics") { + msg <- "The counts file (counts.csv) contains the gene counts for all samples. For proteomics data types other than Olink NPX, the file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample. For Olink NPX, the uploaded file needs to be the standard Olink format." + } else { + msg <- "The counts file (counts.csv) contains the gene counts for all samples. The file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample." + } + bslib::layout_columns( + col_widths = c(-3, 6, -3), + row_heights = list("auto", 8, 1, 2), + gap = "0.5rem", + bslib::as_fill_carrier(bs_alert(tspan(msg), closable = FALSE, translate_js = FALSE)), + bslib::card( + if (upload_datatype() == "multi-omics") { + shiny::radioButtons( + ns("data_source"), + label = "Select input files from:", + choices = c("multi-csv", "pgx", "single-csv"), + selected = "multi-csv", + inline = TRUE + ) + }, + if (upload_datatype() == "multi-omics") { + shiny::conditionalPanel( + condition = sprintf("input['%s'] == 'pgx'", ns("data_source")), + div( + div( + style = "margin-bottom: 15px;", + shiny::radioButtons( + ns("data_processing"), + label = "Select data processing level:", + choices = c("Raw" = "raw", "Normalized (also batch corrected if selected on computation)" = "normalized"), + selected = "raw", + inline = TRUE + ) + ), + div( + style = "display: flex; align-items: center; gap: 10px; margin-bottom: 10px;", + span("Selected:", style = "font-weight: bold;"), + textOutput(ns("selected_rows_text")), + ), + div( + style = "height: 350px; overflow-y: auto;", + DT::DTOutput(ns("available_data_table")) + ), + style = "width: 100%; max-height: 400px; overflow-y: auto;" + ), + selection = "multiple", + options = list(pageLength = 5, dom = "tp", scrollY = TRUE) + ) + }, + + if (upload_datatype() == "multi-omics") { + shiny::conditionalPanel( + condition = sprintf("input['%s'] == 'multi-csv'", ns("data_source")), + shiny::uiOutput(ns("dynamic_file_inputs"))#, + ) + }, + + if (upload_datatype() == "multi-omics") { + shiny::conditionalPanel( + condition = sprintf("input['%s'] == 'single-csv'", ns("data_source")), + fileInputArea( + ns("counts_csv"), + shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), + multiple = FALSE, + accept = c(".csv"), + width = "100%" + ) + ) + }, + + if (upload_datatype() != "multi-omics") { + fileInputArea( + ns("counts_csv"), + shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), + multiple = FALSE, + accept = c(".csv"), + width = "100%" + ) + }, + + style = "background-color: aliceblue; border: 0.07rem dashed steelblue;" + ), + action_buttons, + br() + ) + }, + if (!is.null(uploaded$counts.csv)) { + bslib::layout_columns( + col_widths = 12, + bslib::layout_columns( + col_widths = c(8, 4), + TableModuleUI( + ns("counts_datasets"), + width = width, + height = height, + title = title, + info.text = info.text, + caption = caption, + label = "", + show.maximize = FALSE, + translate_js = FALSE + ), + bslib::navset_card_pill( + bslib::nav_panel(title = "Histogram", br(), plotOutput(ns("histogram"))), + bslib::nav_panel(title = "Box plots", br(), plotOutput(ns("boxplots"))) + ) + ), + bslib::layout_columns(action_buttons, br(), uiOutput(ns("error_summary"))) + ) + } ## end of if-else + ) ## end of div + } + }) output$selected_rows_text <- renderText({ @@ -487,12 +610,7 @@ upload_table_preview_counts_server <- function( shinyalert::shinyalert(title = "Warning", text = err.html, html = TRUE) } }) - - observeEvent(input$counts_csv, { - dbg("-------MNT.K1: uploaded$counts.csv: ", dim(uploaded$counts.csv)) - dbg("-------MNT.K2: uploaded$samples.csv: ", dim(uploaded$samples.csv)) - }) - + # pass counts to uploaded when uploaded observeEvent(input$counts_csv, { # check if counts is csv (necessary due to drag and drop of any file) @@ -533,9 +651,7 @@ upload_table_preview_counts_server <- function( overwrite = TRUE ) } - - dbg("-----------public_dataset_id = ", public_dataset_id) - + ##---counts---## sel <- grep("count|expression|abundance|concentration", tolower(input$counts_csv$name)) if (length(sel)) { @@ -581,7 +697,7 @@ upload_table_preview_counts_server <- function( if (upload_datatype() == "proteomics" && is.olink() && !is.null(df.samples)) { uploaded$samples.csv <- df.samples } - + ## ##---samples---## ## sel <- grep("samples", tolower(input$counts_csv$name)) ## if (length(sel)) { @@ -679,3 +795,4 @@ upload_table_preview_counts_server <- function( ) }) ## end of moduleServer } ## end of server + diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 95af817b6..3385617c5 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -27,6 +27,7 @@ UploadBoard <- function(id, upload_name <- reactiveVal(NULL) upload_description <- reactiveVal(NULL) upload_datatype <- reactiveVal(NULL) + public_dataset_id <- reactiveVal(NULL) upload_gset_methods <- reactiveVal(NULL) upload_gx_methods <- reactiveVal(NULL) process_counter <- reactiveVal(0) @@ -127,39 +128,21 @@ UploadBoard <- function(id, }) observeEvent(input$start_search, { + dbg("-------public_dataset_id = ", public_dataset_id()) if (input$dataset_identifier != "") { - ID <- input$dataset_identifier - is.valid.ID <- playbase::is.GEO.id.valid(ID) - if (!is.valid.ID) { - msg <- paste0(ID, " seems not a valid ID. Please use a valid dataset ID.") - shinyalert::shinyalert(text = msg, type = "error") - ID <- "" - dbg("-----------------ID=",ID) + ID <- public_dataset_id() + valid.ID <- playbase::is.GEO.id.valid(ID) + if (!valid.ID) { + msg <- paste0(ID, " seems not valid. Please use a valid dataset ID.") + shinyalert::shinyalert(text = msg, type = "error") } else { - msg <- paste0("Searching ", ID, " in GEO and ReCount databases...") - shiny::withProgress(message = msg, value = 0.5, { - GEO <- tryCatch({ playbase::pgx.getGEOseries(id = ID, get.info = FALSE)}, - error = function(w) { NULL } ) - }) - if (!is.null(GEO)) { - cm <- intersect(colnames(GEO[["counts"]]), rownames(GEO[["samples"]])) - uploaded$counts.csv <- GEO[["counts"]][, cm, drop = FALSE] - uploaded$samples.csv <- GEO[["samples"]][cm, , drop = FALSE] - msg <- paste0("Success! ", ID, " found in ", GEO[["source"]]) - shinyalert::shinyalert(text = msg, type = "success") - rm(GEO) - new_upload(new_upload() + 1) - } else { - msg <- paste0(ID, " not found in ReCount and GEO. Please try a different ID.") - shinyalert::shinyalert(text = msg, type = "error") - } + new_upload(new_upload() + 1) } } else { - msg <- paste0("Please add a dataset ID") - shinyalert::shinyalert(text = msg, type = "warning") + shinyalert::shinyalert(text = "Please enter a dataset ID", type = "error") } }) - + ## ============================================================================ ## ================== NEW DATA UPLOAD ========================================= ## ============================================================================ @@ -284,8 +267,6 @@ UploadBoard <- function(id, df0 <- uploaded$counts.csv if (is.null(df0)) return(NULL) - dbg("-------------------MNT1: dim(df0)=", dim(df0)) - checked_for_log(FALSE) res <- playbase::pgx.checkINPUT(df0, "COUNTS") write_check_output(res$checks, "COUNTS", raw_dir()) @@ -328,10 +309,7 @@ UploadBoard <- function(id, res <- uploaded_counts()$res olink <- uploaded_counts()$olink if (is.null(res)) { return(list(status = "Missing counts.csv", matrix = NULL)) } - - dbg("-------------------MNT2: is.null(res)=", is.null(res)) - dbg("-------------------MNT3: dim(res$df)=", dim(res$df)) - + ## wait for dialog finished shiny::req(checked_for_log()) @@ -343,7 +321,6 @@ UploadBoard <- function(id, isConfirmed <- input$logCorrectCounts if (is.null(isConfirmed)) isConfirmed = FALSE - ## RESTORE AVERAGE RANK PLOT. if (olink) { res$checks[["e29"]] <- NULL check.e29 = TRUE @@ -381,10 +358,6 @@ UploadBoard <- function(id, status <- "ERROR: incorrect counts matrix" } - ## HACK AZ - checked <- res$df - status <- "OK" - ## -------------------------------------------------------- ## check files: maximum samples allowed ## -------------------------------------------------------- @@ -412,12 +385,6 @@ UploadBoard <- function(id, uploaded[["last_uploaded"]] <- setdiff(uploaded[["last_uploaded"]], "counts.csv") } - dbg("-------------------MNT4: is.null(status)=", is.null(status)) - dbg("-------------------MNT5: status=", status) - dbg("-------------------MNT6: is.null(checked)=", is.null(checked)) - dbg("-------------------MNT7: class(checked)=", class(checked)) - dbg("-------------------MNT8: dim(checked)=", dim(checked)) - if (check.e29) { if (isConfirmed) isConfirmed = TRUE if (is.null(isConfirmed)) isConfirmed = FALSE @@ -442,9 +409,6 @@ UploadBoard <- function(id, df0 <- uploaded$samples.csv if (is.null(df0)) { return(list(status = "Missing samples.csv", matrix = NULL)) } - dbg("---------MNT9: dim(checked_counts()$matrix) = ", dim(checked_counts()$matrix)) - dbg("---------MNT10: dim(uploaded$samples.csv)=", dim(uploaded$samples.csv)) - ## Single matrix counts check res <- playbase::pgx.checkINPUT(df0, "SAMPLES") @@ -502,10 +466,8 @@ UploadBoard <- function(id, uploaded[["contrasts.csv"]] <<- NULL } - dbg("-------------------MNT11: dim(res_counts) = ", dim(res_counts)) - dbg("-------------------MNT12: dim(res_samples) = ", dim(res_samples)) - - list(status = status, SAMPLES = res_samples, COUNTS = res_counts) + LL <- list(status = status, SAMPLES = res_samples, COUNTS = res_counts) + return(LL) } ) @@ -537,18 +499,6 @@ UploadBoard <- function(id, ## Check if samples.csv exists before uploading contrast.csv cc <- checked_samples_counts() - dbg("-------------------MNT13: is.null(cc$COUNTS) = ", is.null(cc$COUNTS)) - dbg("-------------------MNT14: class(cc$COUNTS) = ", class(cc$COUNTS)) - dbg("-------------------MNT15: dim(cc$COUNTS) = ", dim(cc$COUNTS)) - - dbg("-------------------MNT16: is.null(cc$SAMPLES) = ", is.null(cc$SAMPLES)) - dbg("-------------------MNT17: class(cc$SAMPLES) = ", class(cc$SAMPLES)) - dbg("-------------------MNT18: dim(cc$SAMPLES) = ", dim(cc$SAMPLES)) - - dbg("-------------------MNT19: is.null(checked) = ", is.null(checked)) - dbg("-------------------MNT20: class(checked) = ", class(checked)) - dbg("-------------------MNT21: dim(checked) = ", dim(checked)) - ## -------------- max contrast check ------------------ MAXCONTRASTS <- as.integer(auth$options$MAX_COMPARISONS) if (!is.null(checked)) { @@ -564,10 +514,6 @@ UploadBoard <- function(id, } } - dbg("-------------------MNT22: is.null(checked) = ", is.null(checked)) - dbg("-------------------MNT23: class(checked) = ", class(checked)) - dbg("-------------------MNT24: dim(checked) = ", dim(checked)) - ## -------------- cross-check with samples ------------------ if (!is.null(checked) && !is.null(cc$SAMPLES)) { cross_check <- playbase::pgx.crosscheckINPUT( @@ -602,6 +548,7 @@ UploadBoard <- function(id, ## Dynamic render of appropriate wizard output$upload_wizard <- shiny::renderUI({ + counts_ui <- wizardR::wizard_step( step_title = tspan("Step 1: Upload counts", js = FALSE), step_id = "step_counts", @@ -616,10 +563,10 @@ UploadBoard <- function(id, step_id = "step_samples", server = TRUE, upload_table_preview_samples_ui( - ns("samples_preview") + ns("samples_preview") ) ) - + contrasts_ui <- wizardR::wizard_step( step_title = "Step 3: Create comparisons", step_id = "step_comparisons", @@ -787,6 +734,11 @@ UploadBoard <- function(id, upload_organism(input$selected_organism) }) + ## NEW AZ + observeEvent(input$dataset_identifier, { + public_dataset_id(input$dataset_identifier) + }) + observeEvent(input$start_upload, { recompute_pgx(NULL) ## need to reset ??? }) @@ -1237,6 +1189,16 @@ UploadBoard <- function(id, ## ======================== MODULES SERVERS ============================ ## ===================================================================== + shiny::observeEvent(uploaded$counts.csv, { + dbg("-----------------------------") + dbg("-------FINAL CHECKS----------") + dbg("----dim(checked_counts()$matrix) = ", dim(checked_counts()$matrix)) + dbg("----dim(uploaded$counts.csv) = ", dim(uploaded$counts.csv)) + dbg("----all.equal = ", all.equal(uploaded$counts.csv, checked_counts()$matrix)) + dbg("----public_dataset_id = ", public_dataset_id()) + dbg("-------------------------------------") + }) + upload_table_preview_counts_server( id = "counts_preview", create_raw_dir = create_raw_dir, @@ -1253,7 +1215,7 @@ UploadBoard <- function(id, caption = "This is the uploaded counts data.", upload_datatype = upload_datatype, is.olink = is.olink, - public_dataset_id = input$dataset_identifier + public_dataset_id = public_dataset_id ) upload_table_preview_samples_server( @@ -1373,8 +1335,6 @@ UploadBoard <- function(id, probetype = probetype ) - - ## ------------------------------------------------ ## Board return object ## ------------------------------------------------ From 8b439988a7ae98b011f21f7a19e495474988a1a1 Mon Sep 17 00:00:00 2001 From: zitoa Date: Wed, 13 Aug 2025 14:54:39 +0200 Subject: [PATCH 05/23] refactoring and polishing --- .../R/upload_module_preview_counts.R | 13 ++++-------- components/board.upload/R/upload_server.R | 20 ++++--------------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index b0c3a14cf..e7163b1e4 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -100,11 +100,6 @@ upload_table_preview_counts_server <- function( table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$counts.csv)) dt <- uploaded$counts.csv - - dbg("---------class(public_dataset_id) = ", class(public_dataset_id)) - dbg("---------public_dataset_id = ", public_dataset_id()) - dbg("---------class(upload_datatype) = ", class(upload_datatype)) - nrow0 <- nrow(dt) ncol0 <- ncol(dt) MAXROW <- 1000 @@ -186,20 +181,20 @@ upload_table_preview_counts_server <- function( if (public_dataset_id() != "") { ID <- public_dataset_id() - msg <- paste0("Retrieving ", ID, " from GEO or ReCount databases...") + msg <- paste0("Retrieving ", ID, " from GEO, ReCount, or ArrayExpress...
", "May take up to 20 minutes...") showModal(modalDialog( - div(id = "custom-progress-modal", msg, + div(id = "custom-progress-modal", HTML(msg), div(id = "custom-progress-container", div(id = "custom-progress-bar"))), footer = NULL, fade = FALSE)) progress <- shiny::Progress$new(session, min = 0, max = 100) - GEO <- tryCatch({ playbase::pgx.getGEOseries(id = ID, get.info = FALSE)}, + GEO <- tryCatch({ playbase::pgx.getGEOseries(accession = ID, get.info = FALSE)}, error = function(w) { NULL }) removeModal() if (!is.null(GEO)) { if (!GEO_alert_shown()) { - msg <- paste0("Success! ", ID, " found in ", GEO[["source"]]) + msg <- paste0("Success! ", ID, " found in ", GEO[["source"]], ".\nWe're preparing it...") shinyalert::shinyalert(text = msg, type = "success") GEO_alert_shown(TRUE) } diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 3385617c5..600e0b7e5 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -128,18 +128,17 @@ UploadBoard <- function(id, }) observeEvent(input$start_search, { - dbg("-------public_dataset_id = ", public_dataset_id()) - if (input$dataset_identifier != "") { - ID <- public_dataset_id() + ID <- public_dataset_id() + if (ID != "") { valid.ID <- playbase::is.GEO.id.valid(ID) if (!valid.ID) { msg <- paste0(ID, " seems not valid. Please use a valid dataset ID.") - shinyalert::shinyalert(text = msg, type = "error") + shinyalert::shinyalert(text = msg, type = "error") } else { new_upload(new_upload() + 1) } } else { - shinyalert::shinyalert(text = "Please enter a dataset ID", type = "error") + shinyalert::shinyalert(text = "Please enter a dataset ID", type = "error") } }) @@ -734,7 +733,6 @@ UploadBoard <- function(id, upload_organism(input$selected_organism) }) - ## NEW AZ observeEvent(input$dataset_identifier, { public_dataset_id(input$dataset_identifier) }) @@ -1189,16 +1187,6 @@ UploadBoard <- function(id, ## ======================== MODULES SERVERS ============================ ## ===================================================================== - shiny::observeEvent(uploaded$counts.csv, { - dbg("-----------------------------") - dbg("-------FINAL CHECKS----------") - dbg("----dim(checked_counts()$matrix) = ", dim(checked_counts()$matrix)) - dbg("----dim(uploaded$counts.csv) = ", dim(uploaded$counts.csv)) - dbg("----all.equal = ", all.equal(uploaded$counts.csv, checked_counts()$matrix)) - dbg("----public_dataset_id = ", public_dataset_id()) - dbg("-------------------------------------") - }) - upload_table_preview_counts_server( id = "counts_preview", create_raw_dir = create_raw_dir, From 5a682fad84a9b43c3e51b28032d521ff92dd4393 Mon Sep 17 00:00:00 2001 From: zitoa Date: Wed, 13 Aug 2025 15:23:04 +0200 Subject: [PATCH 06/23] Only transcriptomics for now --- components/board.upload/R/upload_ui.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/board.upload/R/upload_ui.R b/components/board.upload/R/upload_ui.R index 4f8d46ce0..e10f7a8c1 100644 --- a/components/board.upload/R/upload_ui.R +++ b/components/board.upload/R/upload_ui.R @@ -92,8 +92,8 @@ UploadUI <- function(id) { p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), shiny::selectInput( ns("selected_datatype"), NULL, - choices = c("Transcriptomics", "Proteomics"), - selected = "Transcriptomics", width = "400px" + choices = c("RNA-seq", "mRNA microarray"), + selected = "RNA-seq", width = "400px" ) ), From bb8597b1cf1715d706d9c00d52849b5d8afff3e8 Mon Sep 17 00:00:00 2001 From: zitoa Date: Thu, 14 Aug 2025 16:29:29 +0200 Subject: [PATCH 07/23] refactor proteomics type box && cleaning --- .../board.upload/R/upload_module_preview_counts.R | 2 +- components/board.upload/R/upload_server.R | 15 --------------- components/board.upload/R/upload_ui.R | 9 +++++++++ 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index e7163b1e4..78d37bc87 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -181,7 +181,7 @@ upload_table_preview_counts_server <- function( if (public_dataset_id() != "") { ID <- public_dataset_id() - msg <- paste0("Retrieving ", ID, " from GEO, ReCount, or ArrayExpress...
", "May take up to 20 minutes...") + msg <- paste0("Retrieving ", ID, " from GEO, ReCount, or ArrayExpress...
", "Please wait. Most datasets take 2-3 mins.") showModal(modalDialog( div(id = "custom-progress-modal", HTML(msg), div(id = "custom-progress-container", diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 600e0b7e5..4c352fa39 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -103,21 +103,6 @@ UploadBoard <- function(id, shiny::updateSelectizeInput(session, "selected_organism", choices = all_species, server = TRUE) }) - ## AZ: 7/8/2025: disappeared!!!! Tell Xavier. - output$proteomics_subtype_ui <- shiny::renderUI({ - if (upload_datatype() == "proteomics") { - shiny::selectInput( - ns("proteomics_type"), - label = "Proteomics type:", - choices = c("MS", "Olink NPX"), - selected = "MS", - width = "150px" - ) - } else { - NULL - } - }) - is.olink <- shiny::reactive({ req(upload_datatype()) if (upload_datatype() == "proteomics" && !is.null(input$proteomics_type)) { diff --git a/components/board.upload/R/upload_ui.R b/components/board.upload/R/upload_ui.R index e10f7a8c1..608bd3b91 100644 --- a/components/board.upload/R/upload_ui.R +++ b/components/board.upload/R/upload_ui.R @@ -63,6 +63,15 @@ UploadUI <- function(id) { ) ), + shiny::conditionalPanel( + condition = sprintf("input['%s'] == 'proteomics'", ns("selected_datatype")), + div(style = "width: 22%;", + shiny::selectInput(ns("proteomics_type"), + label = tags$b("Proteomics type:"), choices = c("MS", "Olink NPX"), + selected = "MS", width = "150px") + ) + ), + div( p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), shiny::selectInput( From 5b0703f8af49797bb339d35cfba16cbb484ebff8 Mon Sep 17 00:00:00 2001 From: zitoa Date: Thu, 14 Aug 2025 16:48:19 +0200 Subject: [PATCH 08/23] add timer to success box --- components/board.upload/R/upload_module_preview_counts.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 78d37bc87..aa8e9e83e 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -195,7 +195,7 @@ upload_table_preview_counts_server <- function( if (!is.null(GEO)) { if (!GEO_alert_shown()) { msg <- paste0("Success! ", ID, " found in ", GEO[["source"]], ".\nWe're preparing it...") - shinyalert::shinyalert(text = msg, type = "success") + shinyalert::shinyalert(text = msg, type = "success", timer = 4000) GEO_alert_shown(TRUE) } uploaded$counts.csv <- GEO[["counts"]] From 38ee72ee0a002deb4fc774bb3a297320a2b07983 Mon Sep 17 00:00:00 2001 From: zitoa Date: Thu, 14 Aug 2025 17:08:58 +0200 Subject: [PATCH 09/23] polishing --- components/board.upload/R/upload_module_preview_counts.R | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index aa8e9e83e..a105c5c9a 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -182,16 +182,17 @@ upload_table_preview_counts_server <- function( ID <- public_dataset_id() msg <- paste0("Retrieving ", ID, " from GEO, ReCount, or ArrayExpress...
", "Please wait. Most datasets take 2-3 mins.") + showModal(modalDialog( div(id = "custom-progress-modal", HTML(msg), div(id = "custom-progress-container", div(id = "custom-progress-bar"))), footer = NULL, fade = FALSE)) - progress <- shiny::Progress$new(session, min = 0, max = 100) + progress <- shiny::Progress$new(session, min = 0, max = 100) GEO <- tryCatch({ playbase::pgx.getGEOseries(accession = ID, get.info = FALSE)}, - error = function(w) { NULL }) + error = function(w) { NULL }) removeModal() - + if (!is.null(GEO)) { if (!GEO_alert_shown()) { msg <- paste0("Success! ", ID, " found in ", GEO[["source"]], ".\nWe're preparing it...") From c40d9b8f7309a664ce6768da53a62515850c9b38 Mon Sep 17 00:00:00 2001 From: zitoa Date: Mon, 18 Aug 2025 18:07:43 +0200 Subject: [PATCH 10/23] add specification --- components/board.upload/R/upload_server.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 8627bfeb4..cb85df052 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -1194,7 +1194,7 @@ UploadBoard <- function(id, caption = "This is the uploaded counts data.", upload_datatype = upload_datatype, is.olink = is.olink, - public_dataset_id = public_dataset_id + public_dataset_id = public_dataset_id ## accession ID ) upload_table_preview_samples_server( From 9c04425bdf4029ee3ca4156c9a91110dc6a3d9d5 Mon Sep 17 00:00:00 2001 From: zitoa Date: Tue, 19 Aug 2025 16:12:39 +0200 Subject: [PATCH 11/23] fixes to display public metadata --- .../R/upload_module_preview_counts.R | 10 ++-- .../R/upload_module_preview_samples.R | 54 +++++++++++++++---- components/board.upload/R/upload_server.R | 4 +- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index a105c5c9a..703e55375 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -189,8 +189,8 @@ upload_table_preview_counts_server <- function( div(id = "custom-progress-bar"))), footer = NULL, fade = FALSE)) progress <- shiny::Progress$new(session, min = 0, max = 100) - GEO <- tryCatch({ playbase::pgx.getGEOseries(accession = ID, get.info = FALSE)}, - error = function(w) { NULL }) + GEO <- tryCatch({ playbase::pgx.getGEOseries(accession = ID, archs.h5 = NULL, get.info = FALSE)}, + error = function(w) { NULL }) removeModal() if (!is.null(GEO)) { @@ -199,9 +199,13 @@ upload_table_preview_counts_server <- function( shinyalert::shinyalert(text = msg, type = "success", timer = 4000) GEO_alert_shown(TRUE) } + dbg("-----------------MNT1: source = ", GEO[["source"]]) + dbg("-----------------MNT2: dim(samples) = ", dim(GEO[["samples"]])) + dbg("-----------------MNT3: colnames(samples) = ", colnames(GEO[["samples"]])) uploaded$counts.csv <- GEO[["counts"]] uploaded$samples.csv <- GEO[["samples"]] - GEO <- NULL + dbg("-----------------MNT4: dim(uploaded$samples.csv) = ", dim(uploaded$samples.csv)) + #GEO <- NULL } if (!is.null(uploaded$counts.csv)) { diff --git a/components/board.upload/R/upload_module_preview_samples.R b/components/board.upload/R/upload_module_preview_samples.R index b60156bf7..c61ae756d 100644 --- a/components/board.upload/R/upload_module_preview_samples.R +++ b/components/board.upload/R/upload_module_preview_samples.R @@ -21,15 +21,31 @@ upload_table_preview_samples_server <- function( title, info.text, caption, - upload_datatype) { + upload_datatype, + public_dataset_id + ) { moduleServer(id, function(input, output, session) { ns <- session$ns + public_metadata_full <- shiny::reactiveVal(NULL) + shiny::observe({ + if (public_dataset_id() != "" && !is.null(uploaded$samples.csv)) { + orig_sample_matrix(uploaded$samples.csv) + if (is.null(public_metadata_full())) { + public_metadata_full(orig_sample_matrix()) + } + } + }) + table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$samples.csv)) - dt <- orig_sample_matrix() + dt <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + public_metadata_full() + } else { + orig_sample_matrix() + } nrow0 <- nrow(dt) ncol0 <- ncol(dt) MAXSHOW <- 100 @@ -50,25 +66,43 @@ upload_table_preview_samples_server <- function( dt <- dt[, vars_selected, drop = FALSE] uploaded$samples.csv <- dt loaded_samples(TRUE) - dt + return(dt) }) shiny::observeEvent(input$vars_selected, { - if (all(input$vars_selected %in% colnames(orig_sample_matrix()))) { + dt_cols <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + colnames(public_metadata_full()) + } else { + colnames(orig_sample_matrix()) + } + if (all(input$vars_selected %in% dt_cols)) { vars_selected(input$vars_selected) } }) - - shiny::observeEvent(orig_sample_matrix(), { - vars_selected(colnames(orig_sample_matrix())) + + shiny::observe({ + cols <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + colnames(public_metadata_full()) + } else { + colnames(orig_sample_matrix()) + } + current_selected <- vars_selected() + if (is.null(current_selected) || length(current_selected) == 0 || !all(current_selected %in% cols)) { + vars_selected(cols) + } }) output$col_sel <- renderUI({ + choices <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + colnames(public_metadata_full()) + } else { + colnames(orig_sample_matrix()) + } shiny::checkboxGroupInput( ns("vars_selected"), label = "Retain variable:", - choices = colnames(orig_sample_matrix()), - selected = colnames(orig_sample_matrix()), + choices = choices, + selected = vars_selected(), inline = TRUE ) }) @@ -125,7 +159,7 @@ upload_table_preview_samples_server <- function( div( bslib::as_fill_carrier(), - if (!loaded_samples()) { + if (!loaded_samples() && public_dataset_id() == "") { bslib::layout_columns( col_widths = c(-3, 6, -3), row_heights = list("auto", 8, 1, 2), diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index cb85df052..a24f080a3 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -394,6 +394,7 @@ UploadBoard <- function(id, { ## get uploaded counts df0 <- uploaded$samples.csv + if (is.null(df0)) { return(list(status = "Missing samples.csv", matrix = NULL)) } ## Single matrix counts check @@ -1210,7 +1211,8 @@ UploadBoard <- function(id, title = "Uploaded Samples", info.text = "This is the uploaded samples data.", caption = "This is the uploaded samples data.", - upload_datatype = upload_datatype + upload_datatype = upload_datatype, + public_dataset_id = public_dataset_id ## accession ID ) modified_ct <- upload_table_preview_contrasts_server( From 56e5b86e26b3a90792751b46961c2421439288b8 Mon Sep 17 00:00:00 2001 From: zitoa Date: Tue, 19 Aug 2025 16:54:58 +0200 Subject: [PATCH 12/23] polishing --- components/board.upload/R/upload_module_preview_counts.R | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 703e55375..3548f34c3 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -199,12 +199,8 @@ upload_table_preview_counts_server <- function( shinyalert::shinyalert(text = msg, type = "success", timer = 4000) GEO_alert_shown(TRUE) } - dbg("-----------------MNT1: source = ", GEO[["source"]]) - dbg("-----------------MNT2: dim(samples) = ", dim(GEO[["samples"]])) - dbg("-----------------MNT3: colnames(samples) = ", colnames(GEO[["samples"]])) uploaded$counts.csv <- GEO[["counts"]] uploaded$samples.csv <- GEO[["samples"]] - dbg("-----------------MNT4: dim(uploaded$samples.csv) = ", dim(uploaded$samples.csv)) #GEO <- NULL } From 47f3a804db0c358995008e4024a0be25d893ea6a Mon Sep 17 00:00:00 2001 From: zitoa Date: Tue, 19 Aug 2025 17:09:24 +0200 Subject: [PATCH 13/23] polishing and set GEO NULL --- components/board.upload/R/upload_module_preview_counts.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 3548f34c3..95680ad2a 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -201,7 +201,8 @@ upload_table_preview_counts_server <- function( } uploaded$counts.csv <- GEO[["counts"]] uploaded$samples.csv <- GEO[["samples"]] - #GEO <- NULL + cm <- intersect(colnames(GEO[["counts"]]), rownames(GEO[["samples"]])) + GEO <- NULL } if (!is.null(uploaded$counts.csv)) { From ca65631daaa4e7731bb1fb5ce8f6373431fb4a2a Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Wed, 20 Aug 2025 15:57:55 +0200 Subject: [PATCH 14/23] remove unneded alerts --- components/board.upload/R/upload_module_preview_counts.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 95680ad2a..8c714db7e 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -188,7 +188,6 @@ upload_table_preview_counts_server <- function( div(id = "custom-progress-container", div(id = "custom-progress-bar"))), footer = NULL, fade = FALSE)) - progress <- shiny::Progress$new(session, min = 0, max = 100) GEO <- tryCatch({ playbase::pgx.getGEOseries(accession = ID, archs.h5 = NULL, get.info = FALSE)}, error = function(w) { NULL }) removeModal() @@ -196,7 +195,6 @@ upload_table_preview_counts_server <- function( if (!is.null(GEO)) { if (!GEO_alert_shown()) { msg <- paste0("Success! ", ID, " found in ", GEO[["source"]], ".\nWe're preparing it...") - shinyalert::shinyalert(text = msg, type = "success", timer = 4000) GEO_alert_shown(TRUE) } uploaded$counts.csv <- GEO[["counts"]] From 63ec8a811aa6a6a4dd4422abb517da86849022ea Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Wed, 20 Aug 2025 15:58:28 +0200 Subject: [PATCH 15/23] remove inserted html/move style to scss --- .../R/upload_module_preview_counts.R | 60 ------------------- scss/components/_progress.scss | 43 +++++++++++++ 2 files changed, 43 insertions(+), 60 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 8c714db7e..8438fdd6a 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -37,66 +37,6 @@ upload_table_preview_counts_server <- function( GEO_alert_shown <- reactiveVal(FALSE) - shiny::insertUI( - selector = "head", - where = "beforeEnd", - ui = list( - tags$style(HTML(" - #custom-progress-modal { - position: fixed; - top: 50% !important; - left: 50% !important; - transform: translate(-50%, -50%); - background-color: #ffffff; - color: black; - padding: 30px 50px; - font-size: 20px; - font-weight: bold; - border-radius: 10px; - z-index: 1050; - text-align: center; - } - #custom-progress-bar { - height: 15px; - background-color: #007bff; - width: 40%; - transition: width 0.3s ease; - color: white; - font-weight: bold; - line-height: 25px; - animation: pulse-blue 2s infinite; - transform-origin: center; - } - @keyframes pulse-blue { - 0% { box-shadow: 0 0 8px 2px #007bff; - transform: scale(1.2); } - 50% { box-shadow: 0 0 18px 8px #3399ff; - transform: scale(1.4); } - 100% { box-shadow: 0 0 8px 2px #007bff; - transform: scale(1); } - } - #custom-progress-container { - width: 100%; - background-color: #e9ecef; - border-radius: 0.25rem; - overflow: hidden; - margin-top: 15px; - } - .shiny-notification{ display: none !important; } - ")), - tags$script(HTML(" - Shiny.addCustomMessageHandler('updateProgressBar', function(message) { - var val = message.value; - var pb = document.getElementById('custom-progress-bar'); - if(pb) { - pb.style.width = val + '%'; - pb.textContent = val + '%'; - } - }); - ")) - ) - ) - table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$counts.csv)) dt <- uploaded$counts.csv diff --git a/scss/components/_progress.scss b/scss/components/_progress.scss index f0b9ae0f1..49f1ca82a 100644 --- a/scss/components/_progress.scss +++ b/scss/components/_progress.scss @@ -34,4 +34,47 @@ html { display: block; } + #custom-progress-modal { + position: fixed; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%); + background-color: #ffffff; + color: black; + padding: 30px 50px; + font-size: 20px; + font-weight: bold; + border-radius: 10px; + z-index: 1050; + text-align: center; + } + + #custom-progress-bar { + height: 15px; + background-color: #007bff; + width: 40%; + transition: width 0.3s ease; + color: white; + font-weight: bold; + line-height: 25px; + animation: pulse-blue 2s infinite; + transform-origin: center; + } + + @keyframes pulse-blue { + 0% { box-shadow: 0 0 8px 2px #007bff; + transform: scale(1.2); } + 50% { box-shadow: 0 0 18px 8px #3399ff; + transform: scale(1.4); } + 100% { box-shadow: 0 0 8px 2px #007bff; + transform: scale(1); } + } + + #custom-progress-container { + width: 100%; + background-color: #e9ecef; + border-radius: 0.25rem; + overflow: hidden; + margin-top: 15px; + } } \ No newline at end of file From 6fa743d63caff1bcf01994aa6698566aa46fce93 Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Wed, 20 Aug 2025 15:58:41 +0200 Subject: [PATCH 16/23] open sidebar on data upload --- components/modules/WelcomeBoard.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/modules/WelcomeBoard.R b/components/modules/WelcomeBoard.R index 7dd56ee9d..cd8d8ba48 100644 --- a/components/modules/WelcomeBoard.R +++ b/components/modules/WelcomeBoard.R @@ -169,6 +169,8 @@ WelcomeBoard <- function(id, auth, load_example, new_upload) { input$btn_upload_new }, { + bigdash.openSettings(lock = TRUE) + bigdash.openSidebar() bigdash.selectTab(session, selected = "upload-tab") } ) From 2f041104b9c70dede6584f9710e57e4c911bc110 Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Wed, 20 Aug 2025 16:02:29 +0200 Subject: [PATCH 17/23] handle public data selectors --- components/board.upload/R/upload_server.R | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index a24f080a3..0be5ab003 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -104,6 +104,7 @@ UploadBoard <- function(id, names(all_species) <- paste0(all_species," (",common_name,")") names(all_species)[all_species=="No organism"] <- "" shiny::updateSelectizeInput(session, "selected_organism", choices = all_species, server = TRUE) + shiny::updateSelectizeInput(session, "selected_organism_public", choices = all_species, server = TRUE) }) is.olink <- shiny::reactive({ @@ -722,6 +723,16 @@ UploadBoard <- function(id, upload_organism(input$selected_organism) }) + observeEvent(input$selected_datatype_public, { + upload_datatype(input$selected_datatype_public) + updateSelectInput(session, "selected_datatype", selected = input$selected_datatype_public) + }) + + observeEvent(input$selected_organism_public, { + upload_organism(input$selected_organism_public) + updateSelectInput(session, "selected_organism", selected = input$selected_organism_public) + }) + observeEvent(input$dataset_identifier, { public_dataset_id(input$dataset_identifier) }) From 357edde4820d61483012f5f632ee47b7fa0b2193 Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Wed, 20 Aug 2025 16:02:34 +0200 Subject: [PATCH 18/23] reshufle public data upload UI --- components/board.upload/R/upload_ui.R | 218 +++++++++++++------------- 1 file changed, 105 insertions(+), 113 deletions(-) diff --git a/components/board.upload/R/upload_ui.R b/components/board.upload/R/upload_ui.R index 608bd3b91..fcb0fc3c5 100644 --- a/components/board.upload/R/upload_ui.R +++ b/components/board.upload/R/upload_ui.R @@ -12,121 +12,115 @@ UploadUI <- function(id) { bslib::layout_columns( fill = TRUE, div( - style = "display: flex; flex-direction: column; align-items: flex-start; gap: 20px; margin-bottom: 150px; margin-top: 250px;", - - div( - style = "display: flex; flex-direction: row; align-items: center; gap: 20px;", - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 0 && input['%s'] == 0", ns("public_data_opts"), ns("show_upload_opts")), - shiny::actionButton(ns("show_upload_opts"), "Upload your data", class = "btn-primary upload-btn-large"), - shiny::actionButton(ns("public_data_opts"), "Retrieve public data", class = "btn-primary upload-btn-large") - ) - ), - br(), - - tags$style(HTML(" - .upload-btn-large { - font-size: 1.6em; - padding: 20px 45px; - min-width: 260px; - border-radius: 8px; - margin-left: 20vw; - display: block; - box-shadow: 0 2px 16px rgba(0,0,0,0.13); - } - .upload-btn-wrapper { - width: 100%; - display: flex; - justify-content: flex-start; - margin: 60px 5vw 0 0; - } - ")), - - shiny::conditionalPanel( - condition = sprintf("input['%s'] > 0", ns("show_upload_opts")), - div( - style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", - div( - style = "width: 60%;", - bs_alert("To upload your own data, you should prepare at least two CSV files: an counts.csv file (containing your experiment data) and a samples.csv file (containing your sample information). A third contrasts.csv file (describing your comparisons) is optional. Read more about data preparation here.", - closable = FALSE, translate = TRUE, html = TRUE) - ), - br(), - - div( - p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - ns("selected_datatype"), NULL, - choices = c("RNA-seq", "mRNA microarray", "proteomics", "scRNA-seq", - "metabolomics (beta)" = "metabolomics", "multi-omics (beta)" = "multi-omics"), - selected = DEFAULTS$datatype, width = "400px" - ) - ), - - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'proteomics'", ns("selected_datatype")), - div(style = "width: 22%;", - shiny::selectInput(ns("proteomics_type"), - label = tags$b("Proteomics type:"), choices = c("MS", "Olink NPX"), - selected = "MS", width = "150px") - ) - ), - - div( - p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - inputId = ns("selected_organism"), label = NULL, - choices = NULL, multiple = FALSE, width = "400px" - ) - ), - br(), - - shiny::actionButton(ns("start_upload"), "Start upload", class = "btn-primary"), - br() - ) - ), - - shiny::conditionalPanel( - condition = sprintf("input['%s'] > 0", ns("public_data_opts")), - div( - style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", - div( - style = "width: 60%;", - bs_alert("The 'Retrieve public data' functionality in OPG allows to query large repositories of publically available data to retrieve a specific dataset. You will need the dataset's unique identifier, such as the GEO ID. At the moment, GEO, ReCount, and ArrayExpress repositories are queried.", - closable = FALSE, translate = TRUE, html = TRUE) - ), - br(), - - div( - p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - ns("selected_datatype"), NULL, - choices = c("RNA-seq", "mRNA microarray"), - selected = "RNA-seq", width = "400px" - ) - ), - + style = "margin-top: 40px;", + tabsetPanel( + id = ns("upload_tabs"), + type = "tabs", + # Upload your own data tab + tabPanel( + "Upload your data", + value = "upload", div( - p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - inputId = ns("selected_organism"), label = NULL, - choices = playbase::SPECIES_TABLE$species_name, multiple = FALSE, width = "400px" - ) - ), - - br(), + style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 40px;", + div( + style = "width: 60%;", + bs_alert("To upload your own data, you should prepare at least two CSV files: an counts.csv file (containing your experiment data) and a samples.csv file (containing your sample information). A third contrasts.csv file (describing your comparisons) is optional. Read more about data preparation here.", closable = FALSE, translate = TRUE, html = TRUE) + ), + br(), + div( + p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + ns("selected_datatype"), NULL, + choices = c( + "RNA-seq", + "mRNA microarray", + "proteomics", + "scRNA-seq", + "metabolomics (beta)" = "metabolomics", + "multi-omics (beta)" = "multi-omics" + ), + selected = DEFAULTS$datatype, + width = "400px" + ), + shiny::uiOutput(ns("proteomics_subtype_ui")) + ), + div( + p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + inputId = ns("selected_organism"), + label = NULL, + choices = NULL, + multiple = FALSE, + width = "400px" + ) + ), + br(), + shiny::actionButton( + ns("start_upload"), + "Start upload", + class = "btn-primary" + ), + br() + ) + ), + + # Retrieve public datasets tab + tabPanel( + "Retrieve public datasets", + value = "public", div( - p("Dataset identifier:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::textInput(ns("dataset_identifier"), label = NULL, width = "400px") - ), - - br(), - shiny::actionButton(ns("start_search"), "Start search & download", class = "btn-primary"), - br() + style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 40px;", + div( + style = "width: 60%;", + bs_alert("The 'Retrieve public data' functionality in OPG allows to query large repositories of publically available data to retrieve a specific dataset. You will need the dataset's unique identifier, such as the GEO ID. At the moment, GEO, recount3, and ArrayExpress repositories are queried.", closable = FALSE, translate = TRUE, html = TRUE) + ), + br(), + div( + p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + ns("selected_datatype_public"), NULL, + choices = c( + "RNA-seq", + "mRNA microarray" + ), + selected = "RNA-seq", + width = "400px" + ) + ), + div( + p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + inputId = ns("selected_organism_public"), + label = NULL, + choices = NULL, + multiple = FALSE, + width = "400px" + ) + ), + div( + p("Dataset identifier:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::textInput( + ns("dataset_identifier"), + label = NULL, + placeholder = "e.g., GSE12345, E-GEOD-12345", + width = "400px" + ), + div( + style = "font-size: 0.85em; color: #666; margin-top: 5px;", + "Supported: GEO (GSE), ArrayExpress (E-), recount3 datasets" + ) + ), + br(), + shiny::actionButton( + ns("start_search"), + "Retrieve dataset", + class = "btn-primary" + ), + br() + ) ) - ), - ) + ) ) ) @@ -135,7 +129,5 @@ UploadUI <- function(id) { uiOutput(ns("upload_wizard")), body ) - return(ui) - } From 3810d0fdc6185351d8925352296b9158acd812c4 Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Thu, 11 Sep 2025 16:39:07 +0200 Subject: [PATCH 19/23] fix: maintain orig sample matrix for public data --- .../R/upload_module_preview_samples.R | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_samples.R b/components/board.upload/R/upload_module_preview_samples.R index c61ae756d..09d4e5d9f 100644 --- a/components/board.upload/R/upload_module_preview_samples.R +++ b/components/board.upload/R/upload_module_preview_samples.R @@ -29,23 +29,15 @@ upload_table_preview_samples_server <- function( ns <- session$ns - public_metadata_full <- shiny::reactiveVal(NULL) shiny::observe({ - if (public_dataset_id() != "" && !is.null(uploaded$samples.csv)) { + if (is.null(orig_sample_matrix()) && !is.null(uploaded$samples.csv)) { orig_sample_matrix(uploaded$samples.csv) - if (is.null(public_metadata_full())) { - public_metadata_full(orig_sample_matrix()) - } } }) table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$samples.csv)) - dt <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { - public_metadata_full() - } else { - orig_sample_matrix() - } + dt <- orig_sample_matrix() nrow0 <- nrow(dt) ncol0 <- ncol(dt) MAXSHOW <- 100 @@ -70,22 +62,14 @@ upload_table_preview_samples_server <- function( }) shiny::observeEvent(input$vars_selected, { - dt_cols <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { - colnames(public_metadata_full()) - } else { - colnames(orig_sample_matrix()) - } + dt_cols <- colnames(orig_sample_matrix()) if (all(input$vars_selected %in% dt_cols)) { vars_selected(input$vars_selected) } }) shiny::observe({ - cols <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { - colnames(public_metadata_full()) - } else { - colnames(orig_sample_matrix()) - } + cols <- colnames(orig_sample_matrix()) current_selected <- vars_selected() if (is.null(current_selected) || length(current_selected) == 0 || !all(current_selected %in% cols)) { vars_selected(cols) @@ -93,11 +77,7 @@ upload_table_preview_samples_server <- function( }) output$col_sel <- renderUI({ - choices <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { - colnames(public_metadata_full()) - } else { - colnames(orig_sample_matrix()) - } + choices <- colnames(orig_sample_matrix()) shiny::checkboxGroupInput( ns("vars_selected"), label = "Retain variable:", From 40552534d83bd0c6db0fc69a56f40271ed2f74ae Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Thu, 2 Oct 2025 14:21:19 +0200 Subject: [PATCH 20/23] fix merge --- .../R/upload_module_preview_counts.R | 88 +------------------ 1 file changed, 1 insertion(+), 87 deletions(-) diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index 9dde1b975..78b0a1cba 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -141,92 +141,7 @@ upload_table_preview_counts_server <- function( cm <- intersect(colnames(GEO[["counts"]]), rownames(GEO[["samples"]])) GEO <- NULL } - div( - bslib::as_fill_carrier(), - style = "width: 100%; display: flex; ", - if (is.null(uploaded$counts.csv)) { - if (upload_datatype() == "proteomics") { - msg <- "The counts file (counts.csv) contains the gene counts for all samples. For proteomics data types other than Olink NPX, the file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample. For Olink NPX, the uploaded file needs to be the standard Olink format." - } else { - msg <- "The counts file (counts.csv) contains the gene counts for all samples. The file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample." - } - bslib::layout_columns( - col_widths = c(-3, 6, -3), - row_heights = list("auto", 8, 1, 2), - gap = "0.5rem", - bslib::as_fill_carrier(bs_alert(tspan(msg), closable = FALSE, translate_js = FALSE)), - bslib::card( - if (upload_datatype() == "multi-omics") { - shiny::radioButtons( - ns("data_source"), - label = "Select input files from:", - choices = c("multi-csv", "pgx", "single-csv"), - selected = "multi-csv", - inline = TRUE - ) - }, - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'pgx'", ns("data_source")), - div( - div( - style = "margin-bottom: 15px;", - shiny::radioButtons( - ns("data_processing"), - label = "Select data processing level:", - choices = c("Raw" = "raw", "Normalized (also batch corrected if selected on computation)" = "normalized"), - selected = "raw", - inline = TRUE - ) - ), - div( - style = "display: flex; align-items: center; gap: 10px; margin-bottom: 10px;", - span("Selected:", style = "font-weight: bold;"), - textOutput(ns("selected_rows_text")), - ), - div( - style = "height: 350px; overflow-y: auto;", - DT::DTOutput(ns("available_data_table")) - ), - style = "width: 100%; max-height: 400px; overflow-y: auto;" - ), - selection = "multiple", - options = list(pageLength = 5, dom = "tp", scrollY = TRUE) - ) - }, - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'multi-csv'", ns("data_source")), - shiny::uiOutput(ns("dynamic_file_inputs")) # , - ) - }, - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'single-csv'", ns("data_source")), - fileInputArea( - ns("counts_csv"), - shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), - multiple = FALSE, - accept = c(".csv"), - width = "100%" - ) - ) - }, - if (upload_datatype() != "multi-omics") { - fileInputArea( - ns("counts_csv"), - shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), - multiple = FALSE, - accept = c(".csv"), - width = "100%" - ) - }, - style = "background-color: aliceblue; border: 0.07rem dashed steelblue;" - ), - action_buttons, - br() - ) - }, + if (!is.null(uploaded$counts.csv)) { bslib::layout_columns( col_widths = 12, @@ -255,7 +170,6 @@ upload_table_preview_counts_server <- function( } } else { - div( bslib::as_fill_carrier(), style = "width: 100%; display: flex; ", From beae8ca6db641099b07e164d5b7171c987dee31b Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Thu, 2 Oct 2025 14:27:37 +0200 Subject: [PATCH 21/23] fix merge2 --- components/board.upload/R/upload_server.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 1614339ab..227fcfecd 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -109,6 +109,7 @@ UploadBoard <- function(id, } else { shiny::updateSelectizeInput(session, "selected_datatype", choices = c("RNA-seq", "mRNA microarray", "proteomics", "scRNA-seq", "metabolomics (beta)" = "metabolomics"), selected = DEFAULTS$datatype) } + }) output$proteomics_subtype_ui <- shiny::renderUI({ if (upload_datatype() == "proteomics") { @@ -329,7 +330,7 @@ UploadBoard <- function(id, return(list(res = res, olink = olink)) } - ) + }) checked_counts <- shiny::eventReactive( { From 6245f412d24623b64980122a2373569f3be402c0 Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Fri, 3 Oct 2025 11:51:59 +0200 Subject: [PATCH 22/23] fix: move return line, was missing olink case --- components/board.upload/R/upload_server.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index 227fcfecd..08c4f2769 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -327,9 +327,8 @@ UploadBoard <- function(id, checked_for_log(TRUE) } } - - return(list(res = res, olink = olink)) } + return(list(res = res, olink = olink)) }) checked_counts <- shiny::eventReactive( From b71538e07d2dfbab8566b622153a197fd612ad45 Mon Sep 17 00:00:00 2001 From: ESCRI11 Date: Fri, 3 Oct 2025 11:52:15 +0200 Subject: [PATCH 23/23] fix: update loaded_samples when auto-filling them for olink --- components/board.upload/R/upload_module_preview_samples.R | 1 + 1 file changed, 1 insertion(+) diff --git a/components/board.upload/R/upload_module_preview_samples.R b/components/board.upload/R/upload_module_preview_samples.R index 8c7133b37..1737420b7 100644 --- a/components/board.upload/R/upload_module_preview_samples.R +++ b/components/board.upload/R/upload_module_preview_samples.R @@ -31,6 +31,7 @@ upload_table_preview_samples_server <- function( shiny::observe({ if (is.null(orig_sample_matrix()) && !is.null(uploaded$samples.csv)) { orig_sample_matrix(uploaded$samples.csv) + loaded_samples(TRUE) } })