From 0bcac55da9b4e840b5c71c8c1b1c19a43a2995c6 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Sun, 7 Jul 2024 16:33:18 +0200 Subject: [PATCH 01/75] Added: Database update system and initial hashing --- App.R | 161 +++++++++++++++++++++++++++------------------------------- 1 file changed, 75 insertions(+), 86 deletions(-) diff --git a/App.R b/App.R index 06f6e8b..ee08bfe 100644 --- a/App.R +++ b/App.R @@ -37,6 +37,7 @@ library(bslib) library(bsicons) library(DT) library(shinyBS) +library(openssl) # Bioconductor Packages library(treeio) library(ggtree) @@ -666,7 +667,6 @@ ui <- dashboardPage( column(1), column( width = 3, - align = "center", br(), br(), br(), @@ -718,32 +718,27 @@ ui <- dashboardPage( ), column( width = 2, - align = "center", br(), br(), br(), - actionButton( - "download_cgMLST", - label = "Download", - icon = icon("download") - ) + h5(textOutput("scheme_timestamp"), style = "color: white") ), column( - width = 6, + width = 2, br(), br(), br(), - align = "center", - conditionalPanel( - "input.download_cgMLST >= 1", - h4(p("Downloaded Loci"), style = "color:white") + actionButton( + "download_cgMLST", + label = "Download", + icon = icon("download") ) ) ), fluidRow( column(1), column( - width = 5, + width = 6, align = "center", br(), br(), @@ -753,21 +748,6 @@ ui <- dashboardPage( spin = "dots", color = "#ffffff" ) - ), - column( - width = 6, - align = "center", - br(), - br(), - br(), - conditionalPanel( - "input.download_cgMLST >= 1", - addSpinner( - dataTableOutput("cgmlst_targets"), - spin = "dots", - color = "#ffffff" - ) - ) ) ) ), @@ -5489,10 +5469,11 @@ server <- function(input, output, session) { phylotraceVersion <- paste("PhyloTrace-1.4.1", Sys.Date()) - # Kill server on session end - session$onSessionEnded( function() { - stopApp() - }) + # TODO Enable this, or leave disabled + # # Kill server on session end + # session$onSessionEnded( function() { + # stopApp() + # }) # Disable MST variable mappings shinyjs::disable('mst_edge_label') @@ -5736,6 +5717,30 @@ server <- function(input, output, session) { }) } + # Function to hash database + hash_database <- function(folder) { + loci_files <- list.files(folder) + loci_names <- sapply(strsplit(loci_files, "[.]"), function(x) x[1]) + loci_paths <- file.path(folder, loci_files) + + hashes <- sapply(loci_paths, hash_locus) + names(hashes) <- loci_names + hashes + } + + # Function to hash a locus + hash_locus <- function(locus_path) { + locus_file <- readLines(locus_path) + seq_list <- locus_file[seq(2, length(locus_file), 3)] + seq_hash <- sha256(seq_list) + seq_idx <- paste0(">", seq_hash) + + locus_file[seq(1, length(locus_file), 3)] <- seq_idx + writeLines(locus_file, locus_path) + + seq_hash + } + # Function to check single typing log file check_new_entry <- reactive({ @@ -6643,11 +6648,7 @@ server <- function(input, output, session) { # Produce Loci Info table DB$loci_info <- read.csv( - paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/targets.csv" - ), + file.path(DB$database, gsub(" ", "_", DB$scheme), "targets.csv"), header = TRUE, sep = "\t", row.names = NULL, @@ -11326,65 +11327,47 @@ server <- function(input, output, session) { } DB$load_selected <- TRUE - Scheme$target_table <- NULL + + # Check if .downloaded_schemes folder exists and if not create it + if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { + dir.create(file.path(DB$database, ".downloaded_schemes")) + } # Download Loci Fasta Files options(timeout = 600) tryCatch({ - download.file(Scheme$link_cgmlst, "dataset.zip") + download.file(Scheme$link_cgmlst, + file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip"))) "Download successful!" }, error = function(e) { paste("Error: ", e$message) }) unzip( - zipfile = "dataset.zip", - exdir = paste0( - DB$database, "/", - Scheme$folder_name, - paste0("/", Scheme$folder_name, "_alleles") + zipfile = file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")), + exdir = file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles") ) ) - unlink("dataset.zip") + # Hash database + hash_database(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) # Download Scheme Info download( Scheme$link_scheme, - dest = paste0(DB$database, "/", Scheme$folder_name, "/scheme_info.html"), - mode = "wb" - ) - - # Download Loci Info - download( - Scheme$link_targets, - dest = paste0(DB$database, "/", Scheme$folder_name, "/targets.csv"), + dest = file.path(DB$database, Scheme$folder_name, "scheme_info.html"), mode = "wb" ) # Send downloaded scheme to database browser overview DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) - Scheme$target_table <- - read.csv( - paste0(DB$database, "/", Scheme$folder_name, "/targets.csv"), - header = TRUE, - sep = "\t", - row.names = NULL, - colClasses = c( - "NULL", - "character", - "character", - "integer", - "integer", - "character", - "integer", - "NULL" - ) - ) - DB$exist <- (length(dir_ls(DB$database)) == 0) @@ -11420,27 +11403,33 @@ server <- function(input, output, session) { # Download Target Info (CSV Table) - - - output$cgmlst_scheme <- renderTable({ + observe({ + input$download_cgMLST + scheme_overview <- read_html(Scheme$link_scheme) %>% html_table(header = FALSE) %>% as.data.frame(stringsAsFactors = FALSE) + + last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], + format = "%B %d, %Y, %H:%M %p") names(scheme_overview) <- NULL - scheme_overview + + last_file_change <- format( + file.info(file.path(DB$database, + ".downloaded_schemes", + paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") + + output$cgmlst_scheme <- renderTable({scheme_overview}) + output$scheme_timestamp <- renderText({ + req(last_file_change) + if (last_file_change < last_scheme_change) { + "(Newer scheme available \u274c)" + } else { + "(Scheme is up-to-date \u2705)" + } + }) }) - ### Display Target Table ---- - - output$cgmlst_targets <- renderDataTable({ - targets_overview <- Scheme$target_table - NULL - }, - options = list(pageLength = 10, - columnDefs = list( - list(searchable = FALSE, targets = "_all") - ))) - # _______________________ #### ## Visualization ---- From 4686366c8fed9331b18c0736eb47801444fab191 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Wed, 10 Jul 2024 11:02:24 +0200 Subject: [PATCH 02/75] Adapted variant detection to hashed sequence indexes; minor fixes for scheme download --- App.R | 49 +++++++++++++++++++++----------------- execute/automatic_typing.R | 2 +- execute/single_typing.R | 18 ++++++-------- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/App.R b/App.R index ee08bfe..43f8b69 100644 --- a/App.R +++ b/App.R @@ -5482,25 +5482,6 @@ server <- function(input, output, session) { # Function to read and format FASTA sequences format_fasta <- function(filepath) { - log_message(log_file = out, - message = paste0("path: ", filepath), - append = TRUE) - - log_message(log_file = out, - message = paste0("db: ", DB$database), - append = TRUE) - - log_message(log_file = out, - message = paste0("scheme: ", DB$scheme), - append = TRUE) - - log_message(log_file = out, - message = paste0("selected: ", input$db_loci_rows_selected), - append = TRUE) - - log_message(log_file = out, - message = paste0("loci: ", head(DB$loci, 1)), - append = TRUE) fasta <- readLines(filepath) formatted_fasta <- list() @@ -11311,6 +11292,7 @@ server <- function(input, output, session) { }) observeEvent(input$download_cgMLST, { + log_message(out, message = paste0("Started download of scheme for ", Scheme$folder_name)) show_toast( @@ -11330,7 +11312,7 @@ server <- function(input, output, session) { # Check if .downloaded_schemes folder exists and if not create it if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { - dir.create(file.path(DB$database, ".downloaded_schemes")) + dir.create(file.path(DB$database, ".downloaded_schemes"), recursive = TRUE) } # Download Loci Fasta Files @@ -11365,11 +11347,34 @@ server <- function(input, output, session) { mode = "wb" ) + # Download Loci Info + download( + Scheme$link_targets, + dest = paste0(DB$database, "/", Scheme$folder_name, "/targets.csv"), + mode = "wb" + ) + # Send downloaded scheme to database browser overview DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) - DB$exist <- - (length(dir_ls(DB$database)) == 0) + Scheme$target_table <- read.csv( + paste0(DB$database, "/", Scheme$folder_name, "/targets.csv"), + header = TRUE, + sep = "\t", + row.names = NULL, + colClasses = c( + "NULL", + "character", + "character", + "integer", + "integer", + "character", + "integer", + "NULL" + ) + ) + + DB$exist <- length(dir_ls(DB$database)) == 0 show_toast( title = "Download successful", diff --git a/execute/automatic_typing.R b/execute/automatic_typing.R index 9656089..9407258 100644 --- a/execute/automatic_typing.R +++ b/execute/automatic_typing.R @@ -323,4 +323,4 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= log.message(log_file = paste0(meta_info$db_directory, "/logs/output.log"), message = paste0("Assembly typing failed for ", sub("\\.(fasta|fna|fa)$", "", basename(assembly)))) -} +} \ No newline at end of file diff --git a/execute/single_typing.R b/execute/single_typing.R index 624229e..8363587 100644 --- a/execute/single_typing.R +++ b/execute/single_typing.R @@ -42,7 +42,7 @@ template <- readLines(assembly) psl_files <- list.files(paste0(meta_info$db_directory, "/execute/blat_single/results"), pattern = "\\.psl$", full.names = TRUE) # Initialize an empty vector to store the results -allele_vector <- integer(length(psl_files)) +allele_vector <- character(length(psl_files)) event_df <- data.frame(Locus = character(0), Event = character(0), Value = character(0)) @@ -66,9 +66,6 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= matches <- data.table::fread(psl_files[i], select = c(1, 5, 6, 7, 8, 10, 11, 14, 16, 17), header = FALSE) - # variant count - n_variants <- max(matches$V10) - if(any(matches$V1 == matches$V11 & (matches$V5 + matches$V7) == 0)) { perf_match <- matches[which(matches$V1 == matches$V11)] @@ -105,16 +102,18 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # if valid variant found if(variant_valid != FALSE) { + hashed_variant <- openssl::sha256(variant_valid) + # Append new variant number to allele fasta file - cat(paste0("\n>", n_variants + 1), file = locus_file, append = TRUE) + cat(paste0("\n>", hashed_variant), file = locus_file, append = TRUE) # Append new variant sequence to allele fasta file cat(paste0("\n", variant_valid, "\n"), file = locus_file, append = TRUE) # Entry in results data frame - event_df <- rbind(event_df, data.frame(Locus = allele_index, Event = "New Variant", Value = as.character(n_variants + 1))) + event_df <- rbind(event_df, data.frame(Locus = allele_index, Event = "New Variant", Value = hashed_variant)) - allele_vector[[i]] <- n_variants + 1 + allele_vector[[i]] <- hashed_variant cat(paste0(allele_index, " has new variant.\n")) @@ -128,15 +127,12 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= cat(paste0(allele_index, " has invalid sequence.\n")) } - } } } saveRDS(event_df, "execute/event_df.rds") - allele_vector <- as.integer(allele_vector) - # Create Results Data Frame if(!any(grepl("Typing", list.files(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing)))))) { @@ -184,7 +180,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= Database[["Typing"]] <- Typing - df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 13:(12+length(list.files(allele_folder)))), function(x) as.integer(x)) + df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 13:(12+length(list.files(allele_folder)))), function(x) as.character(x)) df1 <- dplyr::select(Database$Typing, 1:12) df1 <- dplyr::mutate(df1, Include = as.logical(Include)) From 9bac2d3f30b75c7feb5787fc335cb719cecd177c Mon Sep 17 00:00:00 2001 From: fpaskali Date: Thu, 11 Jul 2024 17:52:28 +0200 Subject: [PATCH 03/75] Changed tab name 'Add Scheme' to 'Manage Schemes' --- App.R | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/App.R b/App.R index 43f8b69..3f3658e 100644 --- a/App.R +++ b/App.R @@ -651,7 +651,7 @@ ui <- dashboardPage( ) ), - ## Tab Add Scheme ---- + ## Tab Manage Schemes ---- tabItem( tabName = "init", @@ -721,7 +721,7 @@ ui <- dashboardPage( br(), br(), br(), - h5(textOutput("scheme_timestamp"), style = "color: white") + h5(textOutput("scheme_update_info"), style = "color: white") ), column( width = 2, @@ -6239,7 +6239,7 @@ server <- function(input, output, session) { DB$block_db <- TRUE DB$select_new <- FALSE - # Render menu with Add Scheme as start tab and no Missing values tab + # Render menu with Manage Schemes as start tab and no Missing values tab output$menu <- renderMenu( sidebarMenu( menuItem( @@ -6265,7 +6265,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus"), selected = TRUE @@ -6366,6 +6366,8 @@ server <- function(input, output, session) { log_message(log_file = out, message = "Missing loci files") + # TODO Check if changes are needed for robust update changes + # Show message that loci files are missing showModal( modalDialog( @@ -6381,7 +6383,7 @@ server <- function(input, output, session) { ) ) - # Render menu with Add Scheme as start tab + # Render menu with Manage Schemes as start tab output$menu <- renderMenu( sidebarMenu( menuItem( @@ -6412,7 +6414,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus"), selected = TRUE @@ -6435,6 +6437,8 @@ server <- function(input, output, session) { output$download_scheme_info <- NULL + # TODO check if changes are needed for robust update changes + log_message(log_file = out, message = "Scheme info file missing") # Show message that scheme info is missing @@ -6452,7 +6456,7 @@ server <- function(input, output, session) { ) ) - # Render menu with Add Scheme as start tab + # Render menu with Manage Schemes as start tab output$menu <- renderMenu( sidebarMenu( menuItem( @@ -6483,7 +6487,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus"), selected = TRUE @@ -6510,6 +6514,8 @@ server <- function(input, output, session) { log_message(log_file = out, message = "Missing loci info (targets.csv)") + # TODO check if changes are needed for robust update changes + # Show message that scheme info is missing showModal( modalDialog( @@ -6525,7 +6531,7 @@ server <- function(input, output, session) { ) ) - # Render menu with Add Scheme as start tab + # Render menu with Manage Schemes as start tab output$menu <- renderMenu( sidebarMenu( menuItem( @@ -6556,7 +6562,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus"), selected = TRUE @@ -6645,6 +6651,8 @@ server <- function(input, output, session) { ) ) + # TODO check if changes are needed for robust update + # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme if(DB$number_loci != length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { @@ -6665,7 +6673,7 @@ server <- function(input, output, session) { ) ) - # Render menu with Add Scheme as start tab + # Render menu with Manage Schemes as start tab output$menu <- renderMenu( sidebarMenu( menuItem( @@ -6696,7 +6704,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus"), selected = TRUE @@ -6861,7 +6869,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus") ), @@ -6909,7 +6917,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus") ), @@ -9069,7 +9077,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus") ), @@ -9408,7 +9416,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus") ), @@ -9452,7 +9460,7 @@ server <- function(input, output, session) { ) ), menuItem( - text = "Add Scheme", + text = "Manage Schemes", tabName = "init", icon = icon("plus") ), @@ -11425,7 +11433,7 @@ server <- function(input, output, session) { paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") output$cgmlst_scheme <- renderTable({scheme_overview}) - output$scheme_timestamp <- renderText({ + output$scheme_update_info <- renderText({ req(last_file_change) if (last_file_change < last_scheme_change) { "(Newer scheme available \u274c)" From dd0b1b3b50df25cf6c3d52553de6211d2470699f Mon Sep 17 00:00:00 2001 From: fpaskali Date: Sat, 20 Jul 2024 17:04:49 +0200 Subject: [PATCH 04/75] Database update system and hashing implemented --- App.R | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 14 deletions(-) diff --git a/App.R b/App.R index 3f3658e..0f39341 100644 --- a/App.R +++ b/App.R @@ -5722,6 +5722,33 @@ server <- function(input, output, session) { seq_hash } + # Get locus hashes + get_locus_hashes <- function(locus_path) { + locus_file <- readLines(locus_path) + hash_list <- locus_file[seq(1, length(locus_file), 3)] + hash_list <- sapply(strsplit(hash_list, "[>]"), function(x) x[2]) + } + + extract_seq <- function(locus_path, hashes) { + locus_file <- readLines(locus_path) + hash_list <- sapply(strsplit(locus_file[seq(1, length(locus_file), 3)], "[>]"), function(x) x[2]) + seq_list <- locus_file[seq(2, length(locus_file), 3)] + seq_idx <- hash_list %in% hashes + + list( + idx = hash_list[seq_idx], + seq = seq_list[seq_idx] + ) + } + + add_new_sequences <- function(locus_path, sequences) { + locus_file <- file(locus_path, open = "a+") + for (i in seq_along(sequences$idx)) { + writeLines(c("", paste0(">", sequences$idx[i]), sequences$seq[i]), locus_file) + } + close(locus_file) + } + # Function to check single typing log file check_new_entry <- reactive({ @@ -6366,8 +6393,6 @@ server <- function(input, output, session) { log_message(log_file = out, message = "Missing loci files") - # TODO Check if changes are needed for robust update changes - # Show message that loci files are missing showModal( modalDialog( @@ -6437,8 +6462,6 @@ server <- function(input, output, session) { output$download_scheme_info <- NULL - # TODO check if changes are needed for robust update changes - log_message(log_file = out, message = "Scheme info file missing") # Show message that scheme info is missing @@ -6514,8 +6537,6 @@ server <- function(input, output, session) { log_message(log_file = out, message = "Missing loci info (targets.csv)") - # TODO check if changes are needed for robust update changes - # Show message that scheme info is missing showModal( modalDialog( @@ -6651,8 +6672,6 @@ server <- function(input, output, session) { ) ) - # TODO check if changes are needed for robust update - # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme if(DB$number_loci != length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { @@ -11320,11 +11339,17 @@ server <- function(input, output, session) { # Check if .downloaded_schemes folder exists and if not create it if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { + print("Creating download schemes folder") dir.create(file.path(DB$database, ".downloaded_schemes"), recursive = TRUE) } - # Download Loci Fasta Files + # Check if remains of old temporary folder exists and remove them + if (dir.exists(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")))) { + print("Deleting old temporary folder") + unlink(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")), recursive = TRUE) + } + # Download Loci Fasta Files options(timeout = 600) tryCatch({ @@ -11335,18 +11360,93 @@ server <- function(input, output, session) { paste("Error: ", e$message) }) + print("Unzipping the scheme") + # Unzip the scheme in temporary folder unzip( zipfile = file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")), exdir = file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles") + paste0(Scheme$folder_name, ".tmp") ) ) - # Hash database + print("Producing hashes for the database") + # Hash temporary folder hash_database(file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"))) + paste0(Scheme$folder_name, ".tmp"))) + + # Get list from local database + local_db_filelist <- list.files(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) + if (!is_empty(local_db_filelist)) { + print("Old database is not empty, resolving the files!") + # Get list from temporary database + tmp_db_filelist <- list.files(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Find the difference (extra files in local database) + local_db_extra <- setdiff(local_db_filelist, tmp_db_filelist) + + # Copy extra files to temporary folder + file.copy(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), local_db_extra), + file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Check differences in file pairs + local_db_hashes <- tools::md5sum(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + local_db_filelist)) + tmp_db_hashes <- tools::md5sum(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + local_db_filelist)) + + diff_files <- local_db_hashes %in% tmp_db_hashes + diff_loci <- names(local_db_hashes)[diff_files == FALSE] + diff_loci <- sapply(strsplit(diff_loci, "/"), function(x) x[length(x)]) + + # Check locus hashes + for (locus in diff_loci) { + local_db_hashes <- get_locus_hashes(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + locus)) + tmp_db_hashes <- get_locus_hashes(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + locus)) + diff_hashes <- setdiff(local_db_hashes, tmp_db_hashes) + + sequences <- extract_seq(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + locus), diff_hashes) + if (!is_empty(sequences$idx) && !is_empty(sequences$seq) && + length(sequences$idx) == length(sequences$seq)) { + add_new_sequences(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + locus), sequences) + } + } + } + + print("Delete old alleles folder") + unlink(file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) + + print("Overwriting old alleles directory with temporary directory") + file.rename(file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp")), + file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) # Download Scheme Info download( @@ -11358,7 +11458,7 @@ server <- function(input, output, session) { # Download Loci Info download( Scheme$link_targets, - dest = paste0(DB$database, "/", Scheme$folder_name, "/targets.csv"), + dest = file.path(DB$database, Scheme$folder_name, "targets.csv"), mode = "wb" ) @@ -11366,7 +11466,7 @@ server <- function(input, output, session) { DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) Scheme$target_table <- read.csv( - paste0(DB$database, "/", Scheme$folder_name, "/targets.csv"), + file.path(DB$database, Scheme$folder_name, "targets.csv"), header = TRUE, sep = "\t", row.names = NULL, @@ -11392,6 +11492,8 @@ server <- function(input, output, session) { width = "400px" ) + # TODO Add log message regarding the update of the scheme + log_message(out, message = "Download successful") showModal( From 2b9ee2e706fbf6cdb82cec1e44204712536c263f Mon Sep 17 00:00:00 2001 From: fpaskali Date: Sat, 20 Jul 2024 17:53:08 +0200 Subject: [PATCH 05/75] Adapted variant detection to hashed sequence indexes --- execute/multi_eval.R | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/execute/multi_eval.R b/execute/multi_eval.R index a164c6f..7cb621b 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -48,7 +48,7 @@ template <- readLines(assembly) psl_files <- list.files(results_folder[which(sub("\\.(fasta|fna|fa)$", "", basename(assembly)) == basename(results_folder))], pattern = "\\.psl$", full.names = TRUE) # Initialize an empty vector to store the results -allele_vector <- integer(length(psl_files)) +allele_vector <- character(length(psl_files)) # Initiate results list if(length(assembly_folder) == 1) { @@ -118,16 +118,18 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # if valid variant found if(variant_valid != FALSE) { + hashed_variant <- openssl::sha256(variant_valid) + # Append new variant number to allele fasta file - cat(paste0("\n>", n_variants + 1), file = locus_file, append = TRUE) + cat(paste0("\n>", hashed_variant), file = locus_file, append = TRUE) # Append new variant sequence to allele fasta file cat(paste0("\n", variant_valid, "\n"), file = locus_file, append = TRUE) # Entry in results data frame - event_list[[basename(assembly)]] <- rbind(event_list[[basename(assembly)]], data.frame(Locus = allele_index, Event = "New Variant", Value = as.character(n_variants + 1))) + event_list[[basename(assembly)]] <- rbind(event_list[[basename(assembly)]], data.frame(Locus = allele_index, Event = "New Variant", Value = hashed_variant)) - allele_vector[[i]] <- n_variants + 1 + allele_vector[[i]] <- hashed_variant cat(paste0(allele_index, " has new variant.\n")) @@ -207,7 +209,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= Database[["Typing"]] <- Typing - df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 13:(12+length(list.files(allele_folder)))), function(x) as.integer(x)) + df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 13:(12+length(list.files(allele_folder)))), function(x) as.character(x)) df1 <- dplyr::select(Database$Typing, 1:12) df1 <- dplyr::mutate(df1, Include = as.logical(Include)) From d04d43ef30016aae1dd22db80a80711588c05ab1 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Sat, 20 Jul 2024 17:55:29 +0200 Subject: [PATCH 06/75] minor fix --- execute/multi_eval.R | 3 --- 1 file changed, 3 deletions(-) diff --git a/execute/multi_eval.R b/execute/multi_eval.R index 7cb621b..7e8e667 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -79,9 +79,6 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= matches <- data.table::fread(psl_files[i], select = c(1, 5, 6, 7, 8, 10, 11, 14, 16, 17), header = FALSE) - # variant count - n_variants <- max(matches$V10) - if(any(matches$V1 == matches$V11 & (matches$V5 + matches$V7) == 0)) { perf_match <- matches[which(matches$V1 == matches$V11)] From 04a81243d152338cf82de147fd00cf8a8aab755b Mon Sep 17 00:00:00 2001 From: fpaskali Date: Sun, 21 Jul 2024 19:53:00 +0200 Subject: [PATCH 07/75] Multi Typing bugfix --- execute/multi_eval.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execute/multi_eval.R b/execute/multi_eval.R index 7e8e667..6e5a560 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -124,7 +124,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= cat(paste0("\n", variant_valid, "\n"), file = locus_file, append = TRUE) # Entry in results data frame - event_list[[basename(assembly)]] <- rbind(event_list[[basename(assembly)]], data.frame(Locus = allele_index, Event = "New Variant", Value = hashed_variant)) + event_list[[basename(assembly)]] <- rbind(event_list[[basename(assembly)]], data.frame(Locus = allele_index, Event = "New Variant", Value = as.character(hashed_variant))) allele_vector[[i]] <- hashed_variant From 6f475b080e362b448c24f2c9a7db6b80ad4b252c Mon Sep 17 00:00:00 2001 From: fpaskali Date: Wed, 24 Jul 2024 21:27:46 +0200 Subject: [PATCH 08/75] Added show long hash switch --- App.R | 96 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 17 deletions(-) diff --git a/App.R b/App.R index 1de5b50..12a72fb 100644 --- a/App.R +++ b/App.R @@ -22046,20 +22046,44 @@ server <- function(input, output, session) { output$typing_result_table <- renderRHandsontable({ typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) if(nrow(typing_result_table) > 0) { + if (input$typing_results_longhash) { + renderer <- htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value; + } + td.innerHTML = value; + return td; + }" + ) + } else { + renderer <- htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + return td; + }" + ) + } + if(nrow(typing_result_table) > 15) { rhandsontable(typing_result_table, rowHeaders = NULL, stretchH = "all", height = 500, readOnly = TRUE, contextMenu = FALSE) %>% hot_cols(columnSorting = TRUE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(typing_result_table), valign = "htMiddle", halign = "htCenter") + hot_col(1:ncol(typing_result_table), valign = "htMiddle", halign = "htCenter") %>% + hot_col("Value", renderer = renderer) } else { rhandsontable(typing_result_table, rowHeaders = NULL, stretchH = "all", readOnly = TRUE, - contextMenu = FALSE,) %>% + contextMenu = FALSE) %>% hot_cols(columnSorting = TRUE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(typing_result_table), valign = "htMiddle", halign = "htCenter") + hot_col(1:ncol(typing_result_table), valign = "htMiddle", halign = "htCenter") %>% + hot_col("Value", renderer = renderer) } } }) @@ -22089,7 +22113,14 @@ server <- function(input, output, session) { HTML(paste("", n_new, if(n_new == 1) " locus with new variant." else " loci with new variants.")), - br(), br(), + br(), + materialSwitch( + "typing_results_longhash", + h5(p("Show Long Hash"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ), + br(), rHandsontableOutput("typing_result_table") ) } else { @@ -23467,23 +23498,45 @@ server <- function(input, output, session) { rowHeaders = NULL, stretchH = "all", readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) - + hot_col(1:3, valign = "htMiddle", halign = "htCenter") + }) } else { + if (input$multi_results_longhash) { + renderer <- NULL + } else { + renderer <- htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.verticalAlign = 'middle'; + td.style.textAlign = 'center'; + return td; + }" + ) + } + if(Typing$multi_table_length > 15) { output$multi_typing_result_table <- renderRHandsontable({ rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, stretchH = "all", height = 500, readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) + hot_col(1:3, valign = "htMiddle", halign = "htCenter") %>% + hot_col("Value", + renderer = renderer) + }) } else { output$multi_typing_result_table <- renderRHandsontable({ rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, stretchH = "all", readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) + hot_col(1:3, valign = "htMiddle", halign = "htCenter") %>% + hot_col("Value", + renderer = renderer) + }) } } @@ -23522,17 +23575,26 @@ server <- function(input, output, session) { width = 9, br(), br(), br(), br(), - br(), - div( - class = "mult_res_sel", - selectInput( - "multi_results_picker", - label = h5("Select Typing Results", style = "color:white"), - choices = names(Typing$result_list), - selected = names(Typing$result_list)[length(names(Typing$result_list))], + br(), + fluidRow( + div( + class = "mult_res_sel", + selectInput( + "multi_results_picker", + label = h5("Select Typing Results", style = "color:white"), + choices = names(Typing$result_list), + selected = names(Typing$result_list)[length(names(Typing$result_list))], + ) ) ), - br(), br(), + br(), + materialSwitch( + "multi_results_longhash", + h5(p("Show Long Hash"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ), + br(), rHandsontableOutput("multi_typing_result_table") ) ) From 9e1a6dd2780afab71193188b3e2d297d04dd79af Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Thu, 25 Jul 2024 15:42:33 +0200 Subject: [PATCH 09/75] Changes typing evaluation logic to consider ambiguous nucleotides, additions to status bar --- App.R | 465 ++++++----- execute/multi_eval.R | 14 +- execute/single_eval.R | 14 +- execute/variant_validation.R | 18 +- www/body.css | 1474 +++++++++++++++++----------------- www/head.css | 25 + 6 files changed, 1050 insertions(+), 960 deletions(-) diff --git a/App.R b/App.R index 12a72fb..0649108 100644 --- a/App.R +++ b/App.R @@ -280,6 +280,8 @@ ui <- dashboardPage( ) ) ), + uiOutput("databasetext"), + uiOutput("statustext"), tags$li(class = "dropdown", tags$span(id = "currentTime", style = "color:white; font-weight:bold;")), disable = FALSE @@ -5801,7 +5803,8 @@ server <- function(input, output, session) { progress = 0, progress_format_start = 0, progress_format_end = 0, - result_list = NULL) # reactive variables related to typing process + result_list = NULL, + status = "") # reactive variables related to typing process Vis <- reactiveValues(cluster = NULL, metadata = list(), @@ -5953,7 +5956,7 @@ server <- function(input, output, session) { }) observeEvent(input$db_location, { - log_print("Input db_location") + log_print("Input db_location") DB$select_new <- FALSE }) @@ -6110,7 +6113,79 @@ server <- function(input, output, session) { observeEvent(input$load, { - log_print("Input load") + log_print("Input load") + + observe({ + if(!is.null(DB$database)){ + output$databasetext <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Database:   ", + DB$database, + "")), + style = "color:white;") + ) + ) + }) + } + }) + + observe({ + if(!is.null(DB$database)) { + if(Typing$status == "Finalized"){ + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    typing finalized")), + style = "color:white;") + ) + ) + ) + } else if(Typing$status == "Attaching"){ + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    evaluating typing results")), + style = "color:white;") + ) + ) + ) + } else if(Typing$status == "Processing") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    running typing")), + style = "color:white;") + ) + ) + ) + } else { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    ready")), + style = "color:white;") + ) + ) + ) + } + } + }) # Null single typing status if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { @@ -6152,13 +6227,13 @@ server <- function(input, output, session) { title = "Directory already contains a database", type = "error", width = "500px", - position = "top-end", + position = "bottom-end", timer = 6000 ) DB$load_selected <- FALSE } else if(DB$select_new | (DB$select_new == FALSE & is.null(input$scheme_db))) { - + log_print(paste0("New database created in ", DB$new_database)) DB$check_new_entries <- TRUE @@ -6410,7 +6485,7 @@ server <- function(input, output, session) { output$download_scheme_info <- NULL - log_print("Scheme info file missing") + log_print("Scheme info file missing") # Show message that scheme info is missing showModal( @@ -6483,7 +6558,7 @@ server <- function(input, output, session) { # Dont render target download button output$download_loci <- NULL - log_print("Missing loci info (targets.csv)") + log_print("Missing loci info (targets.csv)") # Show message that scheme info is missing showModal( @@ -6623,7 +6698,7 @@ server <- function(input, output, session) { # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme if(DB$number_loci != length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { - log_print(paste0("Loci files are missing in the local ", DB$scheme, " folder")) + log_print(paste0("Loci files are missing in the local ", DB$scheme, " folder")) # Show message that loci files are missing showModal( @@ -8999,11 +9074,11 @@ server <- function(input, output, session) { } } else { - log_print("Invalid scheme folder") + log_print("Invalid scheme folder") show_toast( title = "Invalid scheme folder", type = "warning", - position = "top-end", + position = "bottom-end", width = "500px", timer = 4000 ) @@ -9012,6 +9087,12 @@ server <- function(input, output, session) { }) + # _______________________ #### + + ## Status ---- + + + # _______________________ #### ## Database ---- @@ -9353,7 +9434,7 @@ server <- function(input, output, session) { show_toast( title = "Invalid date", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "300px" ) @@ -9362,7 +9443,7 @@ server <- function(input, output, session) { show_toast( title = "Empty name", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "300px" ) @@ -9371,7 +9452,7 @@ server <- function(input, output, session) { show_toast( title = "Empty ID", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "300px" ) @@ -9384,16 +9465,13 @@ server <- function(input, output, session) { # Change scheme observeEvent(input$reload_db, { - fill1 <<- brewer.pal(3, input$upgma_clade_scale) - trest <<- input$upgma_clade_scale - log_print("Input reload_db") if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( title = "Pending Multi Typing", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -9401,7 +9479,7 @@ server <- function(input, output, session) { show_toast( title = "Pending Single Typing", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -9444,7 +9522,7 @@ server <- function(input, output, session) { # Undo db changes observeEvent(input$undo_changes, { - log_print("Input undo_changes") + log_print("Input undo_changes") DB$inhibit_change <- FALSE @@ -10186,34 +10264,34 @@ server <- function(input, output, session) { DB$count <- 0 observeEvent(input$add_new_variable, { - log_print("Input add_new_variable") + log_print("Input add_new_variable") if(nchar(input$new_var_name) > 12) { - log_print("Add variable; max. 10 character") + log_print("Add variable; max. 10 character") show_toast( title = "Max. 10 characters", type = "warning", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) } else { if (input$new_var_name == "") { - log_print("Add variable; min. 1 character") + log_print("Add variable; min. 1 character") show_toast( title = "Min. 1 character", type = "error", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) } else { if(trimws(input$new_var_name) %in% names(DB$meta)) { - log_print("Add variable; name already existing") + log_print("Add variable; name already existing") show_toast( title = "Variable name already existing", type = "warning", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) @@ -10239,7 +10317,7 @@ server <- function(input, output, session) { }) observeEvent(input$conf_new_var, { - log_print("Input conf_new_var") + log_print("Input conf_new_var") removeModal() @@ -10274,7 +10352,7 @@ server <- function(input, output, session) { show_toast( title = paste0("Variable ", trimws(input$new_var_name), " added"), type = "success", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) @@ -10282,14 +10360,14 @@ server <- function(input, output, session) { }) observeEvent(input$delete_new_variable, { - log_print("Input delete_new_variable") + log_print("Input delete_new_variable") if (input$del_which_var == "") { - log_print("Delete custom variables; no custom variable") + log_print("Delete custom variables; no custom variable") show_toast( title = "No custom variables", type = "error", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) @@ -10314,7 +10392,7 @@ server <- function(input, output, session) { }) observeEvent(input$conf_var_del, { - log_print("Input conf_var_del") + log_print("Input conf_var_del") DB$change <- TRUE @@ -10327,12 +10405,12 @@ server <- function(input, output, session) { show_toast( title = paste0("Variable ", input$del_which_var, " removed"), type = "warning", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) - log_print(paste0("Variable ", input$del_which_var, " removed")) + log_print(paste0("Variable ", input$del_which_var, " removed")) DB$cust_var <- DB$cust_var[-which(DB$cust_var$Variable == input$del_which_var),] DB$data <- select(DB$data, -(input$del_which_var)) @@ -10347,13 +10425,13 @@ server <- function(input, output, session) { # Select all button observeEvent(input$sel_all_entries, { - log_print("Input sel_all_entries") + log_print("Input sel_all_entries") DB$data$Include <- TRUE }) observeEvent(input$desel_all_entries, { - log_print("Input desel_all_entries") + log_print("Input desel_all_entries") DB$data$Include <- FALSE }) @@ -10361,7 +10439,7 @@ server <- function(input, output, session) { # Switch to entry table observeEvent(input$change_entries, { - log_print("Input change_entries") + log_print("Input change_entries") removeModal() updateTabItems(session, "tabs", selected = "db_browse_entries") @@ -10371,7 +10449,7 @@ server <- function(input, output, session) { output$download_na_matrix <- downloadHandler( filename = function() { - log_print(paste0("Save missing values table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv"))) + log_print(paste0("Save missing values table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv"))) paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv") }, content = function(file) { @@ -10384,7 +10462,7 @@ server <- function(input, output, session) { output$download_schemeinfo <- downloadHandler( filename = function() { - log_print(paste0("Save scheme info table ", paste0(gsub(" ", "_", DB$scheme), "_scheme.csv"))) + log_print(paste0("Save scheme info table ", paste0(gsub(" ", "_", DB$scheme), "_scheme.csv"))) paste0(gsub(" ", "_", DB$scheme), "_scheme.csv") }, @@ -10404,7 +10482,7 @@ server <- function(input, output, session) { output$download_loci_info <- downloadHandler( filename = function() { - log_print(paste0("Save loci info table ", paste0(gsub(" ", "_", DB$scheme), "_Loci.csv"))) + log_print(paste0("Save loci info table ", paste0(gsub(" ", "_", DB$scheme), "_Loci.csv"))) paste0(gsub(" ", "_", DB$scheme), "_Loci.csv") }, @@ -10423,7 +10501,7 @@ server <- function(input, output, session) { output$download_entry_table <- downloadHandler( filename = function() { - log_print(paste0("Save entry table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv"))) + log_print(paste0("Save entry table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv"))) paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv") }, @@ -10449,13 +10527,13 @@ server <- function(input, output, session) { show_toast( title = "Invalid rows entered. Saving not possible.", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "600px" ) } else { if(!isTRUE(DB$inhibit_change)) { - log_print("Input edit_button") + log_print("Input edit_button") showModal( modalDialog( @@ -10482,11 +10560,11 @@ server <- function(input, output, session) { ) ) } else { - log_print("Input edit_button, invalid values.") + log_print("Input edit_button, invalid values.") show_toast( title = "Invalid values entered. Saving not possible.", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "600px" ) @@ -10495,12 +10573,12 @@ server <- function(input, output, session) { }) observeEvent(input$Cancel, { - log_print("Input Cancel") + log_print("Input Cancel") removeModal() }) observeEvent(input$conf_db_save, { - log_print("Input conf_db_save") + log_print("Input conf_db_save") Data <- readRDS(paste0( DB$database, "/", @@ -10579,32 +10657,32 @@ server <- function(input, output, session) { show_toast( title = "Database successfully saved", type = "success", - position = "top-end", + position = "bottom-end", timer = 4000, width = "500px" ) }) observeEvent(input$del_button, { - log_print("Input del_button") + log_print("Input del_button") if (length(input$select_delete) < 1) { - log_print("Delete entries; no entry selected") + log_print("Delete entries; no entry selected") show_toast( title = "No entry selected", type = "warning", - position = "top-end", + position = "bottom-end", timer = 4000, width = "500px" ) } else if((readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") | (tail(readLogFile(), 1) != "0")) { - log_print("Delete entries; pending typing") + log_print("Delete entries; pending typing") show_toast( title = "Pending Typing", type = "warning", - position = "top-end", + position = "bottom-end", timer = 4000, width = "500px" ) @@ -10644,7 +10722,7 @@ server <- function(input, output, session) { }) observeEvent(input$conf_delete_all, { - log_print("Input conf_delete_all") + log_print("Input conf_delete_all") # remove file with typing data file.remove(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/Typing.rds")) @@ -10673,7 +10751,7 @@ server <- function(input, output, session) { observeEvent(input$conf_delete, { - log_print("Input conf_delete") + log_print("Input conf_delete") DB$deleted_entries <- append(DB$deleted_entries, DB$data$Index[as.numeric(input$select_delete)]) @@ -10698,7 +10776,7 @@ server <- function(input, output, session) { show_toast( title = "Entries deleted", type = "success", - position = "top-end", + position = "bottom-end", timer = 4000, width = "500px" ) @@ -10706,7 +10784,7 @@ server <- function(input, output, session) { show_toast( title = "Entry deleted", type = "success", - position = "top-end", + position = "bottom-end", timer = 4000, width = "500px" ) @@ -10914,7 +10992,7 @@ server <- function(input, output, session) { show_toast( title = "Copied sequence", type = "success", - position = "top-end", + position = "bottom-end", timer = 3000, width = "400px" ) @@ -10923,7 +11001,7 @@ server <- function(input, output, session) { output$get_locus <- downloadHandler( filename = function() { fname <- basename(DB$loci[input$db_loci_rows_selected]) - log_print(paste0("Get locus fasta ", fname)) + log_print(paste0("Get locus fasta ", fname)) fname }, content = function(file) { @@ -11127,12 +11205,12 @@ server <- function(input, output, session) { }) observeEvent(input$download_cgMLST, { - log_print(paste0("Started download of scheme for ", Scheme$folder_name)) + log_print(paste0("Started download of scheme for ", Scheme$folder_name)) show_toast( title = "Download started", type = "success", - position = "top-end", + position = "bottom-end", timer = 5000, width = "400px" ) @@ -11232,28 +11310,28 @@ server <- function(input, output, session) { diff_hashes <- setdiff(local_db_hashes, tmp_db_hashes) sequences <- extract_seq(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), - locus), diff_hashes) + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + locus), diff_hashes) if (!is_empty(sequences$idx) && !is_empty(sequences$seq) && length(sequences$idx) == length(sequences$seq)) { add_new_sequences(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"), - locus), sequences) + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + locus), sequences) } } } print("Delete old alleles folder") unlink(file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) - + paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) + print("Overwriting old alleles directory with temporary directory") file.rename(file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp")), - file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"))) + paste0(Scheme$folder_name, ".tmp")), + file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) # Download Scheme Info download( @@ -11294,13 +11372,13 @@ server <- function(input, output, session) { show_toast( title = "Download successful", type = "success", - position = "top-end", + position = "bottom-end", timer = 5000, width = "400px" ) # TODO Add log message regarding the update of the scheme - log_print("Download successful") + log_print("Download successful") showModal( modalDialog( @@ -11324,13 +11402,13 @@ server <- function(input, output, session) { # Download Target Info (CSV Table) observe({ input$download_cgMLST - + scheme_overview <- read_html(Scheme$link_scheme) %>% html_table(header = FALSE) %>% as.data.frame(stringsAsFactors = FALSE) last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], - format = "%B %d, %Y, %H:%M %p") + format = "%B %d, %Y, %H:%M %p") names(scheme_overview) <- NULL last_file_change <- format( @@ -11499,7 +11577,7 @@ server <- function(input, output, session) { show_toast( title = "Label already exists", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -11508,7 +11586,7 @@ server <- function(input, output, session) { show_toast( title = "Min. 1 character", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -11527,7 +11605,7 @@ server <- function(input, output, session) { show_toast( title = "Label already exists", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -11536,7 +11614,7 @@ server <- function(input, output, session) { show_toast( title = "Min. 1 character", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -15170,7 +15248,6 @@ server <- function(input, output, session) { multiple = TRUE, options = list( `live-search` = TRUE, - `noneSelectedText` = "Test", size = 10, style = "background-color: white; border-radius: 5px;" ), @@ -15184,7 +15261,6 @@ server <- function(input, output, session) { multiple = TRUE, options = list( `live-search` = TRUE, - noneSelectedText = "Test", size = 10, style = "background-color: white; border-radius: 5px;" ), @@ -15202,7 +15278,6 @@ server <- function(input, output, session) { multiple = TRUE, options = list( `live-search` = TRUE, - `noneSelectedText` = "Test", size = 10, style = "background-color: white; border-radius: 5px;" ), @@ -15216,7 +15291,6 @@ server <- function(input, output, session) { multiple = TRUE, options = list( `live-search` = TRUE, - noneSelectedText = "Test", size = 10, style = "background-color: white; border-radius: 5px;" ), @@ -18035,7 +18109,7 @@ server <- function(input, output, session) { fill = fill, type = input$nj_clade_type, to.bottom = TRUE - ) + ) } else {NULL} } }) @@ -20384,7 +20458,7 @@ server <- function(input, output, session) { ### Save MST Plot ---- output$save_plot_html <- downloadHandler( filename = function() { - log_print(paste0("Save MST;", paste0("MST_", Sys.Date(), ".html"))) + log_print(paste0("Save MST;", paste0("MST_", Sys.Date(), ".html"))) paste0("MST_", Sys.Date(), ".html") }, content = function(file) { @@ -20398,7 +20472,7 @@ server <- function(input, output, session) { output$download_nj <- downloadHandler( filename = function() { - log_print(paste0("Save NJ;", paste0("NJ_", Sys.Date(), ".", input$filetype_nj))) + log_print(paste0("Save NJ;", paste0("NJ_", Sys.Date(), ".", input$filetype_nj))) paste0("NJ_", Sys.Date(), ".", input$filetype_nj) }, content = function(file) { @@ -20428,7 +20502,7 @@ server <- function(input, output, session) { output$download_upgma <- downloadHandler( filename = function() { - log_print(paste0("Save UPGMA;", paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma))) + log_print(paste0("Save UPGMA;", paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma))) paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma) }, content = function(file) { @@ -20908,32 +20982,32 @@ server <- function(input, output, session) { }) observeEvent(input$create_tree, { - log_print("Input create_tree") + log_print("Input create_tree") if(is.null(DB$data)) { - log_print("Missing data") + log_print("Missing data") show_toast( title = "Missing data", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) } else if(nrow(DB$allelic_profile_true) < 3) { - log_print("Min. of 3 entries required for visualization") + log_print("Min. of 3 entries required for visualization") show_toast( title = "Min. of 3 entries required for visualization", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) } else { if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { - log_print("Duplicated assemblies") + log_print("Duplicated assemblies") dup_name <- which(duplicated(DB$meta_true$`Assembly Name`)) dup_id <- which(duplicated(DB$meta_true$`Assembly ID`)) @@ -20953,10 +21027,10 @@ server <- function(input, output, session) { } else { if(length(dup_name) == 0) { HTML(c("Entries contain duplicated IDs

", - paste0(unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) + paste0(unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) } else if(length(dup_id) == 0) { HTML(c("Entries contain duplicated names

", - paste0(unique(DB$meta_true$`Assembly Name`[dup_name]), "
"))) + paste0(unique(DB$meta_true$`Assembly Name`[dup_name]), "
"))) } else { HTML(c("Entries contain duplicated names and IDs

", paste0("Name: ", unique(DB$meta_true$`Assembly Name`[dup_name]), "
"), @@ -20994,7 +21068,7 @@ server <- function(input, output, session) { show_toast( title = "Conflicting Custom Variable Names", type = "warning", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) @@ -21150,7 +21224,7 @@ server <- function(input, output, session) { show_toast( title = "Conflicting Custom Variable Names", type = "warning", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) @@ -21311,7 +21385,7 @@ server <- function(input, output, session) { show_toast( title = "Computation might take a while", type = "warning", - position = "top-end", + position = "bottom-end", width = "500px", timer = 10000 ) @@ -21746,7 +21820,7 @@ server <- function(input, output, session) { show_toast( title = "No tree created", type = "error", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) @@ -21902,7 +21976,7 @@ server <- function(input, output, session) { # Save data to an RDS file if any elements were selected if (!is.null(report)) { - log_print("Creating MST report") + log_print("Creating MST report") saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) @@ -21925,7 +21999,7 @@ server <- function(input, output, session) { # Save data to an RDS file if any elements were selected if (!is.null(report)) { - log_print("Creating NJ report") + log_print("Creating NJ report") saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) @@ -21933,7 +22007,7 @@ server <- function(input, output, session) { file.copy(paste0(getwd(), "/Report/Report.html"), file) } else { - log_print("Creating NJ report failed (report is null)") + log_print("Creating NJ report failed (report is null)") } } else { @@ -21949,7 +22023,7 @@ server <- function(input, output, session) { # Save data to an RDS file if any elements were selected if (!is.null(report)) { - log_print("Creating UPGMA report") + log_print("Creating UPGMA report") saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) @@ -21957,7 +22031,7 @@ server <- function(input, output, session) { file.copy(paste0(getwd(), "/Report/Report.html"), file) } else { - log_print("Creating UPGMA report failed (report is null)") + log_print("Creating UPGMA report failed (report is null)") } } @@ -22044,46 +22118,22 @@ server <- function(input, output, session) { if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { output$typing_result_table <- renderRHandsontable({ - typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) - if(nrow(typing_result_table) > 0) { - if (input$typing_results_longhash) { - renderer <- htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value; - } - td.innerHTML = value; - return td; - }" - ) - } else { - renderer <- htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - return td; - }" - ) - } - - if(nrow(typing_result_table) > 15) { - rhandsontable(typing_result_table, rowHeaders = NULL, + Typing$typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) + if(nrow(Typing$typing_result_table) > 0) { + if(nrow(Typing$typing_result_table) > 15) { + rhandsontable(Typing$typing_result_table, rowHeaders = NULL, stretchH = "all", height = 500, readOnly = TRUE, contextMenu = FALSE) %>% hot_cols(columnSorting = TRUE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(typing_result_table), valign = "htMiddle", halign = "htCenter") %>% - hot_col("Value", renderer = renderer) + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter") } else { - rhandsontable(typing_result_table, rowHeaders = NULL, + rhandsontable(Typing$typing_result_table, rowHeaders = NULL, stretchH = "all", readOnly = TRUE, - contextMenu = FALSE) %>% + contextMenu = FALSE,) %>% hot_cols(columnSorting = TRUE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(typing_result_table), valign = "htMiddle", halign = "htCenter") %>% - hot_col("Value", renderer = renderer) + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter") } } }) @@ -22113,14 +22163,7 @@ server <- function(input, output, session) { HTML(paste("", n_new, if(n_new == 1) " locus with new variant." else " loci with new variants.")), - br(), - materialSwitch( - "typing_results_longhash", - h5(p("Show Long Hash"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ), - br(), + br(), br(), rHandsontableOutput("typing_result_table") ) } else { @@ -22375,7 +22418,7 @@ server <- function(input, output, session) { show_toast( title = "Wrong file type (only fasta/fna/fa)", type = "error", - position = "top-end", + position = "bottom-end", width = "500px", timer = 6000 ) @@ -22404,15 +22447,15 @@ server <- function(input, output, session) { observeEvent(input$typing_start, { - log_print("Input typing_start") + log_print("Input typing_start") if(tail(readLogFile(), 1) != "0") { - log_print("Pending multi typing") + log_print("Pending multi typing") show_toast( title = "Pending Multi Typing", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -22439,6 +22482,9 @@ server <- function(input, output, session) { output$metadata_single_box <- NULL output$start_typing_ui <- NULL + # status feedback + Typing$status <- "Processing" + # Locate folder containing cgMLST scheme search_string <- paste0(gsub(" ", "_", DB$scheme), "_alleles") @@ -22457,12 +22503,12 @@ server <- function(input, output, session) { show_toast( title = "Typing Initiated", type = "success", - position = "top-end", - timer = 12000, - width = "500px" + position = "bottom-end", + timer = 6000, + width = "400px" ) - log_print("Initiated single typing") + log_print("Initiated single typing") ### Run blat Typing @@ -22537,7 +22583,7 @@ server <- function(input, output, session) { ) }) } else { - log_print("Folder containing cgMLST alleles not in working directory") + log_print("Folder containing cgMLST alleles not in working directory") show_alert( title = "Error", @@ -22640,9 +22686,19 @@ server <- function(input, output, session) { br(), br(), if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { - HTML(paste("", - sub(".*Successful", "Successful", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), - "Reset to start another typing process.", sep = '
')) + req(Typing$scheme_loci_f, Typing$typing_result_table) + if(sum(Typing$typing_result_table$Event != "New Variant") > (0.5 * length(Typing$scheme_loci_f))){ + HTML( + paste("", + sub(".*Successful", "Finished", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + paste("", "Warning: Isolate contains large number of failed allele assignments."), + paste("", "Reset to start another typing process."), + sep = '
\n')) + } else { + HTML(paste("", + sub(".*Successful", "Successful", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + "Reset to start another typing process.", sep = '
')) + } } else { HTML(paste("", sub(".*typing", "Typing", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), @@ -22668,7 +22724,7 @@ server <- function(input, output, session) { #### Declare Metadata ---- observeEvent(input$conf_meta_single, { - log_print("Single typing metadata confirmed") + log_print("Single typing metadata confirmed") if(nchar(trimws(input$assembly_id)) < 1) { ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) @@ -22700,7 +22756,7 @@ server <- function(input, output, session) { show_toast( title = "Metadata declared", type = "success", - position = "top-end", + position = "bottom-end", timer = 3000, width = "500px" ) @@ -22738,7 +22794,7 @@ server <- function(input, output, session) { #### Events Single Typing ---- observeEvent(input$reset_single_typing, { - log_print("Reset single typing") + log_print("Reset single typing") Typing$progress <- 0 @@ -22808,7 +22864,7 @@ server <- function(input, output, session) { show_toast( title = "Single Typing finalized", type = "success", - position = "top-end", + position = "bottom-end", timer = 8000, width = "500px" ) @@ -23090,7 +23146,7 @@ server <- function(input, output, session) { }) observeEvent(input$conf_meta_multi, { - log_print("Multi typing metadata confirmed") + log_print("Multi typing metadata confirmed") meta_info <- data.frame(cgmlst_typing = DB$scheme, append_isodate = trimws(input$append_isodate_multi), @@ -23105,7 +23161,7 @@ server <- function(input, output, session) { show_toast( title = "Metadata declared", type = "success", - position = "top-end", + position = "bottom-end", timer = 3000, width = "500px" ) @@ -23143,7 +23199,7 @@ server <- function(input, output, session) { # Print Log output$print_log <- downloadHandler( filename = function() { - log_print(paste0("Save multi typing log ", paste("Multi_Typing_", Sys.Date(), ".txt", sep = ""))) + log_print(paste0("Save multi typing log ", paste("Multi_Typing_", Sys.Date(), ".txt", sep = ""))) paste("Multi_Typing_", Sys.Date(), ".txt", sep = "") }, content = function(file) { @@ -23170,7 +23226,7 @@ server <- function(input, output, session) { ) } else { - log_print("Reset multi typing") + log_print("Reset multi typing") # Reset multi typing result list saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) @@ -23245,7 +23301,7 @@ server <- function(input, output, session) { show_toast( title = "Execution cancelled", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -23316,19 +23372,19 @@ server <- function(input, output, session) { show_toast( title = "Pending Single Typing", type = "warning", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) } else { if (any(!grepl("\\.fasta|\\.fna|\\.fa", str_sub(Typing$genome_selected$Files[which(Typing$genome_selected$Include == TRUE)], start = -6)))) { - log_print("Wrong file type (include only fasta/fna/fa)") + log_print("Wrong file type (include only fasta/fna/fa)") show_toast( title = "Wrong file type (include only fasta/fna/fa)", type = "error", - position = "top-end", + position = "bottom-end", timer = 6000, width = "500px" ) @@ -23339,7 +23395,7 @@ server <- function(input, output, session) { show_toast( title = "Multi Typing started", type = "success", - position = "top-end", + position = "bottom-end", timer = 10000, width = "500px" ) @@ -23418,7 +23474,7 @@ server <- function(input, output, session) { title = paste0("Successful", sub(".*Successful", "", tail(log, 1))), type = "success", width = "500px", - position = "top-end", + position = "bottom-end", timer = 8000 ) } else if(str_detect(tail(log, 1), "failed")) { @@ -23427,7 +23483,7 @@ server <- function(input, output, session) { title = paste0("Failed typing of ", sub(".*failed for ", "", tail(log, 1))), type = "error", width = "500px", - position = "top-end", + position = "bottom-end", timer = 8000 ) } else if(str_detect(tail(log, 1), "Processing")) { @@ -23441,7 +23497,7 @@ server <- function(input, output, session) { title = paste0("Successful", sub(".*Successful", "", tail(log, 2)[1])), type = "success", width = "500px", - position = "top-end", + position = "bottom-end", timer = 8000 ) @@ -23454,7 +23510,7 @@ server <- function(input, output, session) { title = paste0("Failed typing of ", sub(".*failed for ", "", tail(log, 2)[1])), type = "error", width = "500px", - position = "top-end", + position = "bottom-end", timer = 8000 ) @@ -23470,7 +23526,7 @@ server <- function(input, output, session) { title = "Typing finalized", type = "success", width = "500px", - position = "top-end", + position = "bottom-end", timer = 8000 ) @@ -23498,45 +23554,23 @@ server <- function(input, output, session) { rowHeaders = NULL, stretchH = "all", readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter") - }) - } else { - if (input$multi_results_longhash) { - renderer <- NULL - } else { - renderer <- htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.verticalAlign = 'middle'; - td.style.textAlign = 'center'; - return td; - }" - ) - } + hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) + } else { if(Typing$multi_table_length > 15) { output$multi_typing_result_table <- renderRHandsontable({ rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, stretchH = "all", height = 500, readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter") %>% - hot_col("Value", - renderer = renderer) - }) + hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) } else { output$multi_typing_result_table <- renderRHandsontable({ rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, stretchH = "all", readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter") %>% - hot_col("Value", - renderer = renderer) - }) + hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) } } @@ -23575,26 +23609,17 @@ server <- function(input, output, session) { width = 9, br(), br(), br(), br(), - br(), - fluidRow( - div( - class = "mult_res_sel", - selectInput( - "multi_results_picker", - label = h5("Select Typing Results", style = "color:white"), - choices = names(Typing$result_list), - selected = names(Typing$result_list)[length(names(Typing$result_list))], - ) - ) - ), br(), - materialSwitch( - "multi_results_longhash", - h5(p("Show Long Hash"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE + div( + class = "mult_res_sel", + selectInput( + "multi_results_picker", + label = h5("Select Typing Results", style = "color:white"), + choices = names(Typing$result_list), + selected = names(Typing$result_list)[length(names(Typing$result_list))], + ) ), - br(), + br(), br(), rHandsontableOutput("multi_typing_result_table") ) ) @@ -23719,6 +23744,8 @@ server <- function(input, output, session) { } }) + + } # end server # _______________________ #### diff --git a/execute/multi_eval.R b/execute/multi_eval.R index 6e5a560..3dc5277 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -113,10 +113,18 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= start_codons = start_codons, stop_codons = stop_codons) # if valid variant found - if(variant_valid != FALSE) { + if(variant_valid == "Ambigous Nucleotides") { + allele_vector[[i]] <- NA + event_list[[basename(assembly)]] <- rbind(event_list[[basename(assembly)]], + data.frame(Locus = allele_index, + Event = "Ambigous Nucleotides Sequence", + Value = "NA")) + cat(paste0(allele_index, " Invalid - Ambigous Nucleotides.\n")) + + } else if(variant_valid != FALSE) { hashed_variant <- openssl::sha256(variant_valid) - + # Append new variant number to allele fasta file cat(paste0("\n>", hashed_variant), file = locus_file, append = TRUE) @@ -324,7 +332,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= message = paste0("Assembly typing failed for ", sub("\\.(fasta|fna|fa)$", "", basename(assembly)))) log_print(paste0("Assembly typing failed for ", - sub("\\.(fasta|fna|fa)$", "", basename(assembly)))) + sub("\\.(fasta|fna|fa)$", "", basename(assembly)))) } log_close() diff --git a/execute/single_eval.R b/execute/single_eval.R index dfb9f52..9b65f81 100644 --- a/execute/single_eval.R +++ b/execute/single_eval.R @@ -91,10 +91,9 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= variants <- readLines(locus_file) - # new variant validation - # decision what is reference sequence + ### new variant validation ### - # sort by score, then number of gaps then number of bases in the gaps + # sort by i) score, ii) number of gaps, iii) number of nt in the gaps matches <- dplyr::arrange(matches, desc(V1), desc(V5 + V7), desc(V6 + V7)) # check which reference sequences have different alignment positions with the template @@ -102,10 +101,15 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # loop over all unique template alignments (regarding position) variant_valid <- variant_validation(references = unique_template_seq, - start_codons = start_codons, stop_codons = stop_codons) + start_codons = start_codons, stop_codons = stop_codons) # if valid variant found - if(variant_valid != FALSE) { + if(variant_valid == "Ambigous Nucleotides") { + allele_vector[[i]] <- NA + event_df <- rbind(event_df, data.frame(Locus = allele_index, Event = "Ambigous Nucleotides", Value = "NA")) + cat(paste0(allele_index, " Invalid - Ambigous Nucleotides.\n")) + + } else if(variant_valid != FALSE) { hashed_variant <- openssl::sha256(variant_valid) diff --git a/execute/variant_validation.R b/execute/variant_validation.R index c9dd4fe..9c9524e 100644 --- a/execute/variant_validation.R +++ b/execute/variant_validation.R @@ -1,4 +1,13 @@ require(Biostrings, quietly = TRUE) + +check_gene_sequence <- function(sequence) { + if (grepl("[^atgc]", sequence, ignore.case = TRUE)) { + return(TRUE) + } else { + return(FALSE) + } +} + # Function to check for length and frameshift of new variant sequence check_length_frameshift <- function(seq, ref_seq) { @@ -65,8 +74,8 @@ validate_start_stop <- function(seq, start_codons, stop_codons) { } } } - - # Check if reverse sequence has start codon + + # Check if reverse sequence has start codon } else if (length(reverse_match@ranges) != 0) { # Verify if stop codon is at other end @@ -99,6 +108,11 @@ variant_validation <- function(references, start_codons, stop_codons) { seq <- substring(contig, references$V16[i] + 1, references$V17[i]) + # invalid if nucleic acid code other than ATGC + if(check_gene_sequence(seq)) { + return("Ambigous Nucleotides") + } + ref_seq_index <- grep(paste0("^>", references$V10[i], "$"), readLines(locus_file)) + 1 ref_seq <- variants[ref_seq_index] diff --git a/www/body.css b/www/body.css index 58bff78..50e3583 100644 --- a/www/body.css +++ b/www/body.css @@ -1,10 +1,10 @@ /* CSS Styling for PhyloTrace */ - -/* General */ - -h1, h2, h3, h4, h5, p, body { - font-family: 'Liberation Sans', sans-serif; -} + + /* General */ + + h1, h2, h3, h4, h5, p, body { + font-family: 'Liberation Sans', sans-serif; + } label { color: white; @@ -17,31 +17,31 @@ label { } .btn-primary.focus, .btn-primary:focus { - color: #000000; + color: #000000; background-color: #20E6E5; border-color: #20E6E5; } .btn-primary.focus, .btn-primary:active:focus { color: #ffffff; - background-color: #282F38; - border-color: white; + background-color: #282F38; + border-color: white; } .datepicker table tr td.active:active, .datepicker table tr td.active.active, .datepicker table tr td.active.highlighted:active, .datepicker table tr td.active.highlighted.active { color: #000000; - background-color: #20E6E5; - border-color: #20E6E5; + background-color: #20E6E5; + border-color: #20E6E5; } .table>caption+thead>tr:first-child>td, .table>caption+thead>tr:first-child>th, .table>colgroup+thead>tr:first-child>td, .table>colgroup+thead>tr:first-child>th, .table>thead:first-child>tr:first-child>td, .table>thead:first-child>tr:first-child>th, .table>caption+thead>tr:last-child>td, .table>caption+thead>tr:last-child>th, .table>colgroup+thead>tr:last-child>td, .table>colgroup+thead>tr:last-child>th, .table>thead:last-child>tr:last-child>td, .table>thead:last-child>tr:last-child>th { - border-top: 1px !important; - border-radius: 5px; + border-top: 1px !important; + border-radius: 5px; } .dropdown-menu>li.selected { - color: #ffffff; + color: #ffffff; background-color: #282F38; } @@ -54,13 +54,13 @@ label { } .dropdown-menu>li>a:hover { - color: #000000; + color: #000000; background-color: #20E6E5; } .selectize-dropdown .selected { background-color: #20E6E5; - color: black; + color: black; } .bs-searchbox .form-control { @@ -82,7 +82,7 @@ label { .main-sidebar .sidebar .sidebar-menu .treeview-menu a { color: #ffffff !important; - margin-left: 25px; + margin-left: 25px; border-radius: 20px; margin-top: 7px; margin-bottom: 7px; @@ -106,7 +106,7 @@ label { border: 1px solid #00000000; border-width: 1px; display: inline-block; /* Make the element inline-block */ - transition: border-color 0.3s ease; /* Smooth transition for border color */ + transition: border-color 0.3s ease; /* Smooth transition for border color */ } .bttn-material-flat:hover{ @@ -115,20 +115,20 @@ label { .action-button.bttn.bttn-material-flat.bttn-sm.bttn-default.bttn-no-outline.shiny-bound-input { background: #282F38 !important; - border: 1px solid transparent; /* Default border color */ - display: inline-block; /* Make the element inline-block */ - transition: border-color 0.3s ease; /* Smooth transition for border color */ - border-width: 1px !important; + border: 1px solid transparent; /* Default border color */ + display: inline-block; /* Make the element inline-block */ + transition: border-color 0.3s ease; /* Smooth transition for border color */ + border-width: 1px !important; border-color: white !important; color: white !important; transition: background 0.3s ease; /* Smooth transition for border color */ - transition: color 0.3s ease; /* Smooth transition for border color */ + transition: color 0.3s ease; /* Smooth transition for border color */ } .action-button.bttn.bttn-material-flat.bttn-sm.bttn-default.bttn-no-outline.shiny-bound-input:hover { border-color: transparent !important; /* Change border color to white on hover */ - background: #20E6E5 !important; - color: black !important; + background: #20E6E5 !important; + color: black !important; } .shiny-input-container input[type = "text"]:hover { @@ -141,14 +141,14 @@ label { .main-sidebar .sidebar .sidebar-menu .treeview-menu li.active a { color: #000000 !important; - border-radius: 20px; + border-radius: 20px; margin-top: 7px; margin-bottom: 7px; } .main-sidebar .sidebar .sidebar-menu .treeview-menu li:hover a { color: #000000; - border-radius: 20px; + border-radius: 20px; margin-top: 7px; margin-bottom: 7px; } @@ -159,7 +159,7 @@ label { .main-sidebar .sidebar .sidebar-menu li:hover a { color: #000000; - border: none; + border: none; } file.select { @@ -167,14 +167,14 @@ file.select { } .box.box-solid.box-info{ - background: #282F38; + background: #282F38; margin-top: 20px; - position: relative; - left: 30px; + position: relative; + left: 30px; } .box.box-solid.box-info, .box.box-info { - border-color: #ffffff; + border-color: #ffffff; border-left-color: #ffffff; border-right-color: #ffffff; border-top-color: #ffffff; @@ -186,7 +186,7 @@ file.select { } #scheme_db .selectize-control { - font-size: 12px; +font-size: 12px; } .scheme_start { @@ -206,17 +206,17 @@ file.select { } #reload_db i.fas.fa-rotate { - position: relative; - left: -5px; - top: -2px; +position: relative; +left: -5px; +top: -2px; } button#reload_db.btn.btn-default.action-button.shiny-bound-input { - height: 30px; - width: 30px; - position: relative; - left: -20px; - border: 1px solid white; +height: 30px; +width: 30px; +position: relative; +left: -20px; +border: 1px solid white; } .irs.irs--shiny.js-irs-0 { @@ -232,19 +232,19 @@ button#reload_db.btn.btn-default.action-button.shiny-bound-input { } div#scheme_db .form-control, .selectize-input, .selectize-control.single .selectize-input { - border-color: #000000 !important; -} +border-color: #000000 !important; + } #distmatrix_triangle { - margin-top: -35px; +margin-top: -35px; } #distmatrix_diag { - margin-top: -55px; +margin-top: -55px; } #distmatrix_true { - margin-top: -15px; +margin-top: -15px; } .format { @@ -271,7 +271,7 @@ div#scheme_db .form-control, .selectize-input, .selectize-control.single .select } button#load.pulsating-button.btn.btn-default.action-button.shiny-bound-input { - background: #20E6E5; +background: #20E6E5; color: #000000; width: 40px; } @@ -281,8 +281,8 @@ button#load.pulsating-button.btn.btn-default.action-button.shiny-bound-input { } #load .fas.fa-rotate { - position: relative; - left: 0px !important; +position: relative; +left: 0px !important; } .shiny-input-container input[type="text"] { @@ -303,7 +303,7 @@ button#load.pulsating-button.btn.btn-default.action-button.shiny-bound-input { } .loci_table .dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate { - color: #ffffff !important; + color: #ffffff !important; } thead { @@ -311,20 +311,20 @@ thead { } .dataTables_wrapper .dataTables_filter input { - border-radius: 5px; - padding: 5px; - background-color: white; - color: black; - font-weight: 100; - margin-left: 3px; + border-radius: 5px; + padding: 5px; + background-color: white; + color: black; + font-weight: 100; + margin-left: 3px; } .dataTables_wrapper .dataTables_length select { - border-radius: 5px; - padding: 5px; - background-color: white; - color: black; - font-weight: 100; + border-radius: 5px; + padding: 5px; + background-color: white; + color: black; + font-weight: 100; } .dataTables_wrapper .dataTables_paginate .paginate_button { @@ -332,75 +332,75 @@ thead { } table.dataTable tbody tr { - background-color: transparent; - border-radius: 5px !important; + background-color: transparent; + border-radius: 5px !important; } table.dataTable.stripe>tbody>tr.odd.selected>*, table.dataTable.display>tbody>tr.odd.selected>* { - box-shadow: inset 0 0 0 9999px #282F38; - box-shadow: inset 0 0 0 9999px #282F38; - color: white !important; + box-shadow: inset 0 0 0 9999px #282F38; + box-shadow: inset 0 0 0 9999px #282F38; + color: white !important; } table.dataTable.stripe>tbody>tr.even.selected>*, table.dataTable.display>tbody>tr.even.selected>* { - box-shadow: inset 0 0 0 9999px #282F38; - box-shadow: inset 0 0 0 9999px #282F38; - color: white !important; + box-shadow: inset 0 0 0 9999px #282F38; + box-shadow: inset 0 0 0 9999px #282F38; + color: white !important; } table.dataTable.display>tbody>tr.selected:hover>* { - box-shadow: inset 0 0 0 9999px #20E6E5 !important; - color: black !important; + box-shadow: inset 0 0 0 9999px #20E6E5 !important; + color: black !important; } table.dataTable.display>tbody>tr:hover>* { - box-shadow: inset 0 0 0 9999px #20E6E5 !important; - color: black !important; + box-shadow: inset 0 0 0 9999px #20E6E5 !important; + color: black !important; } .dataTables_wrapper .dataTables_paginate .paginate_button:hover { - color: white !important; - border: 1px solid #111; - background-color: #20E6E5; + color: white !important; + border: 1px solid #111; + background-color: #20E6E5; background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111)); - background: -webkit-linear-gradient(top, #585858 0%, #111 100%); - background: -moz-linear-gradient(top, #585858 0%, #111 100%); - background: -ms-linear-gradient(top, #585858 0%, #111 100%); - background: -o-linear-gradient(top, #585858 0%, #111 100%); - background: linear-gradient(to bottom, #585858 0%, #111 100%); + background: -webkit-linear-gradient(top, #585858 0%, #111 100%); + background: -moz-linear-gradient(top, #585858 0%, #111 100%); + background: -ms-linear-gradient(top, #585858 0%, #111 100%); + background: -o-linear-gradient(top, #585858 0%, #111 100%); + background: linear-gradient(to bottom, #585858 0%, #111 100%); } .dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active { - cursor: default; - color: #fff !important; + cursor: default; + color: #fff !important; border: 1px solid transparent; - background: transparent; - box-shadow: none; + background: transparent; + box-shadow: none; } .dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { - color: black !important; - border: 1px solid rgb(255 255 255 / 0%); - background-color: #20E6E5 !important; + color: black !important; + border: 1px solid rgb(255 255 255 / 0%); + background-color: #20E6E5 !important; border-radius: 5px; - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 230, 230, 0.05)), color-stop(100%, rgba(0, 0, 0, 0.05))); - background: -webkit-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); - background: -moz-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); - background: -ms-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); - background: -o-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); - background: linear-gradient(to bottom, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 230, 230, 0.05)), color-stop(100%, rgba(0, 0, 0, 0.05))); + background: -webkit-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); + background: -moz-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); + background: -ms-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); + background: -o-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); + background: linear-gradient(to bottom, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); } .dataTables_wrapper .dataTables_paginate .paginate_button:hover { - color: white !important; - border: 1px solid #00f3ff; - background-color: #111; + color: white !important; + border: 1px solid #00f3ff; + background-color: #111; background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111)); - background: -webkit-linear-gradient(top, #585858 0%, #111 100%); - background: -moz-linear-gradient(top, #585858 0%, #111 100%); - background: -ms-linear-gradient(top, #585858 0%, #111 100%); - background: -o-linear-gradient(top, #585858 0%, #111 100%); - background: transparent; + background: -webkit-linear-gradient(top, #585858 0%, #111 100%); + background: -moz-linear-gradient(top, #585858 0%, #111 100%); + background: -ms-linear-gradient(top, #585858 0%, #111 100%); + background: -o-linear-gradient(top, #585858 0%, #111 100%); + background: transparent; } input.form-control.pickr-color { @@ -431,32 +431,44 @@ input.form-control.pickr-color { } button#copy_seq { - background: #282F38; - color: #ffffff; - border: 1px solid white; - transition: border-color 0.3s ease; +background: #282F38; + color: #ffffff; + border: 1px solid white; +transition: border-color 0.3s ease; } button#get_locus_bttn { - background: #282F38; - color: #ffffff; - border: 1px solid white; - transition: border-color 0.3s ease; - opacity: 1; - font-size: 15px; - width: 147px; +background: #282F38; + color: #ffffff; + border: 1px solid white; +transition: border-color 0.3s ease; +opacity: 1; +font-size: 15px; +width: 147px; } button#get_locus_bttn i.fas.fa-download { - position: relative; - top: -1px; - left: -6px; +position: relative; +top: -1px; +left: -6px; } /* Icons */ + + i.fas { + margin-right: 5px; + } -i.fas { - margin-right: 5px; +i.greenstatus.fa-solid.fa-circle-dot. { + lightgreen +} + +i.orangestatus.fa-solid.fa-circle-dot { + orange +} + +i.fa-solid.fa-folder-open { + color: #FFDA73 !important; } i.fas.fa-rotate { @@ -472,7 +484,7 @@ i.fas.fa-sliders { margin-right: 0px; margin-top: 5px; } - + i.fas.fa-xmark, i.fas.fa-download, i.far.fa-bookmark { margin-right: 0px; } @@ -498,28 +510,28 @@ i.far.fa-pen-to-square { } /* Database */ - -#db_entries > div > div > div > div > table > tbody > tr > td, -#db_distancematrix > div > div > div > div > table > tbody > tr > td, -#table_missing_values > div > div > div > div > table > tbody > tr > td, -#multi_select_table > div > div > div > div > table > tbody > tr > td, -#multi_typing_result_table > div > div > div > div > table > tbody > tr > td, -#typing_result_table > div > div > div > div > table > tbody > tr > td{ + + #db_entries > div > div > div > div > table > tbody > tr > td, + #db_distancematrix > div > div > div > div > table > tbody > tr > td, + #table_missing_values > div > div > div > div > table > tbody > tr > td, + #multi_select_table > div > div > div > div > table > tbody > tr > td, + #multi_typing_result_table > div > div > div > div > table > tbody > tr > td, + #typing_result_table > div > div > div > div > table > tbody > tr > td{ color: black !important; } .miss_val_box, #table_missing_values{ - margin-left: 50px; +margin-left: 50px; } #download_na_matrix_bttn > i { - top: 1px !important; +top: 1px !important; } #sel_all_entries, #desel_all_entries, #typing_start, #start_typ_multi, #undo_changes, #genome_file, #genome_file_multi, #reset_multi, #save_cust { - border-color: white; +border-color: white; } .btn-default:hover { @@ -527,24 +539,24 @@ i.far.fa-pen-to-square { } #cgmlst_scheme { - margin-top: 41px; +margin-top: 41px; } .dropdown-menu>.active>a, .dropdown-menu>.active>a:focus, .dropdown-menu>.active>a:hover { - color: #ffffff !important; + color: #ffffff !important; background-color: #282F38 !important; } #shiny-tab-db_browse_entries > div:nth-child(11) > div.col-sm-1, #shiny-tab-init > div:nth-child(4) > div.col-sm-1, #shiny-tab-init > div:nth-child(3) > div.col-sm-1 { - width: 4.333333%; +width: 4.333333%; } .bttn-simple:hover { border-color: #20E6E5 !important; - background: #20E6E5 !important; - color: black !important; + background: #20E6E5 !important; + color: black !important; opacity: 1; } @@ -567,154 +579,154 @@ i.far.fa-pen-to-square { #db_entries, #db_distancematrix, #table_missing_values, #multi_select_table, #typing_result_table, #multi_typing_result_table { - border-radius: 8px; - color: black; +border-radius: 8px; +color: black; } #multi_typing_result_table { - margin-top: -15px; +margin-top: -15px; } #add_new_variable { - background: green; - height: 35px; - width: 38px; - margin-left: -5px; - margin-top: 19px; +background: green; +height: 35px; +width: 38px; +margin-left: -5px; +margin-top: 19px; } #delete_new_variable { - background: #FF5964; +background: #FF5964; height: 35px; - width: 38px; - margin-left: -5px; - margin-top: 20px; +width: 38px; +margin-left: -5px; +margin-top: 20px; } #new_var_name { - height: 33px; - margin-left: -6px; - width: 123px; - margin-top: -12px; +height: 33px; +margin-left: -6px; +width: 123px; +margin-top: -12px; } #cust_var_select { - margin-top: -40px; +margin-top: -40px; } #cust_var_select .selectize-dropdown-content { - max-height: 80px; +max-height: 80px; } div#db_distancematrix.rhandsontable { - font-size: 11px; +font-size: 11px; } button#download_cgMLST { - font-size: 14px; - height: 34px; - background: #282F38; +font-size: 14px; +height: 34px; +background: #282F38; color: #ffffff; border: 1px solid white; } .btn-primary:hover { background-color: #20e6e5; - border-color: #20e6e5; - color: black; + border-color: #20e6e5; + color: black; border-radius: 5px; height: 35px; } .btn-primary { background: #282F38; - color: #ffffff; - border-color: #282F38; - border-radius: 5px; + color: #ffffff; + border-color: #282F38; + border-radius: 5px; height: 35px; padding: 6px 12px; } .btn-default:hover { border-color: #20e6e5 !important; - background: #20e6e5 !important; - color: black !important; + background: #20e6e5 !important; + color: black !important; } button#download_cgMLST i.fas.fa-download { - margin-right: 5px !important +margin-right: 5px !important } #show_cust_var { - color:black; - font-size: 14px; - margin-left: 15px; +color:black; +font-size: 14px; +margin-left: 15px; } button#download_distmatrix_bttn { - font-size: 14px; - height: 34px; - background: #282F38; +font-size: 14px; +height: 34px; +background: #282F38; color: #ffffff; border: 1px solid white; - position: absolute; - top: -50px; - transition: border-color 0.3s ease; /* Smooth transition for border color */ -} +position: absolute; +top: -50px; +transition: border-color 0.3s ease; /* Smooth transition for border color */ + } button#download_entry_table_bttn { - height: 34px; - background: #282F38; +height: 34px; +background: #282F38; color: #ffffff; border: 1px solid white; - transition: border-color 0.3s ease; /* Smooth transition for border color */ -} +transition: border-color 0.3s ease; /* Smooth transition for border color */ + } button#download_schemeinfo_bttn { - height: 28px; - background: #282F38; +height: 28px; +background: #282F38; color: #ffffff; margin-top: 19px; - border: 1px solid white; - margin-left: 10px; - transition: border-color 0.3s ease; /* Smooth transition for border color */ -} +border: 1px solid white; +margin-left: 10px; +transition: border-color 0.3s ease; /* Smooth transition for border color */ + } button#download_loci_info_bttn { - height: 28px; - background: #282F38; - color: #ffffff; - margin-top: 19px; - border: 1px solid white; - margin-left: 10px; - transition: border-color 0.3s ease; +height: 28px; +background: #282F38; + color: #ffffff; + margin-top: 19px; +border: 1px solid white; +margin-left: 10px; +transition: border-color 0.3s ease; } button#download_na_matrix_bttn { - height: 34px; - background: #282F38; +height: 34px; +background: #282F38; color: #ffffff; border: 1px solid white; - margin-top: 14px; - margin-left: 10px; - transition: border-color 0.3s ease; +margin-top: 14px; +margin-left: 10px; +transition: border-color 0.3s ease; } button#edit_button.btn.btn-default.action-button.shiny-bound-input { - background: #20E6E5; +background: #20E6E5; color: #000000; -} + } /* Typing */ - -.mult_res_sel { - margin-bottom: 15px; -} + + .mult_res_sel { + margin-bottom: 15px; + } body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-today.is-selected > button{ color: white; background: #282F38; - border-radius: 5px; + border-radius: 5px; box-shadow: inset 0 1px 3px rgb(0 0 0) } @@ -723,13 +735,13 @@ body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-selected, .is-selected .pika-button { color: white; background: #282F38; - border-radius: 5px; + border-radius: 5px; box-shadow: inset 0 1px 3px rgb(0 0 0) } .pika-button:hover { background: #20E6E5; - color: #000000; + color: #000000; } .pika-button { @@ -746,23 +758,23 @@ body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-today > b body > div.datepicker.datepicker-dropdown.dropdown-menu.datepicker-orient-left.datepicker-orient-top > div.datepicker-days > table > tbody > tr > td.active.day { background: #282F38; - color: white; - + color: white; + } .datepicker table tr td.day:hover, .datepicker table tr td.focused { color: #000; - background: rgba(0,255,213,1); + background: rgba(0,255,213,1); cursor: pointer; } #print_log { - border-color: white; +border-color: white; } #logText, #logTextFull { - margin-top: 5px; +margin-top: 5px; } .append_table { @@ -779,16 +791,16 @@ body > div.datepicker.datepicker-dropdown.dropdown-menu.datepicker-orient-left.d border-color: black; } - + span#progress_bar-title.progress-text { - color: white; - font-size: 13px; - font-weight: normal; +color: white; +font-size: 13px; +font-weight: normal; } div#progress_bar.progress-bar { - font-size:13px; - line-height: 30px; +font-size:13px; +line-height: 30px; } .progress { @@ -802,8 +814,8 @@ border-color: white; } /* Visualization MST */ - -#mst_title_color { + + #mst_title_color { margin-bottom: 21px; } @@ -823,7 +835,7 @@ border-color: white; } #maindivtree_mst, #graphtree_mst { - border-radius: 10px; +border-radius: 10px; } button#create_tree { @@ -868,110 +880,110 @@ left: -7px; } #mst_ratio { - position: absolute; - right: 36px; - top: 23px; +position: absolute; +right: 36px; +top: 23px; } button#mst_general_menu { - height: 27px; - width: 27px; - background: #20E6E5; +height: 27px; +width: 27px; +background: #20E6E5; color: #000000; border-radius: 5px; - margin-top: 2px; +margin-top: 2px; } button#mst_analysis_menu { - height: 27px; - width: 27px; - background: #20E6E5; +height: 27px; +width: 27px; +background: #20E6E5; color: #000000; border-radius: 5px; - margin-top: -17px; - position: relative; - top: -10px; +margin-top: -17px; +position: relative; +top: -10px; } button#mst_node_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; border-radius: 5px; - margin-top: 10px; - margin-bottom: -1px; +margin-top: 10px; +margin-bottom: -1px; } button#mst_edge_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; border-radius: 5px; } button#mst_title_menu { - height: 34px; - margin-top: 20px; - border-radius: 5px +height: 34px; +margin-top: 20px; +border-radius: 5px } button#mst_edgelabel_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 37px; - border-radius: 5px +border-radius: 5px } button#mst_edgecolor_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px +border-radius: 5px } button#mst_subtitle_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px +border-radius: 5px } button#mst_legend_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px +border-radius: 5px } button#mst_label_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 37px; - border-radius: 5px +border-radius: 5px } button#mst_col_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 11px; - margin-bottom: -2px; - border-radius: 5px; +margin-bottom: -2px; +border-radius: 5px; } button#mst_col_map_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 10px; - margin-left: -10px; - border-radius: 5px; - margin-bottom: -1px; +margin-left: -10px; +border-radius: 5px; +margin-bottom: -1px; } .mst_shape_sel div>.selectize-dropdown { @@ -995,69 +1007,69 @@ button#mst_col_map_menu { } #mst_color_node { - margin-top: -10px; - margin-bottom: -1px; +margin-top: -10px; +margin-bottom: -1px; } #mst_background_color { - margin-top: -10px; +margin-top: -10px; } #mst_shadow { - position: relative; - bottom: -1px; +position: relative; +bottom: -1px; } #mst_edge_font_color { - margin-top: 17px; - margin-bottom: 17px; +margin-top: 17px; +margin-bottom: 17px; } #node_font_color { - margin-top: 17px +margin-top: 17px } #scale_nodes { - position: relative; - bottom: -1px +position: relative; +bottom: -1px } #tree_mst { - border-radius: 10px; +border-radius: 10px; } #titletree_mst { - border-radius: 10px; - margin-bottom: 10px; - margin-left: 100px; - text-align: left !important; +border-radius: 10px; +margin-bottom: 10px; +margin-left: 100px; +text-align: left !important; } #subtitletree_mst { - margin-bottom: 10px; - margin-left: 100px; - text-align: left !important; +margin-bottom: 10px; +margin-left: 100px; +text-align: left !important; } #footertree_mst { - border-radius: 10px; - position: relative; - top: -10px; +border-radius: 10px; +position: relative; +top: -10px; } #legendtree_mst { - border-radius: 10px; - position: relative; - top: -10px; +border-radius: 10px; +position: relative; +top: -10px; } /* Visualization NJ & UPGMA */ - -/* Classes*/ - -.label_sel { - margin-bottom: -16px; -} + + /* Classes*/ + + .label_sel { + margin-bottom: -16px; + } .slider { margin-bottom: -6px; @@ -1145,7 +1157,7 @@ button#mst_col_map_menu { .material-switch>label.switch:before { background: #20e6e559 !important; - border-radius: 8px; + border-radius: 8px; content: ""; height: 13px; margin-top: -10px; @@ -1159,10 +1171,10 @@ button#mst_col_map_menu { .material-switch>label.switch:hover:before { border: 1px solid #20e6e5; } - + .material-switch>input[type=checkbox]:checked+label.switch:before { background: #20e6e5 !important; - border-radius: 8px; + border-radius: 8px; content: ""; height: 13px; margin-top: -10px; @@ -1179,7 +1191,7 @@ button#mst_col_map_menu { .material-switch>label.switch:after { background: #E6E6E6 !important; - border-radius: 1pc; + border-radius: 1pc; box-shadow: 0 0 5px rgba(0,0,0,.3); content: ""; height: 20px; @@ -1239,178 +1251,178 @@ button#mst_col_map_menu { } #nj_cust_label_save, #upgma_cust_label_save { - border-color: white; - margin-top: 6px; - margin-bottom: 20px; +border-color: white; +margin-top: 6px; +margin-bottom: 20px; } #nj_add_new_label, #upgma_add_new_label { - background: green; - height: 35px; - width: 38px; - margin-top: 20px; +background: green; +height: 35px; +width: 38px; +margin-top: 20px; } button#nj_del_label, button#upgma_del_label { - background: #FF5964; +background: #FF5964; height: 35px; - width: 38px; - margin-top: 27px; +width: 38px; +margin-top: 27px; } #nj_custom_label_select, #upgma_custom_label_select { - margin-top: 7px; - margin-left: 15px; +margin-top: 7px; +margin-left: 15px; } #nj_tiplab_fill, #upgma_tiplab_fill { - margin-bottom: 39px; +margin-bottom: 39px; } - + #nj_sliderInput_y, #nj_sliderInput_x, #upgma_sliderInput_y, #upgma_sliderInput_x{ - margin-left: 15px; - margin-bottom: 10px; - margin-right: 15px; +margin-left: 15px; +margin-bottom: 10px; +margin-right: 15px; } #nj_heatmap_sel > div > div > button, #upgma_heatmap_sel > div > div > button { - background-color: white; +background-color: white; } #nj_heatmap_sel .filter-option-inner, #upgma_heatmap_sel .filter-option-inner { - text-align: center; +text-align: center; } #nj_clade_scale, #upgma_clade_scale { - margin-bottom:; 1px; +margin-bottom:; 1px; } #nj_parentnode, #upgma_parentnode { - margin-left: 38px; - margin-top: -10px; +margin-left: 38px; +margin-top: -10px; } #nj_layout_ctrl, #nj_label_ctrl, #nj_elements_ctrl, #upgma_layout_ctrl, #upgma_label_ctrl, #upgma_elements_ctrl { - width: 134px; - margin-left: 25px; - margin-bottom: 5px; - margin-top: 10px; - height: 40px; - text-align-last: justify; - font-size: larger; +width: 134px; +margin-left: 25px; +margin-bottom: 5px; +margin-top: 10px; +height: 40px; +text-align-last: justify; +font-size: larger; } #nj_layout_ctrl, #upgma_layout_ctrl { - margin-top: 20px !important; +margin-top: 20px !important; } #nj_field img, #upgma_field img{ - border-radius: 10px; +border-radius: 10px; } button#save_plot_jpeg { - font-size: 14px; - height: 34px; - background: #282F38; +font-size: 14px; +height: 34px; +background: #282F38; color: #ffffff; border: 1px solid white; - position: relative; - top: 10px; - right: 20px +position: relative; +top: 10px; +right: 20px } button#save_plot_png { - font-size: 14px; - height: 34px; - background: #282F38; +font-size: 14px; +height: 34px; +background: #282F38; color: #ffffff; border: 1px solid white; - position: relative; - top: 10px; - right: 20px +position: relative; +top: 10px; +right: 20px } button#save_plot_bmp { - font-size: 14px; - height: 34px; - background: #282F38; +font-size: 14px; +height: 34px; +background: #282F38; color: #ffffff; border: 1px solid white; - position: relative; - top: 10px; - right: 20px; +position: relative; +top: 10px; +right: 20px; } button#save_plot_html_bttn { - font-size: 14px; - height: 34px; - position: relative; - top: 10px; - right: 20px; - background: #282F38; +font-size: 14px; +height: 34px; +position: relative; +top: 10px; +right: 20px; +background: #282F38; color: #ffffff; border: 1px solid white; } button#create_rep.btn.btn-default.action-button.shiny-bound-input { - border: 1px solid white; - margin-left: 11px; +border: 1px solid white; +margin-left: 11px; } button#download_nj_bttn, button#download_upgma_bttn { - font-size: 14px; - height: 34px; - position: relative; - top: 10px; - right: 20px; - background: #282F38; +font-size: 14px; +height: 34px; +position: relative; +top: 10px; +right: 20px; +background: #282F38; color: #ffffff; border: 1px solid white; } #nj_ratio, #upgma_ratio { - position: absolute; - right: 36px; - top: 23px; +position: absolute; +right: 36px; +top: 23px; } #nj_v, #nj_h, #upgma_h, #upgma_v { - padding: initial; - margin-top: 3px; - width: 75px; - text-align: center; +padding: initial; +margin-top: 3px; +width: 75px; +text-align: center; } #nj_title_color, #upgma_title_color { - margin-bottom: -15px; - margin-top: -16px; +margin-bottom: -15px; +margin-top: -16px; } #nj_bg, #upgma_bg { - margin-bottom: 10px; - margin-left: 10px; - margin-top: -22px; +margin-bottom: 10px; +margin-left: 10px; +margin-top: -22px; } #nj_color, #upgma_color { - margin-left: 10px; +margin-left: 10px; } #nj_branch_label_menu-template > div > div:nth-child(2) > div:nth-child(2), #upgma_branch_label_menu-template > div > div:nth-child(2) > div:nth-child(2) { - margin-top: 26px; - margin-bottom: -10px; - margin-left: -10px; +margin-top: 26px; +margin-bottom: -10px; +margin-left: -10px; } #nj_controls, #upgma_controls { - margin-left: 25px; - margin-top: 35px; +margin-left: 25px; +margin-top: 35px; } #nj_controls > div > div:nth-child(1), @@ -1419,19 +1431,19 @@ button#download_nj_bttn, button#download_upgma_bttn { #upgma_controls > div > div:nth-child(2), #nj_controls > div > div:nth-child(3), #upgma_controls > div > div:nth-child(3) { - height: 50px; - width: 100px; +height: 50px; +width: 100px; } #nj_color_mapping, #upgma_color_mapping { - margin-top: -7px; - margin-bottom: 0px; - margin-right: 30px; +margin-top: -7px; +margin-bottom: 0px; +margin-right: 30px; } #nj_heatmap_scale, #nj_tiles_scale_1, #nj_tiles_scale_2, #nj_tiles_scale_3, #nj_tiles_scale_4, #nj_tiles_scale_5, #upgma_heatmap_scale, #upgma_tiles_scale_1, #upgma_tiles_scale_2, #upgma_tiles_scale_3, #upgma_tiles_scale_4, #upgma_tiles_scale_5 { - margin-top: -10px; +margin-top: -10px; } .heatmap-scale div>.selectize-dropdown { @@ -1440,344 +1452,344 @@ button#download_nj_bttn, button#download_upgma_bttn { } #nj_branch_label_color, #upgma_branch_label_color { - margin-top: -7px; +margin-top: -7px; } #nj_new_label_name, #upgma_new_label_name { - margin-left: 15px; - width: 90%; +margin-left: 15px; +width: 90%; } .heatmap-picker, { - margin-right: 105px + margin-right: 105px } button#nj_labeltext_menu, button#upgma_labeltext_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; border-radius: 5px; - margin-top: 20px; - margin-left: -50px +margin-top: 20px; +margin-left: -50px } button#nj_labelformat_menu, button#upgma_labelformat_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; border-radius: 5px; - margin-top: 20px +margin-top: 20px } button#nj_footer_menu, button#upgma_footer_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px +border-radius: 5px } button#nj_title_menu, button#upgma_title_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 4px; - border-radius: 5px; - margin-bottom: -24px; +border-radius: 5px; +margin-bottom: -24px; } button#nj_size_menu, button#upgma_size_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 0px; - border-radius: 5px; - margin-left: -15px; +border-radius: 5px; +margin-left: -15px; } button#nj_branch_label_menu, button#upgma_branch_label_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px; - margin-left: -10px +border-radius: 5px; +margin-left: -10px } button#nj_custom_label_menu, button#upgma_custom_label_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px; - margin-left: -20px; +border-radius: 5px; +margin-left: -20px; } button#nj_legend_menu, button#upgma_legend_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px +border-radius: 5px } button#nj_treescale_menu, button#upgma_treescale_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 20px; - border-radius: 5px +border-radius: 5px } button#nj_tippoint_menu, button#upgma_tippoint_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 21px; - border-radius: 5px +border-radius: 5px } button#nj_rootedge_menu, button#upgma_rootedge_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 16px; - border-radius: 5px; - margin-right: 10px; - margin-bottom: 23px; +border-radius: 5px; +margin-right: 10px; +margin-bottom: 23px; } button#nj_nodepoint_menu, button#upgma_nodepoint_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 21px; - border-radius: 5px +border-radius: 5px } button#nj_heatmap_menu, button#upgma_heatmap_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 21px; - border-radius: 5px; - margin-left: -10px; +border-radius: 5px; +margin-left: -10px; } button#nj_clade_menu, button#upgma_clade_menu { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-top: 19px; - border-radius: 5px; - margin-bottom: 12px; +border-radius: 5px; +margin-bottom: 12px; } button#nj_tile_menu, button#nj_tile_menu_2, button#nj_tile_menu_3, button#nj_tile_menu_4, button#nj_tile_menu_5, button#upgma_tile_menu, button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, button#upgma_tile_menu_5 { - height: 34px; - background: #20E6E5; +height: 34px; +background: #20E6E5; color: #000000; margin-left: 15px; - margin-top: 21px; - border-radius: 5px +margin-top: 21px; +border-radius: 5px } #nj_nodepoint_color, #nj_tippoint_color, #upgma_nodepoint_color, #upgma_tippoint_color { - margin-bottom: 10px; - margin-top: 6px; +margin-bottom: 10px; +margin-top: 6px; } #nj_treescale_show, #upgma_treescale_show { - margin-top: 17px; +margin-top: 17px; } #nj_tiles_show, #nj_tiles_show_2, #nj_tiles_show_3, #nj_tiles_show_4, #nj_tiles_show_5, #upgma_tiles_show, #upgma_tiles_show_2, #upgma_tiles_show_3, #upgma_tiles_show_4, #upgma_tiles_show_5 { - margin-top: 18px; - margin-left: -5px +margin-top: 18px; +margin-left: -5px } #nj_ladder, #upgma_ladder { - margin-top: 8px; - margin-left: -5px +margin-top: 8px; +margin-left: -5px } #nj_align, #upgma_align { - margin-top: 10px; - margin-left: -60px +margin-top: 10px; +margin-left: -60px } #nj_rootedge_show, #upgma_rootedge_show { - margin-top: 8px; - margin-left: -15px; +margin-top: 8px; +margin-left: -15px; } #nj_mapping_show, #upgma_mapping_show { - margin-top: 13px; +margin-top: 13px; } #nj_tipcolor_mapping, #nj_tipshape_mapping_show, #upgma_tipcolor_mapping, #upgma_tipshape_mapping_show { - margin-top: -10px; - margin-right: 30px; +margin-top: -10px; +margin-right: 30px; } #nj_tipshape_mapping, #nj_fruit_variable, #nj_fruit_variable2, #nj_fruit_variable3, #nj_fruit_variable4, #nj_fruit_variable5, #upgma_tipshape_mapping, #upgma_fruit_variable, #upgma_fruit_variable2, #upgma_fruit_variable3, #upgma_fruit_variable4, #upgma_fruit_variable5 { - margin-top: -10px; - margin-right: 30px; +margin-top: -10px; +margin-right: 30px; } #nj_tiplab_scale { - margin-top: 0px; - margin-bottom: -10px; +margin-top: 0px; +margin-bottom: -10px; } #upgma_tiplab_scale { - margin-top: -6px; - margin-bottom: -10px; +margin-top: -6px; +margin-bottom: -10px; } #upgma_tippoint_scale { - margin-top: -10px; +margin-top: -10px; } #shiny-tab-visualization > div:nth-child(5) > div > div:nth-child(5) > div > div > div > div > div > div:nth-child(2) > div:nth-child(3) > div > div > div { - margin-top: -7px; +margin-top: -7px; } #shiny-tab-visualization > div:nth-child(5) > div > div:nth-child(5) > div > div > div > div > div > div:nth-child(3) > div:nth-child(3) > div > div > div { - margin-top: -10px; +margin-top: -10px; } #nj_tipcolor_mapping, #upgma_tipcolor_mapping { - margin-top: -10px; +margin-top: -10px; } #nj_geom, #upgma_geom { - margin-top: 0px; - margin-left: -5px; - margin-bottom: 0px; +margin-top: 0px; +margin-left: -5px; +margin-bottom: 0px; } #nj_tiplab_color, #upgma_tiplab_color { - margin-bottom: 7px; - margin-top: -7px; +margin-bottom: 7px; +margin-top: -7px; } #nj_show_branch_label, #upgma_show_branch_label { - margin-top: 17px; - margin-left: -5px +margin-top: 17px; +margin-left: -5px } #nj_tiplab_show, #upgma_tiplab_show { - margin-top: 17px; - margin-left: -5px +margin-top: 17px; +margin-left: -5px } #nj_fruit_offset, #upgma_fruit_offset { - position: relative; - top: -20px +position: relative; +top: -20px } #nj_layout .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ - margin-bottom: 16px +margin-bottom: 16px } #nj_div_tiles, #upgma_div_tiles { - position: absolute; - bottom: 4px; - margin-left: -5px +position: absolute; +bottom: 4px; +margin-left: -5px } #nj_fruit_offset_2, #upgma_fruit_offset_2 { - position: relative; - top: -20px +position: relative; +top: -20px } #nj_layout_2 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_2 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ - margin-bottom: 16px +margin-bottom: 16px } #nj_div_tiles_2, #upgma_div_tiles_2 { - position: absolute; - bottom: 4px; - margin-left: -5px +position: absolute; +bottom: 4px; +margin-left: -5px } #nj_fruit_offset_3, #upgma_fruit_offset_3 { - position: relative; - top: -20px +position: relative; +top: -20px } #nj_layout_3 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_3 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ - margin-bottom: 16px +margin-bottom: 16px } #nj_div_tiles_3, #upgma_div_tiles_3 { - position: absolute; - bottom: 4px; - margin-left: -5px +position: absolute; +bottom: 4px; +margin-left: -5px } #nj_fruit_offset_4, #upgma_fruit_offset_4 { - position: relative; - top: -20px +position: relative; +top: -20px } #nj_layout_4 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_4 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ - margin-bottom: 16px +margin-bottom: 16px } #nj_div_tiles_4, #upgma_div_tiles_4 { - position: absolute; - bottom: 4px; - margin-left: -5px +position: absolute; +bottom: 4px; +margin-left: -5px } #nj_fruit_offset_5, #upgma_fruit_offset_5 { - position: relative; - top: -20px +position: relative; +top: -20px } #nj_layout_5 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_5 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y { - margin-bottom: 16px +margin-bottom: 16px } #nj_div_tiles_5, #upgma_div_tiles_5 { - position: absolute; - bottom: 4px; - margin-left: -5px +position: absolute; +bottom: 4px; +margin-left: -5px } #nj_heatmap_width, #upgma_heatmap_width { - margin-top: 8px; +margin-top: 8px; } #nj_heatmap_offset, #upgma_heatmap_offset { - margin-top: 4px; - margin-bottom: 2px; +margin-top: 4px; +margin-bottom: 2px; } #nj_fruit_width, #nj_fruit_width2, #nj_fruit_width3, #nj_fruit_width4, #nj_fruit_width5, #upgma_fruit_width, #upgma_fruit_width2, #upgma_fruit_width3, #upgma_fruit_width4, #upgma_fruit_width5{ - margin-top: -5px; - margin-bottom: -15px; +margin-top: -5px; +margin-bottom: -15px; } #nj_heatmap_show, #upgma_heatmap_show { - margin-top: 18px; - margin-left: -5px; +margin-top: 18px; +margin-left: -5px; } #nj_nodepoint_show, #nj_tippoint_show, #upgma_nodepoint_show, #upgma_tippoint_show { - margin-top: 18px; - margin-left: -5px +margin-top: 18px; +margin-left: -5px } #nj_tiplab_scale .option[data-value="Set1"], @@ -1798,10 +1810,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Set1"], #upgma_heatmap_scale .option[data-value="Set1"], #upgma_clade_scale .option[data-value="Set1"] { - background: linear-gradient(to right, #E41A1C 0%, #E41A1C 11%, #377EB8 11%, #377EB8 22%, #4DAF4A 22%, #4DAF4A 33%, #984EA3 33%, #984EA3 44%, #FF7F00 44%, #FF7F00 55%, #FFFF33 55%, #FFFF33 66%, #A65628 66%, #A65628 77%, #F781BF 77%, #F781BF 88%, #999999 88%, #999999 100%); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #E41A1C 0%, #E41A1C 11%, #377EB8 11%, #377EB8 22%, #4DAF4A 22%, #4DAF4A 33%, #984EA3 33%, #984EA3 44%, #FF7F00 44%, #FF7F00 55%, #FFFF33 55%, #FFFF33 66%, #A65628 66%, #A65628 77%, #F781BF 77%, #F781BF 88%, #999999 88%, #999999 100%); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Set2"], #nj_tippoint_scale .option[data-value="Set2"], @@ -1821,10 +1833,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Set2"], #upgma_heatmap_scale .option[data-value="Set2"], #upgma_clade_scale .option[data-value="Set2"] { - background: linear-gradient(to right, #66C2A5 0%, #66C2A5 12.5%, #FC8D62 12.5%, #FC8D62 25%, #8DA0CB 25%, #8DA0CB 37.5%, #E78AC3 37.5%, #E78AC3 50%, #A6D854 50%, #A6D854 62.5%, #FFD92F 62.5%, #FFD92F 75%, #E5C494 75%, #E5C494 87.5%, #B3B3B3 87.5%, #B3B3B3 100%); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #66C2A5 0%, #66C2A5 12.5%, #FC8D62 12.5%, #FC8D62 25%, #8DA0CB 25%, #8DA0CB 37.5%, #E78AC3 37.5%, #E78AC3 50%, #A6D854 50%, #A6D854 62.5%, #FFD92F 62.5%, #FFD92F 75%, #E5C494 75%, #E5C494 87.5%, #B3B3B3 87.5%, #B3B3B3 100%); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Set3"], #nj_tippoint_scale .option[data-value="Set3"], @@ -1844,10 +1856,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Set3"], #upgma_heatmap_scale .option[data-value="Set3"], #upgma_clade_scale .option[data-value="Set3"] { - background: linear-gradient(to right, #8DD3C7 0%, #8DD3C7 8.33333%, #FFFFB3 8.33333%, #FFFFB3 16.6667%, #BEBADA 16.6667%, #BEBADA 25%, #FB8072 25%, #FB8072 33.3333%, #80B1D3 33.3333%, #80B1D3 41.6667%, #FDB462 41.6667%, #FDB462 50%, #B3DE69 50%, #B3DE69 58.3333%, #FCCDE5 58.3333%, #FCCDE5 66.6667%, #D9D9D9 66.6667%, #D9D9D9 75%, #BC80BD 75%, #BC80BD 83.3333%, #CCEBC5 83.3333%, #CCEBC5 91.6667%, #FFED6F 91.6667%, #FFED6F 100%); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #8DD3C7 0%, #8DD3C7 8.33333%, #FFFFB3 8.33333%, #FFFFB3 16.6667%, #BEBADA 16.6667%, #BEBADA 25%, #FB8072 25%, #FB8072 33.3333%, #80B1D3 33.3333%, #80B1D3 41.6667%, #FDB462 41.6667%, #FDB462 50%, #B3DE69 50%, #B3DE69 58.3333%, #FCCDE5 58.3333%, #FCCDE5 66.6667%, #D9D9D9 66.6667%, #D9D9D9 75%, #BC80BD 75%, #BC80BD 83.3333%, #CCEBC5 83.3333%, #CCEBC5 91.6667%, #FFED6F 91.6667%, #FFED6F 100%); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Pastel1"], #nj_tippoint_scale .option[data-value="Pastel1"], @@ -1867,10 +1879,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Pastel1"], #upgma_heatmap_scale .option[data-value="Pastel1"], #upgma_clade_scale .option[data-value="Pastel1"] { - background: linear-gradient(to right, #FBB4AE 0%, #FBB4AE 11.1111%, #B3CDE3 11.1111%, #B3CDE3 22.2222%, #CCEBC5 22.2222%, #CCEBC5 33.3333%, #DECBE4 33.3333%, #DECBE4 44.4444%, #FED9A6 44.4444%, #FED9A6 55.5556%, #FFFFCC 55.5556%, #FFFFCC 66.6667%, #E5D8BD 66.6667%, #E5D8BD 77.7778%, #FDDAEC 77.7778%, #FDDAEC 88.8889%, #F2F2F2 88.8889%, #F2F2F2 100%); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FBB4AE 0%, #FBB4AE 11.1111%, #B3CDE3 11.1111%, #B3CDE3 22.2222%, #CCEBC5 22.2222%, #CCEBC5 33.3333%, #DECBE4 33.3333%, #DECBE4 44.4444%, #FED9A6 44.4444%, #FED9A6 55.5556%, #FFFFCC 55.5556%, #FFFFCC 66.6667%, #E5D8BD 66.6667%, #E5D8BD 77.7778%, #FDDAEC 77.7778%, #FDDAEC 88.8889%, #F2F2F2 88.8889%, #F2F2F2 100%); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Pastel2"], #nj_tippoint_scale .option[data-value="Pastel2"], @@ -1890,10 +1902,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Pastel2"], #upgma_heatmap_scale .option[data-value="Pastel2"], #upgma_clade_scale .option[data-value="Pastel2"] { - background: linear-gradient(to right, #B3E2CD 0%, #B3E2CD 12.5%, #FDCDAC 12.5%, #FDCDAC 25%, #CBD5E8 25%, #CBD5E8 37.5%, #F4CAE4 37.5%, #F4CAE4 50%, #E6F5C9 50%, #E6F5C9 62.5%, #FFF2AE 62.5%, #FFF2AE 75%, #F1E2CC 75%, #F1E2CC 87.5%, #CCCCCC 87.5%, #CCCCCC 100%); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #B3E2CD 0%, #B3E2CD 12.5%, #FDCDAC 12.5%, #FDCDAC 25%, #CBD5E8 25%, #CBD5E8 37.5%, #F4CAE4 37.5%, #F4CAE4 50%, #E6F5C9 50%, #E6F5C9 62.5%, #FFF2AE 62.5%, #FFF2AE 75%, #F1E2CC 75%, #F1E2CC 87.5%, #CCCCCC 87.5%, #CCCCCC 100%); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Paired"], #nj_tippoint_scale .option[data-value="Paired"], @@ -1913,10 +1925,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Paired"], #upgma_heatmap_scale .option[data-value="Paired"], #upgma_clade_scale .option[data-value="Paired"] { - background: linear-gradient(to right, #A6CEE3 0%, #A6CEE3 8.33333%, #1F78B4 8.33333%, #1F78B4 16.6667%, #B2DF8A 16.6667%, #B2DF8A 25%, #33A02C 25%, #33A02C 33.3333%, #FB9A99 33.3333%, #FB9A99 41.6667%, #E31A1C 41.6667%, #E31A1C 50%, #FDBF6F 50%, #FDBF6F 58.3333%, #FF7F00 58.3333%, #FF7F00 66.6667%, #CAB2D6 66.6667%, #CAB2D6 75%, #6A3D9A 75%, #6A3D9A 83.3333%, #FFFF99 83.3333%, #FFFF99 91.6667%, #B15928 91.6667%, #B15928 100%); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #A6CEE3 0%, #A6CEE3 8.33333%, #1F78B4 8.33333%, #1F78B4 16.6667%, #B2DF8A 16.6667%, #B2DF8A 25%, #33A02C 25%, #33A02C 33.3333%, #FB9A99 33.3333%, #FB9A99 41.6667%, #E31A1C 41.6667%, #E31A1C 50%, #FDBF6F 50%, #FDBF6F 58.3333%, #FF7F00 58.3333%, #FF7F00 66.6667%, #CAB2D6 66.6667%, #CAB2D6 75%, #6A3D9A 75%, #6A3D9A 83.3333%, #FFFF99 83.3333%, #FFFF99 91.6667%, #B15928 91.6667%, #B15928 100%); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Dark2"], #nj_tippoint_scale .option[data-value="Dark2"], @@ -1936,10 +1948,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Dark2"], #upgma_heatmap_scale .option[data-value="Dark2"], #upgma_clade_scale .option[data-value="Dark2"] { - background: linear-gradient(to right, #1B9E77 0%, #1B9E77 12.5%, #D95F02 12.5%, #D95F02 25%, #7570B3 25%, #7570B3 37.5%, #E7298A 37.5%, #E7298A 50%, #66A61E 50%, #66A61E 62.5%, #E6AB02 62.5%, #E6AB02 75%, #A6761D 75%, #A6761D 87.5%, #666666 87.5%, #666666 100%); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #1B9E77 0%, #1B9E77 12.5%, #D95F02 12.5%, #D95F02 25%, #7570B3 25%, #7570B3 37.5%, #E7298A 37.5%, #E7298A 50%, #66A61E 50%, #66A61E 62.5%, #E6AB02 62.5%, #E6AB02 75%, #A6761D 75%, #A6761D 87.5%, #666666 87.5%, #666666 100%); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Accent"], #nj_tippoint_scale .option[data-value="Accent"], @@ -1959,9 +1971,9 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Accent"], #upgma_heatmap_scale .option[data-value="Accent"], #upgma_clade_scale .option[data-value="Accent"]{ - background: linear-gradient(to right, #7FC97F 0%, #7FC97F 12.5%, #BEAED4 12.5%, #BEAED4 25%, #FDC086 25%, #FDC086 37.5%, #FFFF99 37.5%, #FFFF99 50%, #386CB0 50%, #386CB0 62.5%, #F0027F 62.5%, #F0027F 75%, #BF5B17 75%, #BF5B17 87.5%, #666666 87.5%, #666666 100%); - color: black; -} +background: linear-gradient(to right, #7FC97F 0%, #7FC97F 12.5%, #BEAED4 12.5%, #BEAED4 25%, #FDC086 25%, #FDC086 37.5%, #FFFF99 37.5%, #FFFF99 50%, #386CB0 50%, #386CB0 62.5%, #F0027F 62.5%, #F0027F 75%, #BF5B17 75%, #BF5B17 87.5%, #666666 87.5%, #666666 100%); + color: black; + } #nj_tiplab_scale .option[data-value="YlOrRd"], #nj_tippoint_scale .option[data-value="YlOrRd"], @@ -1981,10 +1993,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="YlOrRd"], #upgma_heatmap_scale .option[data-value="YlOrRd"], #upgma_clade_scale .option[data-value="YlOrRd"] { - background: linear-gradient(to right, #FFFFCC 0%, #FFFFCC 11.1111%, #FFEDA0 11.1111%, #FFEDA0 22.2222%, #FED976 22.2222%, #FED976 33.3333%, #FEB24C 33.3333%, #FEB24C 44.4444%, #FD8D3C 44.4444%, #FD8D3C 55.5556%, #FC4E2A 55.5556%, #FC4E2A 66.6667%, #E31A1C 66.6667%, #E31A1C 77.7778%, #BD0026 77.7778%, #BD0026 88.8889%, #800026 88.8889%, #800026 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFFFCC 0%, #FFFFCC 11.1111%, #FFEDA0 11.1111%, #FFEDA0 22.2222%, #FED976 22.2222%, #FED976 33.3333%, #FEB24C 33.3333%, #FEB24C 44.4444%, #FD8D3C 44.4444%, #FD8D3C 55.5556%, #FC4E2A 55.5556%, #FC4E2A 66.6667%, #E31A1C 66.6667%, #E31A1C 77.7778%, #BD0026 77.7778%, #BD0026 88.8889%, #800026 88.8889%, #800026 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="YlOrBr"], #nj_tippoint_scale .option[data-value="YlOrBr"], @@ -2004,10 +2016,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="YlOrBr"], #upgma_heatmap_scale .option[data-value="YlOrBr"], #upgma_clade_scale .option[data-value="YlOrBr"] { - background: linear-gradient(to right, #FFFFE5 0%, #FFFFE5 11.1111%, #FFF7BC 11.1111%, #FFF7BC 22.2222%, #FEE391 22.2222%, #FEE391 33.3333%, #FEC44F 33.3333%, #FEC44F 44.4444%, #FE9929 44.4444%, #FE9929 55.5556%, #EC7014 55.5556%, #EC7014 66.6667%, #CC4C02 66.6667%, #CC4C02 77.7778%, #993404 77.7778%, #993404 88.8889%, #662506 88.8889%, #662506 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFFFE5 0%, #FFFFE5 11.1111%, #FFF7BC 11.1111%, #FFF7BC 22.2222%, #FEE391 22.2222%, #FEE391 33.3333%, #FEC44F 33.3333%, #FEC44F 44.4444%, #FE9929 44.4444%, #FE9929 55.5556%, #EC7014 55.5556%, #EC7014 66.6667%, #CC4C02 66.6667%, #CC4C02 77.7778%, #993404 77.7778%, #993404 88.8889%, #662506 88.8889%, #662506 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="YlGnBu"], #nj_tippoint_scale .option[data-value="YlGnBu"], @@ -2027,10 +2039,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="YlGnBu"], #upgma_heatmap_scale .option[data-value="YlGnBu"], #upgma_clade_scale .option[data-value="YlGnBu"] { - background: linear-gradient(to right, #FFFFD9 0%, #FFFFD9 11.1111%, #EDF8B1 11.1111%, #EDF8B1 22.2222%, #C7E9B4 22.2222%, #C7E9B4 33.3333%, #7FCDBB 33.3333%, #7FCDBB 44.4444%, #41B6C4 44.4444%, #41B6C4 55.5556%, #1D91C0 55.5556%, #1D91C0 66.6667%, #225EA8 66.6667%, #225EA8 77.7778%, #253494 77.7778%, #253494 88.8889%, #081D58 88.8889%, #081D58 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFFFD9 0%, #FFFFD9 11.1111%, #EDF8B1 11.1111%, #EDF8B1 22.2222%, #C7E9B4 22.2222%, #C7E9B4 33.3333%, #7FCDBB 33.3333%, #7FCDBB 44.4444%, #41B6C4 44.4444%, #41B6C4 55.5556%, #1D91C0 55.5556%, #1D91C0 66.6667%, #225EA8 66.6667%, #225EA8 77.7778%, #253494 77.7778%, #253494 88.8889%, #081D58 88.8889%, #081D58 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="YlGn"], #nj_tippoint_scale .option[data-value="YlGn"], @@ -2050,10 +2062,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="YlGn"], #upgma_heatmap_scale .option[data-value="YlGn"], #upgma_clade_scale .option[data-value="YlGn"]{ - background: linear-gradient(to right, #FFFFE5 0%, #FFFFE5 11.1111%, #F7FCB9 11.1111%, #F7FCB9 22.2222%, #D9F0A3 22.2222%, #D9F0A3 33.3333%, #ADDD8E 33.3333%, #ADDD8E 44.4444%, #78C679 44.4444%, #78C679 55.5556%, #41AB5D 55.5556%, #41AB5D 66.6667%, #238443 66.6667%, #238443 77.7778%, #006837 77.7778%, #006837 88.8889%, #004529 88.8889%, #004529 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFFFE5 0%, #FFFFE5 11.1111%, #F7FCB9 11.1111%, #F7FCB9 22.2222%, #D9F0A3 22.2222%, #D9F0A3 33.3333%, #ADDD8E 33.3333%, #ADDD8E 44.4444%, #78C679 44.4444%, #78C679 55.5556%, #41AB5D 55.5556%, #41AB5D 66.6667%, #238443 66.6667%, #238443 77.7778%, #006837 77.7778%, #006837 88.8889%, #004529 88.8889%, #004529 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Reds"], #nj_tippoint_scale .option[data-value="Reds"], @@ -2073,10 +2085,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Reds"], #upgma_heatmap_scale .option[data-value="Reds"], #upgma_clade_scale .option[data-value="Reds"] { - background: linear-gradient(to right, #FFF5F0 0%, #FFF5F0 11.1111%, #FEE0D2 11.1111%, #FEE0D2 22.2222%, #FCBBA1 22.2222%, #FCBBA1 33.3333%, #FC9272 33.3333%, #FC9272 44.4444%, #FB6A4A 44.4444%, #FB6A4A 55.5556%, #EF3B2C 55.5556%, #EF3B2C 66.6667%, #CB181D 66.6667%, #CB181D 77.7778%, #A50F15 77.7778%, #A50F15 88.8889%, #67000D 88.8889%, #67000D 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFF5F0 0%, #FFF5F0 11.1111%, #FEE0D2 11.1111%, #FEE0D2 22.2222%, #FCBBA1 22.2222%, #FCBBA1 33.3333%, #FC9272 33.3333%, #FC9272 44.4444%, #FB6A4A 44.4444%, #FB6A4A 55.5556%, #EF3B2C 55.5556%, #EF3B2C 66.6667%, #CB181D 66.6667%, #CB181D 77.7778%, #A50F15 77.7778%, #A50F15 88.8889%, #67000D 88.8889%, #67000D 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="RdPu"], #nj_tippoint_scale .option[data-value="RdPu"], @@ -2096,10 +2108,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="RdPu"], #upgma_heatmap_scale .option[data-value="RdPu"], #upgma_clade_scale .option[data-value="RdPu"] { - background: linear-gradient(to right, #FFF7F3 0%, #FFF7F3 11.1111%, #FDE0DD 11.1111%, #FDE0DD 22.2222%, #FCC5C0 22.2222%, #FCC5C0 33.3333%, #FA9FB5 33.3333%, #FA9FB5 44.4444%, #F768A1 44.4444%, #F768A1 55.5556%, #DD3497 55.5556%, #DD3497 66.6667%, #AE017E 66.6667%, #AE017E 77.7778%, #7A0177 77.7778%, #7A0177 88.8889%, #49006A 88.8889%, #49006A 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFF7F3 0%, #FFF7F3 11.1111%, #FDE0DD 11.1111%, #FDE0DD 22.2222%, #FCC5C0 22.2222%, #FCC5C0 33.3333%, #FA9FB5 33.3333%, #FA9FB5 44.4444%, #F768A1 44.4444%, #F768A1 55.5556%, #DD3497 55.5556%, #DD3497 66.6667%, #AE017E 66.6667%, #AE017E 77.7778%, #7A0177 77.7778%, #7A0177 88.8889%, #49006A 88.8889%, #49006A 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Purples"], #nj_tippoint_scale .option[data-value="Purples"], @@ -2119,10 +2131,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Purples"], #upgma_heatmap_scale .option[data-value="Purples"], #upgma_clade_scale .option[data-value="Purples"] { - background: linear-gradient(to right, #FCFBFD 0%, #FCFBFD 11.1111%, #EFEDF5 11.1111%, #EFEDF5 22.2222%, #DADAEB 22.2222%, #DADAEB 33.3333%, #BCBDDC 33.3333%, #BCBDDC 44.4444%, #9E9AC8 44.4444%, #9E9AC8 55.5556%, #807DBA 55.5556%, #807DBA 66.6667%, #6A51A3 66.6667%, #6A51A3 77.7778%, #54278F 77.7778%, #54278F 88.8889%, #3F007D 88.8889%, #3F007D 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FCFBFD 0%, #FCFBFD 11.1111%, #EFEDF5 11.1111%, #EFEDF5 22.2222%, #DADAEB 22.2222%, #DADAEB 33.3333%, #BCBDDC 33.3333%, #BCBDDC 44.4444%, #9E9AC8 44.4444%, #9E9AC8 55.5556%, #807DBA 55.5556%, #807DBA 66.6667%, #6A51A3 66.6667%, #6A51A3 77.7778%, #54278F 77.7778%, #54278F 88.8889%, #3F007D 88.8889%, #3F007D 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="PuRd"], #nj_tippoint_scale .option[data-value="PuRd"], @@ -2142,10 +2154,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="PuRd"], #upgma_heatmap_scale .option[data-value="PuRd"], #upgma_clade_scale .option[data-value="PuRd"] { - background: linear-gradient(to right, #F7F4F9 0%, #F7F4F9 11.1111%, #E7E1EF 11.1111%, #E7E1EF 22.2222%, #D4B9DA 22.2222%, #D4B9DA 33.3333%, #C994C7 33.3333%, #C994C7 44.4444%, #DF65B0 44.4444%, #DF65B0 55.5556%, #E7298A 55.5556%, #E7298A 66.6667%, #CE1256 66.6667%, #CE1256 77.7778%, #980043 77.7778%, #980043 88.8889%, #67001F 88.8889%, #67001F 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #F7F4F9 0%, #F7F4F9 11.1111%, #E7E1EF 11.1111%, #E7E1EF 22.2222%, #D4B9DA 22.2222%, #D4B9DA 33.3333%, #C994C7 33.3333%, #C994C7 44.4444%, #DF65B0 44.4444%, #DF65B0 55.5556%, #E7298A 55.5556%, #E7298A 66.6667%, #CE1256 66.6667%, #CE1256 77.7778%, #980043 77.7778%, #980043 88.8889%, #67001F 88.8889%, #67001F 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="PuBuGn"], #nj_tippoint_scale .option[data-value="PuBuGn"], @@ -2165,10 +2177,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="PuBuGn"], #upgma_heatmap_scale .option[data-value="PuBuGn"], #upgma_clade_scale .option[data-value="PuBuGn"] { - background: linear-gradient(to right, #FFF7FB 0%, #FFF7FB 11.1111%, #ECE2F0 11.1111%, #ECE2F0 22.2222%, #D0D1E6 22.2222%, #D0D1E6 33.3333%, #A6BDDB 33.3333%, #A6BDDB 44.4444%, #67A9CF 44.4444%, #67A9CF 55.5556%, #3690C0 55.5556%, #3690C0 66.6667%, #02818A 66.6667%, #02818A 77.7778%, #016C59 77.7778%, #016C59 88.8889%, #014636 88.8889%, #014636 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFF7FB 0%, #FFF7FB 11.1111%, #ECE2F0 11.1111%, #ECE2F0 22.2222%, #D0D1E6 22.2222%, #D0D1E6 33.3333%, #A6BDDB 33.3333%, #A6BDDB 44.4444%, #67A9CF 44.4444%, #67A9CF 55.5556%, #3690C0 55.5556%, #3690C0 66.6667%, #02818A 66.6667%, #02818A 77.7778%, #016C59 77.7778%, #016C59 88.8889%, #014636 88.8889%, #014636 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="PuBu"], #nj_tippoint_scale .option[data-value="PuBu"], @@ -2188,10 +2200,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="PuBu"], #upgma_heatmap_scale .option[data-value="PuBu"], #upgma_clade_scale .option[data-value="PuBu"] { - background: linear-gradient(to right, #FFF7FB 0%, #FFF7FB 11.1111%, #ECE7F2 11.1111%, #ECE7F2 22.2222%, #D0D1E6 22.2222%, #D0D1E6 33.3333%, #A6BDDB 33.3333%, #A6BDDB 44.4444%, #74A9CF 44.4444%, #74A9CF 55.5556%, #3690C0 55.5556%, #3690C0 66.6667%, #0570B0 66.6667%, #0570B0 77.7778%, #045A8D 77.7778%, #045A8D 88.8889%, #023858 88.8889%, #023858 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFF7FB 0%, #FFF7FB 11.1111%, #ECE7F2 11.1111%, #ECE7F2 22.2222%, #D0D1E6 22.2222%, #D0D1E6 33.3333%, #A6BDDB 33.3333%, #A6BDDB 44.4444%, #74A9CF 44.4444%, #74A9CF 55.5556%, #3690C0 55.5556%, #3690C0 66.6667%, #0570B0 66.6667%, #0570B0 77.7778%, #045A8D 77.7778%, #045A8D 88.8889%, #023858 88.8889%, #023858 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="OrRd"], #nj_tippoint_scale .option[data-value="OrRd"], @@ -2211,10 +2223,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="OrRd"], #upgma_heatmap_scale .option[data-value="OrRd"], #upgma_clade_scale .option[data-value="OrRd"] { - background: linear-gradient(to right, #FFF7EC 0%, #FFF7EC 11.1111%, #FEE8C8 11.1111%, #FEE8C8 22.2222%, #FDD49E 22.2222%, #FDD49E 33.3333%, #FDBB84 33.3333%, #FDBB84 44.4444%, #FC8D59 44.4444%, #FC8D59 55.5556%, #EF6548 55.5556%, #EF6548 66.6667%, #D7301F 66.6667%, #D7301F 77.7778%, #B30000 77.7778%, #B30000 88.8889%, #7F0000 88.8889%, #7F0000 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFF7EC 0%, #FFF7EC 11.1111%, #FEE8C8 11.1111%, #FEE8C8 22.2222%, #FDD49E 22.2222%, #FDD49E 33.3333%, #FDBB84 33.3333%, #FDBB84 44.4444%, #FC8D59 44.4444%, #FC8D59 55.5556%, #EF6548 55.5556%, #EF6548 66.6667%, #D7301F 66.6667%, #D7301F 77.7778%, #B30000 77.7778%, #B30000 88.8889%, #7F0000 88.8889%, #7F0000 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Oranges"], #nj_tippoint_scale .option[data-value="Oranges"], @@ -2234,10 +2246,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Oranges"], #upgma_heatmap_scale .option[data-value="Oranges"], #upgma_clade_scale .option[data-value="Oranges"] { - background: linear-gradient(to right, #FFF5EB 0%, #FFF5EB 11.1111%, #FEE6CE 11.1111%, #FEE6CE 22.2222%, #FDD0A2 22.2222%, #FDD0A2 33.3333%, #FDAE6B 33.3333%, #FDAE6B 44.4444%, #FD8D3C 44.4444%, #FD8D3C 55.5556%, #F16913 55.5556%, #F16913 66.6667%, #D94801 66.6667%, #D94801 77.7778%, #A63603 77.7778%, #A63603 88.8889%, #7F2704 88.8889%, #7F2704 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #FFF5EB 0%, #FFF5EB 11.1111%, #FEE6CE 11.1111%, #FEE6CE 22.2222%, #FDD0A2 22.2222%, #FDD0A2 33.3333%, #FDAE6B 33.3333%, #FDAE6B 44.4444%, #FD8D3C 44.4444%, #FD8D3C 55.5556%, #F16913 55.5556%, #F16913 66.6667%, #D94801 66.6667%, #D94801 77.7778%, #A63603 77.7778%, #A63603 88.8889%, #7F2704 88.8889%, #7F2704 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Greys"], #nj_tippoint_scale .option[data-value="Greys"], @@ -2257,9 +2269,9 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Greys"], #upgma_heatmap_scale .option[data-value="Greys"], #upgma_clade_scale .option[data-value="Greys"] { - background: linear-gradient(to right, #FFFFFF 0%, #FFFFFF 11.1111%, #F0F0F0 11.1111%, #F0F0F0 22.2222%, #D9D9D9 22.2222%, #D9D9D9 33.3333%, #BDBDBD 33.3333%, #BDBDBD 44.4444%, #969696 44.4444%, #969696 55.5556%, #737373 55.5556%, #737373 66.6667%, #525252 66.6667%, #525252 77.7778%, #252525 77.7778%, #252525 88.8889%, #000000 88.8889%, #000000 100%); - color: white; -} +background: linear-gradient(to right, #FFFFFF 0%, #FFFFFF 11.1111%, #F0F0F0 11.1111%, #F0F0F0 22.2222%, #D9D9D9 22.2222%, #D9D9D9 33.3333%, #BDBDBD 33.3333%, #BDBDBD 44.4444%, #969696 44.4444%, #969696 55.5556%, #737373 55.5556%, #737373 66.6667%, #525252 66.6667%, #525252 77.7778%, #252525 77.7778%, #252525 88.8889%, #000000 88.8889%, #000000 100%); + color: white; + } #nj_tiplab_scale .option[data-value="Greens"], #nj_tippoint_scale .option[data-value="Greens"], @@ -2279,10 +2291,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Greens"], #upgma_heatmap_scale .option[data-value="Greens"], #upgma_clade_scale .option[data-value="Greens"] { - background: linear-gradient(to right, #F7FCF5 0%, #F7FCF5 11.1111%, #E5F5E0 11.1111%, #E5F5E0 22.2222%, #C7E9C0 22.2222%, #C7E9C0 33.3333%, #A1D99B 33.3333%, #A1D99B 44.4444%, #74C476 44.4444%, #74C476 55.5556%, #41AB5D 55.5556%, #41AB5D 66.6667%, #238B45 66.6667%, #238B45 77.7778%, #006D2C 77.7778%, #006D2C 88.8889%, #00441B 88.8889%, #00441B 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #F7FCF5 0%, #F7FCF5 11.1111%, #E5F5E0 11.1111%, #E5F5E0 22.2222%, #C7E9C0 22.2222%, #C7E9C0 33.3333%, #A1D99B 33.3333%, #A1D99B 44.4444%, #74C476 44.4444%, #74C476 55.5556%, #41AB5D 55.5556%, #41AB5D 66.6667%, #238B45 66.6667%, #238B45 77.7778%, #006D2C 77.7778%, #006D2C 88.8889%, #00441B 88.8889%, #00441B 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="GnBu"], #nj_tippoint_scale .option[data-value="GnBu"], @@ -2302,10 +2314,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="GnBu"], #upgma_heatmap_scale .option[data-value="GnBu"], #upgma_clade_scale .option[data-value="GnBu"] { - background: linear-gradient(to right, #F7FCF0 0%, #F7FCF0 11.1111%, #E0F3DB 11.1111%, #E0F3DB 22.2222%, #CCEBC5 22.2222%, #CCEBC5 33.3333%, #A8DDB5 33.3333%, #A8DDB5 44.4444%, #7BCCC4 44.4444%, #7BCCC4 55.5556%, #4EB3D3 55.5556%, #4EB3D3 66.6667%, #2B8CBE 66.6667%, #2B8CBE 77.7778%, #0868AC 77.7778%, #0868AC 88.8889%, #084081 88.8889%, #084081 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #F7FCF0 0%, #F7FCF0 11.1111%, #E0F3DB 11.1111%, #E0F3DB 22.2222%, #CCEBC5 22.2222%, #CCEBC5 33.3333%, #A8DDB5 33.3333%, #A8DDB5 44.4444%, #7BCCC4 44.4444%, #7BCCC4 55.5556%, #4EB3D3 55.5556%, #4EB3D3 66.6667%, #2B8CBE 66.6667%, #2B8CBE 77.7778%, #0868AC 77.7778%, #0868AC 88.8889%, #084081 88.8889%, #084081 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="BuPu"], #nj_tippoint_scale .option[data-value="BuPu"], @@ -2325,10 +2337,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="BuPu"], #upgma_heatmap_scale .option[data-value="BuPu"], #upgma_clade_scale .option[data-value="BuPu"] { - background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E0ECF4 11.1111%, #E0ECF4 22.2222%, #BFD3E6 22.2222%, #BFD3E6 33.3333%, #9EBCDA 33.3333%, #9EBCDA 44.4444%, #8C96C6 44.4444%, #8C96C6 55.5556%, #8C6BB1 55.5556%, #8C6BB1 66.6667%, #88419D 66.6667%, #88419D 77.7778%, #810F7C 77.7778%, #810F7C 88.8889%, #4D004B 88.8889%, #4D004B 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E0ECF4 11.1111%, #E0ECF4 22.2222%, #BFD3E6 22.2222%, #BFD3E6 33.3333%, #9EBCDA 33.3333%, #9EBCDA 44.4444%, #8C96C6 44.4444%, #8C96C6 55.5556%, #8C6BB1 55.5556%, #8C6BB1 66.6667%, #88419D 66.6667%, #88419D 77.7778%, #810F7C 77.7778%, #810F7C 88.8889%, #4D004B 88.8889%, #4D004B 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="BuGn"], #nj_tippoint_scale .option[data-value="BuGn"], @@ -2348,10 +2360,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="BuGn"], #upgma_heatmap_scale .option[data-value="BuGn"], #upgma_clade_scale .option[data-value="BuGn"] { - background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E5F5F9 11.1111%, #E5F5F9 22.2222%, #CCECE6 22.2222%, #CCECE6 33.3333%, #99D8C9 33.3333%, #99D8C9 44.4444%, #66C2A4 44.4444%, #66C2A4 55.5556%, #41AE76 55.5556%, #41AE76 66.6667%, #238B45 66.6667%, #238B45 77.7778%, #006D2C 77.7778%, #006D2C 88.8889%, #00441B 88.8889%, #00441B 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E5F5F9 11.1111%, #E5F5F9 22.2222%, #CCECE6 22.2222%, #CCECE6 33.3333%, #99D8C9 33.3333%, #99D8C9 44.4444%, #66C2A4 44.4444%, #66C2A4 55.5556%, #41AE76 55.5556%, #41AE76 66.6667%, #238B45 66.6667%, #238B45 77.7778%, #006D2C 77.7778%, #006D2C 88.8889%, #00441B 88.8889%, #00441B 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="Blues"], #nj_tippoint_scale .option[data-value="Blues"], @@ -2371,10 +2383,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_5 .option[data-value="Blues"], #upgma_heatmap_scale .option[data-value="Blues"], #upgma_clade_scale .option[data-value="Blues"] { - background: linear-gradient(to right, #F7FBFF 0%, #F7FBFF 11.1111%, #DEEBF7 11.1111%, #DEEBF7 22.2222%, #C6DBEF 22.2222%, #C6DBEF 33.3333%, #9ECAE1 33.3333%, #9ECAE1 44.4444%, #6BAED6 44.4444%, #6BAED6 55.5556%, #4292C6 55.5556%, #4292C6 66.6667%, #2171B5 66.6667%, #2171B5 77.7778%, #08519C 77.7778%, #08519C 88.8889%, #08306B 88.8889%, #08306B 100%); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #F7FBFF 0%, #F7FBFF 11.1111%, #DEEBF7 11.1111%, #DEEBF7 22.2222%, #C6DBEF 22.2222%, #C6DBEF 33.3333%, #9ECAE1 33.3333%, #9ECAE1 44.4444%, #6BAED6 44.4444%, #6BAED6 55.5556%, #4292C6 55.5556%, #4292C6 66.6667%, #2171B5 66.6667%, #2171B5 77.7778%, #08519C 77.7778%, #08519C 88.8889%, #08306B 88.8889%, #08306B 100%); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="magma"], #nj_tippoint_scale .option[data-value="magma"], @@ -2392,10 +2404,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="magma"], #upgma_tiles_scale_5 .option[data-value="magma"], #upgma_heatmap_scale .option[data-value="magma"] { - background: linear-gradient(to right, #000004FF, #07071DFF, #160F3BFF, #29115AFF, #400F73FF, #56147DFF, #6B1D81FF, #802582FF, #952C80FF, #AB337CFF, #C03A76FF, #D6456CFF, #E85362FF, #F4685CFF, #FA815FFF, #FD9A6AFF, #FEB37BFF, #FECC8FFF, #FDE4A6FF, #FCFDBFFF); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #000004FF, #07071DFF, #160F3BFF, #29115AFF, #400F73FF, #56147DFF, #6B1D81FF, #802582FF, #952C80FF, #AB337CFF, #C03A76FF, #D6456CFF, #E85362FF, #F4685CFF, #FA815FFF, #FD9A6AFF, #FEB37BFF, #FECC8FFF, #FDE4A6FF, #FCFDBFFF); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="inferno"], #nj_tippoint_scale .option[data-value="inferno"], @@ -2413,10 +2425,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="inferno"], #upgma_tiles_scale_5 .option[data-value="inferno"], #upgma_heatmap_scale .option[data-value="inferno"] { - background: linear-gradient(to right, #000004FF, #08051EFF, #190C3EFF, #300A5BFF, #460B6AFF, #5C126EFF, #711A6EFF, #87216BFF, #9C2964FF, #B1325AFF, #C43C4EFF, #D64B40FF, #E55C30FF, #F17020FF, #F8870EFF, #FCA007FF, #FBB91FFF, #F7D340FF, #F1ED6FFF, #FCFFA4FF); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #000004FF, #08051EFF, #190C3EFF, #300A5BFF, #460B6AFF, #5C126EFF, #711A6EFF, #87216BFF, #9C2964FF, #B1325AFF, #C43C4EFF, #D64B40FF, #E55C30FF, #F17020FF, #F8870EFF, #FCA007FF, #FBB91FFF, #F7D340FF, #F1ED6FFF, #FCFFA4FF); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="plasma"], #nj_tippoint_scale .option[data-value="plasma"], @@ -2434,10 +2446,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="plasma"], #upgma_tiles_scale_5 .option[data-value="plasma"], #upgma_heatmap_scale .option[data-value="plasma"] { - background: linear-gradient(to right, #0D0887FF, #2D0594FF, #44039EFF, #5901A5FF, #6F00A8FF, #8305A7FF, #9512A1FF, #A72197FF, #B6308BFF, #C5407EFF, #D14E72FF, #DD5E66FF, #E76E5BFF, #EF7F4FFF, #F79044FF, #FBA238FF, #FEB72DFF, #FDCB26FF, #F7E225FF, #F0F921FF); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #0D0887FF, #2D0594FF, #44039EFF, #5901A5FF, #6F00A8FF, #8305A7FF, #9512A1FF, #A72197FF, #B6308BFF, #C5407EFF, #D14E72FF, #DD5E66FF, #E76E5BFF, #EF7F4FFF, #F79044FF, #FBA238FF, #FEB72DFF, #FDCB26FF, #F7E225FF, #F0F921FF); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="viridis"], #nj_tippoint_scale .option[data-value="viridis"], @@ -2455,10 +2467,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="viridis"], #upgma_tiles_scale_5 .option[data-value="viridis"], #upgma_heatmap_scale .option[data-value="viridis"] { - background: linear-gradient(to right, #440154FF, #481568FF, #482677FF, #453781FF, #3F4788FF, #39558CFF, #32648EFF, #2D718EFF, #287D8EFF, #238A8DFF, #1F968BFF, #20A386FF, #29AF7FFF, #3CBC75FF, #56C667FF, #74D055FF, #94D840FF, #B8DE29FF, #DCE318FF, #FDE725FF); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #440154FF, #481568FF, #482677FF, #453781FF, #3F4788FF, #39558CFF, #32648EFF, #2D718EFF, #287D8EFF, #238A8DFF, #1F968BFF, #20A386FF, #29AF7FFF, #3CBC75FF, #56C667FF, #74D055FF, #94D840FF, #B8DE29FF, #DCE318FF, #FDE725FF); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="cividis"], #nj_tippoint_scale .option[data-value="cividis"], @@ -2476,10 +2488,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="cividis"], #upgma_tiles_scale_5 .option[data-value="cividis"], #upgma_heatmap_scale .option[data-value="cividis"] { - background: linear-gradient(to right, #00204DFF, #002A64FF, #00336FFF, #1F3C6DFF, #35466BFF, #444F6BFF, #53596CFF, #5F636EFF, #6B6C71FF, #777776FF, #838079FF, #908B79FF, #9D9677FF, #ABA074FF, #B9AC70FF, #C7B76BFF, #D7C463FF, #E5D05AFF, #F5DD4DFF, #FFEA46FF); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #00204DFF, #002A64FF, #00336FFF, #1F3C6DFF, #35466BFF, #444F6BFF, #53596CFF, #5F636EFF, #6B6C71FF, #777776FF, #838079FF, #908B79FF, #9D9677FF, #ABA074FF, #B9AC70FF, #C7B76BFF, #D7C463FF, #E5D05AFF, #F5DD4DFF, #FFEA46FF); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="rocket"], #nj_tippoint_scale .option[data-value="rocket"], @@ -2497,10 +2509,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="rocket"], #upgma_tiles_scale_5 .option[data-value="rocket"], #upgma_heatmap_scale .option[data-value="rocket"] { - background: linear-gradient(to right, #03051AFF, #150E26FF, #281535FF, #3C1A42FF, #511E4DFF, #661F54FF, #7C1F5AFF, #931C5BFF, #AA185AFF, #C11754FF, #D3214BFF, #E33541FF, #ED4E3EFF, #F26847FF, #F4815AFF, #F5986FFF, #F6AE86FF, #F7C2A2FF, #F8D7BFFF, #FAEBDDFF); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #03051AFF, #150E26FF, #281535FF, #3C1A42FF, #511E4DFF, #661F54FF, #7C1F5AFF, #931C5BFF, #AA185AFF, #C11754FF, #D3214BFF, #E33541FF, #ED4E3EFF, #F26847FF, #F4815AFF, #F5986FFF, #F6AE86FF, #F7C2A2FF, #F8D7BFFF, #FAEBDDFF); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="mako"], #nj_tippoint_scale .option[data-value="mako"], @@ -2518,10 +2530,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="mako"], #upgma_tiles_scale_5 .option[data-value="mako"], #upgma_heatmap_scale .option[data-value="mako"]{ - background: linear-gradient(to right, #0B0405FF, #190E19FF, #27182DFF, #312142FF, #3A2C59FF, #3F3770FF, #414388FF, #3C5397FF, #38639DFF, #3573A1FF, #3482A4FF, #3491A8FF, #35A0ABFF, #3AAEADFF, #46BEADFF, #5ACCADFF, #7ED7AFFF, #A4E0BBFF, #C3E9CEFF, #DEF5E5FF); - color: white; - margin-bottom: 2px; -} +background: linear-gradient(to right, #0B0405FF, #190E19FF, #27182DFF, #312142FF, #3A2C59FF, #3F3770FF, #414388FF, #3C5397FF, #38639DFF, #3573A1FF, #3482A4FF, #3491A8FF, #35A0ABFF, #3AAEADFF, #46BEADFF, #5ACCADFF, #7ED7AFFF, #A4E0BBFF, #C3E9CEFF, #DEF5E5FF); + color: white; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="turbo"], #nj_tippoint_scale .option[data-value="turbo"], @@ -2539,9 +2551,9 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="turbo"], #upgma_tiles_scale_5 .option[data-value="turbo"], #upgma_heatmap_scale .option[data-value="turbo"] { - background: linear-gradient(to right, #30123BFF, #3F3994FF, #455ED2FF, #4681F7FF, #3AA2FCFF, #23C3E4FF, #18DEC1FF, #2CF09EFF, #5BFB72FF, #8EFF49FF, #B5F836FF, #D6E635FF, #EFCD3AFF, #FCB036FF, #FD8A26FF, #F36215FF, #E14209FF, #C82803FF, #A51301FF, #7A0403FF); - color: white; -} +background: linear-gradient(to right, #30123BFF, #3F3994FF, #455ED2FF, #4681F7FF, #3AA2FCFF, #23C3E4FF, #18DEC1FF, #2CF09EFF, #5BFB72FF, #8EFF49FF, #B5F836FF, #D6E635FF, #EFCD3AFF, #FCB036FF, #FD8A26FF, #F36215FF, #E14209FF, #C82803FF, #A51301FF, #7A0403FF); + color: white; + } #nj_tiplab_scale .option[data-value="Spectral"], #nj_tippoint_scale .option[data-value="Spectral"], @@ -2559,10 +2571,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="Spectral"], #upgma_tiles_scale_5 .option[data-value="Spectral"], #upgma_heatmap_scale .option[data-value="Spectral"]{ - background: linear-gradient(to right, #9E0142, #D53E4F, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #E6F598, #ABDDA4, #66C2A5, #3288BD, #5E4FA2); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #9E0142, #D53E4F, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #E6F598, #ABDDA4, #66C2A5, #3288BD, #5E4FA2); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="RdYlGn"], #nj_tippoint_scale .option[data-value="RdYlGn"], @@ -2580,10 +2592,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="RdYlGn"], #upgma_tiles_scale_5 .option[data-value="RdYlGn"], #upgma_heatmap_scale .option[data-value="RdYlGn"]{ - background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #D9EF8B, #A6D96A, #66BD63, #1A9850, #006837); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #D9EF8B, #A6D96A, #66BD63, #1A9850, #006837); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="RdYlBu"], #nj_tippoint_scale .option[data-value="RdYlBu"], @@ -2601,10 +2613,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="RdYlBu"], #upgma_tiles_scale_5 .option[data-value="RdYlBu"], #upgma_heatmap_scale .option[data-value="RdYlBu"]{ - background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE090, #FFFFBF, #E0F3F8, #ABD9E9, #74ADD1, #4575B4, #313695); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE090, #FFFFBF, #E0F3F8, #ABD9E9, #74ADD1, #4575B4, #313695); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="RdGy"], #nj_tippoint_scale .option[data-value="RdGy"], @@ -2622,10 +2634,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="RdGy"], #upgma_tiles_scale_5 .option[data-value="RdGy"], #upgma_heatmap_scale .option[data-value="RdGy"] { - background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #FFFFFF, #E0E0E0, #BABABA, #878787, #4D4D4D, #1A1A1A); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #FFFFFF, #E0E0E0, #BABABA, #878787, #4D4D4D, #1A1A1A); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="RdBu"], #nj_tippoint_scale .option[data-value="RdBu"], @@ -2643,10 +2655,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="RdBu"], #upgma_tiles_scale_5 .option[data-value="RdBu"], #upgma_heatmap_scale .option[data-value="RdBu"] { - background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #F7F7F7, #D1E5F0, #92C5DE, #4393C3, #2166AC, #053061); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #F7F7F7, #D1E5F0, #92C5DE, #4393C3, #2166AC, #053061); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="PuOr"], #nj_tippoint_scale .option[data-value="PuOr"], @@ -2664,10 +2676,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="PuOr"], #upgma_tiles_scale_5 .option[data-value="PuOr"], #upgma_heatmap_scale .option[data-value="PuOr"] { - background: linear-gradient(to right, #7F3B08, #B35806, #E08214, #FDB863, #FEE0B6, #F7F7F7, #D8DAEB, #B2ABD2, #8073AC, #542788, #2D004B); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #7F3B08, #B35806, #E08214, #FDB863, #FEE0B6, #F7F7F7, #D8DAEB, #B2ABD2, #8073AC, #542788, #2D004B); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="PRGn"], #nj_tippoint_scale .option[data-value="PRGn"], @@ -2685,10 +2697,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="PRGn"], #upgma_tiles_scale_5 .option[data-value="PRGn"], #upgma_heatmap_scale .option[data-value="PRGn"] { - background: linear-gradient(to right, #40004B, #762A83, #9970AB, #C2A5CF, #E7D4E8, #F7F7F7, #D9F0D3, #A6DBA0, #5AAE61, #1B7837, #00441B); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #40004B, #762A83, #9970AB, #C2A5CF, #E7D4E8, #F7F7F7, #D9F0D3, #A6DBA0, #5AAE61, #1B7837, #00441B); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="PiYG"], #nj_tippoint_scale .option[data-value="PiYG"], @@ -2706,10 +2718,10 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="PiYG"], #upgma_tiles_scale_5 .option[data-value="PiYG"], #upgma_heatmap_scale .option[data-value="PiYG"] { - background: linear-gradient(to right, #8E0152, #C51B7D, #DE77AE, #F1B6DA, #FDE0EF, #F7F7F7, #E6F5D0, #B8E186, #7FBC41, #4D9221, #276419); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #8E0152, #C51B7D, #DE77AE, #F1B6DA, #FDE0EF, #F7F7F7, #E6F5D0, #B8E186, #7FBC41, #4D9221, #276419); + color: black; + margin-bottom: 2px; + } #nj_tiplab_scale .option[data-value="BrBG"], #nj_tippoint_scale .option[data-value="BrBG"], @@ -2727,44 +2739,44 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #upgma_tiles_scale_4 .option[data-value="BrBG"], #upgma_tiles_scale_5 .option[data-value="BrBG"], #upgma_heatmap_scale .option[data-value="BrBG"] { - background: linear-gradient(to right, #543005, #8C510A, #BF812D, #DFC27D, #F6E8C3, #F5F5F5, #C7EAE5, #80CDC1, #35978F, #01665E, #003C30); - color: black; - margin-bottom: 2px; -} +background: linear-gradient(to right, #543005, #8C510A, #BF812D, #DFC27D, #F6E8C3, #F5F5F5, #C7EAE5, #80CDC1, #35978F, #01665E, #003C30); + color: black; + margin-bottom: 2px; + } /* Report */ - -#shiny-modal > div > div > div.modal-body > div > div > div:nth-child(5) > div > div > div > div > button { + + #shiny-modal > div > div > div.modal-body > div > div > div:nth-child(5) > div > div > div > div > button { border: 1px solid black; } #rep_general { - position: absolute; - top: -10px; - left: -110px; +position: absolute; +top: -10px; +left: -110px; } #rep_entrytable { - position: relative; - top: -10px; - left: -96px; +position: relative; +top: -10px; +left: -96px; } #rep_plot_report { - position: relative; - top: -15px; - left: -96px; +position: relative; +top: -15px; +left: -96px; } #rep_analysis { - position: relative; - top: -10px; - left: -45px; +position: relative; +top: -10px; +left: -45px; } #mst_date_general_select { - margin-top: -14px; - width: 100px; +margin-top: -14px; +width: 100px; } .datepicker { z-index: 99999 !important; } @@ -2783,48 +2795,48 @@ button#upgma_tile_menu_2, button#upgma_tile_menu_3, button#upgma_tile_menu_4, bu #rep_missval, #rep_version, #rep_plot_report { - margin-top: 10px; +margin-top: 10px; } #mst_date_general_select .form-control { - height: 28px; - position: relative; - right: -22px; - margin-top: 7px; +height: 28px; +position: relative; +right: -22px; +margin-top: 7px; } #mst_operator_general_select { - height: 28px; - margin-top: -8px; - position: relative; - right: -22px; - width: 250px; +height: 28px; +margin-top: -8px; +position: relative; +right: -22px; +width: 250px; } #mst_institute_general_select { - height: 28px; - margin-top: -8px; - position: relative; - right: -22px; - width: 250px; +height: 28px; +margin-top: -8px; +position: relative; +right: -22px; +width: 250px; } #mst_comm_general_select { - margin-top: -8px; - border-radius: 5px; - position: relative; - right: -22px; - border-color: black; +margin-top: -8px; +border-radius: 5px; +position: relative; +right: -22px; +border-color: black; } button#download_report_bttn { - font-size: 14px; - height: 36px; - background: #282F38; - color: #ffffff; - border: 1px solid white; - position: relative; - top: 1px; - border-radius: 6px; - margin-left: 10px; +font-size: 14px; +height: 36px; +background: #282F38; + color: #ffffff; + border: 1px solid white; +position: relative; +top: 1px; +border-radius: 6px; +margin-left: 10px; } diff --git a/www/head.css b/www/head.css index 63ff266..5efe422 100644 --- a/www/head.css +++ b/www/head.css @@ -113,12 +113,14 @@ div#bs-select-12::-webkit-scrollbar-thumb, #mst_comm_general_select::-webkit-scrollbar-thumb { background: #bcbcbc; border: 2px solid #F0F0F0; +min-width: 100px; } *::-webkit-scrollbar-thumb { background-color: #F0F0F0; border-radius: 10px; border: 2px solid #282F38; + min-width: 100px; } *::-webkit-scrollbar-corner { @@ -130,4 +132,27 @@ background: #bcbcbc; padding: 50px; position: relative; top: 15px; +} + +#statustext { +position: fixed; +top: 15px; +left: 400px; +} + +#databasetext { +position: fixed; +top: 15px; +left: 800px; +} + +.main-header { + position: relative; + max-height: 100px; + z-index: 1030; + box-shadow: 0px 4px 5px #080c12; +} + +.img_logo { + margin-top: -4px; } \ No newline at end of file From 5c11e2abeb3928d958a432209c381a199dd44307 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Fri, 26 Jul 2024 11:13:20 +0200 Subject: [PATCH 10/75] Moved scheme select to statusbar; small fixes --- App.R | 167 +++++++++++++++++------------------- execute/multi_eval.R | 2 - www/body.css | 19 ++-- www/head.css | 44 ++++++---- www/javascript_functions.js | 17 ++++ 5 files changed, 133 insertions(+), 116 deletions(-) diff --git a/App.R b/App.R index 0649108..09a67d1 100644 --- a/App.R +++ b/App.R @@ -280,6 +280,7 @@ ui <- dashboardPage( ) ) ), + uiOutput("loaded_scheme"), uiOutput("databasetext"), uiOutput("statustext"), tags$li(class = "dropdown", @@ -304,10 +305,8 @@ ui <- dashboardPage( animation: none; }")), br(), br(), - uiOutput("loaded_scheme"), sidebarMenu( id = "tabs", - uiOutput("menu_sep1"), sidebarMenuOutput("menu"), uiOutput("menu_sep2"), conditionalPanel( @@ -6115,8 +6114,61 @@ server <- function(input, output, session) { log_print("Input load") + if(Typing$status == "Finalized") {Typing$status <- "Inactive"} + + #### Render status bar ---- + observe({ + req(DB$scheme) + + if(is.null(input$scheme_position)) { + output$loaded_scheme <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Selected scheme:   ", + DB$scheme, + "")), + style = "color:white;") + ) + ) + }) + } + + if(!is.null(input$scheme_position)) { + output$loaded_scheme <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Selected scheme:   ", + DB$scheme, + "")), + style = "color:white;"), + div( + class = "reload-bttn", + style = paste0("margin-left:", 30 + input$scheme_position, "px; position: relative; top: -24px;"), + actionButton( + "reload_db", + label = "", + icon = icon("rotate") + ) + ) + ) + ) + }) + } + }) + observe({ if(!is.null(DB$database)){ + if(nchar(DB$database) > 60) { + database <- paste0(substring(DB$database, first = 1, last = 60), "...") + } else { + database <- DB$database + } output$databasetext <- renderUI({ fluidRow( tags$li( @@ -6124,10 +6176,14 @@ server <- function(input, output, session) { tags$span(HTML( paste('', "Database:   ", - DB$database, + database, "")), style = "color:white;") - ) + ), + if(nchar(database) > 60) {bsTooltip("databasetext", + HTML(DB$database), + placement = "bottom", + trigger = "hover")} ) }) } @@ -6217,6 +6273,21 @@ server <- function(input, output, session) { } } + shinyjs::runjs( + 'if(document.querySelector("#loaded_scheme > div > li > span") !== null) { + // Select the span element + let spanElement = document.querySelector("#loaded_scheme > div > li > span"); + + // Get the bounding rectangle of the span element + let rect = spanElement.getBoundingClientRect(); + + // Extract the width + let width = rect.width; + + Shiny.setInputValue("scheme_position", width); + }' + ) + # Load app elements based on database availability and missing value presence if(!is.null(DB$select_new)) { if(DB$select_new & (paste0(DB$new_database, "/Database") %in% dir_ls(DB$new_database))) { @@ -6274,7 +6345,6 @@ server <- function(input, output, session) { Startup$sidebar <- FALSE Startup$header <- FALSE - output$menu_sep1 <- renderUI(hr()) output$menu_sep2 <- renderUI(hr()) # Hide start message @@ -6402,7 +6472,6 @@ server <- function(input, output, session) { Startup$sidebar <- FALSE Startup$header <- FALSE - output$menu_sep1 <- renderUI(hr()) output$menu_sep2 <- renderUI(hr()) # Hide start message @@ -6625,44 +6694,6 @@ server <- function(input, output, session) { ) } else { - # Render scheme selector in sidebar - output$loaded_scheme <- renderUI({ - fluidRow( - column(width = 2), - column( - width = 6, - div( - class = "scheme_start", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 14px;', strong("Selected scheme:")) - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 13px; font-style: italic', DB$scheme) - ) - ) - ) - ) - ), - column( - width = 2, - div( - class = "reload-bttn", - actionButton( - "reload_db", - label = "", - icon = icon("rotate") - ) - ) - ) - ) - }) - # Produce Scheme Info Table schemeinfo <- read_html(paste0( @@ -7340,44 +7371,6 @@ server <- function(input, output, session) { } }) - # Render scheme selector in sidebar - output$loaded_scheme <- renderUI({ - fluidRow( - column(width = 2), - column( - width = 6, - div( - class = "scheme_start", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 14px;', strong("Selected scheme:")) - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 13px; font-style: italic', DB$scheme) - ) - ) - ) - ) - ), - column( - width = 2, - div( - class = "reload-bttn", - actionButton( - "reload_db", - label = "", - icon = icon("rotate") - ) - ) - ) - ) - }) - # Render missing values sidebar elements output$missing_values_sidebar <- renderUI({ column( @@ -8977,7 +8970,7 @@ server <- function(input, output, session) { HTML( paste( "", - "No Entries for this scheme available.", + "No Entries for this scheme available.\n", "Type a genome in the section Allelic Typing and add the result to the local database.", sep = '
' ) @@ -9087,12 +9080,6 @@ server <- function(input, output, session) { }) - # _______________________ #### - - ## Status ---- - - - # _______________________ #### ## Database ---- @@ -22796,6 +22783,8 @@ server <- function(input, output, session) { observeEvent(input$reset_single_typing, { log_print("Reset single typing") + Typing$status <- "Inactive" + Typing$progress <- 0 Typing$progress_format <- 900000 diff --git a/execute/multi_eval.R b/execute/multi_eval.R index 3dc5277..d2c19f3 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -155,8 +155,6 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= saveRDS(event_list, "execute/event_list.rds") - allele_vector <- as.integer(allele_vector) - # Find Alleles folder in directory allele_folder <- list.files(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing)), full.names = TRUE)[grep("_alleles", list.files(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing))))] diff --git a/www/body.css b/www/body.css index 50e3583..5f6be8f 100644 --- a/www/body.css +++ b/www/body.css @@ -1,15 +1,20 @@ /* CSS Styling for PhyloTrace */ - /* General */ +/* General */ - h1, h2, h3, h4, h5, p, body { +h1, h2, h3, h4, h5, p, body { font-family: 'Liberation Sans', sans-serif; - } +} label { color: white; } +.tooltip-inner { + white-space: normal; + max-width: 800px; /* Adjust the width as needed */ + } + .btn-default:active:hover. .btn-primary:active:hover{ color: white !important; @@ -207,13 +212,13 @@ font-size: 12px; #reload_db i.fas.fa-rotate { position: relative; -left: -5px; -top: -2px; +left: -6px; +top: -3px; } button#reload_db.btn.btn-default.action-button.shiny-bound-input { -height: 30px; -width: 30px; +height: 27px; +width: 27px; position: relative; left: -20px; border: 1px solid white; diff --git a/www/head.css b/www/head.css index 5efe422..1825811 100644 --- a/www/head.css +++ b/www/head.css @@ -1,12 +1,12 @@ /* Entry table legend */ - .rectangle-orange { - width: 75px; - height: 23px; - margin-top: 10px; - margin-left: 10px; - border: 1px solid #BCBCBC; - background-color: #DEB200; - } +.rectangle-orange { + width: 75px; + height: 23px; + margin-top: 10px; + margin-left: 10px; + border: 1px solid #BCBCBC; + background-color: #DEB200; +} .rectangle-green { width: 75px; @@ -111,16 +111,18 @@ div#bs-select-12::-webkit-scrollbar-thumb, #logTextFull::-webkit-scrollbar-thumb, .selectize-dropdown-content::-webkit-scrollbar-thumb, #mst_comm_general_select::-webkit-scrollbar-thumb { -background: #bcbcbc; + background: #bcbcbc; border: 2px solid #F0F0F0; -min-width: 100px; + min-width: 100px; + min-height: 100px; } *::-webkit-scrollbar-thumb { background-color: #F0F0F0; - border-radius: 10px; + border-radius: 10px; border: 2px solid #282F38; min-width: 100px; + overflow-y: scroll; } *::-webkit-scrollbar-corner { @@ -135,15 +137,21 @@ top: 15px; } #statustext { -position: fixed; -top: 15px; -left: 400px; + position: absolute; + top: 15px; + left: 600px; } #databasetext { -position: fixed; -top: 15px; -left: 800px; + position: absolute; + top: 15px; + left: 900px; +} + +#loaded_scheme { + position: absolute; + top: 15px; + left: 150px; } .main-header { @@ -154,5 +162,5 @@ left: 800px; } .img_logo { - margin-top: -4px; + margin-top: -3px; } \ No newline at end of file diff --git a/www/javascript_functions.js b/www/javascript_functions.js index 1b9aef6..fdc3cf4 100644 --- a/www/javascript_functions.js +++ b/www/javascript_functions.js @@ -15,6 +15,23 @@ function getCurrentDate() { return year + '-' + month + '-' + day; // Formats the date as "YYYY-MM-DD" }; +function checkAndExecute() { + if(document.querySelector("#loaded_scheme > div > li > span") !== null) { + // Select the span element + let spanElement = document.querySelector("#loaded_scheme > div > li > span"); + + // Get the bounding rectangle of the span element + let rect = spanElement.getBoundingClientRect(); + + // Extract the width + let width = rect.width; + + Shiny.setInputValue("scheme_position", width); + } +} +setInterval(checkAndExecute, 1000); +checkAndExecute(); + // Get time function updateTime() { var options = { From 947b1dad21484445b51c166500e3acc0087f6a11 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Fri, 26 Jul 2024 13:22:06 +0200 Subject: [PATCH 11/75] Updated partners --- README.md | 2 +- www/partners_logo_round.svg | 296 ++++++++++++++++++++++-------------- 2 files changed, 182 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index c92687e..db61444 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ working on achieving that. ![PartnerLogos](www/partners_logo_round.svg) Developed in collaboration with Hochschule Furtwangen University (HFU) and Medical -University of Graz (MUG). Featured on ShinyConf 2024. +University of Graz (MUG). Featured on ShinyConf 2024 and R/Medicine 2024. [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.10996423-00e896?labelColor=gray&color=2500ba&logoColor=black)](https://doi.org/10.5281/zenodo.10996423) [![License: GPL diff --git a/www/partners_logo_round.svg b/www/partners_logo_round.svg index a9a13da..457f64a 100644 --- a/www/partners_logo_round.svg +++ b/www/partners_logo_round.svg @@ -1,6 +1,34 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -33,124 +61,162 @@ - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + R Medicine 2024 + + + + + + + + + + + + + + + + - - - - - - - - - - - - \ No newline at end of file From 3dd450afb821ec7514b77bbb01f06f3bd05c8978 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Fri, 26 Jul 2024 13:23:38 +0200 Subject: [PATCH 12/75] Updated partners --- www/partners_logo_round.svg | 305 +++++++++++++++++------------------- 1 file changed, 140 insertions(+), 165 deletions(-) diff --git a/www/partners_logo_round.svg b/www/partners_logo_round.svg index 457f64a..73082ab 100644 --- a/www/partners_logo_round.svg +++ b/www/partners_logo_round.svg @@ -1,14 +1,6 @@ - - - - - - - - - + @@ -26,9 +18,6 @@ - - - @@ -61,160 +50,146 @@ - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - R Medicine 2024 - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + R Medicine 2024 + + + + + + + + + + + + + From 582a0a5224b3815c31cd91c0d5e80ebe70c02518 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Fri, 26 Jul 2024 13:44:54 +0200 Subject: [PATCH 13/75] Changed selected scheme icon --- App.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/App.R b/App.R index 09a67d1..514e7ae 100644 --- a/App.R +++ b/App.R @@ -6126,7 +6126,7 @@ server <- function(input, output, session) { tags$li( class = "dropdown", tags$span(HTML( - paste('', + paste('', "Selected scheme:   ", DB$scheme, "")), @@ -6142,7 +6142,7 @@ server <- function(input, output, session) { tags$li( class = "dropdown", tags$span(HTML( - paste('', + paste('', "Selected scheme:   ", DB$scheme, "")), From 2324e61d5ac6e5d6fb831bc7d9b8c86b6d3dff23 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Fri, 26 Jul 2024 17:22:37 +0200 Subject: [PATCH 14/75] Initial clustering module --- App.R | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 200 insertions(+), 28 deletions(-) diff --git a/App.R b/App.R index 514e7ae..50d4ce2 100644 --- a/App.R +++ b/App.R @@ -1502,7 +1502,7 @@ ui <- dashboardPage( hr(style = "margin-top: 3px !important"), fluidRow( column( - width = 12, + width = 6, fluidRow( column( width = 12, @@ -1511,7 +1511,7 @@ ui <- dashboardPage( ) ), column( - width = 6, + width = 12, align = "left", br(), div( @@ -1577,7 +1577,49 @@ ui <- dashboardPage( ) ) ) - ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Clustering"), style = "color:white; text-align: left;") + ) + ), + br(), + fluidRow( + div( + class = "switch-clusters", + materialSwitch( + "mst_show_clusters", + h5(p("Show Clusters"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + HTML( + paste( + tags$span(style='color: white; text-align: left; font-size: 14px; margin: 10px', 'Threshold') + ) + ) + ), + column( + width = 9, + sliderInput( + inputId = "mst_cluster_threshold", + label = NULL, + min = 0, + max = 10, + value = 4, + ticks = FALSE + ) + ) + ), + br(), ) ), br(), br(), br(), br(), br(), br() ) @@ -5407,6 +5449,42 @@ ui <- dashboardPage( ), br(), br(), br(), br(), br(), br() ) + ), + tabItem( + tabName = "utilities", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Utilities"), style = "color:white") + ) + ), + br(), + hr(), + column( + width = 5, + align = "left", + shinyDirButton( + "hash_dir", + "Hash folder with loci", + title = "Locate the folder with loci", + buttonType = "default", + root = path_home(), + style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + ), + br(), + actionButton( + "backup_database", + "Create backup", + style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + ), + br(), + actionButton( + "import_db_backup", + "Restore backup", + style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + ) + ) ) ) # End tabItems ) # End dashboardPage @@ -5699,6 +5777,37 @@ server <- function(input, output, session) { close(locus_file) } + # Compute clusters to use in visNetwork + compute_clusters <- function(nodes, edges, threshold) { + groups <- rep(0, length(nodes$id)) + + edges_table <- data.frame( + from = edges$from, + to = edges$to, + weight = edges$weight + ) + + count <- 0 + while (any(groups == 0)) { + group_na <- groups == 0 + labels <- nodes$id[group_na] + + cluster <- nodes$id[group_na][1] # Initialize with 1 label + while (!is_empty(labels)) { + sub_tb <- edges_table[(edges_table$from %in% cluster | edges_table$to %in% cluster) & edges_table$weight <= threshold,] + + if (nrow(sub_tb) == 0 | length(unique(c(sub_tb$from, sub_tb$to))) == length(cluster)) { + count <- count + 1 + groups[nodes$id %in% cluster] <- paste("Group", count) + break + } else { + cluster <- unique(c(sub_tb$from, sub_tb$to)) + } + } + } + groups + } + # Function to check single typing log file check_new_entry <- reactive({ @@ -6399,6 +6508,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -6545,6 +6659,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -6616,6 +6735,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -6689,6 +6813,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -6791,6 +6920,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -6955,6 +7089,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -7003,6 +7142,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -8924,6 +9068,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -9263,6 +9412,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -9307,6 +9461,11 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("chart-line") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") ) ) ) @@ -17510,31 +17669,44 @@ server <- function(input, output, session) { label = as.character(data$edges$weight), opacity = mst_edge_opacity()) - visNetwork(data$nodes, data$edges, - main = mst_title(), - background = mst_background_color(), - submain = mst_subtitle()) %>% - visNodes(size = mst_node_size(), - shape = input$mst_node_shape, - shadow = input$mst_shadow, - color = mst_color_node(), - ctxRenderer = ctxRendererJS, - scaling = list(min = mst_node_size_min(), - max = mst_node_size_max()), - font = list(color = node_font_color(), - size = input$node_label_fontsize)) %>% - visEdges(color = mst_color_edge(), - font = list(color = mst_edge_font_color(), - size = mst_edge_font_size(), - strokeWidth = 4)) %>% - visOptions(collapse = TRUE) %>% - visInteraction(hover = TRUE) %>% - visLayout(randomSeed = 1) %>% - visLegend(useGroups = FALSE, - zoom = FALSE, - position = input$mst_legend_ori, - ncol = legend_col(), - addNodes = mst_legend()) + save(data, file="data.Rdata") + + visNetwork_graph <- visNetwork(data$nodes, data$edges, + main = mst_title(), + background = mst_background_color(), + submain = mst_subtitle()) %>% + visNodes(size = mst_node_size(), + shape = input$mst_node_shape, + shadow = input$mst_shadow, + color = mst_color_node(), + ctxRenderer = ctxRendererJS, + scaling = list(min = mst_node_size_min(), + max = mst_node_size_max()), + font = list(color = node_font_color(), + size = input$node_label_fontsize)) %>% + visEdges(color = mst_color_edge(), + font = list(color = mst_edge_font_color(), + size = mst_edge_font_size(), + strokeWidth = 4)) %>% + visOptions(collapse = TRUE) %>% + visInteraction(hover = TRUE) %>% + visLayout(randomSeed = 1) %>% + visLegend(useGroups = FALSE, + zoom = FALSE, + position = input$mst_legend_ori, + ncol = legend_col(), + addNodes = mst_legend()) + + if (input$mst_show_clusters) { + data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + color_palette <- grDevices::rainbow(length(data$nodes$group)) + + for (i in 1:length(unique(data$nodes$group))) { + visNetwork_graph <- visNetwork_graph %>% visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) + } + } + + visNetwork_graph }) # MST legend From 107e5922ca9b53f2e75766866979b1c1a30be250 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Fri, 26 Jul 2024 17:28:13 +0200 Subject: [PATCH 15/75] Small fix --- App.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/App.R b/App.R index 50d4ce2..c160bbe 100644 --- a/App.R +++ b/App.R @@ -17669,8 +17669,6 @@ server <- function(input, output, session) { label = as.character(data$edges$weight), opacity = mst_edge_opacity()) - save(data, file="data.Rdata") - visNetwork_graph <- visNetwork(data$nodes, data$edges, main = mst_title(), background = mst_background_color(), From 74b809934b4451774476842e640e5a6e5de47fa8 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Mon, 29 Jul 2024 15:17:40 +0200 Subject: [PATCH 16/75] Fixed clustering --- App.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/App.R b/App.R index c160bbe..91cd157 100644 --- a/App.R +++ b/App.R @@ -17669,6 +17669,8 @@ server <- function(input, output, session) { label = as.character(data$edges$weight), opacity = mst_edge_opacity()) + data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + visNetwork_graph <- visNetwork(data$nodes, data$edges, main = mst_title(), background = mst_background_color(), @@ -17695,8 +17697,7 @@ server <- function(input, output, session) { ncol = legend_col(), addNodes = mst_legend()) - if (input$mst_show_clusters) { - data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + if (TRUE) { color_palette <- grDevices::rainbow(length(data$nodes$group)) for (i in 1:length(unique(data$nodes$group))) { From a15ab92c3aee8bd8f36469ba8143a7d110684a03 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Mon, 29 Jul 2024 17:07:55 +0200 Subject: [PATCH 17/75] Fully implemented clustering --- App.R | 111 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 34 deletions(-) diff --git a/App.R b/App.R index 91cd157..acf07a5 100644 --- a/App.R +++ b/App.R @@ -1589,33 +1589,58 @@ ui <- dashboardPage( ), br(), fluidRow( - div( - class = "switch-clusters", + column( + width = 9, materialSwitch( "mst_show_clusters", h5(p("Show Clusters"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), value = FALSE, right = TRUE ) - ) - ), - column( - width = 3, - HTML( - paste( - tags$span(style='color: white; text-align: left; font-size: 14px; margin: 10px', 'Threshold') + ), + column( + width = 3, + dropMenu( + actionBttn( + "mst_cluster_col_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + selectInput( + "mst_cluster_col_scale", + label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), + choices = c("Viridis", "Rainbow"), + width = "150px" + ) ) ) ), - column( - width = 9, - sliderInput( - inputId = "mst_cluster_threshold", - label = NULL, - min = 0, - max = 10, - value = 4, - ticks = FALSE + br(), + fluidRow( + column( + width = 4, + HTML( + paste( + tags$span(style='color: white; text-align: left; font-size: 14px; margin: 10px', 'Threshold') + ) + ) + ), + column( + width = 8, + sliderInput( + inputId = "mst_cluster_threshold", + label = NULL, + min = 0, + max = 20, + value = 4, + ticks = FALSE + ) ) ) ), @@ -5470,20 +5495,22 @@ ui <- dashboardPage( title = "Locate the folder with loci", buttonType = "default", root = path_home(), + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" ), - br(), - actionButton( - "backup_database", - "Create backup", - style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - ), - br(), - actionButton( - "import_db_backup", - "Restore backup", - style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - ) + # br(), + # actionButton( + # "backup_database", + # "Create backup", + # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + # ), + # br(), + # actionButton( + # "import_db_backup", + # "Restore backup", + # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + # ) ) ) ) # End tabItems @@ -11708,6 +11735,13 @@ server <- function(input, output, session) { } }) + observe({ + req(DB$schemeinfo) + updateSliderInput(session, "mst_cluster_threshold", + max = as.numeric(DB$schemeinfo[[7,2]]) * 2, + value = as.numeric(DB$schemeinfo[[7,2]])) + }) + # Custom Labels # Add custom label @@ -17669,7 +17703,11 @@ server <- function(input, output, session) { label = as.character(data$edges$weight), opacity = mst_edge_opacity()) - data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + if (input$mst_show_clusters) { + data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + } + + updateSliderInput(session, "mst_cluster_threshold", max = max(data$edges$weight)) visNetwork_graph <- visNetwork(data$nodes, data$edges, main = mst_title(), @@ -17697,11 +17735,16 @@ server <- function(input, output, session) { ncol = legend_col(), addNodes = mst_legend()) - if (TRUE) { - color_palette <- grDevices::rainbow(length(data$nodes$group)) + if (input$mst_show_clusters) { + if (input$mst_cluster_col_scale == "Viridis") { + color_palette <- viridis(length(data$nodes$group)) + } else { + color_palette <- rainbow(length(data$nodes$group)) + } for (i in 1:length(unique(data$nodes$group))) { - visNetwork_graph <- visNetwork_graph %>% visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) + visNetwork_graph <- visNetwork_graph %>% + visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) } } From 17d90949670cc1c48e137baec548116f4f505ebc Mon Sep 17 00:00:00 2001 From: fpaskali Date: Mon, 29 Jul 2024 17:38:37 +0200 Subject: [PATCH 18/75] Implemented hashing utility --- App.R | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/App.R b/App.R index acf07a5..60fc22f 100644 --- a/App.R +++ b/App.R @@ -5494,10 +5494,7 @@ ui <- dashboardPage( "Hash folder with loci", title = "Locate the folder with loci", buttonType = "default", - root = path_home(), - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + style = "border-color: white; margin: 10px; min-width: 200px; text-align: center" ), # br(), # actionButton( @@ -23947,6 +23944,42 @@ server <- function(input, output, session) { } }) + observe({ + # Get selected Genome in Multi Mode + shinyDirChoose(input, + "hash_dir", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + + dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) + req(dir_path) + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    hashing directory")), + style = "color:white;") + ) + ) + ) + hash_database(dir_path) + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    ready")), + style = "color:white;") + ) + ) + ) + }) + } # end server From 8a324acdb746da3c6b8488b5240914f1aabc670f Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Mon, 29 Jul 2024 18:20:29 +0200 Subject: [PATCH 19/75] Enviroment updates for packages xfun, yaml, tinytex and knitr --- PhyloTrace.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PhyloTrace.yml b/PhyloTrace.yml index 47e2911..daaacbd 100644 --- a/PhyloTrace.yml +++ b/PhyloTrace.yml @@ -92,7 +92,7 @@ dependencies: - r-jquerylib=0.1.4 - r-jsonlite=1.8.8 - r-kableExtra=1.3.4 - - r-knitr=1.47 + - r-knitr=1.48 - r-labeling=0.4.3 - r-later=1.3.1 - r-lattice=0.22_5 @@ -159,7 +159,7 @@ dependencies: - r-tidytree=0.4.5 - r-tidyverse=2.0.0 - r-timechange=0.2.0 - - r-tinytex=0.51 + - r-tinytex=0.52 - r-tzdb=0.4.0 - r-utf8=1.2.3 - r-uuid=1.1_1 @@ -169,9 +169,9 @@ dependencies: - r-vroom=1.6.4 - r-webshot=0.5.5 - r-withr=2.5.1 - - r-xfun=0.45 + - r-xfun=0.46 - r-xml2=1.3.5 - r-xtable=1.8_4 - - r-yaml=2.3.8 + - r-yaml=2.3.10 - r-yulab.utils=0.1.0 - r-zoo=1.8_12 From d3aef4965e20219fe1bd1db346215af8788ec2fd Mon Sep 17 00:00:00 2001 From: Marian Freisleben <115372379+infinity-a11y@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:05:12 +0200 Subject: [PATCH 20/75] Reload bttn icon position change --- www/body.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/body.css b/www/body.css index 5f6be8f..c197353 100644 --- a/www/body.css +++ b/www/body.css @@ -212,7 +212,7 @@ font-size: 12px; #reload_db i.fas.fa-rotate { position: relative; -left: -6px; +left: -7px; top: -3px; } From e0f55818a2669cc406003b554d463809fd8a2539 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Wed, 31 Jul 2024 18:24:26 +0200 Subject: [PATCH 21/75] Fixed color palette for visNetwork --- App.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/App.R b/App.R index 60fc22f..f369e32 100644 --- a/App.R +++ b/App.R @@ -17734,9 +17734,9 @@ server <- function(input, output, session) { if (input$mst_show_clusters) { if (input$mst_cluster_col_scale == "Viridis") { - color_palette <- viridis(length(data$nodes$group)) + color_palette <- viridis(length(unique(data$nodes$group))) } else { - color_palette <- rainbow(length(data$nodes$group)) + color_palette <- rainbow(length(unique(data$nodes$group))) } for (i in 1:length(unique(data$nodes$group))) { From 7ff2ec2b8af4b5dff3f55165d0dec28ad3686314 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Wed, 31 Jul 2024 18:49:33 +0200 Subject: [PATCH 22/75] Created Tab for Gene Screening --- App.R | 700 ++++++++++++++++++++++++++++++++-------------------- resources.R | 231 +++++++++++++++++ 2 files changed, 670 insertions(+), 261 deletions(-) create mode 100644 resources.R diff --git a/App.R b/App.R index 60fc22f..dfe1984 100644 --- a/App.R +++ b/App.R @@ -44,222 +44,7 @@ library(treeio) library(ggtree) library(ggtreeExtra) -schemes <- c("Acinetobacter_baumanii", "Bacillus_anthracis", "Bordetella_pertussis", - "Brucella_melitensis", "Brucella_spp", "Burkholderia_mallei_FLI", - "Burkholderia_mallei_RKI", "Burkholderia_pseudomallei", "Campylobacter_jejuni_coli", - "Clostridioides_difficile", "Clostridium_perfringens", "Corynebacterium_diphtheriae", - "Cronobacter_sakazakii_malonaticus", "Enterococcus_faecalis", "Enterococcus_faecium", - "Escherichia_coli", "Francisella_tularensis", "Klebsiella_oxytoca_sensu_lato", "Klebsiella_pneumoniae_sensu_lato", - "Legionella_pneumophila", "Listeria_monocytogenes", "Mycobacterium_tuberculosis_complex", - "Mycobacteroides_abscessus", "Mycoplasma_gallisepticum", "Paenibacillus_larvae", - "Pseudomonas_aeruginosa", "Salmonella_enterica", "Serratia_marcescens", - "Staphylococcus_aureus", "Staphylococcus_capitis", "Streptococcus_pyogenes" -) - -country_names <- c( - "Afghanistan", - "Albania", - "Algeria", - "Andorra", - "Angola", - "Antigua and Barbuda", - "Argentina", - "Armenia", - "Australia", - "Austria", - "Azerbaijan", - "Bahamas", - "Bahrain", - "Bangladesh", - "Barbados", - "Belarus", - "Belgium", - "Belize", - "Benin", - "Bhutan", - "Bolivia", - "Bosnia and Herzegovina", - "Botswana", - "Brazil", - "Brunei", - "Bulgaria", - "Burkina Faso", - "Burundi", - "Côte d'Ivoire", - "Cabo Verde", - "Cambodia", - "Cameroon", - "Canada", - "Central African Republic", - "Chad", - "Chile", - "China", - "Colombia", - "Comoros", - "Congo (Congo-Brazzaville)", - "Costa Rica", - "Croatia", - "Cuba", - "Cyprus", - "Czechia (Czech Republic)", - "Democratic Republic of the Congo", - "Denmark", - "Djibouti", - "Dominica", - "Dominican Republic", - "Ecuador", - "Egypt", - "El Salvador", - "Equatorial Guinea", - "Eritrea", - "Estonia", - 'Eswatini (fmr. "Swaziland")', - "Ethiopia", - "Fiji", - "Finland", - "France", - "Gabon", - "Gambia", - "Georgia", - "Germany", - "Ghana", - "Greece", - "Grenada", - "Guatemala", - "Guinea", - "Guinea-Bissau", - "Guyana", - "Haiti", - "Holy See", - "Honduras", - "Hungary", - "Iceland", - "India", - "Indonesia", - "Iran", - "Iraq", - "Ireland", - "Israel", - "Italy", - "Jamaica", - "Japan", - "Jordan", - "Kazakhstan", - "Kenya", - "Kiribati", - "Kuwait", - "Kyrgyzstan", - "Laos", - "Latvia", - "Lebanon", - "Lesotho", - "Liberia", - "Libya", - "Liechtenstein", - "Lithuania", - "Luxembourg", - "Madagascar", - "Malawi", - "Malaysia", - "Maldives", - "Mali", - "Malta", - "Marshall Islands", - "Mauritania", - "Mauritius", - "Mexico", - "Micronesia", - "Moldova", - "Monaco", - "Mongolia", - "Montenegro", - "Morocco", - "Mozambique", - "Myanmar (formerly Burma)", - "Namibia", - "Nauru", - "Nepal", - "Netherlands", - "New Zealand", - "Nicaragua", - "Niger", - "Nigeria", - "North Korea", - "North Macedonia (formerly Macedonia)", - "Norway", - "Oman", - "Pakistan", - "Palau", - "Palestine State", - "Panama", - "Papua New Guinea", - "Paraguay", - "Peru", - "Philippines", - "Poland", - "Portugal", - "Qatar", - "Romania", - "Russia", - "Rwanda", - "Saint Kitts and Nevis", - "Saint Lucia", - "Saint Vincent and the Grenadines", - "Samoa", - "San Marino", - "Sao Tome and Principe", - "Saudi Arabia", - "Senegal", - "Serbia", - "Seychelles", - "Sierra Leone", - "Singapore", - "Slovakia", - "Slovenia", - "Solomon Islands", - "Somalia", - "South Africa", - "South Korea", - "South Sudan", - "Spain", - "Sri Lanka", - "Sudan", - "Suriname", - "Sweden", - "Switzerland", - "Syria", - "Tajikistan", - "Tanzania", - "Thailand", - "Timor-Leste", - "Togo", - "Tonga", - "Trinidad and Tobago", - "Tunisia", - "Turkey", - "Turkmenistan", - "Tuvalu", - "Uganda", - "Ukraine", - "United Arab Emirates", - "United Kingdom", - "United States of America", - "Uruguay", - "Uzbekistan", - "Vanuatu", - "Venezuela", - "Vietnam", - "Yemen", - "Zambia", - "Zimbabwe" -) - -sel_countries <- - c("Austria", - "Germany", - "Switzerland", - "United Kingdom", - "United States of America") +source("resources.R") options(ignore.negative.edge=TRUE) @@ -5475,6 +5260,9 @@ ui <- dashboardPage( br(), br(), br(), br(), br(), br() ) ), + + ## Tab Utilities ------------------------------------------------------- + tabItem( tabName = "utilities", fluidRow( @@ -5509,6 +5297,53 @@ ui <- dashboardPage( # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" # ) ) + ), + + + ## Tab Gene Screening ------------------------------------------------------- + + tabItem( + tabName = "gs_screening", + fluidRow( + column(1), + column( + width = 3, + align = "left", + h2(p("Gene Screening"), style = "color:white") + ), + column( + width = 7, + uiOutput("gene_screening_info") + ) + ), + br(), + hr(), + uiOutput("screening_interface") + ), + + ## Tab Resistance Profile ------------------------------------------------------- + + tabItem( + tabName = "gs_profile", + fluidRow( + column(1), + column( + width = 3, + align = "left", + h2(p("Resistance Profiles"), style = "color:white") + ), + column( + width = 7, + uiOutput("gene_resistance_info") + ) + ), + br(), + hr(), + column( + width = 12, + align = "left", + + ) ) ) # End tabItems ) # End dashboardPage @@ -5938,6 +5773,8 @@ server <- function(input, output, session) { result_list = NULL, status = "") # reactive variables related to typing process + Screening <- reactiveValues() + Vis <- reactiveValues(cluster = NULL, metadata = list(), custom_label_nj = data.frame(), @@ -6526,12 +6363,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = FALSE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -6677,12 +6528,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = FALSE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -6753,12 +6618,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = FALSE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -6831,12 +6710,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = FALSE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -6938,12 +6831,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = FALSE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -7107,12 +7014,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = FALSE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -7160,12 +7081,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -9086,12 +9021,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -9430,12 +9379,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -9479,12 +9442,26 @@ server <- function(input, output, session) { menuItem( text = "Allelic Typing", tabName = "typing", - icon = icon("dna") + icon = icon("gears") + ), + menuItem( + text = "Gene Screening", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Screen Assembly", + tabName = "gs_screening" + ), + menuSubItem( + text = "Resistance Profile", + tabName = "gs_profile" + ) ), menuItem( text = "Visualization", tabName = "visualization", - icon = icon("chart-line") + icon = icon("circle-nodes") ), menuItem( text = "Utilities", @@ -9635,6 +9612,8 @@ server <- function(input, output, session) { # Change scheme observeEvent(input$reload_db, { + test <<- DB$scheme + log_print("Input reload_db") if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { @@ -17565,12 +17544,12 @@ server <- function(input, output, session) { #### MST ---- mst_tree <- reactive({ - data <- toVisNetworkData(Vis$ggraph_1) - data$nodes <- mutate(data$nodes, + Typing$data <- toVisNetworkData(Vis$ggraph_1) + Typing$data$nodes <- mutate(Typing$data$nodes, label = label_mst(), value = mst_node_scaling(), opacity = node_opacity()) - + test <<- Typing$data ctxRendererJS <- htmlwidgets::JS("({ctx, id, x, y, state: { selected, hover }, style, font, label, metadata}) => { var pieData = JSON.parse(metadata); var radius = style.size; @@ -17652,10 +17631,10 @@ server <- function(input, output, session) { group[i] <- unique(Vis$meta_mst[[input$mst_col_var]])[i] } - data$nodes <- cbind(data$nodes, data.frame(metadata = character(nrow(data$nodes)))) + Typing$data$nodes <- cbind(Typing$data$nodes, data.frame(metadata = character(nrow(Typing$data$nodes)))) - if(length(which(data$nodes$group == "")) != 0) { - data$nodes$group[which(data$nodes$group == "")] <- data$nodes$group[1] + if(length(which(Typing$data$nodes$group == "")) != 0) { + Typing$data$nodes$group[which(Typing$data$nodes$group == "")] <- Typing$data$nodes$group[1] } if(is.null(input$mst_col_scale)) { @@ -17669,9 +17648,9 @@ server <- function(input, output, session) { color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) } - for(i in 1:nrow(data$nodes)) { + for(i in 1:nrow(Typing$data$nodes)) { - iso_subset <- strsplit(data$nodes$label[i], split = "\n")[[1]] + iso_subset <- strsplit(Typing$data$nodes$label[i], split = "\n")[[1]] variable <- Vis$meta_mst[[input$mst_col_var]] values <- variable[which(Vis$meta_mst$`Assembly Name` %in% iso_subset)] @@ -17687,26 +17666,26 @@ server <- function(input, output, session) { } } - data$nodes$metadata[i] <- paste0('[', pie_vec, ']') + Typing$data$nodes$metadata[i] <- paste0('[', pie_vec, ']') } } - data$edges <- mutate(data$edges, + Typing$data$edges <- mutate(Typing$data$edges, length = if(input$mst_scale_edges == FALSE) { input$mst_edge_length } else { - data$edges$weight * input$mst_edge_length_scale + Typing$data$edges$weight * input$mst_edge_length_scale }, - label = as.character(data$edges$weight), - opacity = mst_edge_opacity()) + label = as.character(Typing$data$edges$weight), + opacity = input$mst_edge_opacity) if (input$mst_show_clusters) { - data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + Typing$data$nodes$group <- compute_clusters(Typing$data$nodes, Typing$data$edges, input$mst_cluster_threshold) } - updateSliderInput(session, "mst_cluster_threshold", max = max(data$edges$weight)) + updateSliderInput(session, "mst_cluster_threshold", max = max(Typing$data$edges$weight)) - visNetwork_graph <- visNetwork(data$nodes, data$edges, + visNetwork_graph <- visNetwork(Typing$data$nodes, Typing$data$edges, main = mst_title(), background = mst_background_color(), submain = mst_subtitle()) %>% @@ -17727,7 +17706,8 @@ server <- function(input, output, session) { visInteraction(hover = TRUE) %>% visLayout(randomSeed = 1) %>% visLegend(useGroups = FALSE, - zoom = FALSE, + zoom = TRUE, + width = legend_width(), position = input$mst_legend_ori, ncol = legend_col(), addNodes = mst_legend()) @@ -17767,13 +17747,22 @@ server <- function(input, output, session) { } else { legend <- Typing$var_cols names(legend)[1] <- "label" - mutate(legend, shape = "dot", + legend <- mutate(legend, shape = "dot", font.color = input$mst_legend_color, size = input$mst_symbol_size, font.size = input$mst_font_size) + + legend1 <<- legend + dnode <<- Typing$data$nodes + legend } }) + # Set MST legend width + legend_width <- reactive({ + 0.2 + }) + # Set MST node shape mst_node_shape <- reactive({ if(input$mst_node_shape == "Pie Nodes"){ @@ -17886,11 +17875,6 @@ server <- function(input, output, session) { } }) - # Edge Opacity - mst_edge_opacity <- reactive({ - input$mst_edge_opacity - }) - # Edge font color mst_edge_font_color <- reactive({ input$mst_edge_font_color @@ -22237,6 +22221,202 @@ server <- function(input, output, session) { } ) + + # _______________________ #### + + ## Gene Screening ---- + + ### Render UI Elements ---- + + # Availablity feedback + output$gene_screening_info <- renderUI({ + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + fluidRow( + column( + width = 11, + align = "left", + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + ) + ) + } else { + fluidRow( + column( + width = 11, + align = "left", + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + ) + ) + } + }) + + output$gene_resistance_info <- renderUI({ + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + fluidRow( + column( + width = 11, + align = "left", + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + ) + ) + } else { + fluidRow( + column( + width = 11, + align = "left", + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + ) + ) + } + }) + + # Screening Interface + + output$screening_interface <- renderUI({ + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + fluidRow( + column(1), + column( + width = 3, + align = "center", + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly File (FASTA)') + ) + ) + ), + shinyFilesButton( + "genome_file_gs", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), br(), + uiOutput("genome_path_gs"), + br(), br(), br(), hr(), br(), br(), + uiOutput("screening_start") + ) + ) + } + }) + + ### Screening Events ---- + + # Get selected Genome in Single Mode + + observe({ + shinyFileChoose(input, + "genome_file_gs", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + Screening$single_path <- parseFilePaths(roots = c(Home = path_home(), Root = "/"), input$genome_file_gs) + + }) + + # Get selected assembly + + observe({ + if (nrow(Screening$single_path) < 1) { + output$genome_path_gs <- renderUI(HTML( + paste("", "No file selected.") + )) + + output$screening_start <- NULL + + } else if (nrow(Screening$single_path) > 0) { + + if (str_detect(str_sub(Screening$single_path$name, start = -6), ".fasta") | + str_detect(str_sub(Screening$single_path$name, start = -6), ".fna") | + str_detect(str_sub(Screening$single_path$name, start = -6), ".fa")) { + + # Render selected assembly path + output$genome_path_gs <- renderUI({ + HTML( + paste( + "", + as.character(Screening$single_path$name) + ) + ) + }) + + output$screening_start <- renderUI( + actionButton( + inputId = "screening_start_button", + label = "Start", + icon = icon("circle-play") + ) + ) + } else { + show_toast( + title = "Wrong file type (only fasta/fna/fa)", + type = "error", + position = "bottom-end", + width = "500px", + timer = 6000 + ) + + } + } + }) + + #### Running Screening ---- + + observeEvent(input$screening_start_button, { + + }) + + ### Screening Feedback ---- + + # # Set the path to your .got file + # file_path <- "test_dna.got" + # + # # Read the .got file into a data frame + # amrfinder_data <- read.delim(file_path, header = TRUE, sep = "\t") + # + # # Check the first few rows of the data + # head(amrfinder_data) + + # _______________________ #### ## Typing ---- @@ -22627,8 +22807,6 @@ server <- function(input, output, session) { # Get genome datapath - volumes = getVolumes() - observe({ # Get selected Genome in Single Mode shinyFileChoose(input, diff --git a/resources.R b/resources.R new file mode 100644 index 0000000..162cba1 --- /dev/null +++ b/resources.R @@ -0,0 +1,231 @@ +# Resources + +amrfinder_species <- c( + "Acinetobacter_baumannii", "Burkholderia_cepacia", "Burkholderia_mallei_FLI", + "Burkholderia_mallei_RKI", "Burkholderia_pseudomallei", "Campylobacter_jejuni_coli", + "Citrobacter_freundii", "Clostridioides_difficile", "Corynebacterium_diphtheriae", + "Enterobacter_asburiae", "Enterobacter_cloacae", "Enterococcus_faecalis", + "Enterococcus_faecium", "Escherichia_coli", "Klebsiella_oxytoca_sensu_lato", + "Klebsiella_pneumoniae_sensu_lato", "Neisseria_gonorrhoeae", "Neisseria_meningitidis", + "Pseudomonas_aeruginosa", "Salmonella_enterica", "Serratia_marcescens", + "Staphylococcus_aureus", "Staphylococcus_pseudintermedius", "Streptococcus_agalactiae", + "Streptococcus_pneumoniae", "Streptococcus_pyogenes", "Vibrio_cholerae", + "Vibrio_parahaemolyticus", "Vibrio_vulnificus" + ) + +schemes <- c("Acinetobacter_baumanii", "Bacillus_anthracis", "Bordetella_pertussis", + "Brucella_melitensis", "Brucella_spp", "Burkholderia_mallei_FLI", + "Burkholderia_mallei_RKI", "Burkholderia_pseudomallei", "Campylobacter_jejuni_coli", + "Clostridioides_difficile", "Clostridium_perfringens", "Corynebacterium_diphtheriae", + "Cronobacter_sakazakii_malonaticus", "Enterococcus_faecalis", "Enterococcus_faecium", + "Escherichia_coli", "Francisella_tularensis", "Klebsiella_oxytoca_sensu_lato", "Klebsiella_pneumoniae_sensu_lato", + "Legionella_pneumophila", "Listeria_monocytogenes", "Mycobacterium_tuberculosis_complex", + "Mycobacteroides_abscessus", "Mycoplasma_gallisepticum", "Paenibacillus_larvae", + "Pseudomonas_aeruginosa", "Salmonella_enterica", "Serratia_marcescens", + "Staphylococcus_aureus", "Staphylococcus_capitis", "Streptococcus_pyogenes" +) + +country_names <- c( + "Afghanistan", + "Albania", + "Algeria", + "Andorra", + "Angola", + "Antigua and Barbuda", + "Argentina", + "Armenia", + "Australia", + "Austria", + "Azerbaijan", + "Bahamas", + "Bahrain", + "Bangladesh", + "Barbados", + "Belarus", + "Belgium", + "Belize", + "Benin", + "Bhutan", + "Bolivia", + "Bosnia and Herzegovina", + "Botswana", + "Brazil", + "Brunei", + "Bulgaria", + "Burkina Faso", + "Burundi", + "Côte d'Ivoire", + "Cabo Verde", + "Cambodia", + "Cameroon", + "Canada", + "Central African Republic", + "Chad", + "Chile", + "China", + "Colombia", + "Comoros", + "Congo (Congo-Brazzaville)", + "Costa Rica", + "Croatia", + "Cuba", + "Cyprus", + "Czechia (Czech Republic)", + "Democratic Republic of the Congo", + "Denmark", + "Djibouti", + "Dominica", + "Dominican Republic", + "Ecuador", + "Egypt", + "El Salvador", + "Equatorial Guinea", + "Eritrea", + "Estonia", + 'Eswatini (fmr. "Swaziland")', + "Ethiopia", + "Fiji", + "Finland", + "France", + "Gabon", + "Gambia", + "Georgia", + "Germany", + "Ghana", + "Greece", + "Grenada", + "Guatemala", + "Guinea", + "Guinea-Bissau", + "Guyana", + "Haiti", + "Holy See", + "Honduras", + "Hungary", + "Iceland", + "India", + "Indonesia", + "Iran", + "Iraq", + "Ireland", + "Israel", + "Italy", + "Jamaica", + "Japan", + "Jordan", + "Kazakhstan", + "Kenya", + "Kiribati", + "Kuwait", + "Kyrgyzstan", + "Laos", + "Latvia", + "Lebanon", + "Lesotho", + "Liberia", + "Libya", + "Liechtenstein", + "Lithuania", + "Luxembourg", + "Madagascar", + "Malawi", + "Malaysia", + "Maldives", + "Mali", + "Malta", + "Marshall Islands", + "Mauritania", + "Mauritius", + "Mexico", + "Micronesia", + "Moldova", + "Monaco", + "Mongolia", + "Montenegro", + "Morocco", + "Mozambique", + "Myanmar (formerly Burma)", + "Namibia", + "Nauru", + "Nepal", + "Netherlands", + "New Zealand", + "Nicaragua", + "Niger", + "Nigeria", + "North Korea", + "North Macedonia (formerly Macedonia)", + "Norway", + "Oman", + "Pakistan", + "Palau", + "Palestine State", + "Panama", + "Papua New Guinea", + "Paraguay", + "Peru", + "Philippines", + "Poland", + "Portugal", + "Qatar", + "Romania", + "Russia", + "Rwanda", + "Saint Kitts and Nevis", + "Saint Lucia", + "Saint Vincent and the Grenadines", + "Samoa", + "San Marino", + "Sao Tome and Principe", + "Saudi Arabia", + "Senegal", + "Serbia", + "Seychelles", + "Sierra Leone", + "Singapore", + "Slovakia", + "Slovenia", + "Solomon Islands", + "Somalia", + "South Africa", + "South Korea", + "South Sudan", + "Spain", + "Sri Lanka", + "Sudan", + "Suriname", + "Sweden", + "Switzerland", + "Syria", + "Tajikistan", + "Tanzania", + "Thailand", + "Timor-Leste", + "Togo", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Turkmenistan", + "Tuvalu", + "Uganda", + "Ukraine", + "United Arab Emirates", + "United Kingdom", + "United States of America", + "Uruguay", + "Uzbekistan", + "Vanuatu", + "Venezuela", + "Vietnam", + "Yemen", + "Zambia", + "Zimbabwe" +) + +sel_countries <- + c("Austria", + "Germany", + "Switzerland", + "United Kingdom", + "United States of America") \ No newline at end of file From 28e15e246a02459ea4f6ef640321744f8cf00064 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Wed, 31 Jul 2024 18:51:14 +0200 Subject: [PATCH 23/75] Changed location for resources.R --- resources.R => www/resources.R | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename resources.R => www/resources.R (100%) diff --git a/resources.R b/www/resources.R similarity index 100% rename from resources.R rename to www/resources.R From 5de2c48e7d9779eb699f5df2eae509912dde2111 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Wed, 31 Jul 2024 19:48:38 +0200 Subject: [PATCH 24/75] Added log messages --- App.R | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/App.R b/App.R index f369e32..65f5d86 100644 --- a/App.R +++ b/App.R @@ -6880,7 +6880,7 @@ server <- function(input, output, session) { ) # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme - if(DB$number_loci != length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { + if(DB$number_loci > length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { log_print(paste0("Loci files are missing in the local ", DB$scheme, " folder")) @@ -11394,13 +11394,11 @@ server <- function(input, output, session) { # Check if .downloaded_schemes folder exists and if not create it if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { - print("Creating download schemes folder") dir.create(file.path(DB$database, ".downloaded_schemes"), recursive = TRUE) } # Check if remains of old temporary folder exists and remove them if (dir.exists(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")))) { - print("Deleting old temporary folder") unlink(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")), recursive = TRUE) } @@ -11415,7 +11413,6 @@ server <- function(input, output, session) { paste("Error: ", e$message) }) - print("Unzipping the scheme") # Unzip the scheme in temporary folder unzip( zipfile = file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")), @@ -11425,7 +11422,7 @@ server <- function(input, output, session) { ) ) - print("Producing hashes for the database") + log_print("Hashing downloaded database") # Hash temporary folder hash_database(file.path(DB$database, Scheme$folder_name, @@ -11436,7 +11433,6 @@ server <- function(input, output, session) { Scheme$folder_name, paste0(Scheme$folder_name, "_alleles"))) if (!is_empty(local_db_filelist)) { - print("Old database is not empty, resolving the files!") # Get list from temporary database tmp_db_filelist <- list.files(file.path(DB$database, Scheme$folder_name, @@ -11493,11 +11489,9 @@ server <- function(input, output, session) { } } - print("Delete old alleles folder") unlink(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) - print("Overwriting old alleles directory with temporary directory") file.rename(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")), file.path(DB$database, Scheme$folder_name, @@ -11547,7 +11541,6 @@ server <- function(input, output, session) { width = "400px" ) - # TODO Add log message regarding the update of the scheme log_print("Download successful") showModal( @@ -17565,6 +17558,7 @@ server <- function(input, output, session) { #### MST ---- mst_tree <- reactive({ + log_print("Generating visNetwork") data <- toVisNetworkData(Vis$ggraph_1) data$nodes <- mutate(data$nodes, label = label_mst(), @@ -17744,7 +17738,7 @@ server <- function(input, output, session) { visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) } } - + log_print("Plotting MST graph") visNetwork_graph }) @@ -23955,6 +23949,7 @@ server <- function(input, output, session) { dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) req(dir_path) + log_print("Hashing directory using utilities") output$statustext <- renderUI( fluidRow( tags$li( From efc90a34aee9c31c6a36fe9b240f557df16efd81 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Wed, 31 Jul 2024 20:15:20 +0200 Subject: [PATCH 25/75] Added AMRFinder, first implementation of shell script --- App.R | 41 ++++++++++++++++++++++++++++++++++------- PhyloTrace.yml | 1 + execute/screening.sh | 39 +++++++++++++++++++++++++++++++++++++++ install_phylotrace.sh | 3 +++ 4 files changed, 77 insertions(+), 7 deletions(-) create mode 100755 execute/screening.sh diff --git a/App.R b/App.R index dfe1984..baa406e 100644 --- a/App.R +++ b/App.R @@ -44,7 +44,7 @@ library(treeio) library(ggtree) library(ggtreeExtra) -source("resources.R") +source("www/resources.R") options(ignore.negative.edge=TRUE) @@ -9612,7 +9612,7 @@ server <- function(input, output, session) { # Change scheme observeEvent(input$reload_db, { - test <<- DB$scheme + test <<- Screening$single_path$datapath log_print("Input reload_db") @@ -22331,7 +22331,7 @@ server <- function(input, output, session) { ), br(), br(), uiOutput("genome_path_gs"), - br(), br(), br(), hr(), br(), br(), + br(), br(), br(), uiOutput("screening_start") ) ) @@ -22380,10 +22380,20 @@ server <- function(input, output, session) { }) output$screening_start <- renderUI( - actionButton( - inputId = "screening_start_button", - label = "Start", - icon = icon("circle-play") + fluidRow( + hr(), br(), br(), + column( + width = 8, + actionButton( + inputId = "screening_start_button", + label = "Start", + icon = icon("circle-play") + ) + ), + column( + width = 4, + uiOutput("screening_progress") + ) ) ) } else { @@ -22403,6 +22413,23 @@ server <- function(input, output, session) { observeEvent(input$screening_start_button, { + # Start spinner + output$screening_progress <- renderUI( + HTML('') + ) + + screening_df <- data.frame(wd = getwd(), + assembly_path = Screening$single_path$datapath, + assembly = as.character(basename(Screening$single_path$name)), + species = gsub(" ", "_", DB$scheme)) + + saveRDS(screening_df, paste0(getwd(), "/execute/screening_meta.rds")) + + # System execution screening.sh + system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = TRUE) + + # Stop spinner + output$screening_progress <- NULL }) ### Screening Feedback ---- diff --git a/PhyloTrace.yml b/PhyloTrace.yml index daaacbd..8bd2b59 100644 --- a/PhyloTrace.yml +++ b/PhyloTrace.yml @@ -7,6 +7,7 @@ dependencies: - r-base=4.3.2 - r-remotes=2.5.0 - kma=1.4.14 + - ncbi-amrfinderplus=3.12.8 - parallel=20240522 - pblat=2.5.1 - r-bh=1.81.0-1 diff --git a/execute/screening.sh b/execute/screening.sh new file mode 100755 index 0000000..856c36d --- /dev/null +++ b/execute/screening.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +cd execute +source ~/miniconda3/etc/profile.d/conda.sh +conda activate PhyloTrace +unset R_HOME + +# Set base path +base_path=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'wd'])") +path_assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly_path'])") +assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly'])") +species=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'species'])") + +cat "$path_assembly" + +# Remove the existing directory (if it exists) +if [ -d "$base_path/execute/screening" ]; then + rm -r "$base_path/execute/screening" +fi + +mkdir "$base_path/execute/screening" + +# Directory name +results="$base_path/execute/screening/results" + +# Remove the existing directory (if it exists) +if [ -d "$results" ]; then + rm -r "$results" +fi + +# Create a new directory +mkdir "$results" + +# Get cores +coresall=$(nproc --all) +cores=$((num_processors - 2)) + +amrfinder -n "$path_assembly" --threads $cores #--organism "Klebsiella_oxytoca" + diff --git a/install_phylotrace.sh b/install_phylotrace.sh index f392816..8239529 100755 --- a/install_phylotrace.sh +++ b/install_phylotrace.sh @@ -36,6 +36,9 @@ else fi EOF +# Download AMRFinder Database +amrfinder -u + # Install visNetwork modification Rscript -e "remotes::install_github('fpaskali/visNetwork', force = TRUE)" From 77b74c7f03f8122ed1e7996ba800a05d4086022a Mon Sep 17 00:00:00 2001 From: fpaskali Date: Wed, 31 Jul 2024 21:56:04 +0200 Subject: [PATCH 26/75] added hash formating in tables --- App.R | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 12 deletions(-) diff --git a/App.R b/App.R index 65f5d86..07d717b 100644 --- a/App.R +++ b/App.R @@ -8947,7 +8947,17 @@ server <- function(input, output, session) { td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' } } - }") + }") %>% + hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) }) } else { output$table_missing_values <- renderRHandsontable({ @@ -8974,7 +8984,17 @@ server <- function(input, output, session) { td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' } } - }") + }") %>% + hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) }) } } @@ -22318,14 +22338,36 @@ server <- function(input, output, session) { contextMenu = FALSE) %>% hot_cols(columnSorting = TRUE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter") + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) } else { rhandsontable(Typing$typing_result_table, rowHeaders = NULL, stretchH = "all", readOnly = TRUE, contextMenu = FALSE,) %>% hot_cols(columnSorting = TRUE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter") + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) } } }) @@ -22767,7 +22809,7 @@ server <- function(input, output, session) { ), column(1), column( - width = 3, + width = 5, br(), br(), br(), uiOutput("single_typing_results") ) @@ -23748,7 +23790,19 @@ server <- function(input, output, session) { rowHeaders = NULL, stretchH = "all", readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) } else { if(Typing$multi_table_length > 15) { @@ -23757,15 +23811,38 @@ server <- function(input, output, session) { stretchH = "all", height = 500, readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) } else { output$multi_typing_result_table <- renderRHandsontable({ rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, stretchH = "all", readOnly = TRUE, contextMenu = FALSE) %>% hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter")}) - + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) } } } else { @@ -23813,10 +23890,10 @@ server <- function(input, output, session) { selected = names(Typing$result_list)[length(names(Typing$result_list))], ) ), - br(), br(), - rHandsontableOutput("multi_typing_result_table") + br(), br() ) - ) + ), + rHandsontableOutput("multi_typing_result_table") ) }) } From 0c9c6825100b6629010a431470207edf6b9adace Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Wed, 31 Jul 2024 23:25:19 +0200 Subject: [PATCH 27/75] Implementation of AMRFinder, Set up reactive UI --- App.R | 107 +++++++++++++++++++++++++++++++++++-------- execute/screening.sh | 36 +++++++++------ www/resources.R | 6 +-- 3 files changed, 113 insertions(+), 36 deletions(-) diff --git a/App.R b/App.R index baa406e..29a028c 100644 --- a/App.R +++ b/App.R @@ -5755,6 +5755,11 @@ server <- function(input, output, session) { log_print("Session started") + # Clear screening file + if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { + file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) + } + # Declare reactive variables Startup <- reactiveValues(sidebar = TRUE, header = TRUE) # reactive variables related to startup process @@ -22228,6 +22233,46 @@ server <- function(input, output, session) { ### Render UI Elements ---- + output$screening_results <- renderUI({ + if(!is.null(Screening$results)) { + dataTableOutput("screening_table") + } + }) + + observe({ + if(!is.null(Screening$results)) { + output$screening_reset <- renderUI( + actionButton( + "screening_reset_bttn", + "Reset" + ) + ) + + output$screening_table <- renderDataTable( + select(Screening$results, c(6, 7, 8, 9, 11)), + selection = "single", + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ))) + } else { + output$screening_reset <- NULL + } + }) + # Availablity feedback output$gene_screening_info <- renderUI({ if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { @@ -22310,8 +22355,7 @@ server <- function(input, output, session) { column( width = 3, align = "center", - br(), - br(), + br(), br(), p( HTML( paste( @@ -22332,7 +22376,15 @@ server <- function(input, output, session) { br(), br(), uiOutput("genome_path_gs"), br(), br(), br(), - uiOutput("screening_start") + uiOutput("screening_start"), + br(), br(), br(), + uiOutput("screening_reset") + ), + column(1), + column( + width = 6, + br(), br(), + uiOutput("screening_results") ) ) } @@ -22340,6 +22392,13 @@ server <- function(input, output, session) { ### Screening Events ---- + # Reset screening + observeEvent(input$screening_reset_bttn, { + Screening$status <- "idle" + file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) + Screening$results <- NULL + }) + # Get selected Genome in Single Mode observe({ @@ -22413,10 +22472,7 @@ server <- function(input, output, session) { observeEvent(input$screening_start_button, { - # Start spinner - output$screening_progress <- renderUI( - HTML('') - ) + Screening$status <- "started" screening_df <- data.frame(wd = getwd(), assembly_path = Screening$single_path$datapath, @@ -22426,24 +22482,37 @@ server <- function(input, output, session) { saveRDS(screening_df, paste0(getwd(), "/execute/screening_meta.rds")) # System execution screening.sh - system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = TRUE) - - # Stop spinner - output$screening_progress <- NULL + system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) }) ### Screening Feedback ---- - # # Set the path to your .got file - # file_path <- "test_dna.got" - # - # # Read the .got file into a data frame - # amrfinder_data <- read.delim(file_path, header = TRUE, sep = "\t") - # - # # Check the first few rows of the data - # head(amrfinder_data) + observe({ + req(Screening$status) + if(Screening$status == "started") { + # Start spinner + output$screening_progress <- renderUI( + HTML(paste('')) + ) + + check_screening() + + } else if (Screening$status == "finished") { + output$screening_progress <- NULL + } + }) + check_screening <- reactive({ + invalidateLater(2000, session) + if(Screening$status == "started"){ + if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { + Screening$results <- read.delim(paste0(getwd(), "/execute/screening/output_file.tsv")) + Screening$status <- "finished" + } + } + }) + # _______________________ #### ## Typing ---- diff --git a/execute/screening.sh b/execute/screening.sh index 856c36d..87fe552 100755 --- a/execute/screening.sh +++ b/execute/screening.sh @@ -11,29 +11,39 @@ path_assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly_path']) assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly'])") species=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'species'])") -cat "$path_assembly" +if [ "$species" = "Escherichia_coli" ]; then + species="Escherichia" +fi -# Remove the existing directory (if it exists) -if [ -d "$base_path/execute/screening" ]; then - rm -r "$base_path/execute/screening" +if [ "$species" = "Burkholderia_mallei_FLI" ] || [ "$species" = "Burkholderia_mallei_RKI" ]; then +species="Burkholderia_mallei" fi -mkdir "$base_path/execute/screening" +if [ "$species" = "Klebsiella_oxytoca_sensu_lato" ]; then + species="Klebsiella_oxytoca" +fi -# Directory name -results="$base_path/execute/screening/results" +if [ "$species" = "Salmonella_enterica" ]; then + species="Salmonella" +fi + +if [ "$species" = "Campylobacter_jejuni_coli" ]; then + species="Campylobacter" +fi + +if [ "$species" = "Klebsiella_pneumoniae_sensu_lato" ]; then + species="Klebsiella_pneumoniae" +fi # Remove the existing directory (if it exists) -if [ -d "$results" ]; then - rm -r "$results" +if [ -d "$base_path/execute/screening" ]; then + rm -r "$base_path/execute/screening" fi -# Create a new directory -mkdir "$results" +mkdir "$base_path/execute/screening" # Get cores coresall=$(nproc --all) cores=$((num_processors - 2)) -amrfinder -n "$path_assembly" --threads $cores #--organism "Klebsiella_oxytoca" - +amrfinder -n "$path_assembly" --threads $cores --plus --organism $species -o "screening/output_file.tsv" diff --git a/www/resources.R b/www/resources.R index 162cba1..fc46c7f 100644 --- a/www/resources.R +++ b/www/resources.R @@ -10,8 +10,7 @@ amrfinder_species <- c( "Pseudomonas_aeruginosa", "Salmonella_enterica", "Serratia_marcescens", "Staphylococcus_aureus", "Staphylococcus_pseudintermedius", "Streptococcus_agalactiae", "Streptococcus_pneumoniae", "Streptococcus_pyogenes", "Vibrio_cholerae", - "Vibrio_parahaemolyticus", "Vibrio_vulnificus" - ) + "Vibrio_parahaemolyticus", "Vibrio_vulnificus") schemes <- c("Acinetobacter_baumanii", "Bacillus_anthracis", "Bordetella_pertussis", "Brucella_melitensis", "Brucella_spp", "Burkholderia_mallei_FLI", @@ -22,8 +21,7 @@ schemes <- c("Acinetobacter_baumanii", "Bacillus_anthracis", "Bordetella_pertuss "Legionella_pneumophila", "Listeria_monocytogenes", "Mycobacterium_tuberculosis_complex", "Mycobacteroides_abscessus", "Mycoplasma_gallisepticum", "Paenibacillus_larvae", "Pseudomonas_aeruginosa", "Salmonella_enterica", "Serratia_marcescens", - "Staphylococcus_aureus", "Staphylococcus_capitis", "Streptococcus_pyogenes" -) + "Staphylococcus_aureus", "Staphylococcus_capitis", "Streptococcus_pyogenes") country_names <- c( "Afghanistan", From c5ff229e66ea3a1efc2c76b8987f9c01094db907 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Thu, 1 Aug 2024 11:35:09 +0200 Subject: [PATCH 28/75] Improvements of screening functionality and feedback --- App.R | 253 ++++++++++++++++++++++++++++++------------- execute/screening.sh | 20 +++- www/body.css | 11 ++ www/head.css | 2 + 4 files changed, 209 insertions(+), 77 deletions(-) diff --git a/App.R b/App.R index 29a028c..ac7e57f 100644 --- a/App.R +++ b/App.R @@ -5778,7 +5778,7 @@ server <- function(input, output, session) { result_list = NULL, status = "") # reactive variables related to typing process - Screening <- reactiveValues() + Screening <- reactiveValues(status = "idle") # reactive variables related to gene screening Vis <- reactiveValues(cluster = NULL, metadata = list(), @@ -6202,6 +6202,42 @@ server <- function(input, output, session) { ) ) ) + } else if(Screening$status == "started") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    running gene screening")), + style = "color:white;") + ) + ) + ) + } else if(Screening$status == "finished") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    gene screening finalized")), + style = "color:white;") + ) + ) + ) + } else if(isTRUE(Screening$fail)) { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    gene screening failed")), + style = "color:white;") + ) + ) + ) } else { output$statustext <- renderUI( fluidRow( @@ -22239,14 +22275,20 @@ server <- function(input, output, session) { } }) + observe({ + if(isTRUE(Screening$fail)) { + output$screening_fail <- renderPrint({ + readLines(paste0(getwd(), "/execute/screening/error.txt")) + }) + } else { + output$screening_fail <- NULL + } + }) + + observe({ if(!is.null(Screening$results)) { - output$screening_reset <- renderUI( - actionButton( - "screening_reset_bttn", - "Reset" - ) - ) + req(Screening$results) output$screening_table <- renderDataTable( select(Screening$results, c(6, 7, 8, 9, 11)), @@ -22268,8 +22310,6 @@ server <- function(input, output, session) { "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", "}" ))) - } else { - output$screening_reset <- NULL } }) @@ -22350,41 +22390,48 @@ server <- function(input, output, session) { output$screening_interface <- renderUI({ if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - fluidRow( - column(1), - column( - width = 3, - align = "center", - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly File (FASTA)') + column( + width = 12, + fluidRow( + column(1), + column( + width = 3, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly File (FASTA)') + ) ) - ) - ), - shinyFilesButton( - "genome_file_gs", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() + ), + shinyFilesButton( + "genome_file_gs", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), br(), + uiOutput("genome_path_gs") ), - br(), br(), - uiOutput("genome_path_gs"), - br(), br(), br(), - uiOutput("screening_start"), - br(), br(), br(), - uiOutput("screening_reset") + column(1), + column( + width = 2, + uiOutput("screening_start") + ) ), - column(1), - column( - width = 6, - br(), br(), - uiOutput("screening_results") + fluidRow( + column(1), + column( + width = 10, + br(), br(), br(), br(), + uiOutput("screening_results"), + verbatimTextOutput("screening_fail") + ) ) ) } @@ -22394,9 +22441,13 @@ server <- function(input, output, session) { # Reset screening observeEvent(input$screening_reset_bttn, { + log_print("Reset gene screening") Screening$status <- "idle" file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) + file.remove(paste0(getwd(), "/execute/screening/error.txt")) Screening$results <- NULL + Screening$single_path <- data.frame() + Screening$fail <- NULL }) # Get selected Genome in Single Mode @@ -22438,23 +22489,31 @@ server <- function(input, output, session) { ) }) - output$screening_start <- renderUI( + output$screening_start <- renderUI({ + fluidRow( - hr(), br(), br(), column( width = 8, - actionButton( - inputId = "screening_start_button", - label = "Start", - icon = icon("circle-play") - ) - ), - column( - width = 4, - uiOutput("screening_progress") + br(), br(), + if(Screening$status == "finished") { + actionButton( + "screening_reset_bttn", + "Reset", + icon = icon("arrows-rotate") + ) + } else if(Screening$status == "idle") { + actionButton( + inputId = "screening_start_button", + label = "Start", + icon = icon("circle-play") + ) + } else if(Screening$status == "started") { + HTML(paste('')) + } ) ) - ) + }) + } else { show_toast( title = "Wrong file type (only fasta/fna/fa)", @@ -22472,17 +22531,47 @@ server <- function(input, output, session) { observeEvent(input$screening_start_button, { - Screening$status <- "started" - - screening_df <- data.frame(wd = getwd(), - assembly_path = Screening$single_path$datapath, - assembly = as.character(basename(Screening$single_path$name)), - species = gsub(" ", "_", DB$scheme)) - - saveRDS(screening_df, paste0(getwd(), "/execute/screening_meta.rds")) - - # System execution screening.sh - system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) + if(tail(readLogFile(), 1) != "0") { + show_toast( + title = "Pending Multi Typing", + type = "warning", + position = "bottom-end", + timer = 6000, + width = "500px" + ) + } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000, + width = "500px" + ) + } else { + + log_print("Started gene screening") + + Screening$status <- "started" + + show_toast( + title = "Gene screening started", + type = "success", + position = "bottom-end", + width = "500px", + timer = 6000 + ) + + screening_df <- data.frame(wd = getwd(), + assembly_path = Screening$single_path$datapath, + assembly = as.character(basename(Screening$single_path$name)), + species = gsub(" ", "_", DB$scheme)) + + saveRDS(screening_df, paste0(getwd(), "/execute/screening_meta.rds")) + + # System execution screening.sh + system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) + + } }) ### Screening Feedback ---- @@ -22490,15 +22579,10 @@ server <- function(input, output, session) { observe({ req(Screening$status) if(Screening$status == "started") { - # Start spinner - output$screening_progress <- renderUI( - HTML(paste('')) - ) - + shinyjs::disable("genome_file_gs") check_screening() - - } else if (Screening$status == "finished") { - output$screening_progress <- NULL + } else if(Screening$status == "idle") { + shinyjs::enable("genome_file_gs") } }) @@ -22508,6 +22592,11 @@ server <- function(input, output, session) { if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { Screening$results <- read.delim(paste0(getwd(), "/execute/screening/output_file.tsv")) Screening$status <- "finished" + log_print("Finalized gene screening") + } else if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { + Screening$status <- "finished" + log_print("Failed gene screening") + Screening$fail <- TRUE } } }) @@ -22896,7 +22985,6 @@ server <- function(input, output, session) { width = "500px", timer = 6000 ) - } } }) @@ -22922,8 +23010,6 @@ server <- function(input, output, session) { log_print("Input typing_start") if(tail(readLogFile(), 1) != "0") { - log_print("Pending multi typing") - show_toast( title = "Pending Multi Typing", type = "warning", @@ -22931,6 +23017,14 @@ server <- function(input, output, session) { timer = 6000, width = "500px" ) + } else if (Screening$status == "started") { + show_toast( + title = "Pending Gene Screening", + type = "warning", + position = "bottom-end", + timer = 6000, + width = "500px" + ) } else { if(!is.null(DB$data)) { @@ -23842,7 +23936,6 @@ server <- function(input, output, session) { log_print("Initiate multi typing") if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - log_print("Pending Single Typing") show_toast( title = "Pending Single Typing", type = "warning", @@ -23850,6 +23943,14 @@ server <- function(input, output, session) { timer = 6000, width = "500px" ) + } else if (Screening$status == "started") { + show_toast( + title = "Pending Gene Screening", + type = "warning", + position = "bottom-end", + timer = 6000, + width = "500px" + ) } else { if (any(!grepl("\\.fasta|\\.fna|\\.fa", str_sub(Typing$genome_selected$Files[which(Typing$genome_selected$Include == TRUE)], start = -6)))) { diff --git a/execute/screening.sh b/execute/screening.sh index 87fe552..f0ed3d0 100755 --- a/execute/screening.sh +++ b/execute/screening.sh @@ -11,6 +11,8 @@ path_assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly_path']) assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly'])") species=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'species'])") +error_file="screening/error.txt" + if [ "$species" = "Escherichia_coli" ]; then species="Escherichia" fi @@ -46,4 +48,20 @@ mkdir "$base_path/execute/screening" coresall=$(nproc --all) cores=$((num_processors - 2)) -amrfinder -n "$path_assembly" --threads $cores --plus --organism $species -o "screening/output_file.tsv" +amrfinder -n "$path_assembly" --threads $cores --plus --organism $species -o "screening/output_file.tsv" > amrfinder_stdout.txt 2> amrfinder_stderr.txt +status=$? + +# Check if status variable is set and is an integer +if [ -z "$status" ]; then + echo "AMRFinder execution did not set an exit status." > "$base_path/execute/$error_file" + exit 1 +fi + +if [ "$status" -ne 0 ]; then + echo "AMRFinder failed with status $status" > "$base_path/execute/$error_file" + echo "Error details:" >> "$base_path/execute/$error_file" + cat amrfinder_stderr.txt >> "$base_path/execute/$error_file" + exit $status +fi + +echo "AMRFinder completed successfully" diff --git a/www/body.css b/www/body.css index c197353..28d78c4 100644 --- a/www/body.css +++ b/www/body.css @@ -2845,3 +2845,14 @@ top: 1px; border-radius: 6px; margin-left: 10px; } + +/* Gene Screening */ + +#screening_start_button, +#screening_reset_bttn { + margin-top: 31px; +} + +#screening_fail { + max-width: 1000px; +} \ No newline at end of file diff --git a/www/head.css b/www/head.css index 1825811..2aa66d2 100644 --- a/www/head.css +++ b/www/head.css @@ -89,6 +89,7 @@ div#bs-select-11::-webkit-scrollbar-track, div#bs-select-12::-webkit-scrollbar-track, #logText::-webkit-scrollbar-track, #logTextFull::-webkit-scrollbar-track, +#screening_fail::-webkit-scrollbar-track, .selectize-dropdown-content::-webkit-scrollbar-track, #mst_comm_general_select::-webkit-scrollbar-track { background: #F0F0F0; @@ -109,6 +110,7 @@ div#bs-select-11::-webkit-scrollbar-thumb, div#bs-select-12::-webkit-scrollbar-thumb, #logText::-webkit-scrollbar-thumb, #logTextFull::-webkit-scrollbar-thumb, +#screening_fail::-webkit-scrollbar-thumb, .selectize-dropdown-content::-webkit-scrollbar-thumb, #mst_comm_general_select::-webkit-scrollbar-thumb { background: #bcbcbc; From cba86073176e742fde811e394f86335abbf3285d Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Fri, 2 Aug 2024 11:17:25 +0200 Subject: [PATCH 29/75] Fixes in fasta formatting; assembly file saving --- App.R | 287 +++++++++++++++++++------------ execute/check_duplicate_multi.R | 92 ++++++---- execute/check_duplicate_single.R | 88 +++++++--- execute/multi_eval.R | 63 +++++-- execute/screening.sh | 6 +- execute/single_eval.R | 67 ++++++-- execute/single_typing.sh | 2 +- execute/variant_validation.R | 2 +- www/body.css | 10 +- 9 files changed, 418 insertions(+), 199 deletions(-) diff --git a/App.R b/App.R index ac7e57f..ecdf699 100644 --- a/App.R +++ b/App.R @@ -44,7 +44,7 @@ library(treeio) library(ggtree) library(ggtreeExtra) -source("www/resources.R") +source(paste0(getwd(), "/www/resources.R")) options(ignore.negative.edge=TRUE) @@ -5339,10 +5339,14 @@ ui <- dashboardPage( ), br(), hr(), - column( - width = 12, - align = "left", - + br(), br(), + fluidRow( + column(1), + column( + width = 10, + div(class = "loci_table", + dataTableOutput("gs_isolate_table")) + ) ) ) ) # End tabItems @@ -5357,12 +5361,12 @@ server <- function(input, output, session) { phylotraceVersion <- paste("1.4.1") - # TODO Enable this, or leave disabled - # # Kill server on session end - # session$onSessionEnded( function() { - # stopApp() - # }) - + #TODO Enable this, or leave disabled + # Kill server on session end + session$onSessionEnded( function() { + stopApp() + }) + # Disable various user inputs (visualization control) shinyjs::disable('mst_edge_label') @@ -5760,6 +5764,10 @@ server <- function(input, output, session) { file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) } + if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { + file.remove(paste0(getwd(), "/execute/screening/error.txt")) + } + # Declare reactive variables Startup <- reactiveValues(sidebar = TRUE, header = TRUE) # reactive variables related to startup process @@ -6215,29 +6223,31 @@ server <- function(input, output, session) { ) ) } else if(Screening$status == "finished") { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    gene screening finalized")), - style = "color:white;") + if(isTRUE(Screening$fail)) { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    gene screening failed")), + style = "color:white;") + ) ) ) - ) - } else if(isTRUE(Screening$fail)) { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    gene screening failed")), - style = "color:white;") + } else { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    gene screening finalized")), + style = "color:white;") + ) ) ) - ) + } } else { output$statustext <- renderUI( fluidRow( @@ -6322,6 +6332,8 @@ server <- function(input, output, session) { DB$data <- NULL + DB$meta_gs <- NULL + DB$meta <- NULL DB$meta_true <- NULL @@ -6398,7 +6410,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus"), + icon = icon("layer-group"), selected = TRUE ), menuItem( @@ -6468,6 +6480,8 @@ server <- function(input, output, session) { DB$data <- NULL + DB$meta_gs <- NULL + DB$meta <- NULL DB$meta_true <- NULL @@ -6563,7 +6577,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus"), + icon = icon("layer-group"), selected = TRUE ), menuItem( @@ -6653,7 +6667,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus"), + icon = icon("layer-group"), selected = TRUE ), menuItem( @@ -6745,7 +6759,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus"), + icon = icon("layer-group"), selected = TRUE ), menuItem( @@ -6866,7 +6880,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus"), + icon = icon("layer-group"), selected = TRUE ), menuItem( @@ -6919,8 +6933,8 @@ server <- function(input, output, session) { DB$data <- Database[["Typing"]] if(!is.null(DB$data)){ - if ((ncol(DB$data)-12) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 13:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) } else { DB$cust_var <- data.frame() @@ -6929,11 +6943,13 @@ server <- function(input, output, session) { DB$change <- FALSE - DB$meta <- select(DB$data, 1:(12 + nrow(DB$cust_var))) + DB$meta_gs <- select(DB$data, c(1, 3:13)) + + DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(12 + nrow(DB$cust_var)))) + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] @@ -7050,7 +7066,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus") + icon = icon("layer-group") ), menuItem( text = "Allelic Typing", @@ -7117,7 +7133,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus") + icon = icon("layer-group") ), menuItem( text = "Allelic Typing", @@ -7724,7 +7740,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var))), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), error_highlight = err_thresh() - 1, rowHeaders = NULL, contextMenu = FALSE, @@ -7819,7 +7835,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, dup_names_high = duplicated_names() - 1, dup_ids_high = duplicated_ids() - 1, @@ -7978,7 +7994,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var))), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), rowHeaders = NULL, row_highlight = true_rows() - 1, dup_names_high = duplicated_names()- 1, @@ -8117,7 +8133,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, rowHeaders = NULL, height = table_height(), @@ -8272,7 +8288,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var))), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), rowHeaders = NULL, height = table_height(), dup_names_high = duplicated_names() - 1, @@ -9022,6 +9038,8 @@ server <- function(input, output, session) { DB$meta <- NULL + DB$meta_gs <- NULL + DB$meta_true <- NULL DB$allelic_profile <- NULL @@ -9057,7 +9075,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus") + icon = icon("layer-group") ), menuItem( text = "Allelic Typing", @@ -9415,7 +9433,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus") + icon = icon("layer-group") ), menuItem( text = "Allelic Typing", @@ -9478,7 +9496,7 @@ server <- function(input, output, session) { menuItem( text = "Manage Schemes", tabName = "init", - icon = icon("plus") + icon = icon("layer-group") ), menuItem( text = "Allelic Typing", @@ -9653,8 +9671,6 @@ server <- function(input, output, session) { # Change scheme observeEvent(input$reload_db, { - test <<- Screening$single_path$datapath - log_print("Input reload_db") if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { @@ -9724,8 +9740,8 @@ server <- function(input, output, session) { DB$data <- Data[["Typing"]] - if ((ncol(DB$data)-12) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 13:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) } else { DB$cust_var <- data.frame() @@ -9737,11 +9753,13 @@ server <- function(input, output, session) { DB$no_na_switch <- TRUE - DB$meta <- select(DB$data, 1:(12 + nrow(DB$cust_var))) + DB$meta_gs <- select(DB$data, c(1, 3:13)) + + DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(12 + nrow(DB$cust_var)))) + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] @@ -9753,7 +9771,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var))), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), error_highlight = err_thresh() - 1, rowHeaders = NULL, contextMenu = FALSE, @@ -9848,7 +9866,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, dup_names_high = duplicated_names() - 1, dup_ids_high = duplicated_ids() - 1, @@ -10007,7 +10025,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var))), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), rowHeaders = NULL, row_highlight = true_rows() - 1, dup_names_high = duplicated_names()- 1, @@ -10146,7 +10164,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, rowHeaders = NULL, height = table_height(), @@ -10301,7 +10319,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(DB$data, 1:(12 + nrow(DB$cust_var))), + select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), rowHeaders = NULL, height = table_height(), dup_names_high = duplicated_names() - 1, @@ -10441,8 +10459,8 @@ server <- function(input, output, session) { observe({ if(!is.null(DB$data)){ - if ((ncol(DB$data)-12) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 13:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) } else { @@ -10519,21 +10537,24 @@ server <- function(input, output, session) { if(input$new_var_type == "Categorical (character)") { DB$data <- DB$data %>% - mutate("{name}" := character(nrow(DB$data)), .after = 12) + mutate("{name}" := character(nrow(DB$data)), .after = 13) DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "categ")) } else { DB$data <- DB$data %>% - mutate("{name}" := numeric(nrow(DB$data)), .after = 12) + mutate("{name}" := numeric(nrow(DB$data)), .after = 13) DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "cont")) } - DB$meta <- select(DB$data, 1:(12 + nrow(DB$cust_var))) + + DB$meta_gs <- select(DB$data, c(1, 3:13)) + + DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(12 + nrow(DB$cust_var)))) + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] @@ -10603,13 +10624,18 @@ server <- function(input, output, session) { log_print(paste0("Variable ", input$del_which_var, " removed")) DB$cust_var <- DB$cust_var[-which(DB$cust_var$Variable == input$del_which_var),] + DB$data <- select(DB$data, -(input$del_which_var)) - DB$meta <- select(DB$data, 1:(12 + nrow(DB$cust_var))) + + DB$meta_gs <- select(DB$data, c(1, 3:13)) + + DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(12 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] }) # Select all button @@ -10818,8 +10844,8 @@ server <- function(input, output, session) { DB$data <- Database[["Typing"]] if(!is.null(DB$data)){ - if ((ncol(DB$data)-12) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 13:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) } else { DB$cust_var <- data.frame() @@ -10832,11 +10858,13 @@ server <- function(input, output, session) { DB$no_na_switch <- TRUE - DB$meta <- select(DB$data, 1:(12 + nrow(DB$cust_var))) + DB$meta_gs <- select(DB$data, c(1, 3:13)) + + DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(12 + nrow(DB$cust_var)))) + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] @@ -10953,11 +10981,13 @@ server <- function(input, output, session) { DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] - DB$meta <- select(DB$data, 1:(12 + nrow(DB$cust_var))) + DB$meta_gs <- select(DB$data, c(1, 3:13)) + + DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(12 + nrow(DB$cust_var)))) + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] @@ -11589,33 +11619,34 @@ server <- function(input, output, session) { ) }) - # Download Target Info (CSV Table) - observe({ - input$download_cgMLST - - scheme_overview <- read_html(Scheme$link_scheme) %>% - html_table(header = FALSE) %>% - as.data.frame(stringsAsFactors = FALSE) - - last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], - format = "%B %d, %Y, %H:%M %p") - names(scheme_overview) <- NULL - - last_file_change <- format( - file.info(file.path(DB$database, - ".downloaded_schemes", - paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") - - output$cgmlst_scheme <- renderTable({scheme_overview}) - output$scheme_update_info <- renderText({ - req(last_file_change) - if (last_file_change < last_scheme_change) { - "(Newer scheme available \u274c)" - } else { - "(Scheme is up-to-date \u2705)" - } - }) - }) + # Download Target Info (CSV Table)# + #TODO + # observe({ + # input$download_cgMLST + # + # scheme_overview <- read_html(Scheme$link_scheme) %>% + # html_table(header = FALSE) %>% + # as.data.frame(stringsAsFactors = FALSE) + # + # last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], + # format = "%B %d, %Y, %H:%M %p") + # names(scheme_overview) <- NULL + # + # last_file_change <- format( + # file.info(file.path(DB$database, + # ".downloaded_schemes", + # paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") + # + # output$cgmlst_scheme <- renderTable({scheme_overview}) + # output$scheme_update_info <- renderText({ + # req(last_file_change) + # if (last_file_change < last_scheme_change) { + # "(Newer scheme available \u274c)" + # } else { + # "(Scheme is up-to-date \u2705)" + # } + # }) + # }) # _______________________ #### @@ -17590,7 +17621,7 @@ server <- function(input, output, session) { label = label_mst(), value = mst_node_scaling(), opacity = node_opacity()) - test <<- Typing$data + ctxRendererJS <- htmlwidgets::JS("({ctx, id, x, y, state: { selected, hover }, style, font, label, metadata}) => { var pieData = JSON.parse(metadata); var radius = style.size; @@ -17788,14 +17819,10 @@ server <- function(input, output, session) { } else { legend <- Typing$var_cols names(legend)[1] <- "label" - legend <- mutate(legend, shape = "dot", + mutate(legend, shape = "dot", font.color = input$mst_legend_color, size = input$mst_symbol_size, font.size = input$mst_font_size) - - legend1 <<- legend - dnode <<- Typing$data$nodes - legend } }) @@ -22269,6 +22296,32 @@ server <- function(input, output, session) { ### Render UI Elements ---- + observe({ + req(DB$meta) + output$gs_isolate_table <- renderDataTable( + DB$meta_gs, + selection = "single", + rownames= FALSE, + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + }) + output$screening_results <- renderUI({ if(!is.null(Screening$results)) { dataTableOutput("screening_table") @@ -22430,7 +22483,8 @@ server <- function(input, output, session) { width = 10, br(), br(), br(), br(), uiOutput("screening_results"), - verbatimTextOutput("screening_fail") + verbatimTextOutput("screening_fail"), + br(), br(), br(), br(), br(), br() ) ) ) @@ -22593,10 +22647,24 @@ server <- function(input, output, session) { Screening$results <- read.delim(paste0(getwd(), "/execute/screening/output_file.tsv")) Screening$status <- "finished" log_print("Finalized gene screening") + show_toast( + title = "Successful gene screening", + type = "success", + position = "bottom-end", + width = "500px", + timer = 6000 + ) } else if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { Screening$status <- "finished" log_print("Failed gene screening") Screening$fail <- TRUE + show_toast( + title = "Failed gene screening", + type = "error", + position = "bottom-end", + width = "500px", + timer = 6000 + ) } } }) @@ -22682,6 +22750,7 @@ server <- function(input, output, session) { if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { output$typing_result_table <- renderRHandsontable({ Typing$typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) + Typing$typing_result_table <- mutate_all(Typing$typing_result_table, as.character) if(nrow(Typing$typing_result_table) > 0) { if(nrow(Typing$typing_result_table) > 15) { rhandsontable(Typing$typing_result_table, rowHeaders = NULL, diff --git a/execute/check_duplicate_multi.R b/execute/check_duplicate_multi.R index 21b995e..fe0cf12 100644 --- a/execute/check_duplicate_multi.R +++ b/execute/check_duplicate_multi.R @@ -1,35 +1,33 @@ library(logr) -# Get the command line arguments -args <- commandArgs(trailingOnly = TRUE) - -# Access the first argument -base_path <- args[1] - -# Get selected assembly file names -file_names <- list.files(paste0(getwd(), "/selected_genomes"), full.names = T) - -# Function to log messages -log.message <- function(log_file, message) { - cat(format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "-", message, "\n", file = log_file, append = TRUE) -} -logfile <- file.path(paste0(base_path, "/logs/check_duplicate_multi.log")) - -log <- log_open(logfile, logdir = FALSE) - -log_print("Initiated multi typing fasta name duplicates check") - -# load selected assemblies -assemblies <- lapply(list.files(paste0(getwd(), "/selected_genomes"), full.names = T), readLines) - -# loop through every assembly -for(i in 1:length(assemblies)){ - names <- stringr::str_extract(assemblies[[i]][seq(1, length(assemblies[[i]]), by = 3)], "^[^\\s]+") +process_fasta <- function(fasta_path) { + # Read the FASTA file into a data.table + dt <- data.table::fread(fasta_path, header = FALSE, sep = "\n", col.names = "line", data.table = TRUE) + + # Identify headers and sequence lines + dt[, is_header := grepl("^>", line)] + + # Create a group identifier for each sequence based on headers + dt[, group := cumsum(is_header)] + + # Process each group to concatenate sequences, keeping headers as is + result <- dt[, .(header = line[1], + sequence = paste(line[!is_header], collapse = "")), + by = group] + + # Prepare the final output as a character vector + # Ensure exactly one empty line between sequence end and next header + output <- unlist(result[, .(output = c(header, sequence, "")), by = group]$output) + + # Remove the last empty line to avoid trailing empty line in the file + output <- output[-length(output)] + + names <- stringr::str_extract(output[seq(1, length(output), by = 3)], "^[^\\s]+") # Test if there are duplicates if(length(names) != length(unique(names))){ - log_print(paste0("Duplicate(s) present in ", basename(file_names[i]))) + log_print(paste0("Duplicate(s) present in ", basename(fasta_path))) # add a number to the duplicates for(j in 1:length(names)){ @@ -41,12 +39,46 @@ for(i in 1:length(assemblies)){ # substitute the respective lines in the file with the new names for(k in 1:length(names)){ - assemblies[[i]][3*k - 2] <- paste0(names[k]) + output[3*k - 2] <- paste0(names[k]) } - # save the new assembly - writeLines(assemblies[[i]], file_names[i]) - } + # save formatted fasta + writeLines(output, fasta_path) + + # Return invisible NULL to suppress output + invisible(NULL) + + } else { + + # save formatted fasta + writeLines(output, fasta_path) + + # Return invisible NULL to suppress output + invisible(NULL) + } } +# Get the command line arguments +args <- commandArgs(trailingOnly = TRUE) + +# Access the first argument +base_path <- args[1] + +# Get selected assembly file names +assemblies <- list.files(paste0(getwd(), "/selected_genomes"), full.names = T) + +# Function to log messages +log.message <- function(log_file, message) { + cat(format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "-", message, "\n", file = log_file, append = TRUE) +} + +logfile <- file.path(paste0(base_path, "/logs/check_duplicate_multi.log")) + +log <- log_open(logfile, logdir = FALSE) + +log_print("Initiated multi typing fasta check and formatting") + +# Check and format fasta of assemblies +invisible(lapply(assemblies, process_fasta)) + log_close() diff --git a/execute/check_duplicate_single.R b/execute/check_duplicate_single.R index ae111e2..d5ea766 100644 --- a/execute/check_duplicate_single.R +++ b/execute/check_duplicate_single.R @@ -1,4 +1,63 @@ library(logr) + +process_fasta <- function(fasta_path) { + # Read the FASTA file into a data.table + dt <- data.table::fread(fasta_path, header = FALSE, sep = "\n", col.names = "line", data.table = TRUE) + + # Identify headers and sequence lines + dt[, is_header := grepl("^>", line)] + + # Create a group identifier for each sequence based on headers + dt[, group := cumsum(is_header)] + + # Process each group to concatenate sequences, keeping headers as is + result <- dt[, .(header = line[1], + sequence = paste(line[!is_header], collapse = "")), + by = group] + + # Prepare the final output as a character vector + # Ensure exactly one empty line between sequence end and next header + output <- unlist(result[, .(output = c(header, sequence, "")), by = group]$output) + + # Remove the last empty line to avoid trailing empty line in the file + output <- output[-length(output)] + + names <- stringr::str_extract(output[seq(1, length(output), by = 3)], "^[^\\s]+") + + # Test if there are duplicates + if(length(names) != length(unique(names))){ + + log_print(paste0("Duplicate(s) present in ", basename(fasta_path))) + + # add a number to the duplicates + for(j in 1:length(names)){ + if(sum(names == names[j]) > 1){ + indices <- which(names == names[j]) + names[j] <- paste0(names[j], "_", which(names == names[j])) + } + } + + # substitute the respective lines in the file with the new names + for(k in 1:length(names)){ + output[3*k - 2] <- paste0(names[k]) + } + + # save formatted fasta + writeLines(output, paste0(getwd(), "/blat_single/", basename(fasta_path))) + + # Return invisible NULL to suppress output + invisible(NULL) + + } else { + + # save formatted fasta + writeLines(output, paste0(getwd(), "/blat_single/", basename(fasta_path))) + + # Return invisible NULL to suppress output + invisible(NULL) + } +} + typing_meta <- readRDS(paste0(getwd(), "/single_typing_df.rds")) # Function to log messages @@ -14,32 +73,7 @@ log_print("Initiated single typing fasta name duplicates check") assembly <- typing_meta$genome -lines <- readLines(assembly) - -names <- stringr::str_extract(lines[seq(1, length(lines), by = 3)], "^[^\\s]+") - -# Test if there are duplicates -if(length(names) != length(unique(names))) { - - log_print(paste0("Duplicate(s) present in ", basename(assembly))) - - # add a number to the duplicates - for(i in 1:length(names)) { - if(sum(names == names[i]) > 1) { - indices <- which(names == names[i]) - names[i] <- paste0(names[i], "_", indices[which(indices == i)]) - } - } - - # substitute the respective lines in the file with the new names - for(i in 1:length(names)) { - lines[3*i - 2] <- paste0(names[i]) - } - - # save the new assembly to working directory - writeLines(lines, paste0(getwd(), "/blat_single/assembly.fasta")) -} else { - writeLines(lines, paste0(getwd(), "/blat_single/assembly.fasta")) -} +# Check and format fasta of assemblies +invisible(lapply(assembly, process_fasta)) log_close() diff --git a/execute/multi_eval.R b/execute/multi_eval.R index d2c19f3..6a12612 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -167,7 +167,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= data.frame(matrix( NA, nrow = 0, - ncol = 12 + length(psl_files) + ncol = 13 + length(psl_files) )) metadata <- @@ -183,7 +183,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= meta_info$append_city, as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), - sum(sapply(allele_vector, is.na)) + sum(sapply(allele_vector, is.na)), + "No" ) new_row <- c(metadata, allele_vector) @@ -205,16 +206,17 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= "City", "Typing Date", "Successes", - "Errors" + "Errors", + "Screened" ), gsub(".fasta", "", basename(list.files(allele_folder))) ) Database[["Typing"]] <- Typing - df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 13:(12+length(list.files(allele_folder)))), function(x) as.character(x)) + df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 14:(13+length(list.files(allele_folder)))), function(x) as.character(x)) - df1 <- dplyr::select(Database$Typing, 1:12) + df1 <- dplyr::select(Database$Typing, 1:13) df1 <- dplyr::mutate(df1, Include = as.logical(Include)) Typing <- cbind(df1, df2) @@ -238,12 +240,13 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= meta_info$append_city, as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), - sum(sapply(allele_vector, is.na)) + sum(sapply(allele_vector, is.na)), + "No" ) - if ((ncol(Database$Typing)-12) != length(allele_vector)) { + if ((ncol(Database$Typing)-13) != length(allele_vector)) { - cust_var <- dplyr::select(Database$Typing, 13:(ncol(Database$Typing) - length(allele_vector))) + cust_var <- dplyr::select(Database$Typing, 14:(ncol(Database$Typing) - length(allele_vector))) cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) class_df <- data.frame() @@ -262,7 +265,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= merged <- cbind(metadata, df_profile) - if ((ncol(Database$Typing)-12) != length(allele_vector)) { + if ((ncol(Database$Typing)-13) != length(allele_vector)) { names_vec <- character(0) # Add new columns to df1 for (i in 1:nrow(cust_var)) { @@ -283,7 +286,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= "City", "Typing Date", "Successes", - "Errors" + "Errors", + "Screened" ), names_vec, gsub(".fasta", "", basename(list.files(allele_folder))) @@ -303,7 +307,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= "City", "Typing Date", "Successes", - "Errors" + "Errors", + "Screened" ), gsub(".fasta", "", basename(list.files(allele_folder))) ) @@ -318,6 +323,42 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # Save new Entry in Typing Database saveRDS(Database, paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Typing.rds")) + if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + log_print(paste0("Saved assembly of ", basename(assembly))) + + } else { + + log_print("No isolate folder present yet. Isolate directory created.") + + # Create isolate filder for species + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates")) + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + log_print(paste0("Saved assembly of ", basename(assembly))) + } + # Logging successes log.message(log_file = paste0(getwd(), "/logs/script_log.txt"), message = paste0("Successful typing of ", sub("\\.(fasta|fna|fa)$", "", basename(assembly)))) diff --git a/execute/screening.sh b/execute/screening.sh index f0ed3d0..75b0351 100755 --- a/execute/screening.sh +++ b/execute/screening.sh @@ -44,11 +44,7 @@ fi mkdir "$base_path/execute/screening" -# Get cores -coresall=$(nproc --all) -cores=$((num_processors - 2)) - -amrfinder -n "$path_assembly" --threads $cores --plus --organism $species -o "screening/output_file.tsv" > amrfinder_stdout.txt 2> amrfinder_stderr.txt +amrfinder -n "$path_assembly" --plus --organism $species -o "screening/output_file.tsv" > amrfinder_stdout.txt 2> amrfinder_stderr.txt status=$? # Check if status variable is set and is an integer diff --git a/execute/single_eval.R b/execute/single_eval.R index 9b65f81..098a17d 100644 --- a/execute/single_eval.R +++ b/execute/single_eval.R @@ -3,7 +3,9 @@ library(logr) # Hand over variables meta_info <- readRDS("meta_info_single.rds") db_path <- readRDS("single_typing_df.rds")[, "db_path"] -assembly <- paste0(meta_info$db_directory, "/execute/blat_single/assembly.fasta") +file_list <- list.files(paste0(meta_info$db_directory, "/execute/blat_single"), + full.names = TRUE) +assembly <- file_list[which(list.files(paste0(meta_info$db_directory, "/execute/blat_single")) != "results")] source("variant_validation.R") @@ -147,7 +149,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= Database <- list(Typing = data.frame()) - Typing <- data.frame(matrix(NA, nrow = 0, ncol = 12 + length(psl_files))) + Typing <- data.frame(matrix(NA, nrow = 0, ncol = 13 + length(psl_files))) metadata <- c( 1, @@ -161,7 +163,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= meta_info$append_city, as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), - sum(sapply(allele_vector, is.na)) + sum(sapply(allele_vector, is.na)), + "No" ) new_row <- c(metadata, allele_vector) @@ -182,16 +185,17 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= "City", "Typing Date", "Successes", - "Errors" + "Errors", + "Screened" ), gsub(".fasta", "", basename(list.files(allele_folder))) ) Database[["Typing"]] <- Typing - df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 13:(12+length(list.files(allele_folder)))), function(x) as.character(x)) + df2 <- dplyr::mutate_all(dplyr::select(Database$Typing, 14:(13+length(list.files(allele_folder)))), function(x) as.character(x)) - df1 <- dplyr::select(Database$Typing, 1:12) + df1 <- dplyr::select(Database$Typing, 1:13) df1 <- dplyr::mutate(df1, Include = as.logical(Include)) Typing <- cbind(df1, df2) @@ -215,12 +219,13 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= meta_info$append_city, as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), - sum(sapply(allele_vector, is.na)) + sum(sapply(allele_vector, is.na)), + "No" ) - if ((ncol(Database$Typing)-12) != length(allele_vector)) { + if ((ncol(Database$Typing)-13) != length(allele_vector)) { - cust_var <- dplyr::select(Database$Typing, 13:(ncol(Database$Typing) - length(allele_vector))) + cust_var <- dplyr::select(Database$Typing, 14:(ncol(Database$Typing) - length(allele_vector))) cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) class_df <- data.frame() @@ -239,7 +244,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= merged <- cbind(metadata, df_profile) - if ((ncol(Database$Typing)-12) != length(allele_vector)) { + if ((ncol(Database$Typing)-13) != length(allele_vector)) { names_vec <- character(0) # Add new columns to df1 for (i in 1:nrow(cust_var)) { @@ -260,7 +265,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= "City", "Typing Date", "Successes", - "Errors" + "Errors", + "Screened" ), names_vec, gsub(".fasta", "", basename(list.files(allele_folder))) @@ -280,7 +286,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= "City", "Typing Date", "Successes", - "Errors" + "Errors", + "Screened" ), gsub(".fasta", "", basename(list.files(allele_folder))) ) @@ -300,6 +307,42 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= message = paste0("Successful typing of ", meta_info$assembly_name)) log_print(paste0("Successful typing of ", meta_info$assembly_name)) + if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + log_print(paste0("Saved assembly of ", meta_info$assembly_id)) + + } else { + + log_print("No isolate folder present yet. Isolate directory created.") + + # Create isolate filder for species + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates")) + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + log_print(paste0("Saved assembly of ", meta_info$assembly_id)) + } + } else { failures <- sum(unname(base::sapply(psl_files, file.size)) <= 100) / length(psl_files) * 100 diff --git a/execute/single_typing.sh b/execute/single_typing.sh index a41d05a..2b0490f 100755 --- a/execute/single_typing.sh +++ b/execute/single_typing.sh @@ -37,7 +37,7 @@ mkdir "$results" # Check assembly file and save in the execute folder Rscript "$base_path/execute/check_duplicate_single.R" wait -genome="$base_path/execute/blat_single/assembly.fasta" +genome="$base_path/execute/blat_single/$genome_name" # Run parallelized BLAT find "$alleles" -type f \( -name "*.fasta" -o -name "*.fa" -o -name "*.fna" \) | parallel pblat $genome {} "$results/{/.}.psl" > /dev/null 2>&1 diff --git a/execute/variant_validation.R b/execute/variant_validation.R index 9c9524e..8144843 100644 --- a/execute/variant_validation.R +++ b/execute/variant_validation.R @@ -104,7 +104,7 @@ variant_validation <- function(references, start_codons, stop_codons) { for(i in 1:nrow(references)){ # extract new variant sequence from template - contig <- template[(which(template == paste0(">", references$V14[i])) + 1)] + contig <- template[(which(sub(" .*", "", template) == paste0(">", references$V14[i])) + 1)] seq <- substring(contig, references$V16[i] + 1, references$V17[i]) diff --git a/www/body.css b/www/body.css index 28d78c4..127cbc5 100644 --- a/www/body.css +++ b/www/body.css @@ -724,9 +724,13 @@ background: #20E6E5; /* Typing */ - .mult_res_sel { - margin-bottom: 15px; - } +.mult_res_sel { + margin-bottom: 15px; +} + +#multi_typing_results .mult_res_sel .selectize-input.items.full.has-options.has-items { + width: auto; +} body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-today.is-selected > button{ color: white; From b34f4a30bc218d5c884754ef3b4c3d4a77677f58 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Sun, 4 Aug 2024 19:00:29 +0200 Subject: [PATCH 30/75] UI improvements; User feedback for multi typing; Robustified multi typing --- App.R | 1771 +++++++++++++++++++++++++++-------------- execute/multi_eval.R | 72 +- execute/single_eval.R | 72 +- www/body.css | 138 +++- 4 files changed, 1391 insertions(+), 662 deletions(-) diff --git a/App.R b/App.R index ecdf699..0107f47 100644 --- a/App.R +++ b/App.R @@ -549,11 +549,13 @@ ui <- dashboardPage( tabItem( tabName = "typing", - fluidRow(column( + fluidRow( + column( width = 3, align = "center", h2(p("Generate Allelic Profile"), style = "color:white") - )), + ) + ), hr(), uiOutput("typing_no_db"), conditionalPanel( @@ -563,7 +565,7 @@ ui <- dashboardPage( uiOutput("single_typing_progress"), column(1), uiOutput("metadata_single_box"), - column(width = 1), + column(1), uiOutput("start_typing_ui") ) ), @@ -5305,14 +5307,14 @@ ui <- dashboardPage( tabItem( tabName = "gs_screening", fluidRow( - column(1), column( width = 3, - align = "left", - h2(p("Gene Screening"), style = "color:white") + align = "center", + h2(p("Gene Screening"), style = "color:white; margin-bottom: -20px;") ), column( width = 7, + align = "left", uiOutput("gene_screening_info") ) ), @@ -5326,14 +5328,14 @@ ui <- dashboardPage( tabItem( tabName = "gs_profile", fluidRow( - column(1), column( width = 3, align = "left", - h2(p("Resistance Profiles"), style = "color:white") + h2(p("Resistance Profiles"), style = "color:white; margin-bottom: -20px") ), column( width = 7, + align = "left", uiOutput("gene_resistance_info") ) ), @@ -5671,6 +5673,29 @@ server <- function(input, output, session) { groups } + #Function to check for duplicate isolate IDs for multi typing start + dupl_mult_id <- reactive({ + req(Typing$multi_sel_table, DB$data) + if(!is.null(Typing$new_table)) { + selection <- Typing$new_table[which(unlist(Typing$new_table$Files) %in% unlist(DB$data["Assembly ID"])),] + as.numeric(rownames(selection[selection$Include == TRUE,])) + } else { + selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] + as.numeric(rownames(selection[selection$Include == TRUE,])) + } + }) + + dupl_mult_id_names <- reactive({ + req(Typing$multi_sel_table, DB$data) + if(!is.null(Typing$new_table)) { + selection <- Typing$new_table[which(unlist(Typing$new_table$Files) %in% unlist(DB$data["Assembly ID"])),] + selection$Files + } else { + selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] + selection$Files + } + }) + # Function to check single typing log file check_new_entry <- reactive({ @@ -5962,7 +5987,8 @@ server <- function(input, output, session) { br(), actionButton( "load", - "Create" + "Create", + class = "load-start" ) ) } else if(length(DB$available) > 0 & !(DB$select_new)) { @@ -5990,7 +6016,8 @@ server <- function(input, output, session) { br(), actionButton( "load", - "Load" + "Load", + class = "load-start" ) ) } else { @@ -6008,7 +6035,8 @@ server <- function(input, output, session) { br(), br(), actionButton( "load", - "Load" + "Load", + class = "load-start" ) ) } @@ -6039,7 +6067,8 @@ server <- function(input, output, session) { br(), actionButton( "load", - "Load" + "Load", + class = "load-start" ) ) } else { @@ -6057,7 +6086,8 @@ server <- function(input, output, session) { br(), br(), actionButton( "load", - "Load" + "Load", + class = "load-start" ) ) } @@ -6075,7 +6105,8 @@ server <- function(input, output, session) { br(), actionButton( "load", - "Load" + "Load", + class = "load-start" ) ) } @@ -6422,7 +6453,7 @@ server <- function(input, output, session) { text = "Gene Screening", tabName = "gene_screening", icon = icon("dna"), - startExpanded = FALSE, + startExpanded = TRUE, menuSubItem( text = "Screen Assembly", tabName = "gs_screening" @@ -6589,7 +6620,7 @@ server <- function(input, output, session) { text = "Gene Screening", tabName = "gene_screening", icon = icon("dna"), - startExpanded = FALSE, + startExpanded = TRUE, menuSubItem( text = "Screen Assembly", tabName = "gs_screening" @@ -6679,7 +6710,7 @@ server <- function(input, output, session) { text = "Gene Screening", tabName = "gene_screening", icon = icon("dna"), - startExpanded = FALSE, + startExpanded = TRUE, menuSubItem( text = "Screen Assembly", tabName = "gs_screening" @@ -6771,7 +6802,7 @@ server <- function(input, output, session) { text = "Gene Screening", tabName = "gene_screening", icon = icon("dna"), - startExpanded = FALSE, + startExpanded = TRUE, menuSubItem( text = "Screen Assembly", tabName = "gs_screening" @@ -6892,7 +6923,7 @@ server <- function(input, output, session) { text = "Gene Screening", tabName = "gene_screening", icon = icon("dna"), - startExpanded = FALSE, + startExpanded = TRUE, menuSubItem( text = "Screen Assembly", tabName = "gs_screening" @@ -7002,34 +7033,41 @@ server <- function(input, output, session) { output$initiate_typing_ui <- renderUI({ column( - width = 3, + width = 4, align = "center", br(), br(), - h3(p("Initiate Typing"), style = "color:white"), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly File') + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') ) ) ), - shinyFilesButton( - "genome_file", - "Browse", - icon = icon("folder-open"), - title = "Please select the genome in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - filetypes = c('fasta', 'fna', 'fa'), - root = path_home() - ), - br(), - br(), - uiOutput("genome_path") + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) ) }) @@ -7077,7 +7115,7 @@ server <- function(input, output, session) { text = "Gene Screening", tabName = "gene_screening", icon = icon("dna"), - startExpanded = FALSE, + startExpanded = TRUE, menuSubItem( text = "Screen Assembly", tabName = "gs_screening" @@ -8523,7 +8561,7 @@ server <- function(input, output, session) { align = "center", actionButton( "sel_all_entries", - "Select all", + "Select All", icon = icon("check") ) ), @@ -8532,7 +8570,7 @@ server <- function(input, output, session) { align = "left", actionButton( "desel_all_entries", - "Deselect all", + "Deselect All", icon = icon("xmark") ) ) @@ -22369,34 +22407,22 @@ server <- function(input, output, session) { # Availablity feedback output$gene_screening_info <- renderUI({ if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - fluidRow( - column( - width = 11, - align = "left", - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) - ) - ) + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) ) ) ) } else { - fluidRow( - column( - width = 11, - align = "left", - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) - ) - ) + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) ) ) ) @@ -22405,34 +22431,22 @@ server <- function(input, output, session) { output$gene_resistance_info <- renderUI({ if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - fluidRow( - column( - width = 11, - align = "left", - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) - ) - ) + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) ) ) ) } else { - fluidRow( - column( - width = 11, - align = "left", - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) - ) - ) + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) ) ) ) @@ -22825,33 +22839,41 @@ server <- function(input, output, session) { # Render Initiate Typing UI output$initiate_typing_ui <- renderUI({ column( - width = 3, + width = 4, align = "center", br(), br(), - h3(p("Initiate Typing"), style = "color:white"), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly File (FASTA)') + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') ) ) ), - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path") + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) ) }) @@ -22860,7 +22882,7 @@ server <- function(input, output, session) { observe({ if (nrow(Typing$single_path) < 1) { output$genome_path <- renderUI(HTML( - paste("", "No file selected.") + paste("", "No file selected.") )) # dont show subsequent metadata declaration and typing start UI @@ -22877,7 +22899,7 @@ server <- function(input, output, session) { output$genome_path <- renderUI({ HTML( paste( - "", + "", as.character(Typing$single_path$name) ) ) @@ -22893,157 +22915,158 @@ server <- function(input, output, session) { column( width = 3, align = "center", - br(), - br(), - h3(p("Declare Metadata"), style = "color:white"), - br(), - br(), - box( - solidHeader = TRUE, - status = "primary", - width = "90%", - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("assembly_id", - value = "", - label = "", - width = "80%") + br(), br(), + h3(p("Declare Metadata"), style = "color:white; margin-left:-40px"), + br(), br(), + div( + class = "multi_meta_box", + box( + solidHeader = TRUE, + status = "primary", + width = "90%", + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("assembly_id", + value = "", + label = "", + width = "80%") + ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("assembly_name", - label = "", - width = "80%") + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("assembly_name", + label = "", + width = "80%") + ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - div( - class = "append_table", - dateInput("append_isodate", - label = "", - width = "80%", - max = Sys.Date()) + fluidRow( + column( + width = 5, + align = "left", + h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + dateInput("append_isodate", + label = "", + width = "80%", + max = Sys.Date()) + ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_host", - label = "", - width = "80%") + fluidRow( + column( + width = 5, + align = "left", + h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_host", + label = "", + width = "80%") + ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - div( - class = "append_table_country", - pickerInput( - "append_country", - label = "", - choices = list("Common" = sel_countries, - "All Countries" = country_names), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "90%" + fluidRow( + column( + width = 5, + align = "left", + h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table_country", + pickerInput( + "append_country", + label = "", + choices = list("Common" = sel_countries, + "All Countries" = country_names), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "90%" + ) ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput( - "append_city", - label = "", - width = "80%" + fluidRow( + column( + width = 5, + align = "left", + h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput( + "append_city", + label = "", + width = "80%" + ) ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - actionButton( - inputId = "conf_meta_single", - label = "Confirm" + fluidRow( + column( + width = 5, + align = "left", + h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") ), - br() - ) - ), - br() - ) + column( + width = 7, + align = "left", + h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + actionButton( + inputId = "conf_meta_single", + label = "Confirm" + ), + br() + ) + ), + br() + ) + ) ) }) } else { @@ -23150,6 +23173,7 @@ server <- function(input, output, session) { single_typing_df <- data.frame( db_path = DB$database, wd = getwd(), + save = input$save_assembly_st, scheme = paste0(gsub(" ", "_", DB$scheme)), genome = Typing$single_path$datapath, alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", search_string) @@ -23359,7 +23383,6 @@ server <- function(input, output, session) { #### Declare Metadata ---- observeEvent(input$conf_meta_single, { - log_print("Single typing metadata confirmed") if(nchar(trimws(input$assembly_id)) < 1) { ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) @@ -23373,57 +23396,87 @@ server <- function(input, output, session) { ass_name <- trimws(input$assembly_name) } - meta_info <- data.frame(assembly_id = ass_id, - assembly_name = ass_name, - cgmlst_typing = DB$scheme, - append_isodate = input$append_isodate, - append_host = trimws(input$append_host), - append_country = trimws(input$append_country), - append_city = trimws(input$append_city), - append_analysisdate = Sys.Date(), - db_directory = getwd()) - - saveRDS(meta_info, paste0( - getwd(), - "/execute/meta_info_single.rds" - )) - - show_toast( - title = "Metadata declared", - type = "success", - position = "bottom-end", - timer = 3000, - width = "500px" - ) - - # Render Start Typing UI - - output$start_typing_ui <- renderUI({ - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Start Typing"), style = "color:white"), - br(), - br(), - HTML( - paste( - "", - "Typing by ", - DB$scheme, - " scheme." + if(ass_id %in% unlist(DB$data["Assembly ID"])) { + show_toast( + title = "Assembly ID already present", + type = "error", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + } else { + + log_print("Single typing metadata confirmed") + + meta_info <- data.frame(assembly_id = ass_id, + assembly_name = ass_name, + cgmlst_typing = DB$scheme, + append_isodate = input$append_isodate, + append_host = trimws(input$append_host), + append_country = trimws(input$append_country), + append_city = trimws(input$append_city), + append_analysisdate = Sys.Date(), + db_directory = getwd()) + + saveRDS(meta_info, paste0( + getwd(), + "/execute/meta_info_single.rds" + )) + + show_toast( + title = "Metadata declared", + type = "success", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + + # Render Start Typing UI + + output$start_typing_ui <- renderUI({ + div( + class = "multi_start_col", + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Start Typing"), style = "color:white"), + br(), + br(), + HTML( + paste( + "", + "Typing by ", + DB$scheme, + " scheme." + ) + ), + br(), br(), br(), br(), + div( + class = "save-assembly", + materialSwitch( + "save_assembly_st", + h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), + value = TRUE, + right = TRUE) + ), + HTML( + paste( + "", + "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." + ) + ), + br(), br(), br(), br(), + actionButton( + inputId = "typing_start", + label = "Start", + icon = icon("circle-play") + ) ) - ), - br(), br(), - actionButton( - inputId = "typing_start", - label = "Start", - icon = icon("circle-play") ) - ) - }) - + }) + } }) #### Events Single Typing ---- @@ -23460,33 +23513,41 @@ server <- function(input, output, session) { output$initiate_typing_ui <- renderUI({ column( - width = 3, + width = 4, align = "center", br(), br(), - h3(p("Initiate Typing"), style = "color:white"), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly File (FASTA)') + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') ) ) ), - shinyFilesButton( - "genome_file", - "Browse", - icon = icon("folder-open"), - title = "Please select the genome in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path") + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) ) }) }) @@ -23515,40 +23576,47 @@ server <- function(input, output, session) { #### Render Multi Typing UI Elements ---- output$initiate_multi_typing_ui <- renderUI({ column( - width = 3, + width = 4, align = "center", br(), br(), - h3(p("Initiate Typing"), style = "color:white"), - br(), - br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly Folder') + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') ) ) ), - column( - width = 12, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) ), - column( - width = 12, - align = "left", - rHandsontableOutput("multi_select_table") + uiOutput("multi_select_tab_ctrls"),# + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) ) ) }) @@ -23557,29 +23625,91 @@ server <- function(input, output, session) { output$multi_select_info <- renderUI({ if(!is.null(Typing$multi_path)) { if(length(Typing$multi_path) < 1) { - HTML(paste("", + HTML(paste("", "No files selected.")) } else { - if(!is.null(Typing$multi_sel_table)) { - if(sum(Typing$multi_sel_table$Include == TRUE) < 1) { - HTML(paste("", - "No files selected.")) - } else { - req(Typing$genome_selected) - HTML(paste("", - sum(Typing$genome_selected$Include == TRUE), - " files selected.")) - } - } + HTML(paste("", + sum(Typing$genome_selected$Include == TRUE), + " files selected.")) } } }) + # Render multi selection table issues + output$multi_select_issues <- renderUI({ + req(Typing$multi_sel_table, Typing$genome_selected, input$multi_select_table) + if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) & + any(duplicated(hot_to_r(input$multi_select_table)$Files))){ + HTML( + paste( + paste("", + "Some name(s) are already present in local database.
"), + paste("", + "Duplicated name(s).
") + ) + ) + } else if (any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) & + !any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + HTML( + paste("", + "Some name(s) are already present in local database.
") + ) + } else if (!any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) & + any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + HTML( + paste("", + "Duplicated name(s).
") + ) + } + }) + + output$multi_select_issue_info <- renderUI({ + req(Typing$multi_sel_table, Typing$genome_selected, input$multi_select_table) + if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) | + any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + HTML( + paste("", + "Rename highlighted isolates.") + ) + } + }) + # Render Metadata Select Box after Folder selection observe({ if(!is.null(Typing$multi_sel_table)) { if (nrow(Typing$multi_sel_table) > 0) { + output$multi_select_tab_ctrls <- renderUI( + fluidRow( + column(1), + column( + width = 2, + align = "left", + actionButton( + "sel_all_mt", + "All", + icon = icon("check") + ) + ), + column( + width = 2, + align = "left", + actionButton( + "desel_all_mt", + "None", + icon = icon("xmark") + ) + ), + column(2), + column( + width = 5, + align = "right", + br(), + uiOutput("multi_select_issues") + ) + ) + ) + Typing$genome_selected <- hot_to_r(input$multi_select_table) output$metadata_multi_box <- renderUI({ @@ -23588,140 +23718,143 @@ server <- function(input, output, session) { align = "center", br(), br(), - h3(p("Declare Metadata"), style = "color:white"), + h3(p("Declare Metadata"), style = "color:white;margin-left:-40px"), br(), br(), - box( - solidHeader = TRUE, - status = "primary", - width = "90%", - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") + div( + class = "multi_meta_box", + box( + solidHeader = TRUE, + status = "primary", + width = "90%", + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) ), - column( - width = 7, - align = "left", - h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) ), - column( - width = 7, - align = "left", - div( - class = "append_table", - dateInput("append_isodate_multi", - label = "", - width = "80%", - max = Sys.Date()) + fluidRow( + column( + width = 5, + align = "left", + h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + dateInput("append_isodate_multi", + label = "", + width = "80%", + max = Sys.Date()) + ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_host_multi", - label = "", - width = "80%") + fluidRow( + column( + width = 5, + align = "left", + h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_host_multi", + label = "", + width = "80%") + ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - div( - class = "append_table_country", - pickerInput( - "append_country_multi", - label = "", - choices = list("Common" = sel_countries, - "All Countries" = country_names), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "90%" - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") + fluidRow( + column( + width = 5, + align = "left", + h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table_country", + pickerInput( + "append_country_multi", + label = "", + choices = list("Common" = sel_countries, + "All Countries" = country_names), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "90%" + ) + ) + ) ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_city_multi", - label = "", - width = "80%") + fluidRow( + column( + width = 5, + align = "left", + h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_city_multi", + label = "", + width = "80%") + ) ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") ), - column( - width = 7, - align = "left", - h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - actionButton( - inputId = "conf_meta_multi", - label = "Confirm" + fluidRow( + column( + width = 5, + align = "left", + h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") ), - br() + column( + width = 7, + align = "left", + h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + actionButton( + inputId = "conf_meta_multi", + label = "Confirm" + ), + br(), br(), + uiOutput("multi_select_issue_info") + ) ) - ), - br() + ) ) ) }) @@ -23743,96 +23876,551 @@ server <- function(input, output, session) { Typing$multi_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi) - multi_sel_table <- data.frame(Include = rep(TRUE, length(list.files(as.character(Typing$multi_path)))), - Files = list.files(as.character(Typing$multi_path))) - - Typing$multi_sel_table <- multi_sel_table[which(grepl("\\.fasta|\\.fna|\\.fa", multi_sel_table$Files)),] - - if (between(nrow(Typing$multi_sel_table), 1, 15)) { - output$multi_select_table <- renderRHandsontable({ - rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", contextMenu = FALSE) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = TRUE, - valign = "htBottom") %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - }) + selected_files <- list.files(as.character(Typing$multi_path))[which(!endsWith(list.files(as.character(Typing$multi_path)), ".gz"))] + + Typing$multi_sel_table <- data.frame( + Include = rep(TRUE, length(selected_files)), + Files = gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", + selected_files), + Type = sub(".*(\\.fasta|\\.fasta\\.gz|\\.fna|\\.fna\\.gz|\\.fa|\\.fa\\.gz)$", + "\\1", selected_files, perl = F)) + + if(nrow(Typing$multi_sel_table) > 0) { + output$multi_select_tab_ctrls <- renderUI( + fluidRow( + column(1), + column( + width = 2, + align = "left", + actionButton( + "sel_all_mt", + "All", + icon = icon("check") + ) + ), + column( + width = 2, + align = "left", + actionButton( + "desel_all_mt", + "None", + icon = icon("xmark") + ) + ), + column(2), + column( + width = 5, + align = "left", + uiOutput("multi_select_issues") + ) + ) + ) + } else { + output$multi_select_tab_ctrls <- NULL + } + + if (between(nrow(Typing$multi_sel_table), 1, 15)) { + if(!is.null(Typing$new_table)) { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$new_table, rowHeaders = NULL, + stretchH = "all", contextMenu = FALSE + ) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, + readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()))) + }) + } else { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", contextMenu = FALSE + ) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, + readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()))) + }) + } } else if(nrow(Typing$multi_sel_table) > 15) { - output$multi_select_table <- renderRHandsontable({ - rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", height = 500, - contextMenu = FALSE) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = TRUE, - valign = "htBottom") %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - }) + if(!is.null(Typing$new_table)) { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$new_table, rowHeaders = NULL, + stretchH = "all", height = 500, + contextMenu = FALSE + ) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, + readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()))) + }) + } else { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", height = 500, + contextMenu = FALSE + ) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, + readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()), + jsonlite::toJSON(dupl_mult_id_names()))) + + }) + } } else { output$multi_select_table <- NULL } }) observeEvent(input$conf_meta_multi, { - log_print("Multi typing metadata confirmed") - meta_info <- data.frame(cgmlst_typing = DB$scheme, - append_isodate = trimws(input$append_isodate_multi), - append_host = trimws(input$append_host_multi), - append_country = trimws(input$append_country_multi), - append_city = trimws(input$append_city_multi), - append_analysisdate = Sys.Date(), - db_directory = getwd()) + Typing$new_table <- mutate(hot_to_r(input$multi_select_table), + Include = as.logical(Include)) - saveRDS(meta_info, paste0(getwd(), "/execute/meta_info.rds")) - - show_toast( - title = "Metadata declared", - type = "success", - position = "bottom-end", - timer = 3000, - width = "500px" - ) - - output$start_multi_typing_ui <- renderUI({ - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Start Typing"), style = "color:white"), - br(), - br(), - HTML( - paste( - "", - "Typing by ", - DB$scheme, - " scheme." + if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", Typing$genome_selected[which(Typing$genome_selected$Include == TRUE),]$Files)) %in% unlist(DB$data["Assembly ID"]))) { + show_toast( + title = "Assembly ID(s) already present", + type = "error", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + } else if (any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + show_toast( + title = "Duplicated file name(s)", + type = "error", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + } else if (any(hot_to_r(input$multi_select_table)$Files == "")) { + show_toast( + title = "Empty file name(s)", + type = "error", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + } + else if (any(grepl("[/\\:*?\"<>|]", hot_to_r(input$multi_select_table)$Files))) { + show_toast( + title = "Invalid file name(s). Not allowed: /\\:*?\"<>|", + type = "error", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + } + else if (!any(hot_to_r(input$multi_select_table)$Include == TRUE)) { + show_toast( + title = "No files selected", + type = "error", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + } + else { + + log_print("Multi typing metadata confirmed") + + meta_info <- data.frame(cgmlst_typing = DB$scheme, + append_isodate = trimws(input$append_isodate_multi), + append_host = trimws(input$append_host_multi), + append_country = trimws(input$append_country_multi), + append_city = trimws(input$append_city_multi), + append_analysisdate = Sys.Date(), + db_directory = getwd()) + + saveRDS(meta_info, paste0(getwd(), "/execute/meta_info.rds")) + + show_toast( + title = "Metadata declared", + type = "success", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + + output$start_multi_typing_ui <- renderUI({ + div( + class = "multi_start_col", + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Start Typing"), style = "color:white"), + br(), + br(), + HTML( + paste( + "", + "Typing by ", + DB$scheme, + " scheme." + ) + ), + br(), br(), br(), br(), + div( + class = "save-assembly", + materialSwitch( + "save_assembly_mt", + h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), + value = TRUE, + right = TRUE) + ), + HTML( + paste( + "", + "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." + ) + ), + br(), br(), br(), br(), + actionButton( + "start_typ_multi", + "Start", + icon = icon("circle-play") + ) ) - ), - br(), br(), - actionButton( - "start_typ_multi", - "Start", - icon = icon("circle-play") ) - ) - }) - + }) + } }) #### Events Multi Typing ---- + observeEvent(input$sel_all_mt, { + session$sendCustomMessage(type = "setColumnValue", message = list(value = TRUE)) + }) + + observeEvent(input$desel_all_mt, { + session$sendCustomMessage(type = "setColumnValue", message = list(value = FALSE)) + }) + # Print Log output$print_log <- downloadHandler( filename = function() { @@ -23880,40 +24468,46 @@ server <- function(input, output, session) { output$initiate_multi_typing_ui <- renderUI({ column( - width = 3, + width = 4, align = "center", br(), br(), - h3(p("Initiate Typing"), style = "color:white"), + h3(p("Initiate Typing"), style = "color:white, margin-left: 15px"), br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly Folder') + tags$span(style='color: white; font-size: 15px; margin-left: 15px', 'Select Assembly Folder') ) ) ), - column( - width = 12, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) ), - column( - width = 12, - align = "left", - rHandsontableOutput("multi_select_table") + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) ) ) }) @@ -23961,40 +24555,46 @@ server <- function(input, output, session) { output$initiate_multi_typing_ui <- renderUI({ column( - width = 3, + width = 4, align = "center", br(), br(), - h3(p("Initiate Typing"), style = "color:white"), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly Folder') + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') ) ) ), - column( - width = 12, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Please select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) ), - column( - width = 12, - align = "left", - rHandsontableOutput("multi_select_table") + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) ) ) }) @@ -24044,6 +24644,8 @@ server <- function(input, output, session) { width = "500px" ) + Typing$new_table <- NULL + # Remove Allelic Typing Controls output$initiate_multi_typing_ui <- NULL output$metadata_multi_box <- NULL @@ -24062,6 +24664,7 @@ server <- function(input, output, session) { multi_typing_df <- data.frame( db_path = DB$database, wd = getwd(), + save = input$save_assembly_mt, scheme = paste0(gsub(" ", "_", DB$scheme)), genome_folder = as.character(parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi)), genome_names = paste(Typing$genome_selected$Files[which(Typing$genome_selected$Include == TRUE)], collapse= " "), diff --git a/execute/multi_eval.R b/execute/multi_eval.R index 6a12612..97c2a0d 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -2,6 +2,7 @@ library(logr) meta_info <- readRDS("meta_info.rds") db_path <- readRDS("multi_typing_df.rds")[, "db_path"] +save_assembly <- readRDS("multi_typing_df.rds")[, "save"] assembly_folder <- dir(paste0(getwd(), "/selected_genomes"), full.names = TRUE) assembly <- assembly_folder[which(commandArgs(trailingOnly = TRUE)[1] == basename(assembly_folder))] results_folder <- dir(paste0(meta_info$db_directory, "/execute/blat_multi/results"), full.names = TRUE) @@ -323,40 +324,43 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # Save new Entry in Typing Database saveRDS(Database, paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Typing.rds")) - if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { - - # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) - - # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) - - log_print(paste0("Saved assembly of ", basename(assembly))) - - } else { - - log_print("No isolate folder present yet. Isolate directory created.") - - # Create isolate filder for species - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates")) - - # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) - - # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) - - log_print(paste0("Saved assembly of ", basename(assembly))) + # Save assembly file if TRUE + if(save_assembly) { + if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + log_print(paste0("Saved assembly of ", basename(assembly))) + + } else { + + log_print("No isolate folder present yet. Isolate directory created.") + + # Create isolate filder for species + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates")) + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly))) + + log_print(paste0("Saved assembly of ", basename(assembly))) + } } # Logging successes diff --git a/execute/single_eval.R b/execute/single_eval.R index 098a17d..abbe0fb 100644 --- a/execute/single_eval.R +++ b/execute/single_eval.R @@ -3,6 +3,7 @@ library(logr) # Hand over variables meta_info <- readRDS("meta_info_single.rds") db_path <- readRDS("single_typing_df.rds")[, "db_path"] +save_assembly <- readRDS("multi_typing_df.rds")[, "save"] file_list <- list.files(paste0(meta_info$db_directory, "/execute/blat_single"), full.names = TRUE) assembly <- file_list[which(list.files(paste0(meta_info$db_directory, "/execute/blat_single")) != "results")] @@ -307,40 +308,43 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= message = paste0("Successful typing of ", meta_info$assembly_name)) log_print(paste0("Successful typing of ", meta_info$assembly_name)) - if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { - - # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) - - # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) - - log_print(paste0("Saved assembly of ", meta_info$assembly_id)) - - } else { - - log_print("No isolate folder present yet. Isolate directory created.") - - # Create isolate filder for species - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates")) - - # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) - - # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) - - log_print(paste0("Saved assembly of ", meta_info$assembly_id)) + # Save assembly file if TRUE + if(save_assembly) { + if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + log_print(paste0("Saved assembly of ", meta_info$assembly_id)) + + } else { + + log_print("No isolate folder present yet. Isolate directory created.") + + # Create isolate filder for species + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates")) + + # Create folder for new isolate + dir.create(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + # Copy assembly file in isolate directory + file.copy(assembly, paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", meta_info$assembly_id)) + + log_print(paste0("Saved assembly of ", meta_info$assembly_id)) + } } } else { diff --git a/www/body.css b/www/body.css index 127cbc5..696f955 100644 --- a/www/body.css +++ b/www/body.css @@ -85,6 +85,22 @@ label { font-size: 16px; } +.pretty input:checked~.state.p-primary label:after, .pretty.p-toggle .state.p-primary label:after { + background-color: #20E6E5 !important; +} + +.irs--shiny .irs-bar { + border-color: #20E6E5; + background: #20E6E5; +} + +.irs--shiny .irs-to, +.irs--shiny .irs-from, +.irs--shiny .irs-single{ + background-color: #20E6E5; + color: black; +} + .main-sidebar .sidebar .sidebar-menu .treeview-menu a { color: #ffffff !important; margin-left: 25px; @@ -224,6 +240,10 @@ left: -20px; border: 1px solid white; } +#db_location { + width: 121px +} + .irs.irs--shiny.js-irs-0 { margin-right: -15px; } @@ -276,7 +296,7 @@ margin-top: -15px; } button#load.pulsating-button.btn.btn-default.action-button.shiny-bound-input { -background: #20E6E5; + background: #20E6E5; color: #000000; width: 40px; } @@ -286,13 +306,31 @@ background: #20E6E5; } #load .fas.fa-rotate { -position: relative; -left: 0px !important; + position: relative; + left: 0px !important; } +.load-start { + width: 150px; + font-size: 17px; + overflow: hidden; + box-shadow: 0px 0px 20px 10px rgba(255, 255, 255, 0.23); + transition: box-shadow 0.5s ease; + border: none; + height: 45px; + z-index: 0; +} + +.load-start:hover { + background: #3c8c56 !important; + border: none; + color: white !important; + box-shadow: 0px 0px 20px 15px rgba(40, 47, 56, 1); +} + + .shiny-input-container input[type="text"] { border-radius: 5px; - } .box.box-solid.box-primary>.box-header { @@ -459,10 +497,18 @@ left: -6px; } /* Icons */ - - i.fas { - margin-right: 5px; - } + +i.fa-solid .fa-arrow-right-long { + font-size: 30px; + color: white; + position: relative; + top: -38px; + left: 300px; +} + +i.fas { + margin-right: 5px; +} i.greenstatus.fa-solid.fa-circle-dot. { lightgreen @@ -539,6 +585,11 @@ top: 1px !important; border-color: white; } +#genome_file_multi, +#genome_file { + margin-left: -30px; +} + .btn-default:hover { border-color: transparent !important; } @@ -723,11 +774,34 @@ background: #20E6E5; } /* Typing */ + +#sel_all_mt { + margin-left: 10px; +} + +#sel_all_mt, +#desel_all_mt{ + margin-top: 27px; + margin-bottom: 25px; +} + +#multi_select_issues { + margin-top: 5px; +} .mult_res_sel { margin-bottom: 15px; } +.multi_meta_box { + margin-left: -40px; +} + +.multi_start_col { + position: relative; + left: -40px; +} + #multi_typing_results .mult_res_sel .selectize-input.items.full.has-options.has-items { width: auto; } @@ -1166,7 +1240,7 @@ top: -10px; .material-switch>label.switch:before { background: #20e6e559 !important; - border-radius: 8px; + border-radius: 8px; content: ""; height: 13px; margin-top: -10px; @@ -1177,15 +1251,43 @@ top: -10px; border: 1px solid transparent; } +.save-assembly .material-switch>label.switch:before { + background: #20e6e559 !important; + border-radius: 8px; + content: ""; + height: 13px; + left: -10px; + margin-top: -10px; + opacity: 1; + position: absolute; + width: 40px; + transition: all 0.3s ease-in-out; + border: 1px solid transparent; +} + .material-switch>label.switch:hover:before { border: 1px solid #20e6e5; } .material-switch>input[type=checkbox]:checked+label.switch:before { background: #20e6e5 !important; - border-radius: 8px; + border-radius: 8px; + content: ""; + height: 13px; + margin-top: -10px; + opacity: 1; + position: absolute; + width: 40px; + transition: all 0.3s ease-in-out; + border: 1px solid #20e6e559; +} + +.save-assembly .material-switch>input[type=checkbox]:checked+label.switch:before { + background: #20e6e5 !important; + border-radius: 8px; content: ""; height: 13px; + left: -10px; margin-top: -10px; opacity: 1; position: absolute; @@ -1214,6 +1316,22 @@ top: -10px; border: 1px solid transparent; } +.save-assembly .material-switch>label.switch:after { + background: #E6E6E6 !important; + border-radius: 1pc; + box-shadow: 0 0 5px rgba(0,0,0,.3); + content: ""; + height: 20px; + opacity: 1; + left: -20px; + margin-top: -10px; + position: absolute; + top: -4px; + transition: all 0.3s ease-in-out; + width: 20px; + border: 1px solid transparent; +} + .material-switch>label.switch:hover:after { border: 1px solid #20e6e5 !important; } From e841ac723f4e82ba74b68973b037f328e870ca6b Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Sun, 4 Aug 2024 19:15:46 +0200 Subject: [PATCH 31/75] Fix in multi metadata confirmation --- App.R | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/App.R b/App.R index 0107f47..d6280c7 100644 --- a/App.R +++ b/App.R @@ -23642,7 +23642,7 @@ server <- function(input, output, session) { any(duplicated(hot_to_r(input$multi_select_table)$Files))){ HTML( paste( - paste("", + paste("", "Some name(s) are already present in local database.
"), paste("", "Duplicated name(s).
") @@ -24300,6 +24300,10 @@ server <- function(input, output, session) { Typing$new_table <- mutate(hot_to_r(input$multi_select_table), Include = as.logical(Include)) + ahaaa <<- hot_to_r(input$multi_select_table) + + multi_select_table <<- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] + if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", Typing$genome_selected[which(Typing$genome_selected$Include == TRUE),]$Files)) %in% unlist(DB$data["Assembly ID"]))) { show_toast( title = "Assembly ID(s) already present", @@ -24308,7 +24312,7 @@ server <- function(input, output, session) { timer = 3000, width = "500px" ) - } else if (any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + } else if (any(duplicated(multi_select_table$Files))) { show_toast( title = "Duplicated file name(s)", type = "error", @@ -24316,7 +24320,7 @@ server <- function(input, output, session) { timer = 3000, width = "500px" ) - } else if (any(hot_to_r(input$multi_select_table)$Files == "")) { + } else if (any(multi_select_table$Files == "")) { show_toast( title = "Empty file name(s)", type = "error", @@ -24325,7 +24329,7 @@ server <- function(input, output, session) { width = "500px" ) } - else if (any(grepl("[/\\:*?\"<>|]", hot_to_r(input$multi_select_table)$Files))) { + else if (any(grepl("[/\\:*?\"<>|]", multi_select_table$Files))) { show_toast( title = "Invalid file name(s). Not allowed: /\\:*?\"<>|", type = "error", @@ -24334,7 +24338,7 @@ server <- function(input, output, session) { width = "500px" ) } - else if (!any(hot_to_r(input$multi_select_table)$Include == TRUE)) { + else if (!any(multi_select_table$Include == TRUE)) { show_toast( title = "No files selected", type = "error", From ba03ee7f36879d6b31954f46d8897fc650626966 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Sun, 4 Aug 2024 19:20:39 +0200 Subject: [PATCH 32/75] Disallow editing of entry table Assembly ID --- App.R | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/App.R b/App.R index d6280c7..7e5763f 100644 --- a/App.R +++ b/App.R @@ -7788,6 +7788,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), @@ -7890,6 +7891,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% hot_col(3, validator = " @@ -8046,6 +8048,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), @@ -8190,6 +8193,7 @@ server <- function(input, output, session) { hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(3, validator = " function(value, callback) { try { @@ -8341,6 +8345,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% hot_col(3, validator = " @@ -9819,6 +9824,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), @@ -9921,6 +9927,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), @@ -10077,6 +10084,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), @@ -10221,6 +10229,7 @@ server <- function(input, output, session) { hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% + hot_col(3, readOnly = TRUE) %>% hot_col(3, validator = " function(value, callback) { try { @@ -10374,6 +10383,7 @@ server <- function(input, output, session) { halign = "htCenter") %>% hot_col(c(1, 5, 10, 11, 12), readOnly = TRUE) %>% + hot_col(3, readOnly = TRUE) %>% hot_col(3, validator = " function(value, callback) { try { @@ -24300,9 +24310,7 @@ server <- function(input, output, session) { Typing$new_table <- mutate(hot_to_r(input$multi_select_table), Include = as.logical(Include)) - ahaaa <<- hot_to_r(input$multi_select_table) - - multi_select_table <<- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] + multi_select_table <- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", Typing$genome_selected[which(Typing$genome_selected$Include == TRUE),]$Files)) %in% unlist(DB$data["Assembly ID"]))) { show_toast( From 675b68b1c4975300a57ab612a04a41a435b662d8 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Mon, 5 Aug 2024 12:43:37 +0200 Subject: [PATCH 33/75] Fixes in multi typing file selection & UI --- App.R | 164 +++++++++++++++++++++++++++++++++++------------- www/resources.R | 2 + 2 files changed, 124 insertions(+), 42 deletions(-) diff --git a/App.R b/App.R index 7e5763f..79a0d05 100644 --- a/App.R +++ b/App.R @@ -5330,7 +5330,7 @@ ui <- dashboardPage( fluidRow( column( width = 3, - align = "left", + align = "center", h2(p("Resistance Profiles"), style = "color:white; margin-bottom: -20px") ), column( @@ -6128,8 +6128,11 @@ server <- function(input, output, session) { log_print("Input load") + # reset typing status on start( if(Typing$status == "Finalized") {Typing$status <- "Inactive"} - + if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} + if(!is.null(Screening$single_path)) {Screening$single_path <- data.frame()} + #### Render status bar ---- observe({ req(DB$scheme) @@ -6495,6 +6498,14 @@ server <- function(input, output, session) { output$download_scheme_info <- NULL output$download_loci <- NULL output$entry_table_controls <- NULL + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$test_yes_pending <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL } } else { log_print(paste0("Loading existing ", input$scheme_db, " database from ", DB$database)) @@ -6530,6 +6541,16 @@ server <- function(input, output, session) { output$tree_nj <- NULL output$tree_upgma <- NULL + # null typing initiation UI + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$test_yes_pending <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + # null report values Report$report_list_mst <- list() Report$report_list_nj <- list() @@ -7071,6 +7092,53 @@ server <- function(input, output, session) { ) }) + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"),# + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + if(!anyNA(DB$allelic_profile)) { # no NA's -> dont render missing values sidebar elements @@ -9284,6 +9352,14 @@ server <- function(input, output, session) { output$missing_values <- NULL output$delete_box <- NULL output$entry_table_controls <- NULL + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$test_yes_pending <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL } } @@ -11667,34 +11743,33 @@ server <- function(input, output, session) { ) }) - # Download Target Info (CSV Table)# - #TODO - # observe({ - # input$download_cgMLST - # - # scheme_overview <- read_html(Scheme$link_scheme) %>% - # html_table(header = FALSE) %>% - # as.data.frame(stringsAsFactors = FALSE) - # - # last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], - # format = "%B %d, %Y, %H:%M %p") - # names(scheme_overview) <- NULL - # - # last_file_change <- format( - # file.info(file.path(DB$database, - # ".downloaded_schemes", - # paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") - # - # output$cgmlst_scheme <- renderTable({scheme_overview}) - # output$scheme_update_info <- renderText({ - # req(last_file_change) - # if (last_file_change < last_scheme_change) { - # "(Newer scheme available \u274c)" - # } else { - # "(Scheme is up-to-date \u2705)" - # } - # }) - # }) + # Download Target Info (CSV Table) + observe({ + input$download_cgMLST + + scheme_overview <- read_html(Scheme$link_scheme) %>% + html_table(header = FALSE) %>% + as.data.frame(stringsAsFactors = FALSE) + + last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], + format = "%B %d, %Y, %H:%M %p") + names(scheme_overview) <- NULL + + last_file_change <- format( + file.info(file.path(DB$database, + ".downloaded_schemes", + paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") + + output$cgmlst_scheme <- renderTable({scheme_overview}) + output$scheme_update_info <- renderText({ + req(last_file_change) + if (last_file_change < last_scheme_change) { + "(Newer scheme available \u274c)" + } else { + "(Scheme is up-to-date \u2705)" + } + }) + }) # _______________________ #### @@ -23886,14 +23961,16 @@ server <- function(input, output, session) { Typing$multi_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi) - selected_files <- list.files(as.character(Typing$multi_path))[which(!endsWith(list.files(as.character(Typing$multi_path)), ".gz"))] + files_selected <- list.files(as.character(Typing$multi_path)) + files_filtered <- files_selected[which(!endsWith(files_selected, ".gz") & + grepl("\\.fasta|\\.fna|\\.fa", files_selected))] Typing$multi_sel_table <- data.frame( - Include = rep(TRUE, length(selected_files)), + Include = rep(TRUE, length(files_filtered)), Files = gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", - selected_files), + files_filtered), Type = sub(".*(\\.fasta|\\.fasta\\.gz|\\.fna|\\.fna\\.gz|\\.fa|\\.fa\\.gz)$", - "\\1", selected_files, perl = F)) + "\\1", files_filtered, perl = F)) if(nrow(Typing$multi_sel_table) > 0) { output$multi_select_tab_ctrls <- renderUI( @@ -23920,7 +23997,8 @@ server <- function(input, output, session) { column(2), column( width = 5, - align = "left", + align = "right", + br(), uiOutput("multi_select_issues") ) ) @@ -24312,7 +24390,7 @@ server <- function(input, output, session) { multi_select_table <- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] - if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", Typing$genome_selected[which(Typing$genome_selected$Include == TRUE),]$Files)) %in% unlist(DB$data["Assembly ID"]))) { + if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", multi_select_table$Files)) %in% unlist(DB$data["Assembly ID"]))) { show_toast( title = "Assembly ID(s) already present", type = "error", @@ -24484,13 +24562,12 @@ server <- function(input, output, session) { align = "center", br(), br(), - h3(p("Initiate Typing"), style = "color:white, margin-left: 15px"), - br(), - br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-left: 15px', 'Select Assembly Folder') + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') ) ) ), @@ -24513,6 +24590,8 @@ server <- function(input, output, session) { br() ) ), + uiOutput("multi_select_tab_ctrls"),# + br(), fluidRow( column(1), column( @@ -24572,8 +24651,7 @@ server <- function(input, output, session) { br(), br(), h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), + br(), br(), p( HTML( paste( @@ -24600,6 +24678,8 @@ server <- function(input, output, session) { br() ) ), + uiOutput("multi_select_tab_ctrls"),# + br(), fluidRow( column(1), column( diff --git a/www/resources.R b/www/resources.R index fc46c7f..812f092 100644 --- a/www/resources.R +++ b/www/resources.R @@ -1,7 +1,9 @@ # Resources +#TODO remove B pertussis from list amrfinder_species <- c( "Acinetobacter_baumannii", "Burkholderia_cepacia", "Burkholderia_mallei_FLI", + "Bordetella_pertussis", "Burkholderia_mallei_RKI", "Burkholderia_pseudomallei", "Campylobacter_jejuni_coli", "Citrobacter_freundii", "Clostridioides_difficile", "Corynebacterium_diphtheriae", "Enterobacter_asburiae", "Enterobacter_cloacae", "Enterococcus_faecalis", From d3db7c29533cd05fb7ed2d4133c90feaaaa26c0a Mon Sep 17 00:00:00 2001 From: fpaskali Date: Mon, 5 Aug 2024 17:53:16 +0200 Subject: [PATCH 34/75] Short hash formating in Loci Info tab --- App.R | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/App.R b/App.R index 07d717b..eb1ac4c 100644 --- a/App.R +++ b/App.R @@ -11080,7 +11080,7 @@ server <- function(input, output, session) { fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) - seq <- fasta[[which(fasta == paste0(">", gsub("Variant ", "", sub(" -.*", "", input$seq_sel)))) + 1]] + seq <- fasta[[which(fasta == paste0(">", gsub("Allele ", "", sub(" -.*", "", input$seq_sel)))) + 1]] DB$seq <- seq @@ -11131,12 +11131,18 @@ server <- function(input, output, session) { present <- which(choices %in% names(vec)) absent <- which(!(choices %in% names(vec))) - choices[present] <- paste0("Variant ", choices[present], " - ", unname(var_count), " times in DB (", unname(perc), ")") + choices[present] <- paste0("Allele ", choices[present], " - ", unname(var_count), " times in DB (", unname(perc), ")") - choices[absent] <- paste0("Variant ", choices[absent], " - not present") + choices[absent] <- paste0("Allele ", choices[absent], " - not present") choices <- c(choices[present], choices[absent]) + names(choices) <- sapply(choices, function(x) { + x <- strsplit(x, " ")[[1]] + x[2] <- paste0(substr(x[2], 1, 4), "...", substr(x[2], nchar(x[2])-3, nchar(x[2]))) + paste(x, collapse = " ") + }) + column( width = 3, selectInput( From a510d298cb59284cf163aee9b11200b6c7991923 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Mon, 5 Aug 2024 19:08:17 +0200 Subject: [PATCH 35/75] Fixed minor hashing errors --- execute/multi_eval.R | 4 ++-- execute/single_eval.R | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/execute/multi_eval.R b/execute/multi_eval.R index d2c19f3..3e99c4c 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -123,7 +123,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= } else if(variant_valid != FALSE) { - hashed_variant <- openssl::sha256(variant_valid) + hashed_variant <- as.character(openssl::sha256(variant_valid)) # Append new variant number to allele fasta file cat(paste0("\n>", hashed_variant), file = locus_file, append = TRUE) @@ -132,7 +132,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= cat(paste0("\n", variant_valid, "\n"), file = locus_file, append = TRUE) # Entry in results data frame - event_list[[basename(assembly)]] <- rbind(event_list[[basename(assembly)]], data.frame(Locus = allele_index, Event = "New Variant", Value = as.character(hashed_variant))) + event_list[[basename(assembly)]] <- rbind(event_list[[basename(assembly)]], data.frame(Locus = allele_index, Event = "New Variant", Value = hashed_variant)) allele_vector[[i]] <- hashed_variant diff --git a/execute/single_eval.R b/execute/single_eval.R index 9b65f81..26681ff 100644 --- a/execute/single_eval.R +++ b/execute/single_eval.R @@ -111,7 +111,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= } else if(variant_valid != FALSE) { - hashed_variant <- openssl::sha256(variant_valid) + hashed_variant <- as.character(openssl::sha256(variant_valid)) # Append new variant number to allele fasta file cat(paste0("\n>", hashed_variant), file = locus_file, append = TRUE) From 7ddb27ec968a311312a4c7c071c6066231196157 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Mon, 5 Aug 2024 19:08:48 +0200 Subject: [PATCH 36/75] Added short hash formatting in Browse Local Database --- App.R | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/App.R b/App.R index eb1ac4c..128daa5 100644 --- a/App.R +++ b/App.R @@ -7744,8 +7744,10 @@ server <- function(input, output, session) { observe({ if (!is.null(DB$data)) { + save(DB, file="database.Rdata") if (nrow(DB$data) == 1) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { + write.csv(DB$data, "dataframe.csv") output$db_entries <- renderRHandsontable({ rhandsontable( select(DB$data, 1:(12 + nrow(DB$cust_var))), @@ -7838,7 +7840,7 @@ server <- function(input, output, session) { }") }) } - } else if (between(nrow(DB$data), 1, 40)) { + } else if (between(nrow(DB$data), 2, 40)) { if (length(input$compare_select) > 0) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ @@ -7856,7 +7858,18 @@ server <- function(input, output, session) { ) %>% hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", - halign = "htCenter") %>% + halign = "htCenter", + renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + ) + ) %>% hot_col(1, valign = "htMiddle", halign = "htCenter") %>% @@ -8156,7 +8169,17 @@ server <- function(input, output, session) { hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", - halign = "htCenter") %>% + halign = "htCenter", + renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }") + ) %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% @@ -9861,7 +9884,17 @@ server <- function(input, output, session) { ) %>% hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", - halign = "htCenter") %>% + halign = "htCenter", + renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }") + ) %>% hot_col(1, valign = "htMiddle", halign = "htCenter") %>% @@ -10161,7 +10194,17 @@ server <- function(input, output, session) { hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", - halign = "htCenter") %>% + halign = "htCenter", + renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }") + ) %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% From 49576b218708d603ac8ba03aebaa6f85c694cc47 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Mon, 5 Aug 2024 19:12:37 +0200 Subject: [PATCH 37/75] Removed debug lines --- App.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/App.R b/App.R index 128daa5..67289fa 100644 --- a/App.R +++ b/App.R @@ -7744,10 +7744,8 @@ server <- function(input, output, session) { observe({ if (!is.null(DB$data)) { - save(DB, file="database.Rdata") if (nrow(DB$data) == 1) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { - write.csv(DB$data, "dataframe.csv") output$db_entries <- renderRHandsontable({ rhandsontable( select(DB$data, 1:(12 + nrow(DB$cust_var))), From 8b6ec3d593461e0075a1c117bc0304dc94e015c2 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Tue, 6 Aug 2024 00:11:35 +0200 Subject: [PATCH 38/75] Adaptions of assembly file naming and saving for multi typing --- App.R | 732 ++++++++++++++++++---------------------- execute/multi_eval.R | 13 + execute/multi_typing.sh | 12 +- 3 files changed, 347 insertions(+), 410 deletions(-) diff --git a/App.R b/App.R index 79a0d05..6a1bbba 100644 --- a/App.R +++ b/App.R @@ -551,9 +551,9 @@ ui <- dashboardPage( tabName = "typing", fluidRow( column( - width = 3, - align = "center", - h2(p("Generate Allelic Profile"), style = "color:white") + width = 3, + align = "center", + h2(p("Generate Allelic Profile"), style = "color:white") ) ), hr(), @@ -5368,7 +5368,7 @@ server <- function(input, output, session) { session$onSessionEnded( function() { stopApp() }) - + # Disable various user inputs (visualization control) shinyjs::disable('mst_edge_label') @@ -5675,25 +5675,11 @@ server <- function(input, output, session) { #Function to check for duplicate isolate IDs for multi typing start dupl_mult_id <- reactive({ - req(Typing$multi_sel_table, DB$data) - if(!is.null(Typing$new_table)) { - selection <- Typing$new_table[which(unlist(Typing$new_table$Files) %in% unlist(DB$data["Assembly ID"])),] - as.numeric(rownames(selection[selection$Include == TRUE,])) - } else { - selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] - as.numeric(rownames(selection[selection$Include == TRUE,])) - } - }) - - dupl_mult_id_names <- reactive({ - req(Typing$multi_sel_table, DB$data) - if(!is.null(Typing$new_table)) { - selection <- Typing$new_table[which(unlist(Typing$new_table$Files) %in% unlist(DB$data["Assembly ID"])),] - selection$Files - } else { + req(Typing$multi_sel_table) + if(!is.null(DB$data)) { selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] selection$Files - } + } else {""} }) # Function to check single typing log file @@ -6132,7 +6118,7 @@ server <- function(input, output, session) { if(Typing$status == "Finalized") {Typing$status <- "Inactive"} if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} if(!is.null(Screening$single_path)) {Screening$single_path <- data.frame()} - + #### Render status bar ---- observe({ req(DB$scheme) @@ -6314,8 +6300,6 @@ server <- function(input, output, session) { Typing$single_path <- data.frame() - Typing$multi_path <- data.frame() - # reset results file if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) @@ -6519,19 +6503,12 @@ server <- function(input, output, session) { saveRDS(DB$database, paste0(getwd(), "/execute/last_db.rds")) DB$check_new_entries <- TRUE - DB$data <- NULL - DB$meta_gs <- NULL - DB$meta <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_true <- NULL - DB$scheme <- input$scheme_db # null Distance matrix, entry table and plots @@ -7036,8 +7013,6 @@ server <- function(input, output, session) { Typing$single_path <- data.frame() - Typing$multi_path <- data.frame() - # Null multi typing feedback variable Typing$reset <- TRUE @@ -7126,7 +7101,7 @@ server <- function(input, output, session) { br() ) ), - uiOutput("multi_select_tab_ctrls"),# + uiOutput("multi_select_tab_ctrls"), br(), fluidRow( column(1), @@ -9361,6 +9336,132 @@ server <- function(input, output, session) { output$metadata_single_box <- NULL output$start_typing_ui <- NULL + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) } } } @@ -11746,20 +11847,20 @@ server <- function(input, output, session) { # Download Target Info (CSV Table) observe({ input$download_cgMLST - + scheme_overview <- read_html(Scheme$link_scheme) %>% html_table(header = FALSE) %>% as.data.frame(stringsAsFactors = FALSE) - + last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], format = "%B %d, %Y, %H:%M %p") names(scheme_overview) <- NULL - + last_file_change <- format( file.info(file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") - + output$cgmlst_scheme <- renderTable({scheme_overview}) output$scheme_update_info <- renderText({ req(last_file_change) @@ -17741,9 +17842,9 @@ server <- function(input, output, session) { mst_tree <- reactive({ Typing$data <- toVisNetworkData(Vis$ggraph_1) Typing$data$nodes <- mutate(Typing$data$nodes, - label = label_mst(), - value = mst_node_scaling(), - opacity = node_opacity()) + label = label_mst(), + value = mst_node_scaling(), + opacity = node_opacity()) ctxRendererJS <- htmlwidgets::JS("({ctx, id, x, y, state: { selected, hover }, style, font, label, metadata}) => { var pieData = JSON.parse(metadata); @@ -17866,13 +17967,13 @@ server <- function(input, output, session) { } Typing$data$edges <- mutate(Typing$data$edges, - length = if(input$mst_scale_edges == FALSE) { - input$mst_edge_length - } else { - Typing$data$edges$weight * input$mst_edge_length_scale - }, - label = as.character(Typing$data$edges$weight), - opacity = input$mst_edge_opacity) + length = if(input$mst_scale_edges == FALSE) { + input$mst_edge_length + } else { + Typing$data$edges$weight * input$mst_edge_length_scale + }, + label = as.character(Typing$data$edges$weight), + opacity = input$mst_edge_opacity) if (input$mst_show_clusters) { Typing$data$nodes$group <- compute_clusters(Typing$data$nodes, Typing$data$edges, input$mst_cluster_threshold) @@ -17884,36 +17985,36 @@ server <- function(input, output, session) { main = mst_title(), background = mst_background_color(), submain = mst_subtitle()) %>% - visNodes(size = mst_node_size(), - shape = input$mst_node_shape, - shadow = input$mst_shadow, - color = mst_color_node(), - ctxRenderer = ctxRendererJS, - scaling = list(min = mst_node_size_min(), - max = mst_node_size_max()), - font = list(color = node_font_color(), - size = input$node_label_fontsize)) %>% - visEdges(color = mst_color_edge(), - font = list(color = mst_edge_font_color(), - size = mst_edge_font_size(), - strokeWidth = 4)) %>% - visOptions(collapse = TRUE) %>% - visInteraction(hover = TRUE) %>% - visLayout(randomSeed = 1) %>% - visLegend(useGroups = FALSE, - zoom = TRUE, - width = legend_width(), - position = input$mst_legend_ori, - ncol = legend_col(), - addNodes = mst_legend()) - + visNodes(size = mst_node_size(), + shape = input$mst_node_shape, + shadow = input$mst_shadow, + color = mst_color_node(), + ctxRenderer = ctxRendererJS, + scaling = list(min = mst_node_size_min(), + max = mst_node_size_max()), + font = list(color = node_font_color(), + size = input$node_label_fontsize)) %>% + visEdges(color = mst_color_edge(), + font = list(color = mst_edge_font_color(), + size = mst_edge_font_size(), + strokeWidth = 4)) %>% + visOptions(collapse = TRUE) %>% + visInteraction(hover = TRUE) %>% + visLayout(randomSeed = 1) %>% + visLegend(useGroups = FALSE, + zoom = TRUE, + width = legend_width(), + position = input$mst_legend_ori, + ncol = legend_col(), + addNodes = mst_legend()) + if (input$mst_show_clusters) { if (input$mst_cluster_col_scale == "Viridis") { color_palette <- viridis(length(data$nodes$group)) } else { color_palette <- rainbow(length(data$nodes$group)) } - + for (i in 1:length(unique(data$nodes$group))) { visNetwork_graph <- visNetwork_graph %>% visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) @@ -22768,7 +22869,7 @@ server <- function(input, output, session) { } }) - + # _______________________ #### ## Typing ---- @@ -23693,7 +23794,7 @@ server <- function(input, output, session) { br() ) ), - uiOutput("multi_select_tab_ctrls"),# + uiOutput("multi_select_tab_ctrls"), br(), fluidRow( column(1), @@ -23708,13 +23809,14 @@ server <- function(input, output, session) { # Render selection info output$multi_select_info <- renderUI({ + if(!is.null(Typing$multi_path)) { if(length(Typing$multi_path) < 1) { HTML(paste("", "No files selected.")) } else { HTML(paste("", - sum(Typing$genome_selected$Include == TRUE), + sum(hot_to_r(input$multi_select_table)$Include == TRUE), " files selected.")) } } @@ -23722,8 +23824,8 @@ server <- function(input, output, session) { # Render multi selection table issues output$multi_select_issues <- renderUI({ - req(Typing$multi_sel_table, Typing$genome_selected, input$multi_select_table) - if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) & + req(Typing$multi_sel_table, input$multi_select_table) + if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & any(duplicated(hot_to_r(input$multi_select_table)$Files))){ HTML( paste( @@ -23733,13 +23835,13 @@ server <- function(input, output, session) { "Duplicated name(s).
") ) ) - } else if (any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) & + } else if (any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & !any(duplicated(hot_to_r(input$multi_select_table)$Files))) { HTML( paste("", "Some name(s) are already present in local database.
") ) - } else if (!any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) & + } else if (!any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & any(duplicated(hot_to_r(input$multi_select_table)$Files))) { HTML( paste("", @@ -23749,13 +23851,32 @@ server <- function(input, output, session) { }) output$multi_select_issue_info <- renderUI({ - req(Typing$multi_sel_table, Typing$genome_selected, input$multi_select_table) - if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id_names()) | - any(duplicated(hot_to_r(input$multi_select_table)$Files))) { - HTML( - paste("", - "Rename highlighted isolates.") - ) + req(Typing$multi_sel_table, input$multi_select_table) + + multi_select_table <- hot_to_r(input$multi_select_table) + + if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | + any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)])) | + any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + + if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + + if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | + any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + HTML(paste( + paste("", + "Rename highlighted isolates or deselect them.
"), + paste("", + "Filename(s) contain(s) empty spaces.") + )) + } else { + HTML(paste("", + "Filename(s) contain(s) empty spaces.")) + } + } else { + HTML(paste("", + "Rename highlighted isolates or deselect them.")) + } } }) @@ -23795,8 +23916,6 @@ server <- function(input, output, session) { ) ) - Typing$genome_selected <- hot_to_r(input$multi_select_table) - output$metadata_multi_box <- renderUI({ column( width = 3, @@ -23962,15 +24081,15 @@ server <- function(input, output, session) { Typing$multi_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi) files_selected <- list.files(as.character(Typing$multi_path)) - files_filtered <- files_selected[which(!endsWith(files_selected, ".gz") & - grepl("\\.fasta|\\.fna|\\.fa", files_selected))] + Typing$files_filtered <- files_selected[which(!endsWith(files_selected, ".gz") & + grepl("\\.fasta|\\.fna|\\.fa", files_selected))] Typing$multi_sel_table <- data.frame( - Include = rep(TRUE, length(files_filtered)), + Include = rep(TRUE, length(Typing$files_filtered)), Files = gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", - files_filtered), + Typing$files_filtered), Type = sub(".*(\\.fasta|\\.fasta\\.gz|\\.fna|\\.fna\\.gz|\\.fa|\\.fa\\.gz)$", - "\\1", files_filtered, perl = F)) + "\\1", Typing$files_filtered, perl = F)) if(nrow(Typing$multi_sel_table) > 0) { output$multi_select_tab_ctrls <- renderUI( @@ -24007,116 +24126,23 @@ server <- function(input, output, session) { output$multi_select_tab_ctrls <- NULL } - if (between(nrow(Typing$multi_sel_table), 1, 15)) { - if(!is.null(Typing$new_table)) { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$new_table, rowHeaders = NULL, - stretchH = "all", contextMenu = FALSE - ) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { - var hot = this.hot; - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - var highlightInvalidAndDuplicates = function(invalidValues) { - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - // Find all duplicate values - for (var i = 0; i < columnData.length; i++) { - var value = columnData[i]; - if (value !== null && value !== undefined) { - if (duplicates[value]) { - duplicates[value].push(i); - } else { - duplicates[value] = [i]; - } - } - } - - // Reset all cell backgrounds in the column - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - if (cell) { - cell.style.background = 'white'; - } - } - - // Highlight duplicates and invalid values - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - var value = columnData[i]; - if (cell) { - if (invalidValues.includes(value)) { - cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values - } else if (duplicates[value] && duplicates[value].length > 1) { - cell.style.background = '#FF7334'; // Highlight color for duplicates - } - } - } - }; - - var changefn = function(changes, source) { - if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { - highlightInvalidAndDuplicates(%s); - } - }; - - hot.addHook('afterChange', changefn); - hot.addHook('afterLoadData', function() { - highlightInvalidAndDuplicates(%s); - }); - hot.addHook('afterRender', function() { - highlightInvalidAndDuplicates(%s); - }); - - highlightInvalidAndDuplicates(%s); // Initial highlight on load + if(between(nrow(Typing$multi_sel_table), 1, 15)) { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", contextMenu = FALSE + ) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) - Shiny.addCustomMessageHandler('setColumnValue', function(message) { - var colData = hot.getDataAtCol(0); - for (var i = 0; i < colData.length; i++) { - hot.setDataAtCell(i, 0, message.value); - } - hot.render(); // Re-render the table - }); - }", - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()))) - }) - } else { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", contextMenu = FALSE - ) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { var hot = this.hot; var columnData = hot.getDataAtCol(1); // Change column index if needed @@ -24185,124 +24211,31 @@ server <- function(input, output, session) { hot.render(); // Re-render the table }); }", - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()))) - }) - } + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()))) + }) + } else if(nrow(Typing$multi_sel_table) > 15) { - if(!is.null(Typing$new_table)) { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$new_table, rowHeaders = NULL, - stretchH = "all", height = 500, - contextMenu = FALSE - ) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { - var hot = this.hot; + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", height = 500, + contextMenu = FALSE + ) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, + readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - var highlightInvalidAndDuplicates = function(invalidValues) { - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - // Find all duplicate values - for (var i = 0; i < columnData.length; i++) { - var value = columnData[i]; - if (value !== null && value !== undefined) { - if (duplicates[value]) { - duplicates[value].push(i); - } else { - duplicates[value] = [i]; - } - } - } - - // Reset all cell backgrounds in the column - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - if (cell) { - cell.style.background = 'white'; - } - } - - // Highlight duplicates and invalid values - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - var value = columnData[i]; - if (cell) { - if (invalidValues.includes(value)) { - cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values - } else if (duplicates[value] && duplicates[value].length > 1) { - cell.style.background = '#FF7334'; // Highlight color for duplicates - } - } - } - }; - - var changefn = function(changes, source) { - if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { - highlightInvalidAndDuplicates(%s); - } - }; - - hot.addHook('afterChange', changefn); - hot.addHook('afterLoadData', function() { - highlightInvalidAndDuplicates(%s); - }); - hot.addHook('afterRender', function() { - highlightInvalidAndDuplicates(%s); - }); - - highlightInvalidAndDuplicates(%s); // Initial highlight on load - - Shiny.addCustomMessageHandler('setColumnValue', function(message) { - var colData = hot.getDataAtCol(0); - for (var i = 0; i < colData.length; i++) { - hot.setDataAtCell(i, 0, message.value); - } - hot.render(); // Re-render the table - }); - }", - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()))) - }) - } else { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", height = 500, - contextMenu = FALSE - ) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { var hot = this.hot; var columnData = hot.getDataAtCol(1); // Change column index if needed @@ -24371,23 +24304,20 @@ server <- function(input, output, session) { hot.render(); // Re-render the table }); }", - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()), - jsonlite::toJSON(dupl_mult_id_names()))) - - }) - } + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()))) + + }) + } else { output$multi_select_table <- NULL - } + } }) observeEvent(input$conf_meta_multi, { - Typing$new_table <- mutate(hot_to_r(input$multi_select_table), - Include = as.logical(Include)) - multi_select_table <- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", multi_select_table$Files)) %in% unlist(DB$data["Assembly ID"]))) { @@ -24400,7 +24330,7 @@ server <- function(input, output, session) { ) } else if (any(duplicated(multi_select_table$Files))) { show_toast( - title = "Duplicated file name(s)", + title = "Duplicated filename(s)", type = "error", position = "bottom-end", timer = 3000, @@ -24408,23 +24338,21 @@ server <- function(input, output, session) { ) } else if (any(multi_select_table$Files == "")) { show_toast( - title = "Empty file name(s)", + title = "Empty filename(s)", type = "error", position = "bottom-end", timer = 3000, width = "500px" ) - } - else if (any(grepl("[/\\:*?\"<>|]", multi_select_table$Files))) { + } else if (any(grepl("[/\\:*?\"<>|]", multi_select_table$Files))) { show_toast( - title = "Invalid file name(s). Not allowed: /\\:*?\"<>|", + title = "Invalid filename(s). Not allowed: /\\:*?\"<>|", type = "error", position = "bottom-end", timer = 3000, width = "500px" ) - } - else if (!any(multi_select_table$Include == TRUE)) { + } else if (!any(multi_select_table$Include == TRUE)) { show_toast( title = "No files selected", type = "error", @@ -24432,8 +24360,15 @@ server <- function(input, output, session) { timer = 3000, width = "500px" ) - } - else { + } else if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + show_toast( + title = "Empty spaces in filename(s) not allowed", + type = "error", + position = "bottom-end", + timer = 3000, + width = "500px" + ) + } else { log_print("Multi typing metadata confirmed") @@ -24554,7 +24489,6 @@ server <- function(input, output, session) { # Reset User Feedback variable Typing$pending_format <- 0 Typing$multi_started <- FALSE - Typing$multi_path <- data.frame() output$initiate_multi_typing_ui <- renderUI({ column( @@ -24590,7 +24524,7 @@ server <- function(input, output, session) { br() ) ), - uiOutput("multi_select_tab_ctrls"),# + uiOutput("multi_select_tab_ctrls"), br(), fluidRow( column(1), @@ -24603,8 +24537,6 @@ server <- function(input, output, session) { ) }) - Typing$multi_sel_table <- data.frame() - output$test_yes_pending <- NULL output$multi_typing_results <- NULL } @@ -24678,7 +24610,7 @@ server <- function(input, output, session) { br() ) ), - uiOutput("multi_select_tab_ctrls"),# + uiOutput("multi_select_tab_ctrls"), br(), fluidRow( column(1), @@ -24713,68 +24645,58 @@ server <- function(input, output, session) { width = "500px" ) } else { - if (any(!grepl("\\.fasta|\\.fna|\\.fa", str_sub(Typing$genome_selected$Files[which(Typing$genome_selected$Include == TRUE)], start = -6)))) { - - log_print("Wrong file type (include only fasta/fna/fa)") - - show_toast( - title = "Wrong file type (include only fasta/fna/fa)", - type = "error", - position = "bottom-end", - timer = 6000, - width = "500px" - ) - } else { - - removeModal() - - show_toast( - title = "Multi Typing started", - type = "success", - position = "bottom-end", - timer = 10000, - width = "500px" - ) - - Typing$new_table <- NULL - - # Remove Allelic Typing Controls - output$initiate_multi_typing_ui <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - - # Activate entry detection - DB$check_new_entries <- TRUE - - # Initiate Feedback variables - Typing$multi_started <- TRUE - Typing$pending <- TRUE - Typing$failures <- 0 - Typing$successes <- 0 - - # Start Multi Typing Script - multi_typing_df <- data.frame( - db_path = DB$database, - wd = getwd(), - save = input$save_assembly_mt, - scheme = paste0(gsub(" ", "_", DB$scheme)), - genome_folder = as.character(parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi)), - genome_names = paste(Typing$genome_selected$Files[which(Typing$genome_selected$Include == TRUE)], collapse= " "), - alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles") - ) - - saveRDS(multi_typing_df, "execute/multi_typing_df.rds") - - # Reset selected - Typing$genome_selected <- NULL - - # Execute multi blat script - system(paste("bash", paste0(getwd(), "/execute/multi_typing.sh")), - wait = FALSE) - - } + removeModal() + + show_toast( + title = "Multi Typing started", + type = "success", + position = "bottom-end", + timer = 10000, + width = "500px" + ) + + Typing$new_table <- NULL + + # Remove Allelic Typing Controls + output$initiate_multi_typing_ui <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + + # Activate entry detection + DB$check_new_entries <- TRUE + + # Initiate Feedback variables + Typing$multi_started <- TRUE + Typing$pending <- TRUE + Typing$failures <- 0 + Typing$successes <- 0 + + # get selected file table + multi_select_table <- hot_to_r(input$multi_select_table) + + filenames <- paste(multi_select_table$Files[which(multi_select_table$Include == TRUE)], collapse = " ") + + files <- Typing$multi_sel_table$Files[which(multi_select_table$Include == TRUE)] + type <- Typing$multi_sel_table$Type[which(multi_select_table$Include == TRUE)] + genome_names <- paste(paste0(gsub(" ", "~", files), type), collapse = " ") + + # Start Multi Typing Script + multi_typing_df <- data.frame( + db_path = DB$database, + wd = getwd(), + save = input$save_assembly_mt, + scheme = paste0(gsub(" ", "_", DB$scheme)), + genome_folder = as.character(parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi)), + filenames = paste0(filenames, collapse= " "), + genome_names = genome_names, + alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles") + ) + + saveRDS(multi_typing_df, "execute/multi_typing_df.rds") + + # Execute multi blat script + system(paste("bash", paste0(getwd(), "/execute/multi_typing.sh")), wait = FALSE) } - }) @@ -25119,8 +25041,6 @@ server <- function(input, output, session) { ) }) - - } # end server # _______________________ #### diff --git a/execute/multi_eval.R b/execute/multi_eval.R index 97c2a0d..e0935ae 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -3,6 +3,7 @@ library(logr) meta_info <- readRDS("meta_info.rds") db_path <- readRDS("multi_typing_df.rds")[, "db_path"] save_assembly <- readRDS("multi_typing_df.rds")[, "save"] +filename <- stringr::str_split(readRDS("multi_typing_df.rds")[, "filenames"], " ")[which(commandArgs(trailingOnly = TRUE)[1] == basename(assembly_folder))] assembly_folder <- dir(paste0(getwd(), "/selected_genomes"), full.names = TRUE) assembly <- assembly_folder[which(commandArgs(trailingOnly = TRUE)[1] == basename(assembly_folder))] results_folder <- dir(paste0(meta_info$db_directory, "/execute/blat_multi/results"), full.names = TRUE) @@ -338,6 +339,13 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates/", basename(assembly))) + file.rename(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly)), + filename) + + save_assembly <- readRDS("multi_typing_df.rds")[, "save"] + log_print(paste0("Saved assembly of ", basename(assembly))) } else { @@ -359,6 +367,11 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates/", basename(assembly))) + file.rename(paste0(db_path, "/", + gsub(" ", "_", meta_info$cgmlst_typing), + "/Isolates/", basename(assembly)), + filename) + log_print(paste0("Saved assembly of ", basename(assembly))) } } diff --git a/execute/multi_typing.sh b/execute/multi_typing.sh index 0bb43b7..26274ab 100755 --- a/execute/multi_typing.sh +++ b/execute/multi_typing.sh @@ -41,14 +41,18 @@ file_names=($genome_names) # Loop through the list of file names and copy them to the new folder for file in "${file_names[@]}"; do - if [ -f "$genome_folder/$file" ]; then - cp "$genome_folder/$file" "$selected_genomes/" - echo "$(date +"%Y-%m-%d %H:%M:%S") - Initiated $file" >> "$log_file" + # Replace tilde with space in the filename + new_file="${file//\~/ }" + + if [ -f "$genome_folder/$new_file" ]; then + cp "$genome_folder/$new_file" "$selected_genomes/" + echo "$(date +"%Y-%m-%d %H:%M:%S") - Initiated $new_file" >> "$log_file" else - echo "$(date +"%Y-%m-%d %H:%M:%S") - $file not found in $genome_folder" >> "$log_file" + echo "$(date +"%Y-%m-%d %H:%M:%S") - $new_file not found in $genome_folder" >> "$log_file" fi done + #INDEXING GENOME AS DATABASE blat_database="$base_path/execute/blat_multi/$scheme" From 0df998d9d5eaeab4ff02eea61752475035d5fc24 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Wed, 7 Aug 2024 15:40:00 +0200 Subject: [PATCH 39/75] Fixes in multi typing analysis chain; slight UI adaptions --- App.R | 46 +++++++++++++++++++++++++++-------------- execute/multi_eval.R | 38 +++++++++++----------------------- execute/multi_typing.sh | 37 +++++++++++++++++++++++++-------- www/body.css | 29 +++++++++++++++++++++----- www/head.css | 6 ++++-- 5 files changed, 98 insertions(+), 58 deletions(-) diff --git a/App.R b/App.R index 6a1bbba..61c0c33 100644 --- a/App.R +++ b/App.R @@ -23864,19 +23864,32 @@ server <- function(input, output, session) { if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { HTML(paste( - paste("", - "Rename highlighted isolates or deselect them.
"), - paste("", - "Filename(s) contain(s) empty spaces.") + paste( + '', + paste("", + " Rename highlighted isolates or deselect them.
")), + paste( + '', + paste("", + " Filename(s) contain(s) empty spaces.")) )) } else { - HTML(paste("", - "Filename(s) contain(s) empty spaces.")) + HTML(paste( + '', + paste("", + " Filename(s) contain(s) empty spaces."))) } } else { - HTML(paste("", - "Rename highlighted isolates or deselect them.")) + HTML(paste( + '', + paste("", + " Rename highlighted isolates or deselect them."))) } + } else { + HTML(paste( + '', + paste("", + " Files ready for allelic typing."))) } }) @@ -24131,7 +24144,7 @@ server <- function(input, output, session) { rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, stretchH = "all", contextMenu = FALSE ) %>% - hot_cols(columnSorting = TRUE) %>% + hot_cols(columnSorting = FALSE) %>% hot_rows(rowHeights = 25) %>% hot_col(2, readOnly = FALSE, valign = "htBottom") %>% @@ -24223,7 +24236,7 @@ server <- function(input, output, session) { stretchH = "all", height = 500, contextMenu = FALSE ) %>% - hot_cols(columnSorting = TRUE) %>% + hot_cols(columnSorting = FALSE) %>% hot_rows(rowHeights = 25) %>% hot_col(2, readOnly = FALSE, @@ -24344,9 +24357,9 @@ server <- function(input, output, session) { timer = 3000, width = "500px" ) - } else if (any(grepl("[/\\:*?\"<>|]", multi_select_table$Files))) { + } else if (any(grepl("[()/\\:*?\"<>|]", multi_select_table$Files))) { show_toast( - title = "Invalid filename(s). Not allowed: /\\:*?\"<>|", + title = "Invalid filename(s). No special characters allowed: ()/\\:*?\"<>|", type = "error", position = "bottom-end", timer = 3000, @@ -24741,9 +24754,9 @@ server <- function(input, output, session) { } else if(str_detect(tail(log, 1), "failed")) { Typing$status <- "Failed" show_toast( - title = paste0("Failed typing of ", sub(".*failed for ", "", tail(log, 1))), + title = sub(".* - ", "", tail(log, 1)), type = "error", - width = "500px", + width = "700px", position = "bottom-end", timer = 8000 ) @@ -24764,11 +24777,12 @@ server <- function(input, output, session) { Typing$last_success <- tail(log, 2)[1] } - } else if(any(str_detect(tail(log, 2), "failed for"))) { + } else if(any(str_detect(tail(log, 2), "failed"))) { if(!identical(Typing$last_failure, tail(log, 2)[1])) { + show_toast( - title = paste0("Failed typing of ", sub(".*failed for ", "", tail(log, 2)[1])), + title = sub(".* - ", "", tail(log, 2)[1]), type = "error", width = "500px", position = "bottom-end", diff --git a/execute/multi_eval.R b/execute/multi_eval.R index e0935ae..d045bc5 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -3,10 +3,13 @@ library(logr) meta_info <- readRDS("meta_info.rds") db_path <- readRDS("multi_typing_df.rds")[, "db_path"] save_assembly <- readRDS("multi_typing_df.rds")[, "save"] -filename <- stringr::str_split(readRDS("multi_typing_df.rds")[, "filenames"], " ")[which(commandArgs(trailingOnly = TRUE)[1] == basename(assembly_folder))] -assembly_folder <- dir(paste0(getwd(), "/selected_genomes"), full.names = TRUE) +assembly_folder <- paste0(paste0(getwd(), "/selected_genomes/"), + paste0(stringr::str_split_1(readRDS("multi_typing_df.rds")[, "filenames"], " "), + ".fasta")) assembly <- assembly_folder[which(commandArgs(trailingOnly = TRUE)[1] == basename(assembly_folder))] -results_folder <- dir(paste0(meta_info$db_directory, "/execute/blat_multi/results"), full.names = TRUE) +filename <- stringr::str_split_1(readRDS("multi_typing_df.rds")[, "filenames"], " ")[which(commandArgs(trailingOnly = TRUE)[1] == basename(assembly_folder))] +results_folder <- paste0(paste0(meta_info$db_directory, "/execute/blat_multi/results/"), + stringr::str_split_1(readRDS("multi_typing_df.rds")[, "filenames"], " ")) source("variant_validation.R") @@ -157,9 +160,6 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= saveRDS(event_list, "execute/event_list.rds") - # Find Alleles folder in directory - allele_folder <- list.files(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing)), full.names = TRUE)[grep("_alleles", list.files(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing))))] - # Create Results Data Frame if(!any(grepl("Typing", list.files(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing)))))) { @@ -332,19 +332,11 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # Create folder for new isolate dir.create(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) + "/Isolates/", filename)) # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) - - file.rename(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly)), - filename) - - save_assembly <- readRDS("multi_typing_df.rds")[, "save"] + file.copy(paste0(getwd(), "/execute/selected_genomes/", filename, ".fasta"), + paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates/", filename)) log_print(paste0("Saved assembly of ", basename(assembly))) @@ -360,17 +352,11 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # Create folder for new isolate dir.create(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) + "/Isolates/", filename)) # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly))) - - file.rename(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", basename(assembly)), - filename) + file.copy(paste0(getwd(), "/execute/selected_genomes/", filename, ".fasta"), + paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates/", filename)) log_print(paste0("Saved assembly of ", basename(assembly))) } diff --git a/execute/multi_typing.sh b/execute/multi_typing.sh index 26274ab..1aa57ab 100755 --- a/execute/multi_typing.sh +++ b/execute/multi_typing.sh @@ -11,6 +11,7 @@ scheme=$(Rscript -e "cat(readRDS('multi_typing_df.rds')[,'scheme'])") genome_folder=$(Rscript -e "cat(readRDS('multi_typing_df.rds')[,'genome_folder'])") genome_names=$(Rscript -e "cat(readRDS('multi_typing_df.rds')[,'genome_names'])") alleles=$(Rscript -e "cat(readRDS('multi_typing_df.rds')[,'alleles'])") +rename_file=$(Rscript -e "cat(stringr::str_split_1(readRDS('multi_typing_df.rds')[, 'filenames'], ' '))") # Remove the existing multi directory if [ -d "$base_path/execute/blat_multi" ]; then @@ -38,21 +39,27 @@ fi mkdir $selected_genomes file_names=($genome_names) +new_names=($rename_file) +index=0 # Loop through the list of file names and copy them to the new folder for file in "${file_names[@]}"; do - # Replace tilde with space in the filename - new_file="${file//\~/ }" + + # Replace tilde with space in the filename #TODO + new_file=$(echo "$file" | sed 's/~/ /g') if [ -f "$genome_folder/$new_file" ]; then cp "$genome_folder/$new_file" "$selected_genomes/" + + mv "$selected_genomes/$new_file" "$selected_genomes/${new_names[$index]}.fasta" + echo "$(date +"%Y-%m-%d %H:%M:%S") - Initiated $new_file" >> "$log_file" else echo "$(date +"%Y-%m-%d %H:%M:%S") - $new_file not found in $genome_folder" >> "$log_file" fi + index=$((index + 1)) done - #INDEXING GENOME AS DATABASE blat_database="$base_path/execute/blat_multi/$scheme" @@ -60,10 +67,13 @@ blat_database="$base_path/execute/blat_multi/$scheme" genome_filename_noext="" #Indexing Loop -for genome in "$selected_genomes"/*; do - - # Check read names of assembly file - Rscript "$base_path/execute/check_duplicate_multi.R" "$base_path" +for genome in "$selected_genomes"/*; do + + # Check fasta and formatting + if ! Rscript "$base_path/execute/check_duplicate_multi.R" "$base_path"; then + echo "$(date +"%Y-%m-%d %H:%M:%S") - FASTA check failed. Typing of $(basename "$genome") aborted." >> "$log_file" + continue + fi if [ -f "$genome" ]; then genome_filename=$(basename "$genome") @@ -75,9 +85,18 @@ for genome in "$selected_genomes"/*; do result_folder="$results/$genome_filename_noext" # Run parallelized BLAT - find "$alleles" -type f \( -name "*.fasta" -o -name "*.fa" -o -name "*.fna" \) | parallel pblat $genome {} "$result_folder/{/.}.psl" > /dev/null 2>&1 + if ! find "$alleles" -type f \( -name "*.fasta" -o -name "*.fa" -o -name "*.fna" \) | parallel pblat "$genome" {} "$result_folder/{/.}.psl" > /dev/null 2>&1; then + echo "$(date +"%Y-%m-%d %H:%M:%S") - Allele calling failed. Typing of $genome_filename aborted." >> "$log_file" + continue + fi echo "$(date +"%Y-%m-%d %H:%M:%S") - Attaching $genome_filename" >> "$log_file" - Rscript "$base_path/execute/multi_eval.R" "$genome_filename" + + # Check fasta and formatting + if ! Rscript "$base_path/execute/multi_eval.R" "$genome_filename"; then + echo "$(date +"%Y-%m-%d %H:%M:%S") - Results evaluation failed. Typing of $genome_filename aborted." >> "$log_file" + continue + fi done + echo "$(date +"%Y-%m-%d %H:%M:%S") - Multi Typing finalized." >> "$log_file" diff --git a/www/body.css b/www/body.css index 696f955..63216a2 100644 --- a/www/body.css +++ b/www/body.css @@ -10,10 +10,29 @@ label { color: white; } +input[type="checkbox"] { + accent-color: #20E6E5; + height: 15px; + width: 15px; +} + +.sF-fileList>div.selected .sF-file-name div, .sF-dirList div.selected>.sF-file-name>div { + background: #20E6E5; + color: black; +} + +.handsontableInput { + box-shadow: inset 0 0 0 2px #20e6e5; +} + +.handsontable .wtBorder.current { + background-color: #282F38 !important; +} + .tooltip-inner { - white-space: normal; - max-width: 800px; /* Adjust the width as needed */ - } + white-space: normal; + max-width: 800px; /* Adjust the width as needed */ +} .btn-default:active:hover. .btn-primary:active:hover{ @@ -23,8 +42,8 @@ label { .btn-primary.focus, .btn-primary:focus { color: #000000; - background-color: #20E6E5; - border-color: #20E6E5; + background-color: #20E6E5; + border-color: #20E6E5; } .btn-primary.focus, .btn-primary:active:focus { diff --git a/www/head.css b/www/head.css index 2aa66d2..962b17d 100644 --- a/www/head.css +++ b/www/head.css @@ -91,7 +91,8 @@ div#bs-select-12::-webkit-scrollbar-track, #logTextFull::-webkit-scrollbar-track, #screening_fail::-webkit-scrollbar-track, .selectize-dropdown-content::-webkit-scrollbar-track, -#mst_comm_general_select::-webkit-scrollbar-track { +#mst_comm_general_select::-webkit-scrollbar-track, +.sF-dirInfo>div::-webkit-scrollbar-track{ background: #F0F0F0; } @@ -112,7 +113,8 @@ div#bs-select-12::-webkit-scrollbar-thumb, #logTextFull::-webkit-scrollbar-thumb, #screening_fail::-webkit-scrollbar-thumb, .selectize-dropdown-content::-webkit-scrollbar-thumb, -#mst_comm_general_select::-webkit-scrollbar-thumb { +#mst_comm_general_select::-webkit-scrollbar-thumb, +.sF-dirInfo>div::-webkit-scrollbar-thumb { background: #bcbcbc; border: 2px solid #F0F0F0; min-width: 100px; From 8d6179810caaaa999d85c0fd019332b93b5a52b6 Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Wed, 7 Aug 2024 21:51:05 +0200 Subject: [PATCH 40/75] Adapted single typing to new assembly saving feature; several fixes and UI changes --- App.R | 228 +++++++++++++++++++++------------------ execute/multi_eval.R | 44 +++++--- execute/single_eval.R | 43 +++++--- execute/single_typing.sh | 7 +- www/body.css | 10 ++ 5 files changed, 195 insertions(+), 137 deletions(-) diff --git a/App.R b/App.R index 61c0c33..8e8276a 100644 --- a/App.R +++ b/App.R @@ -6114,6 +6114,9 @@ server <- function(input, output, session) { log_print("Input load") + # set typing start control variable + Typing$reload <- TRUE + # reset typing status on start( if(Typing$status == "Finalized") {Typing$status <- "Inactive"} if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} @@ -6336,7 +6339,6 @@ server <- function(input, output, session) { show_toast( title = "Directory already contains a database", type = "error", - width = "500px", position = "bottom-end", timer = 6000 ) @@ -8513,6 +8515,7 @@ server <- function(input, output, session) { # Dynamic save button when rhandsontable changes or new entries output$edit_entry_table <- renderUI({ if(check_new_entry() & DB$check_new_entries) { + Typing$reload <- FALSE fluidRow( column( width = 8, @@ -9473,7 +9476,6 @@ server <- function(input, output, session) { title = "Invalid scheme folder", type = "warning", position = "bottom-end", - width = "500px", timer = 4000 ) } @@ -9861,8 +9863,7 @@ server <- function(input, output, session) { title = "Invalid date", type = "warning", position = "bottom-end", - timer = 6000, - width = "300px" + timer = 6000 ) DB$inhibit_change <- TRUE } else if (isTRUE(input$empty_name)) { @@ -9870,8 +9871,7 @@ server <- function(input, output, session) { title = "Empty name", type = "warning", position = "bottom-end", - timer = 6000, - width = "300px" + timer = 6000 ) DB$inhibit_change <- TRUE } else if (isTRUE(input$empty_id)) { @@ -9879,8 +9879,7 @@ server <- function(input, output, session) { title = "Empty ID", type = "warning", position = "bottom-end", - timer = 6000, - width = "300px" + timer = 6000 ) DB$inhibit_change <- TRUE } else { @@ -9898,16 +9897,14 @@ server <- function(input, output, session) { title = "Pending Multi Typing", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { show_toast( title = "Pending Single Typing", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else { showModal( @@ -10705,7 +10702,6 @@ server <- function(input, output, session) { title = "Max. 10 characters", type = "warning", position = "bottom-end", - width = "500px", timer = 6000 ) } else { @@ -10715,7 +10711,6 @@ server <- function(input, output, session) { title = "Min. 1 character", type = "error", position = "bottom-end", - width = "500px", timer = 6000 ) } else { @@ -10725,7 +10720,6 @@ server <- function(input, output, session) { title = "Variable name already existing", type = "warning", position = "bottom-end", - width = "500px", timer = 6000 ) } else { @@ -10789,7 +10783,6 @@ server <- function(input, output, session) { title = paste0("Variable ", trimws(input$new_var_name), " added"), type = "success", position = "bottom-end", - width = "500px", timer = 6000 ) @@ -10804,7 +10797,6 @@ server <- function(input, output, session) { title = "No custom variables", type = "error", position = "bottom-end", - width = "500px", timer = 6000 ) } else { @@ -10842,7 +10834,6 @@ server <- function(input, output, session) { title = paste0("Variable ", input$del_which_var, " removed"), type = "warning", position = "bottom-end", - width = "500px", timer = 6000 ) @@ -10969,8 +10960,7 @@ server <- function(input, output, session) { title = "Invalid rows entered. Saving not possible.", type = "error", position = "bottom-end", - timer = 6000, - width = "600px" + timer = 6000 ) } else { if(!isTRUE(DB$inhibit_change)) { @@ -11006,8 +10996,7 @@ server <- function(input, output, session) { title = "Invalid values entered. Saving not possible.", type = "error", position = "bottom-end", - timer = 6000, - width = "600px" + timer = 6000 ) } } @@ -11101,8 +11090,7 @@ server <- function(input, output, session) { title = "Database successfully saved", type = "success", position = "bottom-end", - timer = 4000, - width = "500px" + timer = 4000 ) }) @@ -11115,8 +11103,7 @@ server <- function(input, output, session) { title = "No entry selected", type = "warning", position = "bottom-end", - timer = 4000, - width = "500px" + timer = 4000 ) } else if((readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") | (tail(readLogFile(), 1) != "0")) { @@ -11126,8 +11113,7 @@ server <- function(input, output, session) { title = "Pending Typing", type = "warning", position = "bottom-end", - timer = 4000, - width = "500px" + timer = 4000 ) } else { if( (length(input$select_delete) - nrow(DB$data) ) == 0) { @@ -11222,16 +11208,14 @@ server <- function(input, output, session) { title = "Entries deleted", type = "success", position = "bottom-end", - timer = 4000, - width = "500px" + timer = 4000 ) } else { show_toast( title = "Entry deleted", type = "success", position = "bottom-end", - timer = 4000, - width = "500px" + timer = 4000 ) } }) @@ -11438,8 +11422,7 @@ server <- function(input, output, session) { title = "Copied sequence", type = "success", position = "bottom-end", - timer = 3000, - width = "400px" + timer = 3000 ) }) @@ -11656,8 +11639,7 @@ server <- function(input, output, session) { title = "Download started", type = "success", position = "bottom-end", - timer = 5000, - width = "400px" + timer = 5000 ) if(length(DB$available) == 0) { @@ -11818,8 +11800,7 @@ server <- function(input, output, session) { title = "Download successful", type = "success", position = "bottom-end", - timer = 5000, - width = "400px" + timer = 5000 ) # TODO Add log message regarding the update of the scheme @@ -12030,8 +12011,7 @@ server <- function(input, output, session) { title = "Label already exists", type = "error", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } } else { @@ -12039,8 +12019,7 @@ server <- function(input, output, session) { title = "Min. 1 character", type = "error", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } }) @@ -12058,8 +12037,7 @@ server <- function(input, output, session) { title = "Label already exists", type = "error", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } } else { @@ -12067,8 +12045,7 @@ server <- function(input, output, session) { title = "Min. 1 character", type = "error", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } }) @@ -21465,8 +21442,7 @@ server <- function(input, output, session) { title = "Missing data", type = "error", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else if(nrow(DB$allelic_profile_true) < 3) { log_print("Min. of 3 entries required for visualization") @@ -21475,8 +21451,7 @@ server <- function(input, output, session) { title = "Min. of 3 entries required for visualization", type = "error", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else { @@ -21543,7 +21518,6 @@ server <- function(input, output, session) { title = "Conflicting Custom Variable Names", type = "warning", position = "bottom-end", - width = "500px", timer = 6000 ) } else { @@ -21699,7 +21673,6 @@ server <- function(input, output, session) { title = "Conflicting Custom Variable Names", type = "warning", position = "bottom-end", - width = "500px", timer = 6000 ) } else { @@ -21860,7 +21833,6 @@ server <- function(input, output, session) { title = "Computation might take a while", type = "warning", position = "bottom-end", - width = "500px", timer = 10000 ) } @@ -22295,7 +22267,6 @@ server <- function(input, output, session) { title = "No tree created", type = "error", position = "bottom-end", - width = "500px", timer = 6000 ) } @@ -22773,7 +22744,6 @@ server <- function(input, output, session) { title = "Wrong file type (only fasta/fna/fa)", type = "error", position = "bottom-end", - width = "500px", timer = 6000 ) @@ -22790,16 +22760,14 @@ server <- function(input, output, session) { title = "Pending Multi Typing", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { show_toast( title = "Pending Single Typing", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else { @@ -22811,7 +22779,6 @@ server <- function(input, output, session) { title = "Gene screening started", type = "success", position = "bottom-end", - width = "500px", timer = 6000 ) @@ -22851,7 +22818,6 @@ server <- function(input, output, session) { title = "Successful gene screening", type = "success", position = "bottom-end", - width = "500px", timer = 6000 ) } else if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { @@ -22862,7 +22828,6 @@ server <- function(input, output, session) { title = "Failed gene screening", type = "error", position = "bottom-end", - width = "500px", timer = 6000 ) } @@ -22943,6 +22908,42 @@ server <- function(input, output, session) { #### Render UI Elements ---- + # Render single typing naming issues + output$single_select_issues <- renderUI({ + req(input$assembly_id) + + if(nchar(trimws(input$assembly_id)) < 1) { + ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) + } else { + ass_id <- trimws(input$assembly_id) + } + + if(ass_id %in% unlist(DB$data["Assembly ID"])) { + HTML(paste( + '', + paste("", + "  Assembly ID already present in database."))) + } else if (ass_id == "") { + HTML(paste( + '', + paste("", + "  Empty Assembly ID."))) + } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { + HTML(paste( + '', + paste("", + "  Invalid Assembly ID. Avoid special characters."))) + } else if(grepl(" ", ass_id)) { + HTML(paste( + '', + paste("", + "  Invalid Assembly ID. Avoid empty spaces."))) + } else {HTML(paste( + '', + paste("", + "  Assembly ID compatible with local database.")))} + }) + # Render Typing Results if finished observe({ if(Typing$progress_format_end == 999999) { @@ -23095,8 +23096,8 @@ server <- function(input, output, session) { output$metadata_single_box <- renderUI({ # Render placeholder - updateTextInput(session, "assembly_id", placeholder = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) - updateTextInput(session, "assembly_name", placeholder = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) + updateTextInput(session, "assembly_id", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) + updateTextInput(session, "assembly_name", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) column( width = 3, @@ -23128,6 +23129,12 @@ server <- function(input, output, session) { ) ) ), + fluidRow( + column( + width = 12, + uiOutput("single_select_issues") + ) + ), fluidRow( column( width = 5, @@ -23260,7 +23267,6 @@ server <- function(input, output, session) { title = "Wrong file type (only fasta/fna/fa)", type = "error", position = "bottom-end", - width = "500px", timer = 6000 ) } @@ -23292,16 +23298,14 @@ server <- function(input, output, session) { title = "Pending Multi Typing", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else if (Screening$status == "started") { show_toast( title = "Pending Gene Screening", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else { @@ -23348,8 +23352,7 @@ server <- function(input, output, session) { title = "Typing Initiated", type = "success", position = "bottom-end", - timer = 6000, - width = "400px" + timer = 6000 ) log_print("Initiated single typing") @@ -23587,8 +23590,35 @@ server <- function(input, output, session) { title = "Assembly ID already present", type = "error", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 + ) + } else if (isFALSE(Typing$reload)) { + show_toast( + title = "Reload Database first", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if (ass_id == "") { + show_toast( + title = "Empty Assembly ID", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { + show_toast( + title = "Invalid Assembly ID. No special characters allowed: ()/\\:*?\"<>|", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if(grepl(" ", ass_id)) { + show_toast( + title = "Empty spaces in Assembly ID not allowed", + type = "error", + position = "bottom-end", + timer = 3000 ) } else { @@ -23613,12 +23643,10 @@ server <- function(input, output, session) { title = "Metadata declared", type = "success", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 ) # Render Start Typing UI - output$start_typing_ui <- renderUI({ div( class = "multi_start_col", @@ -23749,8 +23777,7 @@ server <- function(input, output, session) { title = "Single Typing finalized", type = "success", position = "bottom-end", - timer = 8000, - width = "500px" + timer = 8000 ) Typing$single_end <- TRUE } @@ -24338,48 +24365,49 @@ server <- function(input, output, session) { title = "Assembly ID(s) already present", type = "error", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 ) } else if (any(duplicated(multi_select_table$Files))) { show_toast( title = "Duplicated filename(s)", type = "error", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 ) } else if (any(multi_select_table$Files == "")) { show_toast( title = "Empty filename(s)", type = "error", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 ) } else if (any(grepl("[()/\\:*?\"<>|]", multi_select_table$Files))) { show_toast( title = "Invalid filename(s). No special characters allowed: ()/\\:*?\"<>|", type = "error", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 ) } else if (!any(multi_select_table$Include == TRUE)) { show_toast( title = "No files selected", type = "error", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 ) } else if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { show_toast( title = "Empty spaces in filename(s) not allowed", type = "error", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 + ) + } else if (isFALSE(Typing$reload)) { + show_toast( + title = "Reload Database first", + type = "warning", + position = "bottom-end", + timer = 6000 ) } else { @@ -24399,8 +24427,7 @@ server <- function(input, output, session) { title = "Metadata declared", type = "success", position = "bottom-end", - timer = 3000, - width = "500px" + timer = 3000 ) output$start_multi_typing_ui <- renderUI({ @@ -24569,8 +24596,7 @@ server <- function(input, output, session) { title = "Execution cancelled", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) # Kill multi typing and reset logfile @@ -24646,16 +24672,14 @@ server <- function(input, output, session) { title = "Pending Single Typing", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else if (Screening$status == "started") { show_toast( title = "Pending Gene Screening", type = "warning", position = "bottom-end", - timer = 6000, - width = "500px" + timer = 6000 ) } else { removeModal() @@ -24664,8 +24688,7 @@ server <- function(input, output, session) { title = "Multi Typing started", type = "success", position = "bottom-end", - timer = 10000, - width = "500px" + timer = 10000 ) Typing$new_table <- NULL @@ -24747,7 +24770,6 @@ server <- function(input, output, session) { show_toast( title = paste0("Successful", sub(".*Successful", "", tail(log, 1))), type = "success", - width = "500px", position = "bottom-end", timer = 8000 ) @@ -24756,7 +24778,6 @@ server <- function(input, output, session) { show_toast( title = sub(".* - ", "", tail(log, 1)), type = "error", - width = "700px", position = "bottom-end", timer = 8000 ) @@ -24770,7 +24791,6 @@ server <- function(input, output, session) { show_toast( title = paste0("Successful", sub(".*Successful", "", tail(log, 2)[1])), type = "success", - width = "500px", position = "bottom-end", timer = 8000 ) @@ -24784,7 +24804,6 @@ server <- function(input, output, session) { show_toast( title = sub(".* - ", "", tail(log, 2)[1]), type = "error", - width = "500px", position = "bottom-end", timer = 8000 ) @@ -24800,7 +24819,6 @@ server <- function(input, output, session) { show_toast( title = "Typing finalized", type = "success", - width = "500px", position = "bottom-end", timer = 8000 ) diff --git a/execute/multi_eval.R b/execute/multi_eval.R index d045bc5..eba5b90 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -325,18 +325,26 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # Save new Entry in Typing Database saveRDS(Database, paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Typing.rds")) + isolate_dir <- file.path(db_path, gsub(" ", "_", meta_info$cgmlst_typing), "Isolates") + # Save assembly file if TRUE if(save_assembly) { - if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { + if(dir.exists(isolate_dir)) { # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", filename)) + dir.create(file.path(isolate_dir, filename)) # Copy assembly file in isolate directory - file.copy(paste0(getwd(), "/execute/selected_genomes/", filename, ".fasta"), - paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates/", filename)) + file.copy(file.path(getwd(), "execute/selected_genomes", paste0(filename, ".fasta")), + file.path(isolate_dir, filename)) + + setwd(file.path(isolate_dir, filename)) + + zip(zipfile = paste0(filename, ".zip"), + files = paste0(filename, ".fasta"), + zip = "zip") + + file.remove(paste0(filename, ".fasta")) log_print(paste0("Saved assembly of ", basename(assembly))) @@ -345,23 +353,29 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= log_print("No isolate folder present yet. Isolate directory created.") # Create isolate filder for species - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates")) + dir.create(isolate_dir) # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", filename)) + dir.create(file.path(isolate_dir, filename)) # Copy assembly file in isolate directory - file.copy(paste0(getwd(), "/execute/selected_genomes/", filename, ".fasta"), - paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates/", filename)) + file.copy(paste0(getwd(), "/execute/selected_genomes/", filename, ".fasta") , + file.path(isolate_dir, filename)) + + setwd(file.path(isolate_dir, filename)) + + zip(zipfile = paste0(filename, ".zip"), + files = paste0(filename, ".fasta"), + zip = "zip") + + file.remove(paste0(filename, ".fasta")) log_print(paste0("Saved assembly of ", basename(assembly))) } } + setwd(meta_info$db_directory) + # Logging successes log.message(log_file = paste0(getwd(), "/logs/script_log.txt"), message = paste0("Successful typing of ", sub("\\.(fasta|fna|fa)$", "", basename(assembly)))) @@ -369,6 +383,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= } else { + setwd(meta_info$db_directory) + # Logging failures log.message(log_file = paste0(getwd(), "/logs/script_log.txt"), message = paste0("Assembly typing failed for ", diff --git a/execute/single_eval.R b/execute/single_eval.R index abbe0fb..1fb70a3 100644 --- a/execute/single_eval.R +++ b/execute/single_eval.R @@ -3,7 +3,7 @@ library(logr) # Hand over variables meta_info <- readRDS("meta_info_single.rds") db_path <- readRDS("single_typing_df.rds")[, "db_path"] -save_assembly <- readRDS("multi_typing_df.rds")[, "save"] +save_assembly <- readRDS("single_typing_df.rds")[, "save"] file_list <- list.files(paste0(meta_info$db_directory, "/execute/blat_single"), full.names = TRUE) assembly <- file_list[which(list.files(paste0(meta_info$db_directory, "/execute/blat_single")) != "results")] @@ -310,17 +310,24 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= # Save assembly file if TRUE if(save_assembly) { - if(dir.exists(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Isolates"))) { + + isolate_dir <- file.path(db_path, gsub(" ", "_", meta_info$cgmlst_typing), "Isolates") + + if(dir.exists(isolate_dir)) { # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) + dir.create(file.path(isolate_dir, meta_info$assembly_id)) # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) + file.copy(assembly, file.path(isolate_dir, meta_info$assembly_id)) + + setwd(file.path(isolate_dir, meta_info$assembly_id)) + + zip(zipfile = paste0(meta_info$assembly_id, ".zip"), + files = basename(assembly), + zip = "zip") + + file.remove(basename(assembly)) log_print(paste0("Saved assembly of ", meta_info$assembly_id)) @@ -329,20 +336,22 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= log_print("No isolate folder present yet. Isolate directory created.") # Create isolate filder for species - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates")) + dir.create(isolate_dir) # Create folder for new isolate - dir.create(paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) + dir.create(file.path(isolate_dir, meta_info$assembly_id)) # Copy assembly file in isolate directory - file.copy(assembly, paste0(db_path, "/", - gsub(" ", "_", meta_info$cgmlst_typing), - "/Isolates/", meta_info$assembly_id)) + file.copy(assembly, file.path(isolate_dir, meta_info$assembly_id)) + + setwd(file.path(isolate_dir, meta_info$assembly_id)) + + zip(zipfile = paste0(meta_info$assembly_id, ".zip"), + files = basename(assembly), + zip = "zip") + file.remove(basename(assembly)) + log_print(paste0("Saved assembly of ", meta_info$assembly_id)) } } diff --git a/execute/single_typing.sh b/execute/single_typing.sh index 2b0490f..92d05ed 100755 --- a/execute/single_typing.sh +++ b/execute/single_typing.sh @@ -15,6 +15,8 @@ echo 0 > "$base_path/logs/progress.txt" scheme=$(Rscript -e "cat(readRDS('single_typing_df.rds')[,'scheme'])") alleles=$(Rscript -e "cat(readRDS('single_typing_df.rds')[,'alleles'])") genome_name=$(Rscript -e "cat(basename(readRDS('single_typing_df.rds')[,'genome']))") +genome_name=$(echo "$genome_name" | sed 's/~/ /g') +rename_file=$(Rscript -e "cat(readRDS('meta_info_single.rds')[, 'assembly_id'])") # Remove the existing directory (if it exists) if [ -d "$base_path/execute/blat_single" ]; then @@ -39,8 +41,11 @@ Rscript "$base_path/execute/check_duplicate_single.R" wait genome="$base_path/execute/blat_single/$genome_name" +# Rename file +mv "$genome" "$base_path/execute/blat_single/$rename_file.fasta" + # Run parallelized BLAT -find "$alleles" -type f \( -name "*.fasta" -o -name "*.fa" -o -name "*.fna" \) | parallel pblat $genome {} "$results/{/.}.psl" > /dev/null 2>&1 +find "$alleles" -type f \( -name "*.fasta" -o -name "*.fa" -o -name "*.fna" \) | parallel pblat "$base_path/execute/blat_single/$rename_file.fasta" {} "$results/{/.}.psl" > /dev/null 2>&1 # Start appending results echo 888888 >> "$base_path/logs/progress.txt" diff --git a/www/body.css b/www/body.css index 63216a2..a4eb6e7 100644 --- a/www/body.css +++ b/www/body.css @@ -16,6 +16,11 @@ input[type="checkbox"] { width: 15px; } +.swal2-container .swal2-bottom-end .swal2-backdrop-show, +body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { + width: auto; +} + .sF-fileList>div.selected .sF-file-name div, .sF-dirList div.selected>.sF-file-name>div { background: #20E6E5; color: black; @@ -794,6 +799,11 @@ background: #20E6E5; /* Typing */ +#single_select_issues { + margin-top: 15px; + margin-bottom: 10px; +} + #sel_all_mt { margin-left: 10px; } From 80276adfc75041f43d7bb6c0171a0d0a69d796bc Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Thu, 8 Aug 2024 12:05:19 +0200 Subject: [PATCH 41/75] Implemented compressing and deletion of saved assembly files --- App.R | 31 +++++++++++++++++++++---------- www/body.css | 4 ++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/App.R b/App.R index 8e8276a..70a1de8 100644 --- a/App.R +++ b/App.R @@ -11010,6 +11010,14 @@ server <- function(input, output, session) { observeEvent(input$conf_db_save, { log_print("Input conf_db_save") + # Remove isolate assembly file if present + if(!is.null(DB$remove_iso)) { + if(length(DB$remove_iso) > 0) { + lapply(DB$remove_iso, unlink, recursive = TRUE, force = FALSE, expand = TRUE) + } + } + DB$remove_iso <- NULL + Data <- readRDS(paste0( DB$database, "/", gsub(" ", "_", DB$scheme), @@ -11119,7 +11127,7 @@ server <- function(input, output, session) { if( (length(input$select_delete) - nrow(DB$data) ) == 0) { showModal( modalDialog( - paste0("Deleting will lead to removal of all entries from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?"), + paste0("Deleting will lead to removal of all entries and assemblies from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?"), easyClose = TRUE, title = "Deleting Entries", footer = tagList( @@ -11132,7 +11140,7 @@ server <- function(input, output, session) { showModal( modalDialog( paste0( - "Confirmation will lead to irreversible removal of selected entries. Continue?" + "Confirmation will lead to irreversible removal of selected entries and the respectively saved assembly. Continue?" ), title = "Deleting Entries", fade = TRUE, @@ -11154,7 +11162,8 @@ server <- function(input, output, session) { log_print("Input conf_delete_all") # remove file with typing data - file.remove(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/Typing.rds")) + file.remove(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + unlink(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates"), recursive = TRUE, force = FALSE, expand =TRUE) showModal( modalDialog( @@ -11182,27 +11191,29 @@ server <- function(input, output, session) { log_print("Input conf_delete") + # Get isolates selected for deletion DB$deleted_entries <- append(DB$deleted_entries, DB$data$Index[as.numeric(input$select_delete)]) + # Set reactive status variables DB$no_na_switch <- TRUE - DB$change <- TRUE - DB$check_new_entries <- FALSE - DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] + # Set isolate directory deletion variables + isopath <- dir_ls(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates")) + DB$remove_iso <- isopath[which(basename(isopath) == DB$data$`Assembly ID`[as.numeric(input$select_delete)])] + # Reload updated database reactive variables + DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + # User feedback removeModal() + if(length(input$select_delete) > 1) { show_toast( title = "Entries deleted", diff --git a/www/body.css b/www/body.css index a4eb6e7..ff1d0d9 100644 --- a/www/body.css +++ b/www/body.css @@ -57,6 +57,10 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { border-color: white; } +#conf_delete .btn-default:hover { + background-color: #FF5964 !important; +} + .datepicker table tr td.active:active, .datepicker table tr td.active.active, .datepicker table tr td.active.highlighted:active, .datepicker table tr td.active.highlighted.active { color: #000000; background-color: #20E6E5; From 414fe8a606c4886cc6c7813314a5c21276b96d4a Mon Sep 17 00:00:00 2001 From: infinity-a11y Date: Fri, 9 Aug 2024 11:18:03 +0200 Subject: [PATCH 42/75] Small fixes --- App.R | 83 +++++++++++++++++++++++++++++----------------------- www/body.css | 4 +++ 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/App.R b/App.R index 70a1de8..1c4e894 100644 --- a/App.R +++ b/App.R @@ -5522,7 +5522,7 @@ server <- function(input, output, session) { get.entry.table.meta <- reactive({ if(!is.null(hot_to_r(input$db_entries))){ table <- hot_to_r(input$db_entries) - select(table, 1:(12 + nrow(DB$cust_var))) + select(table, 1:(13 + nrow(DB$cust_var))) } }) @@ -6976,7 +6976,7 @@ server <- function(input, output, session) { DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] @@ -7823,7 +7823,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), + select(DB$data, 1:(13 + nrow(DB$cust_var))), error_highlight = err_thresh() - 1, rowHeaders = NULL, contextMenu = FALSE, @@ -7919,7 +7919,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, dup_names_high = duplicated_names() - 1, dup_ids_high = duplicated_ids() - 1, @@ -8079,7 +8079,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), + select(DB$data, 1:(13 + nrow(DB$cust_var))), rowHeaders = NULL, row_highlight = true_rows() - 1, dup_names_high = duplicated_names()- 1, @@ -8219,7 +8219,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, rowHeaders = NULL, height = table_height(), @@ -8375,7 +8375,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), + select(DB$data, 1:(13 + nrow(DB$cust_var))), rowHeaders = NULL, height = table_height(), dup_names_high = duplicated_names() - 1, @@ -9889,9 +9889,14 @@ server <- function(input, output, session) { # Change scheme observeEvent(input$reload_db, { - log_print("Input reload_db") + cust_var2 <<- DB$cust_var + dataa2 <<- DB$data + meta_gs2 <<- DB$meta_gs + meta2 <<- DB$meta + allelic_profile2 <<- DB$allelic_profile + if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( title = "Pending Multi Typing", @@ -9972,7 +9977,7 @@ server <- function(input, output, session) { DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] @@ -9988,7 +9993,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), + select(DB$data, 1:(13 + nrow(DB$cust_var))), error_highlight = err_thresh() - 1, rowHeaders = NULL, contextMenu = FALSE, @@ -10084,7 +10089,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, dup_names_high = duplicated_names() - 1, dup_ids_high = duplicated_ids() - 1, @@ -10244,7 +10249,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), + select(DB$data, 1:(13 + nrow(DB$cust_var))), rowHeaders = NULL, row_highlight = true_rows() - 1, dup_names_high = duplicated_names()- 1, @@ -10384,7 +10389,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var)), input$compare_select), + select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), col_highlight = diff_allele() - 1, rowHeaders = NULL, height = table_height(), @@ -10540,7 +10545,7 @@ server <- function(input, output, session) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { output$db_entries <- renderRHandsontable({ rhandsontable( - select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))), + select(DB$data, 1:(13 + nrow(DB$cust_var))), rowHeaders = NULL, height = table_height(), dup_names_high = duplicated_names() - 1, @@ -10746,12 +10751,12 @@ server <- function(input, output, session) { observeEvent(input$conf_new_var, { log_print("Input conf_new_var") + # User feedback variables removeModal() - DB$count <- DB$count + 1 - DB$change <- TRUE + # Format variable name name <- trimws(input$new_var_name) if(input$new_var_type == "Categorical (character)") { @@ -10765,16 +10770,20 @@ server <- function(input, output, session) { DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "cont")) } - + dataa <<- DB$data + cust_var <<- DB$cust_var DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) + meta_gs <<- DB$meta_gs + + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + meta <<- DB$meta DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - + allelic_profile <<- DB$allelic_profile DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] log_print(paste0("New custom variable added: ", input$new_var_name)) @@ -10845,7 +10854,7 @@ server <- function(input, output, session) { DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] @@ -11018,37 +11027,35 @@ server <- function(input, output, session) { } DB$remove_iso <- NULL - Data <- readRDS(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/Typing.rds" - )) + Data <<- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) - if ((ncol(Data[["Typing"]])-12) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_vars_pre <- select(Data[["Typing"]], 13:(ncol(Data[["Typing"]]) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - cust_vars_pre <- names(cust_vars_pre) + if ((ncol(Data[["Typing"]]) - 13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_vars_pre <- select(Data[["Typing"]], + 14:(ncol(Data[["Typing"]]) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + cust_vars_pre <<- names(cust_vars_pre) } else { - cust_vars_pre <- character() + cust_vars_pre <<- character() } - Data[["Typing"]] <- select(Data[["Typing"]], -(1:(12 + length(cust_vars_pre)))) + checkpoint <<- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) + Data[["Typing"]] <- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) - meta_hot <- hot_to_r(input$db_entries) + meta_hot <<- hot_to_r(input$db_entries) - if(length(DB$deleted_entries > 0)){ + if(length(DB$deleted_entries > 0)) { meta_hot <- mutate(meta_hot, Index = as.character(1:nrow(DB$data))) - Data[["Typing"]] <- mutate(Data[["Typing"]][-as.numeric(DB$deleted_entries),], meta_hot, .before = 1) + Data[["Typing"]] <- mutate(Data[["Typing"]][-as.numeric(DB$deleted_entries), ], + meta_hot, .before = 1) rownames(Data[["Typing"]]) <- Data[["Typing"]]$Index } else { Data[["Typing"]] <- mutate(Data[["Typing"]], meta_hot, .before = 1) - } # Ensure correct logical data type Data[["Typing"]][["Include"]] <- as.logical(Data[["Typing"]][["Include"]]) - + testdata <<- Data saveRDS(Data, paste0( DB$database, "/", gsub(" ", "_", DB$scheme), @@ -11065,6 +11072,8 @@ server <- function(input, output, session) { DB$data <- Database[["Typing"]] + dataa <- DB$data + if(!is.null(DB$data)){ if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) @@ -11082,7 +11091,7 @@ server <- function(input, output, session) { DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] @@ -11206,7 +11215,7 @@ server <- function(input, output, session) { # Reload updated database reactive variables DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(select(DB$data, -13), 1:(12 + nrow(DB$cust_var))) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] diff --git a/www/body.css b/www/body.css index ff1d0d9..a472966 100644 --- a/www/body.css +++ b/www/body.css @@ -34,6 +34,10 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { background-color: #282F38 !important; } +.handsontable .wtBorder .area .corner { + background-color: #20e6e5 !important; +} + .tooltip-inner { white-space: normal; max-width: 800px; /* Adjust the width as needed */ From 9b72a1b26637a1fd5f23f945c38b9d2132f574e9 Mon Sep 17 00:00:00 2001 From: marian Date: Mon, 12 Aug 2024 14:59:13 +0200 Subject: [PATCH 43/75] Gene Screening User Feedback Progression --- App.R | 540 ++++++++++++++++++++++++++----------------- execute/screening.sh | 47 ++-- 2 files changed, 350 insertions(+), 237 deletions(-) diff --git a/App.R b/App.R index 1c4e894..df76356 100644 --- a/App.R +++ b/App.R @@ -5302,7 +5302,7 @@ ui <- dashboardPage( ), - ## Tab Gene Screening ------------------------------------------------------- + ## Tab Screening ------------------------------------------------------- tabItem( tabName = "gs_screening", @@ -5310,7 +5310,7 @@ ui <- dashboardPage( column( width = 3, align = "center", - h2(p("Gene Screening"), style = "color:white; margin-bottom: -20px;") + h2(p("Screening"), style = "color:white; margin-bottom: -20px;") ), column( width = 7, @@ -5331,7 +5331,7 @@ ui <- dashboardPage( column( width = 3, align = "center", - h2(p("Resistance Profiles"), style = "color:white; margin-bottom: -20px") + h2(p("Browse Entries"), style = "color:white; margin-bottom: -20px") ), column( width = 7, @@ -5673,7 +5673,33 @@ server <- function(input, output, session) { groups } - #Function to check for duplicate isolate IDs for multi typing start + # Check gene screening status + check_status <- function(isolate) { + iso_name <- gsub(".zip", "", basename(isolate)) + if(file.exists(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", iso_name, "status.txt"))) { + if(str_detect(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", iso_name, "status.txt"))[1], + "successfully")) { + return("success") + } else { + return("fail") + } + } else {return("unfinished")} + } + + # Reset gene screening status + remove.screening.status <- function(isolate) { + file.remove( + file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Isolates", + Screening$status_df$isolate, + "status.txt") + ) + } + + # Function to check for duplicate isolate IDs for multi typing start dupl_mult_id <- reactive({ req(Typing$multi_sel_table) if(!is.null(DB$data)) { @@ -6120,7 +6146,6 @@ server <- function(input, output, session) { # reset typing status on start( if(Typing$status == "Finalized") {Typing$status <- "Inactive"} if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} - if(!is.null(Screening$single_path)) {Screening$single_path <- data.frame()} #### Render status bar ---- observe({ @@ -6439,17 +6464,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -6617,17 +6642,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -6707,17 +6732,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -6799,17 +6824,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -6920,17 +6945,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -7157,17 +7182,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -7224,17 +7249,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -9172,17 +9197,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -9663,17 +9688,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -9726,17 +9751,17 @@ server <- function(input, output, session) { icon = icon("gears") ), menuItem( - text = "Gene Screening", + text = "Resistance Profile", tabName = "gene_screening", icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Screen Assembly", - tabName = "gs_screening" + text = "Browse entries", + tabName = "gs_profile" ), menuSubItem( - text = "Resistance Profile", - tabName = "gs_profile" + text = "Screening", + tabName = "gs_screening" ) ), menuItem( @@ -9891,11 +9916,7 @@ server <- function(input, output, session) { observeEvent(input$reload_db, { log_print("Input reload_db") - cust_var2 <<- DB$cust_var - dataa2 <<- DB$data - meta_gs2 <<- DB$meta_gs - meta2 <<- DB$meta - allelic_profile2 <<- DB$allelic_profile + test <<- Screening$status_df if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( @@ -22537,48 +22558,37 @@ server <- function(input, output, session) { ) }) - output$screening_results <- renderUI({ - if(!is.null(Screening$results)) { - dataTableOutput("screening_table") - } - }) - observe({ - if(isTRUE(Screening$fail)) { - output$screening_fail <- renderPrint({ - readLines(paste0(getwd(), "/execute/screening/error.txt")) - }) - } else { - output$screening_fail <- NULL - } - }) - - - observe({ - if(!is.null(Screening$results)) { - req(Screening$results) - - output$screening_table <- renderDataTable( - select(Screening$results, c(6, 7, 8, 9, 11)), - selection = "single", - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ))) - } + req(input$screening_res_sel, DB$database, DB$scheme, Screening$status_df) + if(length(input$screening_res_sel) > 0) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", + input$screening_res_sel, "resProfile.tsv")) + + output$screening_table <- renderDataTable( + select(results, c(6, 7, 8, 9, 11)), + selection = "single", + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ))) + } else {output$screening_table <- NULL} + } else { + output$screening_table <- NULL + } }) # Availablity feedback @@ -22639,26 +22649,67 @@ server <- function(input, output, session) { fluidRow( column(1), column( - width = 3, + width = 4, align = "center", br(), br(), p( HTML( paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Assembly File (FASTA)') + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Isolates for Screening') ) ) ), - shinyFilesButton( - "genome_file_gs", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), + if(length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) > 0 & + length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) > 0) { + div( + class = "screening_div", + pickerInput( + "screening_select", + "", + choices = list(Unscreened = DB$data$`Assembly ID`[which(DB$data$Screened == "No")], + Screened = DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + } else if(length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) > 0) { + div( + class = "screening_div", + pickerInput( + "screening_select", + "", + choices = list(Unscreened = DB$data$`Assembly ID`[which(DB$data$Screened == "No")]), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + } else { + div( + class = "screening_div", + pickerInput( + "screening_select", + "", + choices = list(Screened = DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + }, br(), br(), uiOutput("genome_path_gs") ), @@ -22666,18 +22717,33 @@ server <- function(input, output, session) { column( width = 2, uiOutput("screening_start") - ) + ), + column(1) + # column( + # width = 3, + # align = "left", + # box( + # solidHeader = TRUE, + # status = "primary", + # width = "90%", + # HTML(paste("", + # "AMRFinder Database Status")), + # + # ) + # ) ), fluidRow( column(1), column( width = 10, br(), br(), br(), br(), - uiOutput("screening_results"), - verbatimTextOutput("screening_fail"), - br(), br(), br(), br(), br(), br() + uiOutput("screening_result_sel"), + br(), + uiOutput("screening_result"), + br(), br(), br(), br(), br(), br(), br(), br(), br() ) - ) + ), + br(), br(), br(), br(), br(), br(), br(), br() ) } }) @@ -22688,86 +22754,49 @@ server <- function(input, output, session) { observeEvent(input$screening_reset_bttn, { log_print("Reset gene screening") Screening$status <- "idle" - file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) - file.remove(paste0(getwd(), "/execute/screening/error.txt")) + sapply(Screening$status_df$isolate, remove.screening.status) Screening$results <- NULL - Screening$single_path <- data.frame() Screening$fail <- NULL - }) - - # Get selected Genome in Single Mode - - observe({ - shinyFileChoose(input, - "genome_file_gs", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - Screening$single_path <- parseFilePaths(roots = c(Home = path_home(), Root = "/"), input$genome_file_gs) - + output$screening_table <- NULL + Screening$status_df <- NULL }) # Get selected assembly observe({ - if (nrow(Screening$single_path) < 1) { + if (length(input$screening_select) < 1) { output$genome_path_gs <- renderUI(HTML( - paste("", "No file selected.") + paste("", length(input$screening_select), " isolates queried for screening.") )) output$screening_start <- NULL - } else if (nrow(Screening$single_path) > 0) { + } else if (length(input$screening_select) > 0) { - if (str_detect(str_sub(Screening$single_path$name, start = -6), ".fasta") | - str_detect(str_sub(Screening$single_path$name, start = -6), ".fna") | - str_detect(str_sub(Screening$single_path$name, start = -6), ".fa")) { - - # Render selected assembly path - output$genome_path_gs <- renderUI({ - HTML( - paste( - "", - as.character(Screening$single_path$name) - ) - ) - }) + output$screening_start <- renderUI({ - output$screening_start <- renderUI({ - - fluidRow( - column( - width = 8, - br(), br(), - if(Screening$status == "finished") { - actionButton( - "screening_reset_bttn", - "Reset", - icon = icon("arrows-rotate") - ) - } else if(Screening$status == "idle") { - actionButton( - inputId = "screening_start_button", - label = "Start", - icon = icon("circle-play") - ) - } else if(Screening$status == "started") { - HTML(paste('')) - } - ) + fluidRow( + column( + width = 8, + br(), br(), + if(Screening$status == "finished") { + actionButton( + "screening_reset_bttn", + "Reset", + icon = icon("arrows-rotate") + ) + } else if(Screening$status == "idle") { + actionButton( + inputId = "screening_start_button", + label = "Start", + icon = icon("circle-play") + ) + } else if(Screening$status == "started") { + HTML(paste('')) + } ) - }) - - } else { - show_toast( - title = "Wrong file type (only fasta/fna/fa)", - type = "error", - position = "bottom-end", - timer = 6000 ) - - } + }) } }) @@ -22802,58 +22831,135 @@ server <- function(input, output, session) { timer = 6000 ) - screening_df <- data.frame(wd = getwd(), - assembly_path = Screening$single_path$datapath, - assembly = as.character(basename(Screening$single_path$name)), + Screening$meta_df <- data.frame(wd = getwd(), + selected = paste( + file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_select, + paste0(input$screening_select, ".zip")), + collapse = " "), species = gsub(" ", "_", DB$scheme)) - saveRDS(screening_df, paste0(getwd(), "/execute/screening_meta.rds")) + Screening$status_df <- data.frame(isolate = basename(gsub(".zip", "", str_split_1(Screening$meta_df$selected, " "))), + status = "unfinished", shown = FALSE) + + # Reset screening status + sapply(Screening$status_df$isolate, remove.screening.status) + + saveRDS(Screening$meta_df, paste0(getwd(), "/execute/screening_meta.rds")) # System execution screening.sh system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) - } }) ### Screening Feedback ---- observe({ - req(Screening$status) - if(Screening$status == "started") { - shinyjs::disable("genome_file_gs") - check_screening() - } else if(Screening$status == "idle") { - shinyjs::enable("genome_file_gs") - } - }) - - check_screening <- reactive({ - invalidateLater(2000, session) - if(Screening$status == "started"){ - if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { - Screening$results <- read.delim(paste0(getwd(), "/execute/screening/output_file.tsv")) - Screening$status <- "finished" - log_print("Finalized gene screening") - show_toast( - title = "Successful gene screening", - type = "success", - position = "bottom-end", - timer = 6000 + req(Screening$status, Screening$status_df, input$screening_res_sel) + if(Screening$status != "idle") { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + output$screening_result <- renderUI( + dataTableOutput("screening_table") ) - } else if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { - Screening$status <- "finished" - log_print("Failed gene screening") - Screening$fail <- TRUE - show_toast( - title = "Failed gene screening", - type = "error", - position = "bottom-end", - timer = 6000 + } else { + output$screening_result <- renderUI( + verbatimTextOutput("screening_fail") ) } + } else { + output$screening_result <- NULL + } + }) + + observe({ + req(req(Screening$status, Screening$status_df, input$screening_res_sel)) + if(Screening$status != "idle") { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { + output$screening_fail <- renderPrint({ + readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_res_sel, "status.txt")) + }) + } } }) + observe({ + req(Screening$status) + if(Screening$status == "started") { + + # start status screening for user feedback + check_screening() + + if(isTRUE(Screening$first_result)) { + output$screening_result_sel <- renderUI( + selectInput( + "screening_res_sel", + "Select Result", + choices = "" + ) + ) + + Screening$first_result <- FALSE + } + } else if(Screening$status == "idle") { + output$screening_result_sel <- NULL + } + }) + + check_screening <- reactive({ + invalidateLater(2000, session) + + req(Screening$status_df) + + if(Screening$status == "started") { + + Screening$status_df$status <- sapply(Screening$status_df$isolate, check_status) + + if(any("unfinished" != Screening$status_df$status) & + !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status == "success")])) { + + status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] + + Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | + Screening$status_df$status == "fail")] + + if(sum("unfinished" != Screening$status_df$status) == 1) { + Screening$first_result <- TRUE + } + + if(tail(status_df$status, 1) == "success") { + + show_toast( + title = paste("Successful screening of", tail(Screening$choices, 1)), + type = "success", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + + } else if(tail(status_df$status, 1) == "fail") { + show_toast( + title = paste("Failed screening of", tail(status_df$isolate, 1)), + type = "error", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + } + + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } + } + }) + # _______________________ #### diff --git a/execute/screening.sh b/execute/screening.sh index 75b0351..0a9a0f9 100755 --- a/execute/screening.sh +++ b/execute/screening.sh @@ -7,12 +7,9 @@ unset R_HOME # Set base path base_path=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'wd'])") -path_assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly_path'])") -assembly=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'assembly'])") +selected=$(Rscript -e "cat(stringr::str_split_1(readRDS('screening_meta.rds')[,'selected'], ' '))") species=$(Rscript -e "cat(readRDS('screening_meta.rds')[,'species'])") -error_file="screening/error.txt" - if [ "$species" = "Escherichia_coli" ]; then species="Escherichia" fi @@ -42,22 +39,32 @@ if [ -d "$base_path/execute/screening" ]; then rm -r "$base_path/execute/screening" fi -mkdir "$base_path/execute/screening" - -amrfinder -n "$path_assembly" --plus --organism $species -o "screening/output_file.tsv" > amrfinder_stdout.txt 2> amrfinder_stderr.txt -status=$? +isolates=($selected) -# Check if status variable is set and is an integer -if [ -z "$status" ]; then - echo "AMRFinder execution did not set an exit status." > "$base_path/execute/$error_file" - exit 1 -fi +# Loop through the list of file names and copy them to the new folder +for file in "${isolates[@]}"; do -if [ "$status" -ne 0 ]; then - echo "AMRFinder failed with status $status" > "$base_path/execute/$error_file" - echo "Error details:" >> "$base_path/execute/$error_file" - cat amrfinder_stderr.txt >> "$base_path/execute/$error_file" - exit $status -fi + # Get the directory and base name of the zip file + zip_dir=$(dirname "$file") + zip_base=$(basename "$file" .zip) + + unzip -o "$file" -d "$zip_dir" + + amrfinder -n "$zip_dir/$zip_base.fasta" --plus --organism $species -o "$zip_dir/resProfile.tsv" > amrfinder_stdout.txt 2> amrfinder_stderr.txt + status=$? + + # Check exit status + if [ "$status" -ne 0 ]; then + echo "AMRFinder failed with status $status" > "$zip_dir/status.txt" + echo "Error details:" >> "$zip_dir/status.txt" + cat amrfinder_stderr.txt >> "$zip_dir/status.txt" + else + # Write success message if AMRFinder executed successfully + echo "AMRFinder executed successfully for $zip_base" > "$zip_dir/status.txt" + fi + + # Clear unzipped assembly + rm -rf "$zip_dir/$zip_base.fasta" +done -echo "AMRFinder completed successfully" +echo "AMRFinder finalized" From ec4217bf01fc9462ca626b759e021d76173ce426 Mon Sep 17 00:00:00 2001 From: marian Date: Mon, 12 Aug 2024 23:40:45 +0200 Subject: [PATCH 44/75] Polished Screening UI; Added Screening Termination --- App.R | 431 ++++++++++++++++++++++++++++-------------- execute/kill_multi.sh | 2 +- www/body.css | 346 ++++++++++++++++----------------- 3 files changed, 465 insertions(+), 314 deletions(-) diff --git a/App.R b/App.R index df76356..b028abf 100644 --- a/App.R +++ b/App.R @@ -582,7 +582,7 @@ ui <- dashboardPage( fluidRow( column( width = 6, - uiOutput("test_yes_pending") + uiOutput("pending_typing") ), column( width = 6, @@ -5320,7 +5320,9 @@ ui <- dashboardPage( ), br(), hr(), - uiOutput("screening_interface") + fluidRow( + uiOutput("screening_interface") + ) ), ## Tab Resistance Profile ------------------------------------------------------- @@ -5690,13 +5692,19 @@ server <- function(input, output, session) { # Reset gene screening status remove.screening.status <- function(isolate) { - file.remove( - file.path(DB$database, - gsub(" ", "_", DB$scheme), - "Isolates", - Screening$status_df$isolate, - "status.txt") - ) + if(file.exists(file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Isolates", + isolate, + "status.txt"))) { + file.remove( + file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Isolates", + isolate, + "status.txt") + ) + } } # Function to check for duplicate isolate IDs for multi typing start @@ -6469,7 +6477,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -6512,7 +6520,7 @@ server <- function(input, output, session) { output$multi_stop <- NULL output$metadata_multi_box <- NULL output$start_multi_typing_ui <- NULL - output$test_yes_pending <- NULL + output$pending_typing <- NULL output$multi_typing_results <- NULL output$single_typing_progress <- NULL output$metadata_single_box <- NULL @@ -6549,7 +6557,7 @@ server <- function(input, output, session) { output$multi_stop <- NULL output$metadata_multi_box <- NULL output$start_multi_typing_ui <- NULL - output$test_yes_pending <- NULL + output$pending_typing <- NULL output$multi_typing_results <- NULL output$single_typing_progress <- NULL output$metadata_single_box <- NULL @@ -6647,7 +6655,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -6737,7 +6745,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -6829,7 +6837,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -6950,7 +6958,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -7187,7 +7195,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -7254,7 +7262,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -9202,7 +9210,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -9358,7 +9366,7 @@ server <- function(input, output, session) { output$multi_stop <- NULL output$metadata_multi_box <- NULL output$start_multi_typing_ui <- NULL - output$test_yes_pending <- NULL + output$pending_typing <- NULL output$multi_typing_results <- NULL output$single_typing_progress <- NULL output$metadata_single_box <- NULL @@ -9693,7 +9701,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -9756,7 +9764,7 @@ server <- function(input, output, session) { icon = icon("dna"), startExpanded = TRUE, menuSubItem( - text = "Browse entries", + text = "Browse Entries", tabName = "gs_profile" ), menuSubItem( @@ -22559,7 +22567,8 @@ server <- function(input, output, session) { }) observe({ - req(input$screening_res_sel, DB$database, DB$scheme, Screening$status_df) + req(input$screening_res_sel, DB$database, DB$scheme) + if(!is.null(Screening$status_df)) { if(length(input$screening_res_sel) > 0) { if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", @@ -22589,6 +22598,10 @@ server <- function(input, output, session) { } else { output$screening_table <- NULL } + } else { + output$screening_table <- NULL + } + }) # Availablity feedback @@ -22649,7 +22662,7 @@ server <- function(input, output, session) { fluidRow( column(1), column( - width = 4, + width = 3, align = "center", br(), br(), p( @@ -22713,11 +22726,16 @@ server <- function(input, output, session) { br(), br(), uiOutput("genome_path_gs") ), - column(1), column( - width = 2, + width = 3, uiOutput("screening_start") ), + column( + width = 3, + align = "center", + br(), br(), + uiOutput("screening_result_sel") + ), column(1) # column( # width = 3, @@ -22736,14 +22754,11 @@ server <- function(input, output, session) { column(1), column( width = 10, - br(), br(), br(), br(), - uiOutput("screening_result_sel"), - br(), + br(), br(), uiOutput("screening_result"), - br(), br(), br(), br(), br(), br(), br(), br(), br() + br(), br(), br(), br() ) - ), - br(), br(), br(), br(), br(), br(), br(), br() + ) ) } }) @@ -22753,12 +22768,54 @@ server <- function(input, output, session) { # Reset screening observeEvent(input$screening_reset_bttn, { log_print("Reset gene screening") - Screening$status <- "idle" + + # reset status file sapply(Screening$status_df$isolate, remove.screening.status) + + # set feedback variables + Screening$status <- "idle" Screening$results <- NULL Screening$fail <- NULL + Screening$status_df <- NULL + + # change reactive UI output$screening_table <- NULL + output$screening_result <- NULL + output$screening_fail <- NULL + + updatePickerInput(session, "screening_select", selected = character(0)) + + # disable isolate picker + shinyjs::runjs("$('#screening_select').prop('disabled', false);") + shinyjs::runjs("$('#screening_select').selectpicker('refresh');") + }) + + # Cancel screening + observeEvent(input$screening_cancel, { + log_print("Cancelled gene screening") + + # terminate screening + system(paste("kill $(pgrep -f 'execute/screening.sh')"), wait = FALSE) + system(paste("killall -TERM tblastn"), wait = FALSE) + + # reset status file + sapply(Screening$status_df$isolate, remove.screening.status) + + # set feedback variables + Screening$status <- "idle" + Screening$results <- NULL + Screening$fail <- NULL Screening$status_df <- NULL + + # change reactive UI + output$screening_table <- NULL + output$screening_result <- NULL + + updatePickerInput(session, "screening_select", selected = character(0)) + + # disable isolate picker + shinyjs::runjs("$('#screening_select').prop('disabled', false);") + shinyjs::runjs("$('#screening_select').selectpicker('refresh');") }) # Get selected assembly @@ -22777,22 +22834,91 @@ server <- function(input, output, session) { fluidRow( column( - width = 8, + width = 12, br(), br(), - if(Screening$status == "finished") { - actionButton( - "screening_reset_bttn", - "Reset", - icon = icon("arrows-rotate") + if(length(input$screening_select) < 1) { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Select Isolate(s) for Screening"))) + ) + ) + } else if(Screening$status == "finished") { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Reset to Perform Screening Again"))) + ), + actionButton( + "screening_reset_bttn", + "Reset", + icon = icon("arrows-rotate") + ), + if(!is.null(Screening$status_df)) { + p( + HTML(paste("", + sum(Screening$status_df$status != "unfinished"), "/", + nrow(Screening$status_df), " Isolate(s) screened")) + ) + } ) } else if(Screening$status == "idle") { - actionButton( - inputId = "screening_start_button", - label = "Start", - icon = icon("circle-play") + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Screening Ready"))) + ), + actionButton( + inputId = "screening_start_button", + label = "Start", + icon = icon("circle-play") + ) ) } else if(Screening$status == "started") { - HTML(paste('')) + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Running Screening ..."))) + ), + fluidRow( + column(3), + column( + width = 3, + actionButton( + inputId = "screening_cancel", + label = "Terminate", + icon = icon("ban") + ) + ), + column( + width = 3, + HTML(paste('')) + ) + ), + if(!is.null(Screening$status_df)) { + p( + HTML(paste("", + sum(Screening$status_df$status != "unfinished"), "/", + nrow(Screening$status_df), " Isolate(s) screened")) + ) + } + ) } ) ) @@ -22824,6 +22950,9 @@ server <- function(input, output, session) { Screening$status <- "started" + shinyjs::runjs("$('#screening_select').prop('disabled', true);") + shinyjs::runjs("$('#screening_select').selectpicker('refresh');") + show_toast( title = "Gene screening started", type = "success", @@ -22855,16 +22984,28 @@ server <- function(input, output, session) { ### Screening Feedback ---- observe({ - req(Screening$status, Screening$status_df, input$screening_res_sel) - if(Screening$status != "idle") { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { - output$screening_result <- renderUI( - dataTableOutput("screening_table") - ) + req(Screening$status, input$screening_res_sel) + if(!is.null(Screening$status_df)) { + if(Screening$status != "idle") { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + dataTableOutput("screening_table") + ) + ) + } else { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + verbatimTextOutput("screening_fail") + ) + ) + } } else { - output$screening_result <- renderUI( - verbatimTextOutput("screening_fail") - ) + output$screening_result <- NULL } } else { output$screening_result <- NULL @@ -22872,93 +23013,99 @@ server <- function(input, output, session) { }) observe({ - req(req(Screening$status, Screening$status_df, input$screening_res_sel)) - if(Screening$status != "idle") { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { - output$screening_fail <- renderPrint({ - readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", input$screening_res_sel, "status.txt")) - }) + req(Screening$status, input$screening_res_sel) + if(!is.null(Screening$status_df)) { + if(Screening$status != "idle") { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { + output$screening_fail <- renderPrint({ + cat(paste(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_res_sel, "status.txt")),"\n")) + }) + } + } else { + output$screening_fail <- NULL } + } else { + output$screening_fail <- NULL } }) - observe({ - req(Screening$status) - if(Screening$status == "started") { - - # start status screening for user feedback - check_screening() - - if(isTRUE(Screening$first_result)) { - output$screening_result_sel <- renderUI( - selectInput( - "screening_res_sel", - "Select Result", - choices = "" - ) - ) - - Screening$first_result <- FALSE - } - } else if(Screening$status == "idle") { - output$screening_result_sel <- NULL - } - }) - - check_screening <- reactive({ - invalidateLater(2000, session) - - req(Screening$status_df) - - if(Screening$status == "started") { - - Screening$status_df$status <- sapply(Screening$status_df$isolate, check_status) - - if(any("unfinished" != Screening$status_df$status) & - !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status == "success")])) { - - status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] - - Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | - Screening$status_df$status == "fail")] - - if(sum("unfinished" != Screening$status_df$status) == 1) { - Screening$first_result <- TRUE - } - - if(tail(status_df$status, 1) == "success") { - - show_toast( - title = paste("Successful screening of", tail(Screening$choices, 1)), - type = "success", - position = "bottom-end", - timer = 6000) - - updateSelectInput(session = session, - inputId = "screening_res_sel", - choices = Screening$choices, - selected = tail(Screening$choices, 1)) - - } else if(tail(status_df$status, 1) == "fail") { - show_toast( - title = paste("Failed screening of", tail(status_df$isolate, 1)), - type = "error", - position = "bottom-end", - timer = 6000) - - updateSelectInput(session = session, - inputId = "screening_res_sel", - choices = Screening$choices, - selected = tail(Screening$choices, 1)) - } - - if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - Screening$status <- "finished" - } - } - } - }) + observe({ + req(Screening$status) + if(Screening$status == "started") { + + # start status screening for user feedback + check_screening() + + if(isTRUE(Screening$first_result)) { + output$screening_result_sel <- renderUI( + selectInput( + "screening_res_sel", + label = h5("Select Result", style = "color:white; margin-bottom: 32px; margin-top: -10px;"), + choices = "" + ) + ) + + Screening$first_result <- FALSE + } + } else if(Screening$status == "idle") { + output$screening_result_sel <- NULL + } + }) + + check_screening <- reactive({ + invalidateLater(2000, session) + + req(Screening$status_df) + + if(Screening$status == "started") { + + Screening$status_df$status <- sapply(Screening$status_df$isolate, check_status) + + if(any("unfinished" != Screening$status_df$status) & + !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status != "unfinished")])) { + + status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] + + Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | + Screening$status_df$status == "fail")] + + if(sum("unfinished" != Screening$status_df$status) == 1) { + Screening$first_result <- TRUE + } + + if(tail(status_df$status, 1) == "success") { + + show_toast( + title = paste("Successful screening of", tail(Screening$choices, 1)), + type = "success", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + + } else if(tail(status_df$status, 1) == "fail") { + show_toast( + title = paste("Failed screening of", tail(status_df$isolate, 1)), + type = "error", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + } + + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } + } + }) # _______________________ #### @@ -24703,7 +24850,7 @@ server <- function(input, output, session) { ) }) - output$test_yes_pending <- NULL + output$pending_typing <- NULL output$multi_typing_results <- NULL } }) @@ -24735,7 +24882,7 @@ server <- function(input, output, session) { # Reset User Feedback variable Typing$pending_format <- 0 - output$test_yes_pending <- NULL + output$pending_typing <- NULL output$multi_typing_results <- NULL Typing$failures <- 0 Typing$successes <- 0 @@ -25066,14 +25213,14 @@ server <- function(input, output, session) { output$initiate_multi_typing_ui <- NULL - output$test_yes_pending <- renderUI({ + output$pending_typing <- renderUI({ fluidRow( fluidRow( br(), br(), column(width = 2), column( width = 4, - h3(p("Pending Multi Typing ..."), style = "color:white"), + h3(p("Pending Typing ..."), style = "color:white"), br(), br(), fluidRow( column( @@ -25110,7 +25257,7 @@ server <- function(input, output, session) { output$initiate_multi_typing_ui <- NULL - output$test_yes_pending <- renderUI({ + output$pending_typing <- renderUI({ fluidRow( fluidRow( @@ -25158,7 +25305,7 @@ server <- function(input, output, session) { ) }) } else if (!grepl("Start Multi Typing", head(readLogFile(), n = 1))){ - output$test_yes_pending <- NULL + output$pending_typing <- NULL Typing$multi_result_status <- "idle" } }) diff --git a/execute/kill_multi.sh b/execute/kill_multi.sh index 6d1c7e7..2708e6e 100755 --- a/execute/kill_multi.sh +++ b/execute/kill_multi.sh @@ -33,4 +33,4 @@ else kill "$PID" fi -echo 0 > $log_file \ No newline at end of file +echo 0 > $log_file diff --git a/www/body.css b/www/body.css index a472966..c0652e4 100644 --- a/www/body.css +++ b/www/body.css @@ -159,7 +159,7 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { border: 1px solid #00000000; border-width: 1px; display: inline-block; /* Make the element inline-block */ - transition: border-color 0.3s ease; /* Smooth transition for border color */ + transition: border-color 0.3s ease; /* Smooth transition for border color */ } .bttn-material-flat:hover{ @@ -168,20 +168,20 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { .action-button.bttn.bttn-material-flat.bttn-sm.bttn-default.bttn-no-outline.shiny-bound-input { background: #282F38 !important; - border: 1px solid transparent; /* Default border color */ - display: inline-block; /* Make the element inline-block */ - transition: border-color 0.3s ease; /* Smooth transition for border color */ - border-width: 1px !important; + border: 1px solid transparent; /* Default border color */ + display: inline-block; /* Make the element inline-block */ + transition: border-color 0.3s ease; /* Smooth transition for border color */ + border-width: 1px !important; border-color: white !important; color: white !important; transition: background 0.3s ease; /* Smooth transition for border color */ - transition: color 0.3s ease; /* Smooth transition for border color */ + transition: color 0.3s ease; /* Smooth transition for border color */ } .action-button.bttn.bttn-material-flat.bttn-sm.bttn-default.bttn-no-outline.shiny-bound-input:hover { border-color: transparent !important; /* Change border color to white on hover */ - background: #20E6E5 !important; - color: black !important; + background: #20E6E5 !important; + color: black !important; } .shiny-input-container input[type = "text"]:hover { @@ -194,14 +194,14 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { .main-sidebar .sidebar .sidebar-menu .treeview-menu li.active a { color: #000000 !important; - border-radius: 20px; + border-radius: 20px; margin-top: 7px; margin-bottom: 7px; } .main-sidebar .sidebar .sidebar-menu .treeview-menu li:hover a { color: #000000; - border-radius: 20px; + border-radius: 20px; margin-top: 7px; margin-bottom: 7px; } @@ -212,7 +212,7 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { .main-sidebar .sidebar .sidebar-menu li:hover a { color: #000000; - border: none; + border: none; } file.select { @@ -221,17 +221,17 @@ file.select { .box.box-solid.box-info{ background: #282F38; - margin-top: 20px; + margin-top: 20px; position: relative; left: 30px; } .box.box-solid.box-info, .box.box-info { border-color: #ffffff; - border-left-color: #ffffff; - border-right-color: #ffffff; - border-top-color: #ffffff; - border-radius: 7px; + border-left-color: #ffffff; + border-right-color: #ffffff; + border-top-color: #ffffff; + border-radius: 7px; } .selectize-control.single .selectize-input:after { @@ -1847,108 +1847,108 @@ margin-left: -5px } #nj_tiplab_show, #upgma_tiplab_show { -margin-top: 17px; -margin-left: -5px + margin-top: 17px; + margin-left: -5px } #nj_fruit_offset, #upgma_fruit_offset { -position: relative; -top: -20px + position: relative; + top: -20px } #nj_layout .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ -margin-bottom: 16px + margin-bottom: 16px } #nj_div_tiles, #upgma_div_tiles { -position: absolute; -bottom: 4px; -margin-left: -5px + position: absolute; + bottom: 4px; + margin-left: -5px } #nj_fruit_offset_2, #upgma_fruit_offset_2 { -position: relative; -top: -20px + position: relative; + top: -20px } #nj_layout_2 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_2 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ -margin-bottom: 16px + margin-bottom: 16px } #nj_div_tiles_2, #upgma_div_tiles_2 { -position: absolute; -bottom: 4px; -margin-left: -5px + position: absolute; + bottom: 4px; + margin-left: -5px } #nj_fruit_offset_3, #upgma_fruit_offset_3 { -position: relative; -top: -20px + position: relative; + top: -20px } #nj_layout_3 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_3 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ -margin-bottom: 16px + margin-bottom: 16px } #nj_div_tiles_3, #upgma_div_tiles_3 { -position: absolute; -bottom: 4px; -margin-left: -5px + position: absolute; + bottom: 4px; + margin-left: -5px } #nj_fruit_offset_4, #upgma_fruit_offset_4 { -position: relative; -top: -20px + position: relative; + top: -20px } #nj_layout_4 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_4 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y{ -margin-bottom: 16px + margin-bottom: 16px } #nj_div_tiles_4, #upgma_div_tiles_4 { -position: absolute; -bottom: 4px; -margin-left: -5px + position: absolute; + bottom: 4px; + margin-left: -5px } #nj_fruit_offset_5, #upgma_fruit_offset_5 { -position: relative; -top: -20px + position: relative; + top: -20px } #nj_layout_5 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y, #upgma_layout_5 .shiny-input-select.shinyjs-resettable.selectize-control.single plugin-selectize-plugin-a11y { -margin-bottom: 16px + margin-bottom: 16px } #nj_div_tiles_5, #upgma_div_tiles_5 { -position: absolute; -bottom: 4px; -margin-left: -5px + position: absolute; + bottom: 4px; + margin-left: -5px } #nj_heatmap_width, #upgma_heatmap_width { -margin-top: 8px; + margin-top: 8px; } #nj_heatmap_offset, #upgma_heatmap_offset { -margin-top: 4px; -margin-bottom: 2px; + margin-top: 4px; + margin-bottom: 2px; } #nj_fruit_width, #nj_fruit_width2, #nj_fruit_width3, #nj_fruit_width4, #nj_fruit_width5, #upgma_fruit_width, #upgma_fruit_width2, #upgma_fruit_width3, #upgma_fruit_width4, #upgma_fruit_width5{ -margin-top: -5px; -margin-bottom: -15px; + margin-top: -5px; + margin-bottom: -15px; } #nj_heatmap_show, #upgma_heatmap_show { -margin-top: 18px; -margin-left: -5px; + margin-top: 18px; + margin-left: -5px; } #nj_nodepoint_show, #nj_tippoint_show, #upgma_nodepoint_show, #upgma_tippoint_show { @@ -2524,10 +2524,10 @@ background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E0ECF4 11.1 #upgma_tiles_scale_5 .option[data-value="BuGn"], #upgma_heatmap_scale .option[data-value="BuGn"], #upgma_clade_scale .option[data-value="BuGn"] { -background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E5F5F9 11.1111%, #E5F5F9 22.2222%, #CCECE6 22.2222%, #CCECE6 33.3333%, #99D8C9 33.3333%, #99D8C9 44.4444%, #66C2A4 44.4444%, #66C2A4 55.5556%, #41AE76 55.5556%, #41AE76 66.6667%, #238B45 66.6667%, #238B45 77.7778%, #006D2C 77.7778%, #006D2C 88.8889%, #00441B 88.8889%, #00441B 100%); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E5F5F9 11.1111%, #E5F5F9 22.2222%, #CCECE6 22.2222%, #CCECE6 33.3333%, #99D8C9 33.3333%, #99D8C9 44.4444%, #66C2A4 44.4444%, #66C2A4 55.5556%, #41AE76 55.5556%, #41AE76 66.6667%, #238B45 66.6667%, #238B45 77 .7778%, #006D2C 77.7778%, #006D2C 88.8889%, #00441B 88.8889%, #00441B 100%); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="Blues"], #nj_tippoint_scale .option[data-value="Blues"], @@ -2547,10 +2547,10 @@ background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E5F5F9 11.1 #upgma_tiles_scale_5 .option[data-value="Blues"], #upgma_heatmap_scale .option[data-value="Blues"], #upgma_clade_scale .option[data-value="Blues"] { -background: linear-gradient(to right, #F7FBFF 0%, #F7FBFF 11.1111%, #DEEBF7 11.1111%, #DEEBF7 22.2222%, #C6DBEF 22.2222%, #C6DBEF 33.3333%, #9ECAE1 33.3333%, #9ECAE1 44.4444%, #6BAED6 44.4444%, #6BAED6 55.5556%, #4292C6 55.5556%, #4292C6 66.6667%, #2171B5 66.6667%, #2171B5 77.7778%, #08519C 77.7778%, #08519C 88.8889%, #08306B 88.8889%, #08306B 100%); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #F7FBFF 0%, #F7FBFF 11.1111%, #DEEBF7 11.1111%, #DEEBF7 22.2222%, #C6DBEF 22.2222%, #C6DBEF 33.3333%, #9ECAE1 33.3333%, #9ECAE1 44.4444%, #6BAED6 44.4444%, #6BAED6 55.5556%, #4292C6 55.5556%, #4292C6 66.6667%, #2171B5 66.6667%, #2171B5 77 .7778%, #08519C 77.7778%, #08519C 88.8889%, #08306B 88.8889%, #08306B 100%); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="magma"], #nj_tippoint_scale .option[data-value="magma"], @@ -2568,10 +2568,10 @@ background: linear-gradient(to right, #F7FBFF 0%, #F7FBFF 11.1111%, #DEEBF7 11.1 #upgma_tiles_scale_4 .option[data-value="magma"], #upgma_tiles_scale_5 .option[data-value="magma"], #upgma_heatmap_scale .option[data-value="magma"] { -background: linear-gradient(to right, #000004FF, #07071DFF, #160F3BFF, #29115AFF, #400F73FF, #56147DFF, #6B1D81FF, #802582FF, #952C80FF, #AB337CFF, #C03A76FF, #D6456CFF, #E85362FF, #F4685CFF, #FA815FFF, #FD9A6AFF, #FEB37BFF, #FECC8FFF, #FDE4A6FF, #FCFDBFFF); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #000004FF, #07071DFF, #160F3BFF, #29115AFF, #400F73FF, #56147DFF, #6B1D81FF, #802582FF, #952C80FF, #AB337CFF, #C03A76FF, #D6456CFF, #E85362FF, #F4685CFF, #FA815FFF, #FD9A6AFF, #FEB37BFF, #FECC8FFF, #FDE4A6FF, #FCFDBFFF); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="inferno"], #nj_tippoint_scale .option[data-value="inferno"], @@ -2589,10 +2589,10 @@ background: linear-gradient(to right, #000004FF, #07071DFF, #160F3BFF, #29115AFF #upgma_tiles_scale_4 .option[data-value="inferno"], #upgma_tiles_scale_5 .option[data-value="inferno"], #upgma_heatmap_scale .option[data-value="inferno"] { -background: linear-gradient(to right, #000004FF, #08051EFF, #190C3EFF, #300A5BFF, #460B6AFF, #5C126EFF, #711A6EFF, #87216BFF, #9C2964FF, #B1325AFF, #C43C4EFF, #D64B40FF, #E55C30FF, #F17020FF, #F8870EFF, #FCA007FF, #FBB91FFF, #F7D340FF, #F1ED6FFF, #FCFFA4FF); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #000004FF, #08051EFF, #190C3EFF, #300A5BFF, #460B6AFF, #5C126EFF, #711A6EFF, #87216BFF, #9C2964FF, #B1325AFF, #C43C4EFF, #D64B40FF, #E55C30FF, #F17020FF, #F8870EFF, #FCA007FF, #FBB91FFF, #F7D340FF, #F1ED6FFF, #FCFFA4FF); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="plasma"], #nj_tippoint_scale .option[data-value="plasma"], @@ -2610,10 +2610,10 @@ background: linear-gradient(to right, #000004FF, #08051EFF, #190C3EFF, #300A5BFF #upgma_tiles_scale_4 .option[data-value="plasma"], #upgma_tiles_scale_5 .option[data-value="plasma"], #upgma_heatmap_scale .option[data-value="plasma"] { -background: linear-gradient(to right, #0D0887FF, #2D0594FF, #44039EFF, #5901A5FF, #6F00A8FF, #8305A7FF, #9512A1FF, #A72197FF, #B6308BFF, #C5407EFF, #D14E72FF, #DD5E66FF, #E76E5BFF, #EF7F4FFF, #F79044FF, #FBA238FF, #FEB72DFF, #FDCB26FF, #F7E225FF, #F0F921FF); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #0D0887FF, #2D0594FF, #44039EFF, #5901A5FF, #6F00A8FF, #8305A7FF, #9512A1FF, #A72197FF, #B6308BFF, #C5407EFF, #D14E72FF, #DD5E66FF, #E76E5BFF, #EF7F4FFF, #F79044FF, #FBA238FF, #FEB72DFF, #FDCB26FF, #F7E225FF, #F0F921FF); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="viridis"], #nj_tippoint_scale .option[data-value="viridis"], @@ -2631,10 +2631,10 @@ background: linear-gradient(to right, #0D0887FF, #2D0594FF, #44039EFF, #5901A5FF #upgma_tiles_scale_4 .option[data-value="viridis"], #upgma_tiles_scale_5 .option[data-value="viridis"], #upgma_heatmap_scale .option[data-value="viridis"] { -background: linear-gradient(to right, #440154FF, #481568FF, #482677FF, #453781FF, #3F4788FF, #39558CFF, #32648EFF, #2D718EFF, #287D8EFF, #238A8DFF, #1F968BFF, #20A386FF, #29AF7FFF, #3CBC75FF, #56C667FF, #74D055FF, #94D840FF, #B8DE29FF, #DCE318FF, #FDE725FF); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #440154FF, #481568FF, #482677FF, #453781FF, #3F4788FF, #39558CFF, #32648EFF, #2D718EFF, #287D8EFF, #238A8DFF, #1F968BFF, #20A386FF, #29AF7FFF, #3CBC75FF, #56C667FF, #74D055FF, #94D840FF, #B8DE29FF, #DCE318FF, #FDE725FF); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="cividis"], #nj_tippoint_scale .option[data-value="cividis"], @@ -2652,10 +2652,10 @@ background: linear-gradient(to right, #440154FF, #481568FF, #482677FF, #453781FF #upgma_tiles_scale_4 .option[data-value="cividis"], #upgma_tiles_scale_5 .option[data-value="cividis"], #upgma_heatmap_scale .option[data-value="cividis"] { -background: linear-gradient(to right, #00204DFF, #002A64FF, #00336FFF, #1F3C6DFF, #35466BFF, #444F6BFF, #53596CFF, #5F636EFF, #6B6C71FF, #777776FF, #838079FF, #908B79FF, #9D9677FF, #ABA074FF, #B9AC70FF, #C7B76BFF, #D7C463FF, #E5D05AFF, #F5DD4DFF, #FFEA46FF); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #00204DFF, #002A64FF, #00336FFF, #1F3C6DFF, #35466BFF, #444F6BFF, #53596CFF, #5F636EFF, #6B6C71FF, #777776FF, #838079FF, #908B79FF, #9D9677FF, #ABA074FF, #B9AC70FF, #C7B76BFF, #D7C463FF, #E5D05AFF, #F5DD4DFF, #FFEA46FF); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="rocket"], #nj_tippoint_scale .option[data-value="rocket"], @@ -2673,10 +2673,10 @@ background: linear-gradient(to right, #00204DFF, #002A64FF, #00336FFF, #1F3C6DFF #upgma_tiles_scale_4 .option[data-value="rocket"], #upgma_tiles_scale_5 .option[data-value="rocket"], #upgma_heatmap_scale .option[data-value="rocket"] { -background: linear-gradient(to right, #03051AFF, #150E26FF, #281535FF, #3C1A42FF, #511E4DFF, #661F54FF, #7C1F5AFF, #931C5BFF, #AA185AFF, #C11754FF, #D3214BFF, #E33541FF, #ED4E3EFF, #F26847FF, #F4815AFF, #F5986FFF, #F6AE86FF, #F7C2A2FF, #F8D7BFFF, #FAEBDDFF); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #03051AFF, #150E26FF, #281535FF, #3C1A42FF, #511E4DFF, #661F54FF, #7C1F5AFF, #931C5BFF, #AA185AFF, #C11754FF, #D3214BFF, #E33541FF, #ED4E3EFF, #F26847FF, #F4815AFF, #F5986FFF, #F6AE86FF, #F7C2A2FF, #F8D7BFFF, #FAEBDDFF); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="mako"], #nj_tippoint_scale .option[data-value="mako"], @@ -2694,10 +2694,10 @@ background: linear-gradient(to right, #03051AFF, #150E26FF, #281535FF, #3C1A42FF #upgma_tiles_scale_4 .option[data-value="mako"], #upgma_tiles_scale_5 .option[data-value="mako"], #upgma_heatmap_scale .option[data-value="mako"]{ -background: linear-gradient(to right, #0B0405FF, #190E19FF, #27182DFF, #312142FF, #3A2C59FF, #3F3770FF, #414388FF, #3C5397FF, #38639DFF, #3573A1FF, #3482A4FF, #3491A8FF, #35A0ABFF, #3AAEADFF, #46BEADFF, #5ACCADFF, #7ED7AFFF, #A4E0BBFF, #C3E9CEFF, #DEF5E5FF); - color: white; - margin-bottom: 2px; - } + background: linear-gradient(to right, #0B0405FF, #190E19FF, #27182DFF, #312142FF, #3A2C59FF, #3F3770FF, #414388FF, #3C5397FF, #38639DFF, #3573A1FF, #3482A4FF, #3491A8FF, #35A0ABFF, #3AAEADFF, #46BEADFF, #5ACCADFF, #7ED7AFFF, #A4E0BBFF, #C3E9CEFF, #DEF5E5FF); + color: white; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="turbo"], #nj_tippoint_scale .option[data-value="turbo"], @@ -2715,9 +2715,9 @@ background: linear-gradient(to right, #0B0405FF, #190E19FF, #27182DFF, #312142FF #upgma_tiles_scale_4 .option[data-value="turbo"], #upgma_tiles_scale_5 .option[data-value="turbo"], #upgma_heatmap_scale .option[data-value="turbo"] { -background: linear-gradient(to right, #30123BFF, #3F3994FF, #455ED2FF, #4681F7FF, #3AA2FCFF, #23C3E4FF, #18DEC1FF, #2CF09EFF, #5BFB72FF, #8EFF49FF, #B5F836FF, #D6E635FF, #EFCD3AFF, #FCB036FF, #FD8A26FF, #F36215FF, #E14209FF, #C82803FF, #A51301FF, #7A0403FF); - color: white; - } + background: linear-gradient(to right, #30123BFF, #3F3994FF, #455ED2FF, #4681F7FF, #3AA2FCFF, #23C3E4FF, #18DEC1FF, #2CF09EFF, #5BFB72FF, #8EFF49FF, #B5F836FF, #D6E635FF, #EFCD3AFF, #FCB036FF, #FD8A26FF, #F36215FF, #E14209FF, #C82803FF, #A51301FF, #7A0403FF); + color: white; +} #nj_tiplab_scale .option[data-value="Spectral"], #nj_tippoint_scale .option[data-value="Spectral"], @@ -2735,10 +2735,10 @@ background: linear-gradient(to right, #30123BFF, #3F3994FF, #455ED2FF, #4681F7FF #upgma_tiles_scale_4 .option[data-value="Spectral"], #upgma_tiles_scale_5 .option[data-value="Spectral"], #upgma_heatmap_scale .option[data-value="Spectral"]{ -background: linear-gradient(to right, #9E0142, #D53E4F, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #E6F598, #ABDDA4, #66C2A5, #3288BD, #5E4FA2); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #9E0142, #D53E4F, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #E6F598, #ABDDA4, #66C2A5, #3288BD, #5E4FA2); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="RdYlGn"], #nj_tippoint_scale .option[data-value="RdYlGn"], @@ -2756,10 +2756,10 @@ background: linear-gradient(to right, #9E0142, #D53E4F, #F46D43, #FDAE61, #FEE08 #upgma_tiles_scale_4 .option[data-value="RdYlGn"], #upgma_tiles_scale_5 .option[data-value="RdYlGn"], #upgma_heatmap_scale .option[data-value="RdYlGn"]{ -background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #D9EF8B, #A6D96A, #66BD63, #1A9850, #006837); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE08B, #FFFFBF, #D9EF8B, #A6D96A, #66BD63, #1A9850, #006837); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="RdYlBu"], #nj_tippoint_scale .option[data-value="RdYlBu"], @@ -2777,10 +2777,10 @@ background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE08 #upgma_tiles_scale_4 .option[data-value="RdYlBu"], #upgma_tiles_scale_5 .option[data-value="RdYlBu"], #upgma_heatmap_scale .option[data-value="RdYlBu"]{ -background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE090, #FFFFBF, #E0F3F8, #ABD9E9, #74ADD1, #4575B4, #313695); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE090, #FFFFBF, #E0F3F8, #ABD9E9, #74ADD1, #4575B4, #313695); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="RdGy"], #nj_tippoint_scale .option[data-value="RdGy"], @@ -2798,10 +2798,10 @@ background: linear-gradient(to right, #A50026, #D73027, #F46D43, #FDAE61, #FEE09 #upgma_tiles_scale_4 .option[data-value="RdGy"], #upgma_tiles_scale_5 .option[data-value="RdGy"], #upgma_heatmap_scale .option[data-value="RdGy"] { -background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #FFFFFF, #E0E0E0, #BABABA, #878787, #4D4D4D, #1A1A1A); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #FFFFFF, #E0E0E0, #BABABA, #878787, #4D4D4D, #1A1A1A); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="RdBu"], #nj_tippoint_scale .option[data-value="RdBu"], @@ -2819,10 +2819,10 @@ background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC #upgma_tiles_scale_4 .option[data-value="RdBu"], #upgma_tiles_scale_5 .option[data-value="RdBu"], #upgma_heatmap_scale .option[data-value="RdBu"] { -background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #F7F7F7, #D1E5F0, #92C5DE, #4393C3, #2166AC, #053061); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC7, #F7F7F7, #D1E5F0, #92C5DE, #4393C3, #2166AC, #053061); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="PuOr"], #nj_tippoint_scale .option[data-value="PuOr"], @@ -2840,10 +2840,10 @@ background: linear-gradient(to right, #67001F, #B2182B, #D6604D, #F4A582, #FDDBC #upgma_tiles_scale_4 .option[data-value="PuOr"], #upgma_tiles_scale_5 .option[data-value="PuOr"], #upgma_heatmap_scale .option[data-value="PuOr"] { -background: linear-gradient(to right, #7F3B08, #B35806, #E08214, #FDB863, #FEE0B6, #F7F7F7, #D8DAEB, #B2ABD2, #8073AC, #542788, #2D004B); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #7F3B08, #B35806, #E08214, #FDB863, #FEE0B6, #F7F7F7, #D8DAEB, #B2ABD2, #8073AC, #542788, #2D004B); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="PRGn"], #nj_tippoint_scale .option[data-value="PRGn"], @@ -2861,10 +2861,10 @@ background: linear-gradient(to right, #7F3B08, #B35806, #E08214, #FDB863, #FEE0B #upgma_tiles_scale_4 .option[data-value="PRGn"], #upgma_tiles_scale_5 .option[data-value="PRGn"], #upgma_heatmap_scale .option[data-value="PRGn"] { -background: linear-gradient(to right, #40004B, #762A83, #9970AB, #C2A5CF, #E7D4E8, #F7F7F7, #D9F0D3, #A6DBA0, #5AAE61, #1B7837, #00441B); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #40004B, #762A83, #9970AB, #C2A5CF, #E7D4E8, #F7F7F7, #D9F0D3, #A6DBA0, #5AAE61, #1B7837, #00441B); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="PiYG"], #nj_tippoint_scale .option[data-value="PiYG"], @@ -2882,10 +2882,10 @@ background: linear-gradient(to right, #40004B, #762A83, #9970AB, #C2A5CF, #E7D4E #upgma_tiles_scale_4 .option[data-value="PiYG"], #upgma_tiles_scale_5 .option[data-value="PiYG"], #upgma_heatmap_scale .option[data-value="PiYG"] { -background: linear-gradient(to right, #8E0152, #C51B7D, #DE77AE, #F1B6DA, #FDE0EF, #F7F7F7, #E6F5D0, #B8E186, #7FBC41, #4D9221, #276419); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #8E0152, #C51B7D, #DE77AE, #F1B6DA, #FDE0EF, #F7F7F7, #E6F5D0, #B8E186, #7FBC41, #4D9221, #276419); + color: black; + margin-bottom: 2px; +} #nj_tiplab_scale .option[data-value="BrBG"], #nj_tippoint_scale .option[data-value="BrBG"], @@ -2903,47 +2903,49 @@ background: linear-gradient(to right, #8E0152, #C51B7D, #DE77AE, #F1B6DA, #FDE0E #upgma_tiles_scale_4 .option[data-value="BrBG"], #upgma_tiles_scale_5 .option[data-value="BrBG"], #upgma_heatmap_scale .option[data-value="BrBG"] { -background: linear-gradient(to right, #543005, #8C510A, #BF812D, #DFC27D, #F6E8C3, #F5F5F5, #C7EAE5, #80CDC1, #35978F, #01665E, #003C30); - color: black; - margin-bottom: 2px; - } + background: linear-gradient(to right, #543005, #8C510A, #BF812D, #DFC27D, #F6E8C3, #F5F5F5, #C7EAE5, #80CDC1, #35978F, #01665E, #003C30); + color: black; + margin-bottom: 2px; +} /* Report */ - #shiny-modal > div > div > div.modal-body > div > div > div:nth-child(5) > div > div > div > div > button { +#shiny-modal > div > div > div.modal-body > div > div > div:nth-child(5) > div > div > div > div > button { border: 1px solid black; } #rep_general { -position: absolute; -top: -10px; -left: -110px; + position: absolute; + top: -10px; + left: -110px; } #rep_entrytable { -position: relative; -top: -10px; -left: -96px; + position: relative; + top: -10px; + left: -96px; } #rep_plot_report { -position: relative; -top: -15px; -left: -96px; + position: relative; + top: -15px; + left: -96px; } #rep_analysis { -position: relative; -top: -10px; -left: -45px; + position: relative; + top: -10px; + left: -45px; } #mst_date_general_select { -margin-top: -14px; -width: 100px; + margin-top: -14px; + width: 100px; } -.datepicker { z-index: 99999 !important; } +.datepicker { + z-index: 99999 !important; +} .rep_tab_sel { margin-top: -25px; @@ -2959,7 +2961,7 @@ width: 100px; #rep_missval, #rep_version, #rep_plot_report { -margin-top: 10px; + margin-top: 10px; } #mst_date_general_select .form-control { @@ -2970,46 +2972,48 @@ margin-top: 7px; } #mst_operator_general_select { -height: 28px; -margin-top: -8px; -position: relative; -right: -22px; -width: 250px; + height: 28px; + margin-top: -8px; + position: relative; + right: -22px; + width: 250px; } #mst_institute_general_select { -height: 28px; -margin-top: -8px; -position: relative; -right: -22px; -width: 250px; + height: 28px; + margin-top: -8px; + position: relative; + right: -22px; + width: 250px; } #mst_comm_general_select { -margin-top: -8px; -border-radius: 5px; -position: relative; -right: -22px; -border-color: black; + margin-top: -8px; + border-radius: 5px; + position: relative; + right: -22px; + border-color: black; } button#download_report_bttn { -font-size: 14px; -height: 36px; -background: #282F38; + font-size: 14px; + height: 36px; + background: #282F38; color: #ffffff; border: 1px solid white; -position: relative; -top: 1px; -border-radius: 6px; -margin-left: 10px; + position: relative; + top: 1px; + border-radius: 6px; + margin-left: 10px; } /* Gene Screening */ #screening_start_button, -#screening_reset_bttn { - margin-top: 31px; +#screening_reset_bttn, +#screening_cancel { + margin-top: 20px; + border: 1px solid white; } #screening_fail { From 37c149b5b672f89f3943c2c10e03fdac0f39901b Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 13 Aug 2024 12:07:54 +0200 Subject: [PATCH 45/75] Fixes in gene screening --- App.R | 276 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 148 insertions(+), 128 deletions(-) diff --git a/App.R b/App.R index b028abf..051b729 100644 --- a/App.R +++ b/App.R @@ -6279,31 +6279,17 @@ server <- function(input, output, session) { ) ) } else if(Screening$status == "finished") { - if(isTRUE(Screening$fail)) { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    gene screening failed")), - style = "color:white;") - ) - ) - ) - } else { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    gene screening finalized")), - style = "color:white;") - ) + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    gene screening finalized")), + style = "color:white;") ) ) - } + ) } else { output$statustext <- renderUI( fluidRow( @@ -7867,7 +7853,7 @@ server <- function(input, output, session) { valign = "htMiddle", halign = "htCenter") %>% hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", @@ -7970,7 +7956,7 @@ server <- function(input, output, session) { valign = "htMiddle", halign = "htCenter") %>% hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3, validator = " function(value, callback) { @@ -8127,7 +8113,7 @@ server <- function(input, output, session) { valign = "htMiddle", halign = "htCenter") %>% hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", @@ -8306,7 +8292,7 @@ server <- function(input, output, session) { } } ") %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(8, type = "dropdown", source = country_names) %>% hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, @@ -8424,7 +8410,7 @@ server <- function(input, output, session) { valign = "htMiddle", halign = "htCenter") %>% hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3, validator = " function(value, callback) { @@ -9924,8 +9910,6 @@ server <- function(input, output, session) { observeEvent(input$reload_db, { log_print("Input reload_db") - test <<- Screening$status_df - if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( title = "Pending Multi Typing", @@ -10033,7 +10017,7 @@ server <- function(input, output, session) { valign = "htMiddle", halign = "htCenter") %>% hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", @@ -10136,7 +10120,7 @@ server <- function(input, output, session) { valign = "htMiddle", halign = "htCenter") %>% hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", @@ -10293,7 +10277,7 @@ server <- function(input, output, session) { valign = "htMiddle", halign = "htCenter") %>% hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", @@ -10472,7 +10456,7 @@ server <- function(input, output, session) { } } ") %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(8, type = "dropdown", source = country_names) %>% hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, @@ -10589,7 +10573,7 @@ server <- function(input, output, session) { hot_col(1, valign = "htMiddle", halign = "htCenter") %>% - hot_col(c(1, 5, 10, 11, 12), + hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% hot_col(3, readOnly = TRUE) %>% hot_col(3, validator = " @@ -10799,20 +10783,11 @@ server <- function(input, output, session) { DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "cont")) } - dataa <<- DB$data - cust_var <<- DB$cust_var DB$meta_gs <- select(DB$data, c(1, 3:13)) - - meta_gs <<- DB$meta_gs - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - meta <<- DB$meta - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - allelic_profile <<- DB$allelic_profile DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] log_print(paste0("New custom variable added: ", input$new_var_name)) @@ -11056,20 +11031,19 @@ server <- function(input, output, session) { } DB$remove_iso <- NULL - Data <<- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) + Data <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) if ((ncol(Data[["Typing"]]) - 13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { cust_vars_pre <- select(Data[["Typing"]], 14:(ncol(Data[["Typing"]]) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - cust_vars_pre <<- names(cust_vars_pre) + cust_vars_pre <- names(cust_vars_pre) } else { - cust_vars_pre <<- character() + cust_vars_pre <- character() } - checkpoint <<- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) Data[["Typing"]] <- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) - meta_hot <<- hot_to_r(input$db_entries) + meta_hot <- hot_to_r(input$db_entries) if(length(DB$deleted_entries > 0)) { @@ -11084,7 +11058,6 @@ server <- function(input, output, session) { # Ensure correct logical data type Data[["Typing"]][["Include"]] <- as.logical(Data[["Typing"]][["Include"]]) - testdata <<- Data saveRDS(Data, paste0( DB$database, "/", gsub(" ", "_", DB$scheme), @@ -22568,33 +22541,38 @@ server <- function(input, output, session) { observe({ req(input$screening_res_sel, DB$database, DB$scheme) - if(!is.null(Screening$status_df)) { + if(!is.null(Screening$status_df) & + !is.null(input$screening_res_sel) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate)) { if(length(input$screening_res_sel) > 0) { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { - results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", - input$screening_res_sel, "resProfile.tsv")) - - output$screening_table <- renderDataTable( - select(results, c(6, 7, 8, 9, 11)), - selection = "single", - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ))) - } else {output$screening_table <- NULL} + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", + input$screening_res_sel, "resProfile.tsv")) + + output$screening_table <- renderDataTable( + select(results, c(6, 7, 8, 9, 11)), + selection = "single", + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ))) + } else {output$screening_table <- NULL} + } } else { output$screening_table <- NULL } @@ -22774,9 +22752,8 @@ server <- function(input, output, session) { # set feedback variables Screening$status <- "idle" - Screening$results <- NULL - Screening$fail <- NULL Screening$status_df <- NULL + Screening$choices <- NULL # change reactive UI output$screening_table <- NULL @@ -22792,7 +22769,25 @@ server <- function(input, output, session) { # Cancel screening observeEvent(input$screening_cancel, { + showModal( + modalDialog( + paste0( + "Gene screening is still pending. Stopping this process will cancel the screening." + ), + title = "Reset Multi Typing", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_screening_cancel", "Stop", class = "btn btn-danger") + ) + ) + ) + }) + + observeEvent(input$conf_screening_cancel, { log_print("Cancelled gene screening") + removeModal() # terminate screening system(paste("kill $(pgrep -f 'execute/screening.sh')"), wait = FALSE) @@ -22803,9 +22798,8 @@ server <- function(input, output, session) { # set feedback variables Screening$status <- "idle" - Screening$results <- NULL - Screening$fail <- NULL Screening$status_df <- NULL + Screening$choices <- NULL # change reactive UI output$screening_table <- NULL @@ -22819,11 +22813,10 @@ server <- function(input, output, session) { }) # Get selected assembly - observe({ if (length(input$screening_select) < 1) { output$genome_path_gs <- renderUI(HTML( - paste("", length(input$screening_select), " isolates queried for screening.") + paste("", length(input$screening_select), " isolate(s) queried for screening") )) output$screening_start <- NULL @@ -22877,7 +22870,7 @@ server <- function(input, output, session) { p( HTML(paste( '', - paste("", + paste("", "  Screening Ready"))) ), actionButton( @@ -22893,7 +22886,7 @@ server <- function(input, output, session) { p( HTML(paste( '', - paste("", + paste("", "  Running Screening ..."))) ), fluidRow( @@ -22915,7 +22908,7 @@ server <- function(input, output, session) { p( HTML(paste("", sum(Screening$status_df$status != "unfinished"), "/", - nrow(Screening$status_df), " Isolate(s) screened")) + nrow(Screening$status_df), " isolate(s) screened")) ) } ) @@ -22969,7 +22962,7 @@ server <- function(input, output, session) { species = gsub(" ", "_", DB$scheme)) Screening$status_df <- data.frame(isolate = basename(gsub(".zip", "", str_split_1(Screening$meta_df$selected, " "))), - status = "unfinished", shown = FALSE) + status = "unfinished") # Reset screening status sapply(Screening$status_df$isolate, remove.screening.status) @@ -22984,25 +22977,30 @@ server <- function(input, output, session) { ### Screening Feedback ---- observe({ - req(Screening$status, input$screening_res_sel) - if(!is.null(Screening$status_df)) { - if(Screening$status != "idle") { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { - output$screening_result <- renderUI( - column( - width = 12, - hr(), br(), - dataTableOutput("screening_table") + req(Screening$status, input$screening_res_sel, Screening$status_df) + if(!is.null(Screening$status_df) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate) & + !is.null(input$screening_res_sel)) { + if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + dataTableOutput("screening_table") + ) ) - ) - } else { - output$screening_result <- renderUI( - column( - width = 12, - hr(), br(), - verbatimTextOutput("screening_fail") + } else { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + verbatimTextOutput("screening_fail") + ) ) - ) + } } } else { output$screening_result <- NULL @@ -23014,13 +23012,18 @@ server <- function(input, output, session) { observe({ req(Screening$status, input$screening_res_sel) - if(!is.null(Screening$status_df)) { - if(Screening$status != "idle") { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { - output$screening_fail <- renderPrint({ - cat(paste(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", input$screening_res_sel, "status.txt")),"\n")) - }) + if(!is.null(Screening$status_df) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate) & + !is.null(input$screening_res_sel)) { + if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { + output$screening_fail <- renderPrint({ + cat(paste(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_res_sel, "status.txt")),"\n")) + }) + } } } else { output$screening_fail <- NULL @@ -23031,25 +23034,26 @@ server <- function(input, output, session) { }) observe({ - req(Screening$status) - if(Screening$status == "started") { - - # start status screening for user feedback - check_screening() - - if(isTRUE(Screening$first_result)) { - output$screening_result_sel <- renderUI( - selectInput( - "screening_res_sel", - label = h5("Select Result", style = "color:white; margin-bottom: 32px; margin-top: -10px;"), - choices = "" - ) - ) + if(!is.null(Screening$status)) { + if(Screening$status != "idle") { + + # start status screening for user feedback + check_screening() - Screening$first_result <- FALSE + if(isTRUE(Screening$first_result)) { + output$screening_result_sel <- renderUI( + selectInput( + "screening_res_sel", + label = h5("Select Result", style = "color:white; margin-bottom: 28px; margin-top: -10px;"), + choices = "" + ) + ) + + Screening$first_result <- FALSE + } + } else if(Screening$status == "idle") { + output$screening_result_sel <- NULL } - } else if(Screening$status == "idle") { - output$screening_result_sel <- NULL } }) @@ -23065,6 +23069,8 @@ server <- function(input, output, session) { if(any("unfinished" != Screening$status_df$status) & !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status != "unfinished")])) { + # Screening$first_check <- FALSE + status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | @@ -23076,6 +23082,11 @@ server <- function(input, output, session) { if(tail(status_df$status, 1) == "success") { + #TODO + # hjier einfügen laden der rds datenbank, ändern direkt lokal + + #DB$meta$Screened[which(DB$meta["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + show_toast( title = paste("Successful screening of", tail(Screening$choices, 1)), type = "success", @@ -23088,6 +23099,7 @@ server <- function(input, output, session) { selected = tail(Screening$choices, 1)) } else if(tail(status_df$status, 1) == "fail") { + show_toast( title = paste("Failed screening of", tail(status_df$isolate, 1)), type = "error", @@ -23103,7 +23115,15 @@ server <- function(input, output, session) { if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { Screening$status <- "finished" } - } + } else { + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } + + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } } }) From 43a51053de597f36a627d304b337ae735987bb3b Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 13 Aug 2024 19:08:52 +0200 Subject: [PATCH 46/75] Advanced gene screening section; Changes in Resistance Profile Tab --- App.R | 201 +++++++++++++++++++++++++++++++++++++++------------ www/body.css | 19 +++++ www/head.css | 24 +++++- 3 files changed, 193 insertions(+), 51 deletions(-) diff --git a/App.R b/App.R index 051b729..ebdda86 100644 --- a/App.R +++ b/App.R @@ -5351,6 +5351,15 @@ ui <- dashboardPage( div(class = "loci_table", dataTableOutput("gs_isolate_table")) ) + ), + hr(), + fluidRow( + column(1), + column( + width = 10, + div(class = "loci_table", + DT::dataTableOutput("gs_profile_table")) + ) ) ) ) # End tabItems @@ -5524,7 +5533,7 @@ server <- function(input, output, session) { get.entry.table.meta <- reactive({ if(!is.null(hot_to_r(input$db_entries))){ table <- hot_to_r(input$db_entries) - select(table, 1:(13 + nrow(DB$cust_var))) + select(select(table, -13), 1:(12 + nrow(DB$cust_var))) } }) @@ -5722,13 +5731,13 @@ server <- function(input, output, session) { invalidateLater(5000, session) if(!is.null(DB$database)) { - if(file_exists(paste0( - DB$database, "/", + if(file_exists(file.path( + DB$database, gsub(" ", "_", DB$scheme), - "/Typing.rds" + "Typing.rds" ))) { - Database <- readRDS(paste0(DB$database, "/", gsub(" ", "_", DB$scheme),"/Typing.rds")) + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) if(is.null(DB$data)) { if(nrow(Database[["Typing"]]) >= 1) { @@ -5831,7 +5840,8 @@ server <- function(input, output, session) { result_list = NULL, status = "") # reactive variables related to typing process - Screening <- reactiveValues(status = "idle") # reactive variables related to gene screening + Screening <- reactiveValues(status = "idle", + picker_status = TRUE) # reactive variables related to gene screening Vis <- reactiveValues(cluster = NULL, metadata = list(), @@ -8572,7 +8582,7 @@ server <- function(input, output, session) { HTML(paste('')) ) ) - } else if((DB$change == TRUE) | !identical(get.entry.table.meta(), DB$meta)) { + } else if((DB$change == TRUE) | !identical(get.entry.table.meta(), select(DB$meta, -13))) { if(!is.null(input$db_entries)) { fluidRow( column( @@ -9910,6 +9920,9 @@ server <- function(input, output, session) { observeEvent(input$reload_db, { log_print("Input reload_db") + pick_stat <<- Screening$picker_status + ttest <<- input$screening_select + if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( title = "Pending Multi Typing", @@ -11360,7 +11373,6 @@ server <- function(input, output, session) { output$sequence_selector <- renderUI({ if(!is.null(input$db_loci_rows_selected)) { - req(input$db_loci_rows_selected, DB$database, DB$scheme) DB$loci <- list.files( @@ -22513,10 +22525,65 @@ server <- function(input, output, session) { ### Render UI Elements ---- + # Resistance profile table + observe({ + req(DB$meta_gs, input$gs_isolate_table_rows_selected, DB$database, DB$scheme) + + if(DB$meta_gs$Screened[input$gs_isolate_table_rows_selected] == "Yes") { + iso_select <- DB$meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] + iso_path <- file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", + iso_select, "resProfile.tsv") + res_profile <- read.delim(iso_path) + + colnames(res_profile) <- c( + "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", + "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", + "Subclass", "Method", "Target Length", "Reference Sequence Length", + "% Coverage of Reference Sequence", "% Identity to Reference Sequence", + "Alignment Length", "Accession of Closest Sequence", + "Name of Closest Sequence", "HMM ID", "HMM Description") + + + res_profile <- res_profile %>% + relocate(c("Gene Symbol", "Sequence Name", "Element Subtype", "Class", + "Subclass", "Scope", "Contig ID", "Target Length", "Alignment Length", + "Start", "Stop", "Strand")) + + # Generate gene profile table + output$gs_profile_table <- DT::renderDataTable( + res_profile, + selection = "single", + rownames= FALSE, + options = list(pageLength = 10, scrollX = TRUE, + autoWidth = TRUE, + columnDefs = list(list(width = '400px', targets = c("Sequence Name"))), + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + } else { + output$gs_profile_table <- NULL + } + }) + + #Resistance profile selection table observe({ req(DB$meta) output$gs_isolate_table <- renderDataTable( - DB$meta_gs, + select(DB$meta_gs, -c(2, 4, 10, 11, 12)), selection = "single", rownames= FALSE, options = list(pageLength = 10, @@ -22633,7 +22700,7 @@ server <- function(input, output, session) { # Screening Interface - output$screening_interface <- renderUI({ + output$screening_interface <- renderUI( if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { column( width = 12, @@ -22650,31 +22717,30 @@ server <- function(input, output, session) { ) ) ), - if(length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) > 0 & - length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) > 0) { + if(Screening$picker_status) { div( class = "screening_div", pickerInput( "screening_select", "", - choices = list(Unscreened = DB$data$`Assembly ID`[which(DB$data$Screened == "No")], - Screened = DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" + choices = list( + Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + } + ), + choicesOpt = list( + disabled = c( + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])) + ) ), - multiple = TRUE - ) - ) - } else if(length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) > 0) { - div( - class = "screening_div", - pickerInput( - "screening_select", - "", - choices = list(Unscreened = DB$data$`Assembly ID`[which(DB$data$Screened == "No")]), options = list( `live-search` = TRUE, `actions-box` = TRUE, @@ -22682,7 +22748,7 @@ server <- function(input, output, session) { style = "background-color: white; border-radius: 5px;" ), multiple = TRUE - ) + ) ) } else { div( @@ -22690,7 +22756,8 @@ server <- function(input, output, session) { pickerInput( "screening_select", "", - choices = list(Screened = DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]), + choices = Screening$picker_choices, + selected = Screening$picker_selected, options = list( `live-search` = TRUE, `actions-box` = TRUE, @@ -22698,7 +22765,7 @@ server <- function(input, output, session) { style = "background-color: white; border-radius: 5px;" ), multiple = TRUE - ) + ) ) }, br(), br(), @@ -22739,7 +22806,7 @@ server <- function(input, output, session) { ) ) } - }) + ) ### Screening Events ---- @@ -22754,6 +22821,7 @@ server <- function(input, output, session) { Screening$status <- "idle" Screening$status_df <- NULL Screening$choices <- NULL + Screening$picker_status <- TRUE # change reactive UI output$screening_table <- NULL @@ -22800,6 +22868,7 @@ server <- function(input, output, session) { Screening$status <- "idle" Screening$status_df <- NULL Screening$choices <- NULL + Screening$picker_status <- TRUE # change reactive UI output$screening_table <- NULL @@ -22816,7 +22885,7 @@ server <- function(input, output, session) { observe({ if (length(input$screening_select) < 1) { output$genome_path_gs <- renderUI(HTML( - paste("", length(input$screening_select), " isolate(s) queried for screening") + paste("", length(input$screening_select), " Isolate(s) queried for screening") )) output$screening_start <- NULL @@ -22942,9 +23011,22 @@ server <- function(input, output, session) { log_print("Started gene screening") Screening$status <- "started" - - shinyjs::runjs("$('#screening_select').prop('disabled', true);") - shinyjs::runjs("$('#screening_select').selectpicker('refresh');") + Screening$picker_choices <- list( + Unscreened = if (sum(DB$data$Screened == "No") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + Screened = if (sum(DB$data$Screened == "Yes") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + } + ) + pick_choices <<- Screening$picker_choices + Screening$picker_selected <- input$screening_select + okayy <<- Screening$picker_selected + Screening$picker_status <- FALSE show_toast( title = "Gene screening started", @@ -22964,11 +23046,15 @@ server <- function(input, output, session) { Screening$status_df <- data.frame(isolate = basename(gsub(".zip", "", str_split_1(Screening$meta_df$selected, " "))), status = "unfinished") - # Reset screening status + # Reset screening status sapply(Screening$status_df$isolate, remove.screening.status) saveRDS(Screening$meta_df, paste0(getwd(), "/execute/screening_meta.rds")) + # Disable pickerInput + shinyjs::delay(200, shinyjs::runjs("$('#screening_select').prop('disabled', true);")) + shinyjs::delay(200, shinyjs::runjs("$('#screening_select').selectpicker('refresh');")) + # System execution screening.sh system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) } @@ -23042,10 +23128,27 @@ server <- function(input, output, session) { if(isTRUE(Screening$first_result)) { output$screening_result_sel <- renderUI( - selectInput( - "screening_res_sel", - label = h5("Select Result", style = "color:white; margin-bottom: 28px; margin-top: -10px;"), - choices = "" + column( + width = 12, + align = "center", + selectInput( + "screening_res_sel", + label = h5("Select Result", style = "color:white; margin-bottom: 28px; margin-top: -10px;"), + choices = "" + ), + if(!is.null(Screening$status_df)) { + p(HTML(paste("", + if(sum(Screening$status_df$status == "success") == 1) { + "1 success   /  " + } else { + paste0(sum(Screening$status_df$status == "success"), " successes   /  ") + }, + if(sum(Screening$status_df$status == "fail") == 1) { + "1 failure" + } else { + paste0(sum(Screening$status_df$status == "fail"), " failures") + }))) + } ) ) @@ -23069,8 +23172,6 @@ server <- function(input, output, session) { if(any("unfinished" != Screening$status_df$status) & !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status != "unfinished")])) { - # Screening$first_check <- FALSE - status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | @@ -23082,11 +23183,15 @@ server <- function(input, output, session) { if(tail(status_df$status, 1) == "success") { - #TODO - # hjier einfügen laden der rds datenbank, ändern direkt lokal - - #DB$meta$Screened[which(DB$meta["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + # Changing "Screened" metadata variable in database + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + Database[["Typing"]]$Screened[which(Database[["Typing"]]["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + + saveRDS(Database, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + DB$data$Screened[which(DB$data["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + show_toast( title = paste("Successful screening of", tail(Screening$choices, 1)), type = "success", diff --git a/www/body.css b/www/body.css index c0652e4..21ec938 100644 --- a/www/body.css +++ b/www/body.css @@ -411,6 +411,12 @@ table.dataTable tbody tr { border-radius: 5px !important; } +#gs_profile_table table.dataTable tbody tr { + background-color: transparent; + border-bottom-left-radius: 0px !important; + border-bottom-right-radius: 0px !important; +} + table.dataTable.stripe>tbody>tr.odd.selected>*, table.dataTable.display>tbody>tr.odd.selected>* { box-shadow: inset 0 0 0 9999px #282F38; box-shadow: inset 0 0 0 9999px #282F38; @@ -530,6 +536,10 @@ left: -6px; /* Icons */ +.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark { + right: 0px !important; +} + i.fa-solid .fa-arrow-right-long { font-size: 30px; color: white; @@ -3009,6 +3019,15 @@ button#download_report_bttn { /* Gene Screening */ +.dataTables_wrapper.no-footer .dataTables_scrollBody { + border-bottom: none; +} + +#DataTables_Table_8_wrapper > div.dataTables_scroll > div.dataTables_scrollBody, +.display .dataTable .no-footer, +#DataTables_Table_8, +.dataTables_scrollBody + #screening_start_button, #screening_reset_bttn, #screening_cancel { diff --git a/www/head.css b/www/head.css index 962b17d..c9e4b51 100644 --- a/www/head.css +++ b/www/head.css @@ -93,8 +93,20 @@ div#bs-select-12::-webkit-scrollbar-track, .selectize-dropdown-content::-webkit-scrollbar-track, #mst_comm_general_select::-webkit-scrollbar-track, .sF-dirInfo>div::-webkit-scrollbar-track{ -background: #F0F0F0; - } + background: #F0F0F0; +} + +#DataTables_Table_8_wrapper > div.dataTables_scroll > div.dataTables_scrollBody::-webkit-scrollbar-track, +.display .dataTable .no-footer::-webkit-scrollbar-track, +#DataTables_Table_8::-webkit-scrollbar-track, +.dataTables_scrollBody::-webkit-scrollbar-track, +div#gs_profile_table::-webkit-scrollbar-track, +#gs_profile_table::-webkit-scrollbar-track { + background: #F0F0F0; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; +} + .wtHolder::-webkit-scrollbar-thumb, div#bs-select-1::-webkit-scrollbar-thumb, @@ -114,7 +126,13 @@ div#bs-select-12::-webkit-scrollbar-thumb, #screening_fail::-webkit-scrollbar-thumb, .selectize-dropdown-content::-webkit-scrollbar-thumb, #mst_comm_general_select::-webkit-scrollbar-thumb, -.sF-dirInfo>div::-webkit-scrollbar-thumb { +.sF-dirInfo>div::-webkit-scrollbar-thumb, +#DataTables_Table_8_wrapper > div.dataTables_scroll > div.dataTables_scrollBody::-webkit-scrollbar-thumb, +.display .dataTable .no-footer::-webkit-scrollbar-thumb, +#DataTables_Table_8::-webkit-scrollbar-thumb, +.dataTables_scrollBody::-webkit-scrollbar-thumb, +#gs_profile_table::-webkit-scrollbar-thumb, +div#gs_profile_table::-webkit-scrollbar-thumb { background: #bcbcbc; border: 2px solid #F0F0F0; min-width: 100px; From 4f2f1657d40176728ca9819fda261873a5db6098 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Wed, 14 Aug 2024 09:30:02 +0200 Subject: [PATCH 47/75] Added spinner while downloading scheme --- App.R | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/App.R b/App.R index 67289fa..c8f41e8 100644 --- a/App.R +++ b/App.R @@ -737,7 +737,10 @@ ui <- dashboardPage( "download_cgMLST", label = "Download", icon = icon("download") - ) + ), + shinyjs::hidden( + div(id = "loading", + HTML(''))) ) ), fluidRow( @@ -11444,6 +11447,21 @@ server <- function(input, output, session) { observeEvent(input$download_cgMLST, { log_print(paste0("Started download of scheme for ", Scheme$folder_name)) + shinyjs::hide("download_cgMLST") + shinyjs::show("loading") + + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    Downloading scheme...")), + style = "color:white;") + ) + ) + ) + show_toast( title = "Download started", type = "success", @@ -11600,6 +11618,21 @@ server <- function(input, output, session) { DB$exist <- length(dir_ls(DB$database)) == 0 + shinyjs::show("download_cgMLST") + shinyjs::hide("loading") + + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    ready")), + style = "color:white;") + ) + ) + ) + show_toast( title = "Download successful", type = "success", From c9f879d56cd4d417368af622463f8199971c4ec2 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Wed, 14 Aug 2024 20:25:05 +0200 Subject: [PATCH 48/75] Added gene resistance profile legend --- App.R | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/App.R b/App.R index ebdda86..da8d1e0 100644 --- a/App.R +++ b/App.R @@ -5358,7 +5358,17 @@ ui <- dashboardPage( column( width = 10, div(class = "loci_table", - DT::dataTableOutput("gs_profile_table")) + DT::dataTableOutput("gs_profile_table")), + br(), + HTML( + paste0("", + 'RSL = Reference Sequence Length  |  ', + '%CRS = % Coverage of Reference Sequence  |  ', + '%IRS = % Identity to Reference Sequence  |  ', + 'ACS = Accession of Closest Sequence  |  ', + 'NCS = Name of Closest Sequence') + + ) ) ) ) @@ -22534,15 +22544,17 @@ server <- function(input, output, session) { iso_path <- file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", iso_select, "resProfile.tsv") res_profile <- read.delim(iso_path) - + # + # colnames(res_profile) <- c( + # "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", + # "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", + # "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", "Alignment Length", + # "ACS", "NCS", "HMM ID", "HMM Description") colnames(res_profile) <- c( "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", - "Subclass", "Method", "Target Length", "Reference Sequence Length", - "% Coverage of Reference Sequence", "% Identity to Reference Sequence", - "Alignment Length", "Accession of Closest Sequence", - "Name of Closest Sequence", "HMM ID", "HMM Description") - + "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", + "Alignment Length", "ACS", "Name of Closest Sequence", "HMM ID", "HMM Description") res_profile <- res_profile %>% relocate(c("Gene Symbol", "Sequence Name", "Element Subtype", "Class", @@ -22556,7 +22568,9 @@ server <- function(input, output, session) { rownames= FALSE, options = list(pageLength = 10, scrollX = TRUE, autoWidth = TRUE, - columnDefs = list(list(width = '400px', targets = c("Sequence Name"))), + columnDefs = list(list(width = '400px', targets = c("Sequence Name", + "Name of Closest Sequence"))), + columnDefs = list(list(width = 'auto', targets = "_all")), columnDefs = list(list(searchable = TRUE, targets = "_all")), initComplete = DT::JS( From a9b3f0e0d03be465c409f50b4cf9b1105176fce2 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Thu, 15 Aug 2024 12:48:40 +0200 Subject: [PATCH 49/75] Screening UI refinements --- App.R | 293 +++++++++++++++++++++++++++++++++++++++++---------- www/body.css | 14 +++ www/head.css | 3 +- 3 files changed, 254 insertions(+), 56 deletions(-) diff --git a/App.R b/App.R index da8d1e0..99c860d 100644 --- a/App.R +++ b/App.R @@ -52,7 +52,7 @@ options(ignore.negative.edge=TRUE) ui <- dashboardPage( - title = "PhyloTrace 1.4.1", + title = "PhyloTrace 1.5.0", # Title dashboardHeader( @@ -113,6 +113,10 @@ ui <- dashboardPage( conditionalPanel( "input.tabs==='visualization'", uiOutput("visualization_sidebar") + ), + conditionalPanel( + "input.tabs==='gs_profile'", + uiOutput("screening_sidebar") ) ) ), @@ -5344,32 +5348,10 @@ ui <- dashboardPage( br(), hr(), br(), br(), + uiOutput("gs_table_selection"), fluidRow( column(1), - column( - width = 10, - div(class = "loci_table", - dataTableOutput("gs_isolate_table")) - ) - ), - hr(), - fluidRow( - column(1), - column( - width = 10, - div(class = "loci_table", - DT::dataTableOutput("gs_profile_table")), - br(), - HTML( - paste0("", - 'RSL = Reference Sequence Length  |  ', - '%CRS = % Coverage of Reference Sequence  |  ', - '%IRS = % Identity to Reference Sequence  |  ', - 'ACS = Accession of Closest Sequence  |  ', - 'NCS = Name of Closest Sequence') - - ) - ) + uiOutput("gs_profile_display") ) ) ) # End tabItems @@ -5382,7 +5364,7 @@ ui <- dashboardPage( server <- function(input, output, session) { - phylotraceVersion <- paste("1.4.1") + phylotraceVersion <- paste("1.5.0") #TODO Enable this, or leave disabled # Kill server on session end @@ -9930,9 +9912,6 @@ server <- function(input, output, session) { observeEvent(input$reload_db, { log_print("Input reload_db") - pick_stat <<- Screening$picker_status - ttest <<- input$screening_select - if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( title = "Pending Multi Typing", @@ -22535,35 +22514,227 @@ server <- function(input, output, session) { ### Render UI Elements ---- + # Rendering results table + output$gs_results_table <- renderUI({ + if(!is.null(Screening$selected_isolate)) { + if(length(Screening$selected_isolate) > 0) { + fluidRow( + div(class = "loci_table", + DT::dataTableOutput("gs_profile_table")), + br(), + HTML( + paste0("", + 'RSL = Reference Sequence Length  |  ', + '%CRS = % Coverage of Reference Sequence  |  ', + '%IRS = % Identity to Reference Sequence  |  ', + 'ACS = Accession of Closest Sequence  |  ', + 'NCS = Name of Closest Sequence') + + ) + ) + } else { + fluidRow( + br(), br(), + p( + HTML( + paste0("", + 'Select entry from the table to display resistance profile') + + ) + ) + ) + } + } else { + fluidRow( + br(), br(), + p( + HTML( + paste0("", + 'Select entry from the table to display resistance profile') + + ) + ) + ) + } + }) + + # Gene screening download button + output$gs_download <- renderUI({ + if(!is.null(Screening$selected_isolate)) { + if(length(Screening$selected_isolate) > 0) { + fluidRow( + downloadBttn( + "download_resistance_profile", + style = "simple", + label = "Profile Table", + size = "sm", + icon = icon("download"), + color = "primary" + ), + bsTooltip("download_resistance_profile_bttn", + HTML(paste0("Save resistance profile table for
", + Screening$selected_isolate)), + placement = "bottom", trigger = "hover") + ) + } else {NULL} + } else {NULL} + }) + + # Conditionally render table selectiom interface + output$gs_table_selection <- renderUI({ + req(input$gs_view) + if(input$gs_view == "Table") { + fluidRow( + column(1), + column( + width = 10, + div(class = "loci_table", + dataTableOutput("gs_isolate_table")) + ) + ) + } else {NULL} + }) + + # Resistance profile table output display + output$gs_profile_display <- renderUI({ + if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { + if(input$gs_view == "Table") { + column( + width = 10, + hr(), + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) + ) + ), + column( + width = 4, + uiOutput("gs_download") + ) + ), + br(), + uiOutput("gs_results_table") + ) + } else { + column( + width = 10, + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) + ) + ), + column( + width = 4, + div( + class = "gs-picker", + pickerInput( + "gs_profile_select", + "", + choices = list( + Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + } + ), + choicesOpt = list( + disabled = c( + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])) + ) + ), + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ) + ) + ) + ), + column( + width = 3, + uiOutput("gs_download") + ) + ), + br(), + uiOutput("gs_results_table") + ) + } + } else {NULL} + }) + + # Screening sidebar + output$screening_sidebar <- renderUI({ + if(!is.null(DB$meta_gs)) { + column( + width = 12, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Toggle View') + ) + ) + ), + radioGroupButtons( + inputId = "gs_view", + choices = c("Picker", "Table"), + selected = "Picker", + checkIcon = list( + yes = icon("square-check"), + no = icon("square") + ) + ), + br() + ) + } else {NULL} + }) + # Resistance profile table observe({ - req(DB$meta_gs, input$gs_isolate_table_rows_selected, DB$database, DB$scheme) + req(DB$meta_gs, Screening$selected_isolate, DB$database, DB$scheme) - if(DB$meta_gs$Screened[input$gs_isolate_table_rows_selected] == "Yes") { - iso_select <- DB$meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] + if(length(Screening$selected_isolate) > 0 & any(Screening$selected_isolate %in% DB$data$`Assembly ID`)) { + iso_select <- Screening$selected_isolate iso_path <- file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", iso_select, "resProfile.tsv") + res_profile <- read.delim(iso_path) - # - # colnames(res_profile) <- c( - # "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", - # "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", - # "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", "Alignment Length", - # "ACS", "NCS", "HMM ID", "HMM Description") + colnames(res_profile) <- c( "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", "Alignment Length", "ACS", "Name of Closest Sequence", "HMM ID", "HMM Description") - res_profile <- res_profile %>% + Screening$res_profile <- res_profile %>% relocate(c("Gene Symbol", "Sequence Name", "Element Subtype", "Class", "Subclass", "Scope", "Contig ID", "Target Length", "Alignment Length", "Start", "Stop", "Strand")) # Generate gene profile table output$gs_profile_table <- DT::renderDataTable( - res_profile, + Screening$res_profile, selection = "single", rownames= FALSE, options = list(pageLength = 10, scrollX = TRUE, @@ -22597,7 +22768,7 @@ server <- function(input, output, session) { observe({ req(DB$meta) output$gs_isolate_table <- renderDataTable( - select(DB$meta_gs, -c(2, 4, 10, 11, 12)), + select(DB$meta_gs, -c(3, 4, 10, 11, 12)), selection = "single", rownames= FALSE, options = list(pageLength = 10, @@ -22796,18 +22967,6 @@ server <- function(input, output, session) { uiOutput("screening_result_sel") ), column(1) - # column( - # width = 3, - # align = "left", - # box( - # solidHeader = TRUE, - # status = "primary", - # width = "90%", - # HTML(paste("", - # "AMRFinder Database Status")), - # - # ) - # ) ), fluidRow( column(1), @@ -22824,6 +22983,32 @@ server <- function(input, output, session) { ### Screening Events ---- + observe({ + req(input$gs_view) + if(input$gs_view == "Table") { + Screening$selected_isolate <- DB$meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] + } else if(input$gs_view == "Picker") { + Screening$selected_isolate <- input$gs_profile_select + } + }) + + output$download_resistance_profile <- downloadHandler( + filename = function() { + log_print(paste0("Save resistance profile table ", Screening$selected_isolate, "_Profile.csv")) + + paste0(format(Sys.Date()), "_", Screening$selected_isolate, "_Profile.csv") + }, + content = function(file) { + write.table( + Screening$res_profile, + file, + sep = ";", + row.names = FALSE, + quote = FALSE + ) + } + ) + # Reset screening observeEvent(input$screening_reset_bttn, { log_print("Reset gene screening") @@ -23037,9 +23222,7 @@ server <- function(input, output, session) { DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] } ) - pick_choices <<- Screening$picker_choices Screening$picker_selected <- input$screening_select - okayy <<- Screening$picker_selected Screening$picker_status <- FALSE show_toast( diff --git a/www/body.css b/www/body.css index 21ec938..ffae73c 100644 --- a/www/body.css +++ b/www/body.css @@ -3019,6 +3019,20 @@ button#download_report_bttn { /* Gene Screening */ +.gs-picker { + margin-top: -13px; +} + +button#download_resistance_profile_bttn { + background: #282F38; + color: #ffffff; + border: 1px solid white; + transition: border-color 0.3s ease; + opacity: 1; + font-size: 15px; + margin-top: 10px; +} + .dataTables_wrapper.no-footer .dataTables_scrollBody { border-bottom: none; } diff --git a/www/head.css b/www/head.css index c9e4b51..ff46edc 100644 --- a/www/head.css +++ b/www/head.css @@ -87,6 +87,7 @@ div#bs-select-9::-webkit-scrollbar-track, div#bs-select-10::-webkit-scrollbar-track, div#bs-select-11::-webkit-scrollbar-track, div#bs-select-12::-webkit-scrollbar-track, +div#bs-select-17::-webkit-scrollbar-track, #logText::-webkit-scrollbar-track, #logTextFull::-webkit-scrollbar-track, #screening_fail::-webkit-scrollbar-track, @@ -107,7 +108,6 @@ div#gs_profile_table::-webkit-scrollbar-track, border-bottom-left-radius: 5px; } - .wtHolder::-webkit-scrollbar-thumb, div#bs-select-1::-webkit-scrollbar-thumb, div#bs-select-2::-webkit-scrollbar-thumb, @@ -121,6 +121,7 @@ div#bs-select-9::-webkit-scrollbar-thumb, div#bs-select-10::-webkit-scrollbar-thumb, div#bs-select-11::-webkit-scrollbar-thumb, div#bs-select-12::-webkit-scrollbar-thumb, +div#bs-select-17::-webkit-scrollbar-thumb, #logText::-webkit-scrollbar-thumb, #logTextFull::-webkit-scrollbar-thumb, #screening_fail::-webkit-scrollbar-thumb, From c55cdb280bb26389067733bbfd04df2ca2c5ac52 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Thu, 15 Aug 2024 20:48:11 +0200 Subject: [PATCH 50/75] Fixed and robustified AMRFinder feature --- App.R | 186 ++++++++++++++++++++++++------------------ execute/multi_eval.R | 8 +- execute/single_eval.R | 8 +- www/body.css | 6 +- www/head.css | 18 +++- 5 files changed, 140 insertions(+), 86 deletions(-) diff --git a/App.R b/App.R index 99c860d..b14aaf1 100644 --- a/App.R +++ b/App.R @@ -6148,6 +6148,21 @@ server <- function(input, output, session) { observeEvent(input$load, { + # Reset reactive screening variables + output$screening_start <- NULL + output$screening_result_sel <- NULL + output$screening_result <- NULL + output$screening_fail <- NULL + Screening$status_df <- NULL + Screening$choices <- NULL + Screening$picker_status <- TRUE + Screening$status <- "idle" + if(!is.null(input$screening_select)) { + if(!is.null(DB$data)) { + updatePickerInput(session, "screening_select", selected = character(0)) + } + } + log_print("Input load") # set typing start control variable @@ -6263,7 +6278,7 @@ server <- function(input, output, session) { class = "dropdown", tags$span(HTML( paste('', - "Status:    running typing")), + "Status:    pending typing")), style = "color:white;") ) ) @@ -6275,7 +6290,7 @@ server <- function(input, output, session) { class = "dropdown", tags$span(HTML( paste('', - "Status:    running gene screening")), + "Status:    pending gene screening")), style = "color:white;") ) ) @@ -6370,19 +6385,12 @@ server <- function(input, output, session) { log_print(paste0("New database created in ", DB$new_database)) DB$check_new_entries <- TRUE - DB$data <- NULL - DB$meta_gs <- NULL - DB$meta <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_true <- NULL - DB$scheme <- input$scheme_db # null Distance matrix, entry table and plots @@ -6513,6 +6521,7 @@ server <- function(input, output, session) { output$single_typing_progress <- NULL output$metadata_single_box <- NULL output$start_typing_ui <- NULL + } } else { log_print(paste0("Loading existing ", input$scheme_db, " database from ", DB$database)) @@ -6975,12 +6984,9 @@ server <- function(input, output, session) { ))))) { # Load database from files - Database <- - readRDS(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/Typing.rds" - )) + Database <- readRDS(file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Typing.rds")) DB$data <- Database[["Typing"]] @@ -6994,15 +7000,10 @@ server <- function(input, output, session) { } DB$change <- FALSE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] # Null pipe @@ -7015,25 +7016,15 @@ server <- function(input, output, session) { # Reset other reactive typing variables Typing$progress_format_end <- 0 - Typing$progress_format_start <- 0 - Typing$pending_format <- 0 - Typing$entry_added <- 0 - Typing$progress <- 0 - Typing$progress_format <- 900000 - output$single_typing_progress <- NULL - output$typing_fin <- NULL - output$single_typing_results <- NULL - output$typing_formatting <- NULL - Typing$single_path <- data.frame() # Null multi typing feedback variable @@ -9145,15 +9136,10 @@ server <- function(input, output, session) { # null underlying database DB$data <- NULL - DB$meta <- NULL - DB$meta_gs <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_true <- NULL # Render menu without missing values tab @@ -9926,6 +9912,13 @@ server <- function(input, output, session) { position = "bottom-end", timer = 6000 ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Screening", + type = "warning", + position = "bottom-end", + timer = 6000 + ) } else { showModal( modalDialog( @@ -9985,21 +9978,13 @@ server <- function(input, output, session) { } DB$change <- FALSE - DB$count <- 0 - DB$no_na_switch <- TRUE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - DB$deleted_entries <- character(0) observe({ @@ -10855,17 +10840,11 @@ server <- function(input, output, session) { log_print(paste0("Variable ", input$del_which_var, " removed")) DB$cust_var <- DB$cust_var[-which(DB$cust_var$Variable == input$del_which_var),] - DB$data <- select(DB$data, -(input$del_which_var)) - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] }) @@ -11076,8 +11055,6 @@ server <- function(input, output, session) { DB$data <- Database[["Typing"]] - dataa <- DB$data - if(!is.null(DB$data)){ if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) @@ -11088,21 +11065,13 @@ server <- function(input, output, session) { } DB$change <- FALSE - DB$count <- 0 - DB$no_na_switch <- TRUE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - DB$deleted_entries <- character(0) removeModal() @@ -22516,6 +22485,7 @@ server <- function(input, output, session) { # Rendering results table output$gs_results_table <- renderUI({ + req(DB$data) if(!is.null(Screening$selected_isolate)) { if(length(Screening$selected_isolate) > 0) { fluidRow( @@ -22560,6 +22530,7 @@ server <- function(input, output, session) { # Gene screening download button output$gs_download <- renderUI({ + req(DB$data) if(!is.null(Screening$selected_isolate)) { if(length(Screening$selected_isolate) > 0) { fluidRow( @@ -22582,7 +22553,7 @@ server <- function(input, output, session) { # Conditionally render table selectiom interface output$gs_table_selection <- renderUI({ - req(input$gs_view) + req(DB$data, input$gs_view) if(input$gs_view == "Table") { fluidRow( column(1), @@ -22597,6 +22568,7 @@ server <- function(input, output, session) { # Resistance profile table output display output$gs_profile_display <- renderUI({ + req(DB$data) if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { if(input$gs_view == "Table") { column( @@ -22654,12 +22626,18 @@ server <- function(input, output, session) { as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) } else { DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] } ), choicesOpt = list( disabled = c( + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), - rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])) + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) ) ), options = list( @@ -22684,6 +22662,7 @@ server <- function(input, output, session) { # Screening sidebar output$screening_sidebar <- renderUI({ + req(DB$data) if(!is.null(DB$meta_gs)) { column( width = 12, @@ -22712,7 +22691,7 @@ server <- function(input, output, session) { # Resistance profile table observe({ - req(DB$meta_gs, Screening$selected_isolate, DB$database, DB$scheme) + req(DB$meta_gs, Screening$selected_isolate, DB$database, DB$scheme, DB$data) if(length(Screening$selected_isolate) > 0 & any(Screening$selected_isolate %in% DB$data$`Assembly ID`)) { iso_select <- Screening$selected_isolate @@ -22766,9 +22745,9 @@ server <- function(input, output, session) { #Resistance profile selection table observe({ - req(DB$meta) + req(DB$meta, DB$data) output$gs_isolate_table <- renderDataTable( - select(DB$meta_gs, -c(3, 4, 10, 11, 12)), + select(DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ], -c(3, 4, 10, 11, 12)), selection = "single", rownames= FALSE, options = list(pageLength = 10, @@ -22792,7 +22771,7 @@ server <- function(input, output, session) { }) observe({ - req(input$screening_res_sel, DB$database, DB$scheme) + req(input$screening_res_sel, DB$database, DB$scheme, DB$data) if(!is.null(Screening$status_df) & !is.null(input$screening_res_sel) & !is.null(Screening$status_df$status) & @@ -22836,6 +22815,7 @@ server <- function(input, output, session) { # Availablity feedback output$gene_screening_info <- renderUI({ + req(DB$data) if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { p( HTML( @@ -22860,6 +22840,7 @@ server <- function(input, output, session) { }) output$gene_resistance_info <- renderUI({ + req(DB$data) if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { p( HTML( @@ -22885,7 +22866,8 @@ server <- function(input, output, session) { # Screening Interface - output$screening_interface <- renderUI( + output$screening_interface <- renderUI({ + req(DB$data) if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { column( width = 12, @@ -22918,12 +22900,18 @@ server <- function(input, output, session) { as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) } else { DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] } ), choicesOpt = list( disabled = c( rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])) + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) ) ), options = list( @@ -22979,14 +22967,15 @@ server <- function(input, output, session) { ) ) } - ) + }) ### Screening Events ---- observe({ - req(input$gs_view) + req(DB$data, input$gs_view) if(input$gs_view == "Table") { - Screening$selected_isolate <- DB$meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] + meta_gs <- DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ] + Screening$selected_isolate <- meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] } else if(input$gs_view == "Picker") { Screening$selected_isolate <- input$gs_profile_select } @@ -23056,6 +23045,13 @@ server <- function(input, output, session) { log_print("Cancelled gene screening") removeModal() + show_toast( + title = "Gene Screening Terminated", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + # terminate screening system(paste("kill $(pgrep -f 'execute/screening.sh')"), wait = FALSE) system(paste("killall -TERM tblastn"), wait = FALSE) @@ -23082,9 +23078,10 @@ server <- function(input, output, session) { # Get selected assembly observe({ + req(DB$data, Screening$status) if (length(input$screening_select) < 1) { output$genome_path_gs <- renderUI(HTML( - paste("", length(input$screening_select), " Isolate(s) queried for screening") + paste("", length(input$screening_select), " isolate(s) queried for screening") )) output$screening_start <- NULL @@ -23184,7 +23181,7 @@ server <- function(input, output, session) { ) ) }) - } + } else {NULL} }) #### Running Screening ---- @@ -23220,6 +23217,11 @@ server <- function(input, output, session) { as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) } else { DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] } ) Screening$picker_selected <- input$screening_select @@ -23257,10 +23259,8 @@ server <- function(input, output, session) { } }) - ### Screening Feedback ---- - observe({ - req(Screening$status, input$screening_res_sel, Screening$status_df) + req(DB$data, Screening$status, input$screening_res_sel, Screening$status_df) if(!is.null(Screening$status_df) & !is.null(Screening$status_df$status) & !is.null(Screening$status_df$isolate) & @@ -23294,7 +23294,7 @@ server <- function(input, output, session) { }) observe({ - req(Screening$status, input$screening_res_sel) + req(DB$data, Screening$status, input$screening_res_sel) if(!is.null(Screening$status_df) & !is.null(Screening$status_df$status) & !is.null(Screening$status_df$isolate) & @@ -23317,6 +23317,7 @@ server <- function(input, output, session) { }) observe({ + req(DB$data) if(!is.null(Screening$status)) { if(Screening$status != "idle") { @@ -23374,7 +23375,7 @@ server <- function(input, output, session) { Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | Screening$status_df$status == "fail")] - if(sum("unfinished" != Screening$status_df$status) == 1) { + if(sum(Screening$status_df$status != "unfinished") == 1) { Screening$first_result <- TRUE } @@ -23388,7 +23389,11 @@ server <- function(input, output, session) { saveRDS(Database, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) DB$data$Screened[which(DB$data["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" - + + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + show_toast( title = paste("Successful screening of", tail(Screening$choices, 1)), type = "success", @@ -23415,15 +23420,24 @@ server <- function(input, output, session) { } if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + if(sum(Screening$status_df$status != "unfinished") == 1) { + Screening$first_result <- TRUE + } Screening$status <- "finished" } } else { if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + if(sum(Screening$status_df$status != "unfinished") == 1) { + Screening$first_result <- TRUE + } Screening$status <- "finished" } } if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + if(sum(Screening$status_df$status != "unfinished") == 1) { + Screening$first_result <- TRUE + } Screening$status <- "finished" } } @@ -24194,7 +24208,7 @@ server <- function(input, output, session) { position = "bottom-end", timer = 6000 ) - } else if (ass_id == "") { + } else if (ass_id == "") { show_toast( title = "Empty Assembly ID", type = "error", @@ -24215,6 +24229,13 @@ server <- function(input, output, session) { position = "bottom-end", timer = 3000 ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) } else { log_print("Single typing metadata confirmed") @@ -25004,6 +25025,13 @@ server <- function(input, output, session) { position = "bottom-end", timer = 6000 ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) } else { log_print("Multi typing metadata confirmed") diff --git a/execute/multi_eval.R b/execute/multi_eval.R index eba5b90..8742546 100644 --- a/execute/multi_eval.R +++ b/execute/multi_eval.R @@ -172,6 +172,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= ncol = 13 + length(psl_files) )) + if(!save_assembly) {screen <- "NA"} else {screen <- "No"} + metadata <- c( 1, @@ -186,7 +188,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), sum(sapply(allele_vector, is.na)), - "No" + screen ) new_row <- c(metadata, allele_vector) @@ -229,6 +231,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= Database <- readRDS(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Typing.rds")) + if(!save_assembly) {screen <- "NA"} else {screen <- "No"} + metadata <- data.frame( nrow(Database[["Typing"]]) + 1, @@ -243,7 +247,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), sum(sapply(allele_vector, is.na)), - "No" + screen ) if ((ncol(Database$Typing)-13) != length(allele_vector)) { diff --git a/execute/single_eval.R b/execute/single_eval.R index 1fb70a3..3dea406 100644 --- a/execute/single_eval.R +++ b/execute/single_eval.R @@ -152,6 +152,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= Typing <- data.frame(matrix(NA, nrow = 0, ncol = 13 + length(psl_files))) + if(!save_assembly) {screen <- "NA"} else {screen <- "No"} + metadata <- c( 1, TRUE, @@ -165,7 +167,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), sum(sapply(allele_vector, is.na)), - "No" + screen ) new_row <- c(metadata, allele_vector) @@ -207,6 +209,8 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= Database <- readRDS(paste0(db_path, "/", gsub(" ", "_", meta_info$cgmlst_typing), "/Typing.rds")) + if(!save_assembly) {screen <- "NA"} else {screen <- "No"} + metadata <- data.frame( nrow(Database[["Typing"]]) + 1, @@ -221,7 +225,7 @@ if(sum(unname(base::sapply(psl_files, file.size)) <= 427) / length(psl_files) <= as.character(meta_info$append_analysisdate), length(allele_vector) - sum(sapply(allele_vector, is.na)), sum(sapply(allele_vector, is.na)), - "No" + screen ) if ((ncol(Database$Typing)-13) != length(allele_vector)) { diff --git a/www/body.css b/www/body.css index ffae73c..4f31873 100644 --- a/www/body.css +++ b/www/body.css @@ -3045,10 +3045,14 @@ button#download_resistance_profile_bttn { #screening_start_button, #screening_reset_bttn, #screening_cancel { - margin-top: 20px; + margin-top: 20px !important; border: 1px solid white; } +#screening_start_button { + margin-top: 20px !important; +} + #screening_fail { max-width: 1000px; } \ No newline at end of file diff --git a/www/head.css b/www/head.css index ff46edc..06bfdad 100644 --- a/www/head.css +++ b/www/head.css @@ -87,13 +87,20 @@ div#bs-select-9::-webkit-scrollbar-track, div#bs-select-10::-webkit-scrollbar-track, div#bs-select-11::-webkit-scrollbar-track, div#bs-select-12::-webkit-scrollbar-track, +div#bs-select-13::-webkit-scrollbar-track, +div#bs-select-14::-webkit-scrollbar-track, +div#bs-select-15::-webkit-scrollbar-track, +div#bs-select-16::-webkit-scrollbar-track, div#bs-select-17::-webkit-scrollbar-track, +div#bs-select-18::-webkit-scrollbar-track, +div#bs-select-19::-webkit-scrollbar-track, #logText::-webkit-scrollbar-track, #logTextFull::-webkit-scrollbar-track, #screening_fail::-webkit-scrollbar-track, .selectize-dropdown-content::-webkit-scrollbar-track, #mst_comm_general_select::-webkit-scrollbar-track, -.sF-dirInfo>div::-webkit-scrollbar-track{ +.sF-dirInfo>div::-webkit-scrollbar-track, +[id^="bs-select-"]::-webkit-scrollbar-thumb{ background: #F0F0F0; } @@ -121,7 +128,13 @@ div#bs-select-9::-webkit-scrollbar-thumb, div#bs-select-10::-webkit-scrollbar-thumb, div#bs-select-11::-webkit-scrollbar-thumb, div#bs-select-12::-webkit-scrollbar-thumb, +div#bs-select-13::-webkit-scrollbar-thumb, +div#bs-select-14::-webkit-scrollbar-thumb, +div#bs-select-15::-webkit-scrollbar-thumb, +div#bs-select-16::-webkit-scrollbar-thumb, div#bs-select-17::-webkit-scrollbar-thumb, +div#bs-select-18::-webkit-scrollbar-thumb, +div#bs-select-19::-webkit-scrollbar-thumb, #logText::-webkit-scrollbar-thumb, #logTextFull::-webkit-scrollbar-thumb, #screening_fail::-webkit-scrollbar-thumb, @@ -133,7 +146,8 @@ div#bs-select-17::-webkit-scrollbar-thumb, #DataTables_Table_8::-webkit-scrollbar-thumb, .dataTables_scrollBody::-webkit-scrollbar-thumb, #gs_profile_table::-webkit-scrollbar-thumb, -div#gs_profile_table::-webkit-scrollbar-thumb { +div#gs_profile_table::-webkit-scrollbar-thumb, +[id^="bs-select-"]::-webkit-scrollbar-thumb { background: #bcbcbc; border: 2px solid #F0F0F0; min-width: 100px; From 965a8651d64fd9e03a81a18f3b06e9e0a1649c18 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Fri, 16 Aug 2024 13:20:26 +0200 Subject: [PATCH 51/75] Minor change in screening UI rendering --- App.R | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/App.R b/App.R index a942ae6..e52e431 100644 --- a/App.R +++ b/App.R @@ -5836,7 +5836,8 @@ server <- function(input, output, session) { status = "") # reactive variables related to typing process Screening <- reactiveValues(status = "idle", - picker_status = TRUE) # reactive variables related to gene screening + picker_status = TRUE, + first_result = NULL) # reactive variables related to gene screening Vis <- reactiveValues(cluster = NULL, metadata = list(), @@ -6160,6 +6161,7 @@ server <- function(input, output, session) { Screening$choices <- NULL Screening$picker_status <- TRUE Screening$status <- "idle" + Screening$first_result <- NULL if(!is.null(input$screening_select)) { if(!is.null(DB$data)) { updatePickerInput(session, "screening_select", selected = character(0)) @@ -23104,6 +23106,7 @@ server <- function(input, output, session) { Screening$status_df <- NULL Screening$choices <- NULL Screening$picker_status <- TRUE + Screening$first_result <- NULL # change reactive UI output$screening_table <- NULL @@ -23158,6 +23161,7 @@ server <- function(input, output, session) { Screening$status_df <- NULL Screening$choices <- NULL Screening$picker_status <- TRUE + Screening$first_result <- NULL # change reactive UI output$screening_table <- NULL @@ -23453,7 +23457,7 @@ server <- function(input, output, session) { }) check_screening <- reactive({ - invalidateLater(2000, session) + invalidateLater(500, session) req(Screening$status_df) @@ -23469,8 +23473,10 @@ server <- function(input, output, session) { Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | Screening$status_df$status == "fail")] - if(sum(Screening$status_df$status != "unfinished") == 1) { - Screening$first_result <- TRUE + if(sum(Screening$status_df$status != "unfinished") > 0) { + if(is.null(Screening$first_result)) { + Screening$first_result <- TRUE + } } if(tail(status_df$status, 1) == "success") { @@ -23514,24 +23520,15 @@ server <- function(input, output, session) { } if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - if(sum(Screening$status_df$status != "unfinished") == 1) { - Screening$first_result <- TRUE - } Screening$status <- "finished" } } else { if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - if(sum(Screening$status_df$status != "unfinished") == 1) { - Screening$first_result <- TRUE - } Screening$status <- "finished" } } if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - if(sum(Screening$status_df$status != "unfinished") == 1) { - Screening$first_result <- TRUE - } Screening$status <- "finished" } } From 3e921574d9d40a3811905d1eec8474025fcd7a13 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Fri, 16 Aug 2024 13:41:14 +0200 Subject: [PATCH 52/75] Adapted entry table locus column properties --- App.R | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/App.R b/App.R index e52e431..9d4e246 100644 --- a/App.R +++ b/App.R @@ -7947,9 +7947,10 @@ server <- function(input, output, session) { highlightRow = TRUE, contextMenu = FALSE ) %>% - hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", halign = "htCenter", + readOnly = TRUE, renderer = htmlwidgets::JS( "function(instance, td, row, col, prop, value, cellProperties) { if (value.length > 8) { @@ -8259,7 +8260,7 @@ server <- function(input, output, session) { highlightCol = TRUE, highlightRow = TRUE ) %>% - hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", halign = "htCenter", @@ -10146,9 +10147,10 @@ server <- function(input, output, session) { highlightRow = TRUE, contextMenu = FALSE ) %>% - hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", halign = "htCenter", + readOnly = TRUE, renderer = htmlwidgets::JS( "function(instance, td, row, col, prop, value, cellProperties) { if (value.length > 8) { @@ -10457,7 +10459,7 @@ server <- function(input, output, session) { highlightCol = TRUE, highlightRow = TRUE ) %>% - hot_col((13 + nrow(DB$cust_var)):((12 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", halign = "htCenter", From c9e4862c130a36de8efa4159e318cd657a6b60e0 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Fri, 16 Aug 2024 14:40:49 +0200 Subject: [PATCH 53/75] Added feedback for Hash a directory function --- App.R | 66 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/App.R b/App.R index 9d4e246..84ea7fa 100644 --- a/App.R +++ b/App.R @@ -529,7 +529,8 @@ ui <- dashboardPage( ), shinyjs::hidden( div(id = "loading", - HTML(''))) + HTML('')) + ) ) ), fluidRow( @@ -5288,11 +5289,17 @@ ui <- dashboardPage( align = "left", shinyDirButton( "hash_dir", - "Hash folder with loci", - title = "Locate the folder with loci", + "Choose folder with .fasta files", + title = "Locate folder with loci", buttonType = "default", style = "border-color: white; margin: 10px; min-width: 200px; text-align: center" ), + actionButton("hash_start", "Start Hashing", icon = icon("circle-play")), + shinyjs::hidden( + div(id = "hash_loading", + HTML('')) + ) + ) # br(), # actionButton( # "backup_database", @@ -5305,7 +5312,6 @@ ui <- dashboardPage( # "Restore backup", # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" # ) - ) ), @@ -25818,33 +25824,37 @@ server <- function(input, output, session) { defaultRoot = "Home", session = session, filetypes = c('', 'fasta', 'fna', 'fa')) - + }) + + observeEvent(input$hash_start, { dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) - req(dir_path) - log_print("Hashing directory using utilities") - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    hashing directory")), - style = "color:white;") - ) + if (!is_empty(list.files(dir_path)) && all(endsWith(list.files(dir_path), ".fasta"))) { + log_print("Hashing directory using utilities") + shinyjs::hide("hash_start") + shinyjs::show("hash_loading") + show_toast( + title = "Hashing started!", + type = "success", + position = "bottom-end", + timer = 6000 ) - ) - hash_database(dir_path) - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    ready")), - style = "color:white;") - ) + hash_database(dir_path) + shinyjs::hide("hash_loading") + shinyjs::show("hash_start") + show_toast( + title = "Hashing completed!", + type = "success", + position = "bottom-end", + timer = 6000 ) - ) + } else { + show_toast( + title = "Incorrect folder selected!", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } }) } # end server From 28038e6a4f9850e62d18e3340b8053f7efa33975 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Sat, 17 Aug 2024 22:53:18 +0200 Subject: [PATCH 54/75] Revised distance matrix generation --- App.R | 91 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/App.R b/App.R index 84ea7fa..4a3afbd 100644 --- a/App.R +++ b/App.R @@ -5556,17 +5556,30 @@ server <- function(input, output, session) { return(varying_columns) } - # Functions to compute Hamming distance between two vectors - hamming_distance <- function(x, y) { + # Functions to compute hamming distances dependent on missing value handling + hamming.dist <- function(x, y) { sum(x != y) } - hamming_distance_ignore <- function(x, y) { + hamming.distIgnore <- function(x, y) { sum( (x != y) & !is.na(x) & !is.na(y) ) } - hamming_distance_category <- function(x, y) { - sum( ( (x != y) | (is.na(x) & !is.na(y)) | (!is.na(x) & is.na(y)) ) & !(is.na(x) & is.na(y)) ) + hamming.distCategory <- function(x, y) { + sum((x != y | xor(is.na(x), is.na(y))) & !(is.na(x) & is.na(y))) + } + + compute.distMatrix <- function(profile, hamming.method) { + mat <- as.matrix(profile) + n <- nrow(mat) + dist_mat <- matrix(0, n, n) + for (i in 1:(n-1)) { + for (j in (i+1):n) { + dist_mat[i, j] <- hamming.method(x = mat[i, ], y = mat[j, ]) + dist_mat[j, i] <- dist_mat[i, j] + } + } + return(dist_mat) } # Function to determine entry table height @@ -11291,7 +11304,6 @@ server <- function(input, output, session) { ### Distance Matrix ---- hamming_df <- reactive({ - # Create a custom proxy object for Hamming distance if(input$distmatrix_true == TRUE) { if(anyNA(DB$allelic_profile)) { if(input$na_handling == "omit") { @@ -11299,54 +11311,57 @@ server <- function(input, output, session) { allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - DB$hamming_proxy <- proxy::dist(allelic_profile_noNA_true, method = hamming_distance) + hamming_mat <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) } else if(input$na_handling == "ignore_na"){ - DB$hamming_proxy <- proxy::dist(DB$allelic_profile_true, method = hamming_distance_ignore) + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) } else { - DB$hamming_proxy <- proxy::dist(DB$allelic_profile_true, method = hamming_distance_category) + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) } } else { - DB$hamming_proxy <- proxy::dist(DB$allelic_profile_true, method = hamming_distance) + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) } } else { if(anyNA(DB$allelic_profile)) { if(input$na_handling == "omit") { allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - DB$hamming_proxy <- proxy::dist(allelic_profile_noNA, method = hamming_distance) + hamming_mat <- compute.distMatrix(allelic_profile_noNA, hamming.dist) } else if(input$na_handling == "ignore_na"){ - DB$hamming_proxy <- proxy::dist(DB$allelic_profile, method = hamming_distance_ignore) + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distIgnore) } else { - DB$hamming_proxy <- proxy::dist(DB$allelic_profile, method = hamming_distance_category) + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distCategory) } } else { - DB$hamming_proxy <- proxy::dist(DB$allelic_profile, method = hamming_distance) + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.dist) } } - hamming_matrix <- as.matrix(DB$hamming_proxy) - - DB$matrix_min <- min(hamming_matrix, na.rm = TRUE) - DB$matrix_max <- max(hamming_matrix, na.rm = TRUE) + # Extreme values for distance matrix heatmap display + DB$matrix_min <- min(hamming_mat, na.rm = TRUE) + DB$matrix_max <- max(hamming_mat, na.rm = TRUE) if(input$distmatrix_triangle == FALSE) { - hamming_matrix[upper.tri(hamming_matrix, diag = !input$distmatrix_diag)] <- NA + hamming_mat[upper.tri(hamming_mat, diag = !input$distmatrix_diag)] <- NA } - # Rownames change - rownames(hamming_matrix) <- select(DB$data, 1:(12 + nrow(DB$cust_var)))[rownames(select(DB$data, 1:(12 + nrow(DB$cust_var)))) %in% rownames(hamming_matrix), - input$distmatrix_label] - colnames(hamming_matrix) <- rownames(hamming_matrix) + # Row- and colnames change + if(input$distmatrix_true == TRUE) { + rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label][which(DB$data$Include == TRUE),]) + } else { + rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label]) + } + colnames(hamming_mat) <- rownames(hamming_mat) - mode(hamming_matrix) <- "integer" + mode(hamming_mat) <- "integer" - DB$ham_matrix <- hamming_matrix %>% + DB$ham_matrix <- hamming_mat %>% as.data.frame() %>% - mutate(Index = colnames(hamming_matrix)) %>% + mutate(Index = colnames(hamming_mat)) %>% relocate(Index) DB$distancematrix_nrow <- nrow(DB$ham_matrix) + DB$ham_matrix }) @@ -21195,16 +21210,16 @@ server <- function(input, output, session) { allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - proxy::dist(allelic_profile_noNA_true, method = hamming_distance) + compute.distMatrix(allelic_profile_noNA_true, hamming.dist) } else if(input$na_handling == "ignore_na"){ - proxy::dist(DB$allelic_profile_true, method = hamming_distance_ignore) + compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) } else { - proxy::dist(DB$allelic_profile_true, method = hamming_distance_category) + compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) } - } else {proxy::dist(DB$allelic_profile_true, method = hamming_distance)} + } else {compute.distMatrix(DB$allelic_profile_true, hamming.dist)} }) hamming_mst <- reactive({ @@ -21214,15 +21229,15 @@ server <- function(input, output, session) { allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - dist <- proxy::dist(allelic_profile_noNA_true, method = hamming_distance) + dist <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) } else if (input$na_handling == "ignore_na") { - dist <- proxy::dist(DB$allelic_profile_true, method = hamming_distance_ignore) + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) } else { - dist <- proxy::dist(DB$allelic_profile_true, method = hamming_distance_category) + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) } } else { - dist <- proxy::dist(DB$allelic_profile_true, method = hamming_distance) + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) } # Find indices of pairs with a distance of 0 @@ -21507,13 +21522,13 @@ server <- function(input, output, session) { if(anyNA(DB$allelic_profile)){ if(input$na_handling == "omit") { allelic_profile_clean_noNA_names <- allelic_profile_clean[, colSums(is.na(allelic_profile_clean)) == 0] - proxy::dist(allelic_profile_clean_noNA_names, method = hamming_distance) + compute.distMatrix(allelic_profile_clean_noNA_names, hamming.dist) } else if (input$na_handling == "ignore_na") { - proxy::dist(allelic_profile_clean, method = hamming_distance_ignore) + compute.distMatrix(allelic_profile_clean, hamming.distIgnore) } else { - proxy::dist(allelic_profile_clean, method = hamming_distance_category) + compute.distMatrix(allelic_profile_clean, hamming.distCategory) } - } else {proxy::dist(allelic_profile_clean, method = hamming_distance)} + } else {compute.distMatrix(allelic_profile_clean, hamming.dist)} } else { From 3b05d06941bc21d40041e4c4e04fd5ba5ab5d25f Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Sat, 17 Aug 2024 23:13:07 +0200 Subject: [PATCH 55/75] Fixes in MST creation --- App.R | 64 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/App.R b/App.R index 4a3afbd..e4251c7 100644 --- a/App.R +++ b/App.R @@ -17927,9 +17927,8 @@ server <- function(input, output, session) { #### MST ---- mst_tree <- reactive({ - log_print("Generating visNetwork") - Typing$data <- toVisNetworkData(Vis$ggraph_1) - Typing$data$nodes <- mutate(Typing$data$nodes, + data <- toVisNetworkData(Vis$ggraph_1) + data$nodes <- mutate(data$nodes, label = label_mst(), value = mst_node_scaling(), opacity = node_opacity()) @@ -18005,7 +18004,7 @@ server <- function(input, output, session) { }; }") - Typing$var_cols <- NULL + Vis$var_cols <- NULL # Generate pie charts as nodes if(input$mst_color_var == TRUE & (!is.null(input$mst_col_var))) { @@ -18015,33 +18014,33 @@ server <- function(input, output, session) { group[i] <- unique(Vis$meta_mst[[input$mst_col_var]])[i] } - Typing$data$nodes <- cbind(Typing$data$nodes, data.frame(metadata = character(nrow(Typing$data$nodes)))) + data$nodes <- cbind(data$nodes, data.frame(metadata = character(nrow(data$nodes)))) - if(length(which(Typing$data$nodes$group == "")) != 0) { - Typing$data$nodes$group[which(Typing$data$nodes$group == "")] <- Typing$data$nodes$group[1] + if(length(which(data$nodes$group == "")) != 0) { + data$nodes$group[which(data$nodes$group == "")] <- data$nodes$group[1] } if(is.null(input$mst_col_scale)) { - Typing$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) } else if (input$mst_col_scale == "Rainbow") { - Typing$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), color = rainbow(length(unique(Vis$meta_mst[[input$mst_col_var]])))) } else if (input$mst_col_scale == "Viridis") { - Typing$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) } - for(i in 1:nrow(Typing$data$nodes)) { + for(i in 1:nrow(data$nodes)) { - iso_subset <- strsplit(Typing$data$nodes$label[i], split = "\n")[[1]] + iso_subset <- strsplit(data$nodes$label[i], split = "\n")[[1]] variable <- Vis$meta_mst[[input$mst_col_var]] values <- variable[which(Vis$meta_mst$`Assembly Name` %in% iso_subset)] for(j in 1:length(unique(values))) { share <- sum(unique(values)[j] == values) / length(values) * 100 - color <- Typing$var_cols$color[Typing$var_cols$value == unique(values)[j]] + color <- Vis$var_cols$color[Vis$var_cols$value == unique(values)[j]] if(j == 1) { pie_vec <- paste0('{"value":', share,',"color":"', color,'"}') @@ -18050,26 +18049,26 @@ server <- function(input, output, session) { } } - Typing$data$nodes$metadata[i] <- paste0('[', pie_vec, ']') + data$nodes$metadata[i] <- paste0('[', pie_vec, ']') } } - Typing$data$edges <- mutate(Typing$data$edges, + data$edges <- mutate(data$edges, length = if(input$mst_scale_edges == FALSE) { input$mst_edge_length } else { - Typing$data$edges$weight * input$mst_edge_length_scale + data$edges$weight * input$mst_edge_length_scale }, - label = as.character(Typing$data$edges$weight), + label = as.character(data$edges$weight), opacity = input$mst_edge_opacity) if (input$mst_show_clusters) { - Typing$data$nodes$group <- compute_clusters(Typing$data$nodes, Typing$data$edges, input$mst_cluster_threshold) + data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) } - updateSliderInput(session, "mst_cluster_threshold", max = max(Typing$data$edges$weight)) + updateSliderInput(session, "mst_cluster_threshold", max = max(data$edges$weight)) - visNetwork_graph <- visNetwork(Typing$data$nodes, Typing$data$edges, + visNetwork_graph <- visNetwork(data$nodes, data$edges, main = mst_title(), background = mst_background_color(), submain = mst_subtitle()) %>% @@ -18108,16 +18107,15 @@ server <- function(input, output, session) { visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) } } - log_print("Plotting MST graph") visNetwork_graph }) # MST legend legend_col <- reactive({ - if(!is.null(Typing$var_cols)) { - if(nrow(Typing$var_cols) > 10) { + if(!is.null(Vis$var_cols)) { + if(nrow(Vis$var_cols) > 10) { 3 - } else if(nrow(Typing$var_cols) > 5) { + } else if(nrow(Vis$var_cols) > 5) { 2 } else { 1 @@ -18126,10 +18124,10 @@ server <- function(input, output, session) { }) mst_legend <- reactive({ - if(is.null(Typing$var_cols)) { + if(is.null(Vis$var_cols)) { NULL } else { - legend <- Typing$var_cols + legend <- Vis$var_cols names(legend)[1] <- "label" mutate(legend, shape = "dot", font.color = input$mst_legend_color, @@ -18391,7 +18389,7 @@ server <- function(input, output, session) { hjust = input$nj_h, vjust = input$nj_v) - Typing$nj_true <- TRUE + Vis$nj_true <- TRUE # Correct background color if zoomed out cowplot::ggdraw(Vis$nj_plot) + @@ -21763,7 +21761,7 @@ server <- function(input, output, session) { nj_tree() }) - Typing$nj_true <- TRUE + Vis$nj_true <- TRUE } } else if (input$tree_algo == "UPGMA") { @@ -21918,7 +21916,7 @@ server <- function(input, output, session) { upgma_tree() }) - Typing$upgma_true <- TRUE + Vis$upgma_true <- TRUE } } else { @@ -21961,7 +21959,7 @@ server <- function(input, output, session) { mst_tree() }) - Typing$mst_true <- TRUE + Vis$mst_true <- TRUE } } } @@ -21988,9 +21986,9 @@ server <- function(input, output, session) { observeEvent(input$create_rep, { - if((input$tree_algo == "Minimum-Spanning" & isTRUE(Typing$mst_true)) | - (input$tree_algo == "UPGMA" & isTRUE(Typing$upgma_true)) | - (input$tree_algo == "Neighbour-Joining" & isTRUE(Typing$nj_true))) { + if((input$tree_algo == "Minimum-Spanning" & isTRUE(Vis$mst_true)) | + (input$tree_algo == "UPGMA" & isTRUE(Vis$upgma_true)) | + (input$tree_algo == "Neighbour-Joining" & isTRUE(Vis$nj_true))) { # Get currently selected missing value handling option if(input$na_handling == "ignore_na") { na_handling <- "Ignore missing values for pairwise comparison" From 9a06ed876d70ed436b346596841a6503eeff475a Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Sun, 18 Aug 2024 17:25:48 +0200 Subject: [PATCH 56/75] Slight adaptions in clustering controls for MST --- App.R | 83 ++++++++++++++++++++++++++++++--------------- www/body.css | 96 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 119 insertions(+), 60 deletions(-) diff --git a/App.R b/App.R index e4251c7..511f1ca 100644 --- a/App.R +++ b/App.R @@ -991,7 +991,7 @@ ui <- dashboardPage( column( width = 2, bslib::tooltip( - bsicons::bs_icon("info-circle", title = "Only categorical variables can \nbe mapped to the node color.", color = "white", + bsicons::bs_icon("info-circle", title = "Only categorical variables can \nbe mapped to the node color", color = "white", height = "12px", width = "12px", position = "relative", top = "27px", right = "56px"), "Text shown in the tooltip.", show = FALSE, @@ -1377,20 +1377,35 @@ ui <- dashboardPage( width = 6, fluidRow( column( - width = 12, + width = 6, align = "left", - h4(p("Clustering"), style = "color:white; text-align: left;") + h4(p("Clustering"), style = "color:white; text-align: left; position: relative; right: -15px") + ), + column( + width = 2, + bslib::tooltip( + bsicons::bs_icon("info-circle", + title = "Cluster threshold according to species-specific\nComplex Type Distance (cgMLST.org)", + color = "white", height = "14px", width = "14px", + position = "relative", top = "9px", right = "28px"), + "Text shown in the tooltip.", + show = FALSE, + id = "mst_cluster_info" + ) ) ), br(), fluidRow( column( width = 9, - materialSwitch( - "mst_show_clusters", - h5(p("Show Clusters"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE + div( + class = "mst-cluster-switch", + materialSwitch( + "mst_show_clusters", + h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) ) ), column( @@ -1422,20 +1437,24 @@ ui <- dashboardPage( width = 4, HTML( paste( - tags$span(style='color: white; text-align: left; font-size: 14px; margin: 10px', 'Threshold') + tags$span(style='color: white; text-align: left; font-size: 14px; margin-left: 15px', 'Threshold') ) ) ), column( - width = 8, - sliderInput( - inputId = "mst_cluster_threshold", - label = NULL, - min = 0, - max = 20, - value = 4, - ticks = FALSE - ) + width = 4, + uiOutput("mst_cluster") + ), + column( + width = 4, + actionButton( + "mst_cluster_reset", + label = "", + icon = icon("rotate") + ), + bsTooltip("mst_cluster_reset", + HTML("Reset to default Complex Type Distance"), + placement = "top", trigger = "hover") ) ) ), @@ -12098,13 +12117,6 @@ server <- function(input, output, session) { } }) - observe({ - req(DB$schemeinfo) - updateSliderInput(session, "mst_cluster_threshold", - max = as.numeric(DB$schemeinfo[[7,2]]) * 2, - value = as.numeric(DB$schemeinfo[[7,2]])) - }) - # Custom Labels # Add custom label @@ -17803,8 +17815,19 @@ server <- function(input, output, session) { #### MST controls ---- - # Mst color mapping + # Clustering UI + output$mst_cluster <- renderUI({ + req(DB$schemeinfo) + numericInput( + inputId = "mst_cluster_threshold", + label = NULL, + value = as.numeric(DB$schemeinfo[7, 2]), + min = 1, + max = 99 + ) + }) + # MST color mapping output$mst_color_mapping <- renderUI({ if(input$mst_color_var == FALSE) { fluidRow( @@ -18066,8 +18089,6 @@ server <- function(input, output, session) { data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) } - updateSliderInput(session, "mst_cluster_threshold", max = max(data$edges$weight)) - visNetwork_graph <- visNetwork(data$nodes, data$edges, main = mst_title(), background = mst_background_color(), @@ -21088,6 +21109,12 @@ server <- function(input, output, session) { ### Reactive Events ---- + # MST cluster reset button + observeEvent(input$mst_cluster_reset, { + if(!is.null(DB$schemeinfo)) + updateNumericInput(session, "mst_cluster_threshold", value = as.numeric(DB$schemeinfo[7, 2])) + }) + # Shut off "Align Labels" control for UPGMA trees shinyjs::disable('upgma_align') shinyjs::disable('upgma_tiplab_linesize') diff --git a/www/body.css b/www/body.css index 4f31873..9563a5c 100644 --- a/www/body.css +++ b/www/body.css @@ -945,10 +945,25 @@ border-color: white; /* Visualization MST */ - #mst_title_color { +#mst_title_color { margin-bottom: 21px; } +#mst_cluster_reset i.fas.fa-rotate { +position: relative; +left: -6px; +top: -3px; +} + +button#mst_cluster_reset.btn.btn-default.action-button.shiny-bound-input { +height: 27px; +width: 27px; +position: relative; +left: -5px; +top: -3px; +border: 1px solid white; +} + .mat-switch-mst-mult { margin-top: 10px; margin-left: 2px; @@ -965,18 +980,27 @@ border-color: white; } #maindivtree_mst, #graphtree_mst { -border-radius: 10px; + border-radius: 10px; +} + +.mst-cluster-switch { + margin-top: 6px; + margin-left: 20px; +} + +#mst_cluster_threshold { + margin-top: -7px; } button#create_tree { -position: relative; -overflow: hidden; -box-shadow: 0px 0px 20px 10px rgba(255, 255, 255, 0.23); -transition: box-shadow 0.3s ease; -left: -15px; -border: none; -height: 45px; -z-index: 0; + position: relative; + overflow: hidden; + box-shadow: 0px 0px 20px 10px rgba(255, 255, 255, 0.23); + transition: box-shadow 0.3s ease; + left: -15px; + border: none; + height: 45px; + z-index: 0; } button#create_tree:hover { @@ -986,8 +1010,8 @@ box-shadow: 0px 0px 20px 15px rgba(40, 47, 56, 1); } #button-wrapper { -position: relative; -display: inline-block; + position: relative; + display: inline-block; } .icon { @@ -1002,17 +1026,17 @@ display: inline-block; } #button-wrapper:hover .icon { -transform: scale(1.2); -width: 43px; -height: auto; -top: -2px; -left: -7px; + transform: scale(1.2); + width: 43px; + height: auto; + top: -2px; + left: -7px; } #mst_ratio { -position: absolute; -right: 36px; -top: 23px; + position: absolute; + right: 36px; + top: 23px; } button#mst_general_menu { @@ -1052,33 +1076,41 @@ background: #20E6E5; } button#mst_title_menu { -height: 34px; -margin-top: 20px; -border-radius: 5px + height: 34px; + margin-top: 20px; + border-radius: 5px } button#mst_edgelabel_menu { -height: 34px; -background: #20E6E5; + height: 34px; + background: #20E6E5; color: #000000; margin-top: 37px; -border-radius: 5px + border-radius: 5px +} + +button#mst_cluster_col_menu { + height: 34px; + background: #20E6E5; + color: #000000; + border-radius: 5px; + margin-left: -32px; } button#mst_edgecolor_menu { -height: 34px; -background: #20E6E5; + height: 34px; + background: #20E6E5; color: #000000; margin-top: 20px; -border-radius: 5px + border-radius: 5px } button#mst_subtitle_menu { -height: 34px; -background: #20E6E5; + height: 34px; + background: #20E6E5; color: #000000; margin-top: 20px; -border-radius: 5px + border-radius: 5px } button#mst_legend_menu { From f6366f1a5921f8a6aa8db8c30487b09cce2ac304 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Sun, 18 Aug 2024 18:30:39 +0200 Subject: [PATCH 57/75] Fixed PB-19: New entries button appearing after failed typing --- App.R | 107 +++++++++++++++++++-------------------- execute/single_typing.sh | 1 + www/resources.R | 2 - 3 files changed, 53 insertions(+), 57 deletions(-) diff --git a/App.R b/App.R index 511f1ca..d7191f5 100644 --- a/App.R +++ b/App.R @@ -5764,11 +5764,7 @@ server <- function(input, output, session) { invalidateLater(5000, session) if(!is.null(DB$database)) { - if(file_exists(file.path( - DB$database, - gsub(" ", "_", DB$scheme), - "Typing.rds" - ))) { + if(file_exists(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds"))) { Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) @@ -9320,7 +9316,7 @@ server <- function(input, output, session) { ) ) } else { - if(is.null(Typing$entry_added)) { + #if(is.null(Typing$entry_added)) { output$db_no_entries <- renderUI( column( width = 12, @@ -9341,55 +9337,56 @@ server <- function(input, output, session) { ) ) ) - } else { - if(Typing$entry_added == 999999) { - output$db_no_entries <- renderUI( - column( - width = 12, - fluidRow( - column(1), - column( - width = 3, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 15px; position: absolute; bottom: -30px; right: -5px', 'New entries - reload database') - ) - ) - ), - column( - width = 4, - actionButton( - "load", - "", - icon = icon("rotate"), - class = "pulsating-button" - ) - ) - ) - ) - ) - } else { - output$db_no_entries <- renderUI( - column( - width = 12, - fluidRow( - column(1), - column( - width = 11, - align = "left", - HTML(paste( - "", - "No Entries for this scheme available.", - "Type a genome in the section Allelic Typing and add the result to the local database.", - sep = '
' - )) - ) - ) - ) - ) - } - } + #} + # else { + # if(Typing$entry_added == 999999) { + # output$db_no_entries <- renderUI( + # column( + # width = 12, + # fluidRow( + # column(1), + # column( + # width = 3, + # align = "left", + # HTML( + # paste( + # tags$span(style='color: white; font-size: 15px; position: absolute; bottom: -30px; right: -5px', 'New entries - reload database') + # ) + # ) + # ), + # column( + # width = 4, + # actionButton( + # "load", + # "", + # icon = icon("rotate"), + # class = "pulsating-button" + # ) + # ) + # ) + # ) + # ) + # } else { + # output$db_no_entries <- renderUI( + # column( + # width = 12, + # fluidRow( + # column(1), + # column( + # width = 11, + # align = "left", + # HTML(paste( + # "", + # "No Entries for this scheme available.", + # "Type a genome in the section Allelic Typing and add the result to the local database.", + # sep = '
' + # )) + # ) + # ) + # ) + # ) + # } + # } } } }) diff --git a/execute/single_typing.sh b/execute/single_typing.sh index 92d05ed..c8b5595 100755 --- a/execute/single_typing.sh +++ b/execute/single_typing.sh @@ -45,6 +45,7 @@ genome="$base_path/execute/blat_single/$genome_name" mv "$genome" "$base_path/execute/blat_single/$rename_file.fasta" # Run parallelized BLAT +#TODO remove X find "$alleles" -type f \( -name "*.fasta" -o -name "*.fa" -o -name "*.fna" \) | parallel pblat "$base_path/execute/blat_single/$rename_file.fasta" {} "$results/{/.}.psl" > /dev/null 2>&1 # Start appending results diff --git a/www/resources.R b/www/resources.R index 812f092..fc46c7f 100644 --- a/www/resources.R +++ b/www/resources.R @@ -1,9 +1,7 @@ # Resources -#TODO remove B pertussis from list amrfinder_species <- c( "Acinetobacter_baumannii", "Burkholderia_cepacia", "Burkholderia_mallei_FLI", - "Bordetella_pertussis", "Burkholderia_mallei_RKI", "Burkholderia_pseudomallei", "Campylobacter_jejuni_coli", "Citrobacter_freundii", "Clostridioides_difficile", "Corynebacterium_diphtheriae", "Enterobacter_asburiae", "Enterobacter_cloacae", "Enterococcus_faecalis", From b8154fd3e0046ab8184c4200e0067435b8811a02 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Sun, 18 Aug 2024 19:02:46 +0200 Subject: [PATCH 58/75] Fixed PB-20: Scheme present if new DB created --- App.R | 89 ++++++++++++++--------------------------------------------- 1 file changed, 21 insertions(+), 68 deletions(-) diff --git a/App.R b/App.R index d7191f5..a2dadbd 100644 --- a/App.R +++ b/App.R @@ -6430,7 +6430,9 @@ server <- function(input, output, session) { DB$meta_true <- NULL DB$allelic_profile <- NULL DB$allelic_profile_true <- NULL - DB$scheme <- input$scheme_db + if(!DB$select_new) { + DB$scheme <- input$scheme_db + } # null Distance matrix, entry table and plots output$db_distancematrix <- NULL @@ -6580,7 +6582,9 @@ server <- function(input, output, session) { DB$meta_true <- NULL DB$allelic_profile <- NULL DB$allelic_profile_true <- NULL - DB$scheme <- input$scheme_db + if(!DB$select_new) { + DB$scheme <- input$scheme_db + } # null Distance matrix, entry table and plots output$db_distancematrix <- NULL @@ -9316,77 +9320,26 @@ server <- function(input, output, session) { ) ) } else { - #if(is.null(Typing$entry_added)) { - output$db_no_entries <- renderUI( - column( - width = 12, - fluidRow( - column(1), - column( - width = 11, - align = "left", - HTML( - paste( - "", - "No Entries for this scheme available.\n", - "Type a genome in the section Allelic Typing and add the result to the local database.", - sep = '
' - ) + output$db_no_entries <- renderUI( + column( + width = 12, + fluidRow( + column(1), + column( + width = 11, + align = "left", + HTML( + paste( + "", + "No Entries for this scheme available.\n", + "Type a genome in the section Allelic Typing and add the result to the local database.", + sep = '
' ) ) ) ) ) - #} - # else { - # if(Typing$entry_added == 999999) { - # output$db_no_entries <- renderUI( - # column( - # width = 12, - # fluidRow( - # column(1), - # column( - # width = 3, - # align = "left", - # HTML( - # paste( - # tags$span(style='color: white; font-size: 15px; position: absolute; bottom: -30px; right: -5px', 'New entries - reload database') - # ) - # ) - # ), - # column( - # width = 4, - # actionButton( - # "load", - # "", - # icon = icon("rotate"), - # class = "pulsating-button" - # ) - # ) - # ) - # ) - # ) - # } else { - # output$db_no_entries <- renderUI( - # column( - # width = 12, - # fluidRow( - # column(1), - # column( - # width = 11, - # align = "left", - # HTML(paste( - # "", - # "No Entries for this scheme available.", - # "Type a genome in the section Allelic Typing and add the result to the local database.", - # sep = '
' - # )) - # ) - # ) - # ) - # ) - # } - # } + ) } } }) From de346fe191916914b5b6f02bb8ccf26241129751 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Mon, 19 Aug 2024 12:00:51 +0200 Subject: [PATCH 59/75] Minor correction PB-20; syntax polishing css files --- App.R | 19 ++- www/body.css | 324 +++++++++++++++++++++++++-------------------------- www/head.css | 36 ++++-- 3 files changed, 196 insertions(+), 183 deletions(-) diff --git a/App.R b/App.R index a2dadbd..a4b4368 100644 --- a/App.R +++ b/App.R @@ -5916,14 +5916,14 @@ server <- function(input, output, session) { DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available } - } else if (DB$select_new == TRUE) { - DB$database <- paste0(DB$new_database, "/Database") + } else if (DB$select_new == TRUE) { + DB$database <- file.path(DB$new_database, "Database") } } else { - if(!is.null(DB$last_db) & file.exists(paste0(getwd(), "/execute/last_db.rds"))) { + if(!is.null(DB$last_db) & file.exists(file.path(getwd(), "execute/last_db.rds"))) { - DB$database <- readRDS(paste0(getwd(), "/execute/last_db.rds")) + DB$database <- readRDS(file.path(getwd(), "execute/last_db.rds")) if(dir_exists(DB$database)) { DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present @@ -6407,7 +6407,7 @@ server <- function(input, output, session) { # Load app elements based on database availability and missing value presence if(!is.null(DB$select_new)) { - if(DB$select_new & (paste0(DB$new_database, "/Database") %in% dir_ls(DB$new_database))) { + if(DB$select_new & (file.path(DB$new_database, "Database") %in% dir_ls(DB$new_database))) { log_print("Directory already contains a database") @@ -6430,9 +6430,6 @@ server <- function(input, output, session) { DB$meta_true <- NULL DB$allelic_profile <- NULL DB$allelic_profile_true <- NULL - if(!DB$select_new) { - DB$scheme <- input$scheme_db - } # null Distance matrix, entry table and plots output$db_distancematrix <- NULL @@ -6466,7 +6463,7 @@ server <- function(input, output, session) { DB$load_selected <- FALSE # Declare database path - DB$database <- paste0(DB$new_database, "/Database") + DB$database <- file.path(DB$new_database, "Database") # Set database availability screening variables to present database DB$block_db <- TRUE @@ -6582,9 +6579,7 @@ server <- function(input, output, session) { DB$meta_true <- NULL DB$allelic_profile <- NULL DB$allelic_profile_true <- NULL - if(!DB$select_new) { - DB$scheme <- input$scheme_db - } + DB$scheme <- input$scheme_db # null Distance matrix, entry table and plots output$db_distancematrix <- NULL diff --git a/www/body.css b/www/body.css index 9563a5c..96c94e3 100644 --- a/www/body.css +++ b/www/body.css @@ -3,7 +3,7 @@ /* General */ h1, h2, h3, h4, h5, p, body { - font-family: 'Liberation Sans', sans-serif; + font-family: 'Liberation Sans', sans-serif; } label { @@ -57,8 +57,8 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { .btn-primary.focus, .btn-primary:active:focus { color: #ffffff; - background-color: #282F38; - border-color: white; + background-color: #282F38; + border-color: white; } #conf_delete .btn-default:hover { @@ -67,8 +67,8 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { .datepicker table tr td.active:active, .datepicker table tr td.active.active, .datepicker table tr td.active.highlighted:active, .datepicker table tr td.active.highlighted.active { color: #000000; - background-color: #20E6E5; - border-color: #20E6E5; + background-color: #20E6E5; + border-color: #20E6E5; } .table>caption+thead>tr:first-child>td, .table>caption+thead>tr:first-child>th, .table>colgroup+thead>tr:first-child>td, .table>colgroup+thead>tr:first-child>th, .table>thead:first-child>tr:first-child>td, .table>thead:first-child>tr:first-child>th, @@ -79,7 +79,7 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { .dropdown-menu>li.selected { color: #ffffff; - background-color: #282F38; + background-color: #282F38; } .dropdown-menu>li>a.selected{ @@ -91,13 +91,13 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { } .dropdown-menu>li>a:hover { - color: #000000; - background-color: #20E6E5; + Color: #000000; + background-color: #20E6E5; } .selectize-dropdown .selected { background-color: #20E6E5; - color: black; + color: black; } .bs-searchbox .form-control { @@ -135,7 +135,7 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { .main-sidebar .sidebar .sidebar-menu .treeview-menu a { color: #ffffff !important; - margin-left: 25px; + margin-left: 25px; border-radius: 20px; margin-top: 7px; margin-bottom: 7px; @@ -259,17 +259,17 @@ font-size: 12px; } #reload_db i.fas.fa-rotate { -position: relative; -left: -7px; -top: -3px; + position: relative; + left: -7px; + top: -3px; } button#reload_db.btn.btn-default.action-button.shiny-bound-input { -height: 27px; -width: 27px; -position: relative; -left: -20px; -border: 1px solid white; + height: 27px; + width: 27px; + position: relative; + left: -20px; + border: 1px solid white; } #db_location { @@ -443,18 +443,18 @@ table.dataTable.display>tbody>tr:hover>* { color: white !important; border: 1px solid #111; background-color: #20E6E5; - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111)); - background: -webkit-linear-gradient(top, #585858 0%, #111 100%); - background: -moz-linear-gradient(top, #585858 0%, #111 100%); - background: -ms-linear-gradient(top, #585858 0%, #111 100%); - background: -o-linear-gradient(top, #585858 0%, #111 100%); - background: linear-gradient(to bottom, #585858 0%, #111 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111)); + background: -webkit-linear-gradient(top, #585858 0%, #111 100%); + background: -moz-linear-gradient(top, #585858 0%, #111 100%); + background: -ms-linear-gradient(top, #585858 0%, #111 100%); + background: -o-linear-gradient(top, #585858 0%, #111 100%); + background: linear-gradient(to bottom, #585858 0%, #111 100%); } .dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active { cursor: default; color: #fff !important; - border: 1px solid transparent; + border: 1px solid transparent; background: transparent; box-shadow: none; } @@ -463,7 +463,7 @@ table.dataTable.display>tbody>tr:hover>* { color: black !important; border: 1px solid rgb(255 255 255 / 0%); background-color: #20E6E5 !important; - border-radius: 5px; + border-radius: 5px; background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 230, 230, 0.05)), color-stop(100%, rgba(0, 0, 0, 0.05))); background: -webkit-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); background: -moz-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%); @@ -476,12 +476,12 @@ table.dataTable.display>tbody>tr:hover>* { color: white !important; border: 1px solid #00f3ff; background-color: #111; - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111)); - background: -webkit-linear-gradient(top, #585858 0%, #111 100%); - background: -moz-linear-gradient(top, #585858 0%, #111 100%); - background: -ms-linear-gradient(top, #585858 0%, #111 100%); - background: -o-linear-gradient(top, #585858 0%, #111 100%); - background: transparent; + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111)); + background: -webkit-linear-gradient(top, #585858 0%, #111 100%); + background: -moz-linear-gradient(top, #585858 0%, #111 100%); + background: -ms-linear-gradient(top, #585858 0%, #111 100%); + background: -o-linear-gradient(top, #585858 0%, #111 100%); + background: transparent; } input.form-control.pickr-color { @@ -512,26 +512,26 @@ input.form-control.pickr-color { } button#copy_seq { -background: #282F38; + background: #282F38; color: #ffffff; border: 1px solid white; -transition: border-color 0.3s ease; + transition: border-color 0.3s ease; } button#get_locus_bttn { -background: #282F38; + background: #282F38; color: #ffffff; border: 1px solid white; -transition: border-color 0.3s ease; -opacity: 1; -font-size: 15px; -width: 147px; + transition: border-color 0.3s ease; + opacity: 1; + font-size: 15px; + width: 147px; } button#get_locus_bttn i.fas.fa-download { -position: relative; -top: -1px; -left: -6px; + position: relative; + top: -1px; + left: -6px; } /* Icons */ @@ -609,22 +609,22 @@ i.far.fa-pen-to-square { #table_missing_values > div > div > div > div > table > tbody > tr > td, #multi_select_table > div > div > div > div > table > tbody > tr > td, #multi_typing_result_table > div > div > div > div > table > tbody > tr > td, - #typing_result_table > div > div > div > div > table > tbody > tr > td{ + #typing_result_table > div > div > div > div > table > tbody > tr > td { color: black !important; } .miss_val_box, -#table_missing_values{ -margin-left: 50px; +#table_missing_values { + margin-left: 50px; } #download_na_matrix_bttn > i { -top: 1px !important; + top: 1px !important; } #sel_all_entries, #desel_all_entries, #typing_start, #start_typ_multi, #undo_changes, #genome_file, #genome_file_multi, #reset_multi, #save_cust { -border-color: white; + border-color: white; } #genome_file_multi, @@ -637,24 +637,24 @@ border-color: white; } #cgmlst_scheme { -margin-top: 41px; + margin-top: 41px; } .dropdown-menu>.active>a, .dropdown-menu>.active>a:focus, .dropdown-menu>.active>a:hover { color: #ffffff !important; - background-color: #282F38 !important; + background-color: #282F38 !important; } #shiny-tab-db_browse_entries > div:nth-child(11) > div.col-sm-1, #shiny-tab-init > div:nth-child(4) > div.col-sm-1, #shiny-tab-init > div:nth-child(3) > div.col-sm-1 { -width: 4.333333%; + width: 4.333333%; } .bttn-simple:hover { border-color: #20E6E5 !important; - background: #20E6E5 !important; - color: black !important; + background: #20E6E5 !important; + color: black !important; opacity: 1; } @@ -677,143 +677,143 @@ width: 4.333333%; #db_entries, #db_distancematrix, #table_missing_values, #multi_select_table, #typing_result_table, #multi_typing_result_table { -border-radius: 8px; -color: black; + border-radius: 8px; + color: black; } #multi_typing_result_table { -margin-top: -15px; + margin-top: -15px; } #add_new_variable { -background: green; -height: 35px; -width: 38px; -margin-left: -5px; -margin-top: 19px; + background: green; + height: 35px; + width: 38px; + margin-left: -5px; + margin-top: 19px; } #delete_new_variable { -background: #FF5964; + background: #FF5964; height: 35px; -width: 38px; -margin-left: -5px; -margin-top: 20px; + width: 38px; + margin-left: -5px; + margin-top: 20px; } #new_var_name { -height: 33px; -margin-left: -6px; -width: 123px; -margin-top: -12px; + height: 33px; + margin-left: -6px; + width: 123px; + margin-top: -12px; } #cust_var_select { -margin-top: -40px; + margin-top: -40px; } #cust_var_select .selectize-dropdown-content { -max-height: 80px; + max-height: 80px; } div#db_distancematrix.rhandsontable { -font-size: 11px; + font-size: 11px; } button#download_cgMLST { -font-size: 14px; -height: 34px; -background: #282F38; + font-size: 14px; + height: 34px; + background: #282F38; color: #ffffff; border: 1px solid white; } .btn-primary:hover { background-color: #20e6e5; - border-color: #20e6e5; - color: black; + border-color: #20e6e5; + color: black; border-radius: 5px; height: 35px; } .btn-primary { background: #282F38; - color: #ffffff; - border-color: #282F38; - border-radius: 5px; + color: #ffffff; + border-color: #282F38; + border-radius: 5px; height: 35px; padding: 6px 12px; } .btn-default:hover { border-color: #20e6e5 !important; - background: #20e6e5 !important; - color: black !important; + background: #20e6e5 !important; + color: black !important; } button#download_cgMLST i.fas.fa-download { -margin-right: 5px !important + margin-right: 5px !important } #show_cust_var { -color:black; -font-size: 14px; -margin-left: 15px; + color:black; + font-size: 14px; + margin-left: 15px; } button#download_distmatrix_bttn { -font-size: 14px; -height: 34px; -background: #282F38; + font-size: 14px; + height: 34px; + background: #282F38; color: #ffffff; border: 1px solid white; -position: absolute; -top: -50px; -transition: border-color 0.3s ease; /* Smooth transition for border color */ - } + position: absolute; + top: -50px; + transition: border-color 0.3s ease; /* Smooth transition for border color */ +} button#download_entry_table_bttn { -height: 34px; -background: #282F38; + height: 34px; + background: #282F38; color: #ffffff; border: 1px solid white; -transition: border-color 0.3s ease; /* Smooth transition for border color */ - } + transition: border-color 0.3s ease; +} button#download_schemeinfo_bttn { -height: 28px; -background: #282F38; + height: 28px; + background: #282F38; color: #ffffff; margin-top: 19px; -border: 1px solid white; -margin-left: 10px; -transition: border-color 0.3s ease; /* Smooth transition for border color */ + border: 1px solid white; + margin-left: 10px; + transition: border-color 0.3s ease; } button#download_loci_info_bttn { -height: 28px; -background: #282F38; + height: 28px; + background: #282F38; color: #ffffff; margin-top: 19px; -border: 1px solid white; -margin-left: 10px; -transition: border-color 0.3s ease; + border: 1px solid white; + margin-left: 10px; + transition: border-color 0.3s ease; } button#download_na_matrix_bttn { -height: 34px; -background: #282F38; + height: 34px; + background: #282F38; color: #ffffff; border: 1px solid white; -margin-top: 14px; -margin-left: 10px; -transition: border-color 0.3s ease; + margin-top: 14px; + margin-left: 10px; + transition: border-color 0.3s ease; } button#edit_button.btn.btn-default.action-button.shiny-bound-input { -background: #20E6E5; + background: #20E6E5; color: #000000; - } +} /* Typing */ @@ -856,7 +856,7 @@ background: #20E6E5; body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-today.is-selected > button{ color: white; background: #282F38; - border-radius: 5px; + border-radius: 5px; box-shadow: inset 0 1px 3px rgb(0 0 0) } @@ -865,7 +865,7 @@ body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-selected, .is-selected .pika-button { color: white; background: #282F38; - border-radius: 5px; + border-radius: 5px; box-shadow: inset 0 1px 3px rgb(0 0 0) } @@ -888,23 +888,23 @@ body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-today > b body > div.datepicker.datepicker-dropdown.dropdown-menu.datepicker-orient-left.datepicker-orient-top > div.datepicker-days > table > tbody > tr > td.active.day { background: #282F38; - color: white; + color: white; } .datepicker table tr td.day:hover, .datepicker table tr td.focused { color: #000; - background: rgba(0,255,213,1); + background: rgba(0,255,213,1); cursor: pointer; } #print_log { -border-color: white; + border-color: white; } #logText, #logTextFull { -margin-top: 5px; + margin-top: 5px; } .append_table { @@ -923,14 +923,14 @@ margin-top: 5px; span#progress_bar-title.progress-text { -color: white; -font-size: 13px; -font-weight: normal; + color: white; + font-size: 13px; + font-weight: normal; } div#progress_bar.progress-bar { -font-size:13px; -line-height: 30px; + font-size:13px; + line-height: 30px; } .progress { @@ -950,18 +950,18 @@ border-color: white; } #mst_cluster_reset i.fas.fa-rotate { -position: relative; -left: -6px; -top: -3px; + position: relative; + left: -6px; + top: -3px; } button#mst_cluster_reset.btn.btn-default.action-button.shiny-bound-input { -height: 27px; -width: 27px; -position: relative; -left: -5px; -top: -3px; -border: 1px solid white; + height: 27px; + width: 27px; + position: relative; + left: -5px; + top: -3px; + border: 1px solid white; } .mat-switch-mst-mult { @@ -1004,9 +1004,9 @@ button#create_tree { } button#create_tree:hover { -background: #3c8c56 !important; + background: #3c8c56 !important; border: none; -box-shadow: 0px 0px 20px 15px rgba(40, 47, 56, 1); + box-shadow: 0px 0px 20px 15px rgba(40, 47, 56, 1); } #button-wrapper { @@ -1040,37 +1040,37 @@ box-shadow: 0px 0px 20px 15px rgba(40, 47, 56, 1); } button#mst_general_menu { -height: 27px; -width: 27px; -background: #20E6E5; + height: 27px; + width: 27px; + background: #20E6E5; color: #000000; border-radius: 5px; -margin-top: 2px; + margin-top: 2px; } button#mst_analysis_menu { -height: 27px; -width: 27px; -background: #20E6E5; + height: 27px; + width: 27px; + background: #20E6E5; color: #000000; border-radius: 5px; -margin-top: -17px; -position: relative; -top: -10px; + margin-top: -17px; + position: relative; + top: -10px; } button#mst_node_menu { -height: 34px; -background: #20E6E5; + height: 34px; + background: #20E6E5; color: #000000; border-radius: 5px; -margin-top: 10px; -margin-bottom: -1px; + margin-top: 10px; + margin-bottom: -1px; } button#mst_edge_menu { -height: 34px; -background: #20E6E5; + height: 34px; + background: #20E6E5; color: #000000; border-radius: 5px; } @@ -3007,10 +3007,10 @@ background: linear-gradient(to right, #F7FCFD 0%, #F7FCFD 11.1111%, #E0ECF4 11.1 } #mst_date_general_select .form-control { -height: 28px; -position: relative; -right: -22px; -margin-top: 7px; + height: 28px; + position: relative; + right: -22px; + margin-top: 7px; } #mst_operator_general_select { @@ -3056,13 +3056,13 @@ button#download_report_bttn { } button#download_resistance_profile_bttn { - background: #282F38; - color: #ffffff; - border: 1px solid white; - transition: border-color 0.3s ease; - opacity: 1; - font-size: 15px; - margin-top: 10px; + background: #282F38; + Color: #ffffff; + border: 1px solid white; + transition: border-color 0.3s ease; + opacity: 1; + font-size: 15px; + margin-top: 10px; } .dataTables_wrapper.no-footer .dataTables_scrollBody { diff --git a/www/head.css b/www/head.css index 06bfdad..2359336 100644 --- a/www/head.css +++ b/www/head.css @@ -45,10 +45,22 @@ } /* Style sequence display*/ - .base-a { color: black; text-shadow: 0px 0px 4px red; } -.base-t { color: black; text-shadow: 0px 0px 4px green; } -.base-g { color: black; text-shadow: 0px 0px 4px blue; } -.base-c { color: black; text-shadow: 0px 0px 4px orange; } +.base-a { + color: black; + text-shadow: 0px 0px 4px red; +} +.base-t { + color: black; + text-shadow: 0px 0px 4px green; +} +.base-g { + color: black; + text-shadow: 0px 0px 4px blue; +} +.base-c { + color: black; + text-shadow: 0px 0px 4px orange; +} .sequence { font-family: monospace; @@ -58,10 +70,15 @@ right: 160px; } -.clipboard-button { margin-left: 10px; cursor: pointer; border: none; background: none;} +.clipboard-button { + margin-left: 10px; + cursor: pointer; + border: none; + background: none; +} #loci_sequences { -color: white; + color: white; } /* Scrollbar Styling */ @@ -167,10 +184,11 @@ div#gs_profile_table::-webkit-scrollbar-thumb, } /* Other */ - #currentTime { + +#currentTime { padding: 50px; -position: relative; -top: 15px; + position: relative; + top: 15px; } #statustext { From 1b9d8896c034ca8778235330084b1f0e5cf8a9d5 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Mon, 19 Aug 2024 15:17:40 +0200 Subject: [PATCH 60/75] Changed truncated hash display --- App.R | 103 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/App.R b/App.R index a4b4368..a5b8c99 100644 --- a/App.R +++ b/App.R @@ -5749,6 +5749,13 @@ server <- function(input, output, session) { } } + # Truncate hashes + truncHash <- function(hash) { + if(!is.na(hash)) { + paste0(str_sub(hash, 1, 4), "...", str_sub(hash, nchar(hash) - 3, nchar(hash))) + } else {NA} + } + # Function to check for duplicate isolate IDs for multi typing start dupl_mult_id <- reactive({ req(Typing$multi_sel_table) @@ -5916,14 +5923,14 @@ server <- function(input, output, session) { DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available } - } else if (DB$select_new == TRUE) { - DB$database <- file.path(DB$new_database, "Database") + } else if (DB$select_new == TRUE) { + DB$database <- paste0(DB$new_database, "/Database") } } else { - if(!is.null(DB$last_db) & file.exists(file.path(getwd(), "execute/last_db.rds"))) { + if(!is.null(DB$last_db) & file.exists(paste0(getwd(), "/execute/last_db.rds"))) { - DB$database <- readRDS(file.path(getwd(), "execute/last_db.rds")) + DB$database <- readRDS(paste0(getwd(), "/execute/last_db.rds")) if(dir_exists(DB$database)) { DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present @@ -6407,7 +6414,7 @@ server <- function(input, output, session) { # Load app elements based on database availability and missing value presence if(!is.null(DB$select_new)) { - if(DB$select_new & (file.path(DB$new_database, "Database") %in% dir_ls(DB$new_database))) { + if(DB$select_new & (paste0(DB$new_database, "/Database") %in% dir_ls(DB$new_database))) { log_print("Directory already contains a database") @@ -6429,6 +6436,7 @@ server <- function(input, output, session) { DB$meta <- NULL DB$meta_true <- NULL DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL DB$allelic_profile_true <- NULL # null Distance matrix, entry table and plots @@ -6578,6 +6586,7 @@ server <- function(input, output, session) { DB$meta <- NULL DB$meta_true <- NULL DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL DB$allelic_profile_true <- NULL DB$scheme <- input$scheme_db @@ -7042,6 +7051,7 @@ server <- function(input, output, session) { DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] # Null pipe @@ -7968,8 +7978,13 @@ server <- function(input, output, session) { if (length(input$compare_select) > 0) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), + entry_data, col_highlight = diff_allele() - 1, dup_names_high = duplicated_names() - 1, dup_ids_high = duplicated_ids() - 1, @@ -7983,18 +7998,7 @@ server <- function(input, output, session) { hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", halign = "htCenter", - readOnly = TRUE, - renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - ) - ) %>% + readOnly = TRUE) %>% hot_col(1, valign = "htMiddle", halign = "htCenter") %>% @@ -8280,8 +8284,13 @@ server <- function(input, output, session) { if (length(input$compare_select) > 0) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), + entry_data, col_highlight = diff_allele() - 1, rowHeaders = NULL, height = table_height(), @@ -8296,17 +8305,7 @@ server <- function(input, output, session) { hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", - halign = "htCenter", - renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }") - ) %>% + halign = "htCenter") %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% @@ -8626,6 +8625,7 @@ server <- function(input, output, session) { ) ) } else if((DB$change == TRUE) | !identical(get.entry.table.meta(), select(DB$meta, -13))) { + if(!is.null(input$db_entries)) { fluidRow( column( @@ -9220,6 +9220,7 @@ server <- function(input, output, session) { DB$meta_gs <- NULL DB$meta_true <- NULL DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL DB$allelic_profile_true <- NULL # Render menu without missing values tab @@ -10014,6 +10015,7 @@ server <- function(input, output, session) { DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] DB$deleted_entries <- character(0) @@ -10118,8 +10120,13 @@ server <- function(input, output, session) { if (length(input$compare_select) > 0) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), + entry_data, col_highlight = diff_allele() - 1, dup_names_high = duplicated_names() - 1, dup_ids_high = duplicated_ids() - 1, @@ -10133,17 +10140,7 @@ server <- function(input, output, session) { hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", halign = "htCenter", - readOnly = TRUE, - renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }") - ) %>% + readOnly = TRUE) %>% hot_col(1, valign = "htMiddle", halign = "htCenter") %>% @@ -10429,8 +10426,13 @@ server <- function(input, output, session) { if (length(input$compare_select) > 0) { if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var)), input$compare_select), + entry_data, col_highlight = diff_allele() - 1, rowHeaders = NULL, height = table_height(), @@ -10445,17 +10447,7 @@ server <- function(input, output, session) { hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", - halign = "htCenter", - renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }") - ) %>% + halign = "htCenter") %>% hot_col(3:(12 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% @@ -10896,6 +10888,7 @@ server <- function(input, output, session) { DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] }) @@ -11122,6 +11115,7 @@ server <- function(input, output, session) { DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] DB$deleted_entries <- character(0) @@ -11242,6 +11236,7 @@ server <- function(input, output, session) { DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] # User feedback From 4886c7c887ea01335751ee1ef878592674344b5e Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Mon, 19 Aug 2024 15:51:03 +0200 Subject: [PATCH 61/75] Small fixes for entry table --- App.R | 54 ++++++++++++++++++++++++---------------------------- www/body.css | 9 ++++++++- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/App.R b/App.R index a5b8c99..05028db 100644 --- a/App.R +++ b/App.R @@ -5563,13 +5563,13 @@ server <- function(input, output, session) { varying_columns <- c() for (col in 1:ncol(dataframe)) { - if(class(dataframe[, col]) == "integer") { + #if(class(dataframe[, col]) == "integer") { unique_values <- unique(dataframe[, col]) if (length(unique_values) > 1) { varying_columns <- c(varying_columns, col) } - } + #} } return(varying_columns) @@ -5794,7 +5794,7 @@ server <- function(input, output, session) { diff_allele <- reactive({ if (!is.null(DB$data) & !is.null(input$compare_select) & !is.null(DB$cust_var)) { - var_alleles(select(DB$data, input$compare_select)) + (12 + nrow(DB$cust_var)) + var_alleles(select(DB$data, input$compare_select)) + (13 + nrow(DB$cust_var)) } }) @@ -7896,7 +7896,7 @@ server <- function(input, output, session) { hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(3, validator = " @@ -7995,7 +7995,7 @@ server <- function(input, output, session) { highlightRow = TRUE, contextMenu = FALSE ) %>% - hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", halign = "htCenter", readOnly = TRUE) %>% @@ -8039,7 +8039,7 @@ server <- function(input, output, session) { } } ") %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(8, type = "dropdown", source = country_names) %>% @@ -8162,7 +8162,7 @@ server <- function(input, output, session) { hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(3, validator = " @@ -8302,11 +8302,11 @@ server <- function(input, output, session) { highlightCol = TRUE, highlightRow = TRUE ) %>% - hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", halign = "htCenter") %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(3, readOnly = TRUE) %>% @@ -8522,7 +8522,7 @@ server <- function(input, output, session) { Shiny.setInputValue('invalid_date', true); } }") %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_rows(fixedRowsTop = 0) %>% @@ -9929,6 +9929,11 @@ server <- function(input, output, session) { observeEvent(input$reload_db, { log_print("Input reload_db") + dataa <<- DB$data + comp_sel <<- input$compare_select + cust_var <<- DB$cust_var + all_prof <<- DB$allelic_profile + if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( title = "Pending Multi Typing", @@ -10038,7 +10043,7 @@ server <- function(input, output, session) { hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(3, validator = " @@ -10137,7 +10142,7 @@ server <- function(input, output, session) { highlightRow = TRUE, contextMenu = FALSE ) %>% - hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), valign = "htMiddle", halign = "htCenter", readOnly = TRUE) %>% @@ -10147,7 +10152,7 @@ server <- function(input, output, session) { hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(3, validator = " @@ -10304,7 +10309,7 @@ server <- function(input, output, session) { hot_col(3, readOnly = TRUE) %>% hot_col(c(1, 5, 10, 11, 12, 13), readOnly = TRUE) %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(3, validator = " @@ -10444,11 +10449,11 @@ server <- function(input, output, session) { highlightCol = TRUE, highlightRow = TRUE ) %>% - hot_col((13 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), readOnly = TRUE, valign = "htMiddle", halign = "htCenter") %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_col(3, readOnly = TRUE) %>% @@ -10664,7 +10669,7 @@ server <- function(input, output, session) { Shiny.setInputValue('invalid_date', true); } }") %>% - hot_col(3:(12 + nrow(DB$cust_var)), + hot_col(3:(13 + nrow(DB$cust_var)), valign = "htMiddle", halign = "htLeft") %>% hot_rows(fixedRowsTop = 0) %>% @@ -10983,7 +10988,7 @@ server <- function(input, output, session) { } if (input$download_table_loci == FALSE) { - download_matrix <- select(download_matrix, 1:(12 + nrow(DB$cust_var))) + download_matrix <- select(download_matrix, 1:(13 + nrow(DB$cust_var))) } write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) @@ -11083,19 +11088,10 @@ server <- function(input, output, session) { # Ensure correct logical data type Data[["Typing"]][["Include"]] <- as.logical(Data[["Typing"]][["Include"]]) - saveRDS(Data, paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/Typing.rds" - )) + saveRDS(Data, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) # Load database from files - Database <- - readRDS(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/Typing.rds" - )) + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) DB$data <- Database[["Typing"]] diff --git a/www/body.css b/www/body.css index 96c94e3..96b963f 100644 --- a/www/body.css +++ b/www/body.css @@ -34,10 +34,17 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { background-color: #282F38 !important; } -.handsontable .wtBorder .area .corner { +.handsontable .wtBorder.area.corner { background-color: #20e6e5 !important; } +/*.handsontable td.area:before, +.handsontable .htBottom.fill.area.highlight +.handsontable .wtBorder.area, +.handsontable .wtBorder.corner { + background: #20e6e5 !important; +}*/ + .tooltip-inner { white-space: normal; max-width: 800px; /* Adjust the width as needed */ From 0a03a715528021503e602bd2f9bd82f489f1b70b Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Mon, 19 Aug 2024 15:52:18 +0200 Subject: [PATCH 62/75] Minor corrections for last commit --- App.R | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/App.R b/App.R index 05028db..d2803dc 100644 --- a/App.R +++ b/App.R @@ -5563,13 +5563,11 @@ server <- function(input, output, session) { varying_columns <- c() for (col in 1:ncol(dataframe)) { - #if(class(dataframe[, col]) == "integer") { - unique_values <- unique(dataframe[, col]) - - if (length(unique_values) > 1) { - varying_columns <- c(varying_columns, col) - } - #} + unique_values <- unique(dataframe[, col]) + + if (length(unique_values) > 1) { + varying_columns <- c(varying_columns, col) + } } return(varying_columns) @@ -9929,11 +9927,6 @@ server <- function(input, output, session) { observeEvent(input$reload_db, { log_print("Input reload_db") - dataa <<- DB$data - comp_sel <<- input$compare_select - cust_var <<- DB$cust_var - all_prof <<- DB$allelic_profile - if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { show_toast( title = "Pending Multi Typing", From 556c1a46014b1e11d84d3fea7147c776771bf20d Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 13:49:17 +0200 Subject: [PATCH 63/75] Added hash truncation to entry table download; Minor Entry Browser UI changes --- App.R | 170 ++++++++++++++++++++++++++++++++------------------- www/body.css | 11 +++- www/head.css | 22 +++---- 3 files changed, 128 insertions(+), 75 deletions(-) diff --git a/App.R b/App.R index d2803dc..e77a663 100644 --- a/App.R +++ b/App.R @@ -282,7 +282,93 @@ ui <- dashboardPage( column(1), column( width = 8, - uiOutput("db_entries_table") + uiOutput("db_entries_table"), + fluidRow( + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-blue" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px", " = included for analyses") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-orange" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -45px", " = duplicated assembly name") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-red" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -75px", " = ≥ 5% of loci missing") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-green" + ) + ), + column( + width = 9, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -105px", " = locus contains multiple variants") + ) + ) + ) + ) + ) + ) + ) ), column( width = 3, @@ -8930,9 +9016,8 @@ server <- function(input, output, session) { ), hr(), fluidRow( - column(2), column( - width = 10, + width = 8, align = "left", br(), div( @@ -8953,12 +9038,19 @@ server <- function(input, output, session) { right = TRUE ) ), + div( + class = "mat-switch-db", + materialSwitch( + "download_table_hashes", + h5(p("Truncate Hashes"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), br(), - ) - ), - fluidRow( + ), column( - width = 12, + width = 4, align = "center", downloadBttn( "download_entry_table", @@ -8969,59 +9061,6 @@ server <- function(input, output, session) { color = "primary" ) ) - ), - br() - ) - ), - column( - width = 12, - fluidRow( - column( - width = 2, - div( - class = "rectangle-blue" - ), - div( - class = "rectangle-orange" - ), - div( - class = "rectangle-red" - ), - div( - class = "rectangle-green" - ) - ), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -12px", " = included for analyses") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -13px", " = duplicated name/ID") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -14px", " = ≥ 5% of loci missing") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -15px", " = locus contains multiple variants") - ) - ) - ), ) ) ) @@ -10974,7 +11013,13 @@ server <- function(input, output, session) { paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv") }, content = function(file) { - download_matrix <- hot_to_r(input$db_entries) + download_matrix <<- hot_to_r(input$db_entries) + + if(input$download_table_hashes == TRUE) { + included_loci <<- colnames(select(download_matrix, -(1:(13 + nrow(DB$cust_var))))) + full_hashes <<- DB$allelic_profile[included_loci] + download_matrix[included_loci] <- full_hashes + } if (input$download_table_include == TRUE) { download_matrix <- download_matrix[which(download_matrix$Include == TRUE),] @@ -11066,7 +11111,8 @@ server <- function(input, output, session) { Data[["Typing"]] <- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) - meta_hot <- hot_to_r(input$db_entries) + meta_hot <- hot_to_r(input$db_entries) %>% + select(1:(13 + nrow(DB$cust_var))) if(length(DB$deleted_entries > 0)) { diff --git a/www/body.css b/www/body.css index 96b963f..976d7a3 100644 --- a/www/body.css +++ b/www/body.css @@ -776,7 +776,7 @@ button#download_distmatrix_bttn { border: 1px solid white; position: absolute; top: -50px; - transition: border-color 0.3s ease; /* Smooth transition for border color */ + transition: border-color 0.3s ease; } button#download_entry_table_bttn { @@ -785,6 +785,13 @@ button#download_entry_table_bttn { color: #ffffff; border: 1px solid white; transition: border-color 0.3s ease; + margin-top: 55px; +} + +#download_entry_table_bttn .fas .fa-download, +#download_entry_table_bttn > i { + position: relative; + top: 1px; } button#download_schemeinfo_bttn { @@ -857,7 +864,7 @@ button#edit_button.btn.btn-default.action-button.shiny-bound-input { } #multi_typing_results .mult_res_sel .selectize-input.items.full.has-options.has-items { - width: auto; + width: -webkit-fill-available; } body > div.htDatepickerHolder > div > div > table > tbody > tr > td.is-today.is-selected > button{ diff --git a/www/head.css b/www/head.css index 2359336..64d296b 100644 --- a/www/head.css +++ b/www/head.css @@ -1,27 +1,27 @@ /* Entry table legend */ .rectangle-orange { - width: 75px; - height: 23px; + width: 50px; + height: 20px; margin-top: 10px; - margin-left: 10px; + margin-left: -40px; border: 1px solid #BCBCBC; background-color: #DEB200; } .rectangle-green { - width: 75px; - height: 23px; + width: 50px; + height: 20px; margin-top: 10px; - margin-left: 10px; + margin-left: -100px; border: 1px solid #BCBCBC; background-color: #74BC8B; } .rectangle-red { - width: 75px; - height: 23px; + width: 50px; + height: 20px; margin-top: 10px; - margin-left: 10px; + margin-left: -70px; border: 1px solid #BCBCBC; background-color: #FF7334; } @@ -36,8 +36,8 @@ } .rectangle-blue { - width: 75px; - height: 23px; + width: 50px; + height: 20px; margin-top: 10px; margin-left: 10px; border: 1px solid #BCBCBC; From d418e37fe70249ba7018ef52ab8de5843183b660 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 14:16:15 +0200 Subject: [PATCH 64/75] Minor changes in MST Cluster scale default value; Deleting entries button UI --- App.R | 44 +++++++++++++++++++++++++++++++++++--------- www/body.css | 15 +++++---------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/App.R b/App.R index e77a663..1de9ff7 100644 --- a/App.R +++ b/App.R @@ -283,6 +283,7 @@ ui <- dashboardPage( column( width = 8, uiOutput("db_entries_table"), + br(), fluidRow( column( width = 3, @@ -1511,7 +1512,7 @@ ui <- dashboardPage( selectInput( "mst_cluster_col_scale", label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), - choices = c("Viridis", "Rainbow"), + choices = c("Rainbow", "Viridis"), width = "150px" ) ) @@ -11189,12 +11190,25 @@ server <- function(input, output, session) { if( (length(input$select_delete) - nrow(DB$data) ) == 0) { showModal( modalDialog( - paste0("Deleting will lead to removal of all entries and assemblies from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?"), + HTML(paste0("Deleting will lead to removal of ALL entries and assemblies from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?")), easyClose = TRUE, title = "Deleting Entries", footer = tagList( - modalButton("Cancel"), - actionButton("conf_delete_all", "Delete", class = "btn btn-danger") + fluidRow( + column(6), + column( + width = 4, + modalButton("Cancel"), + ), + column( + width = 2, + div( + class = "danger-button", + actionButton("conf_delete_all", "Delete") + ) + ) + ) + ) ) ) @@ -11208,11 +11222,23 @@ server <- function(input, output, session) { fade = TRUE, easyClose = TRUE, footer = tagList( - modalButton("Cancel"), - actionButton( - "conf_delete", - "Delete", - class = "btn btn-danger") + fluidRow( + column(6), + column( + width = 4, + modalButton("Cancel") + ), + column( + width = 2, + div( + class = "danger-button", + actionButton( + "conf_delete", + "Delete" + ) + ) + ) + ) ) ) ) diff --git a/www/body.css b/www/body.css index 976d7a3..ef35f62 100644 --- a/www/body.css +++ b/www/body.css @@ -38,12 +38,11 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { background-color: #20e6e5 !important; } -/*.handsontable td.area:before, -.handsontable .htBottom.fill.area.highlight -.handsontable .wtBorder.area, -.handsontable .wtBorder.corner { - background: #20e6e5 !important; -}*/ +.danger-button .btn-default:hover { + background-color: #ff5964 !important; + border-color: #ff5964 !important; + color: white !important; +} .tooltip-inner { white-space: normal; @@ -68,10 +67,6 @@ body > div.swal2-container.swal2-bottom-end.swal2-backdrop-show { border-color: white; } -#conf_delete .btn-default:hover { - background-color: #FF5964 !important; -} - .datepicker table tr td.active:active, .datepicker table tr td.active.active, .datepicker table tr td.active.highlighted:active, .datepicker table tr td.active.highlighted.active { color: #000000; background-color: #20E6E5; From 4f2f27f756103e6c97bde82d488b776e71b2dad9 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 14:58:15 +0200 Subject: [PATCH 65/75] Changes in download status UI; Manage schemes functionality --- App.R | 480 ++++++++++++++++++++++++++++++++++----------------- www/body.css | 12 +- 2 files changed, 330 insertions(+), 162 deletions(-) diff --git a/App.R b/App.R index 1de9ff7..e836b2c 100644 --- a/App.R +++ b/App.R @@ -284,92 +284,6 @@ ui <- dashboardPage( width = 8, uiOutput("db_entries_table"), br(), - fluidRow( - column( - width = 3, - fluidRow( - column( - width = 3, - div( - class = "rectangle-blue" - ) - ), - column( - width = 7, - p( - HTML( - paste( - tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px", " = included for analyses") - ) - ) - ) - ) - ) - ), - column( - width = 3, - fluidRow( - column( - width = 3, - div( - class = "rectangle-orange" - ) - ), - column( - width = 7, - p( - HTML( - paste( - tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -45px", " = duplicated assembly name") - ) - ) - ) - ) - ) - ), - column( - width = 3, - fluidRow( - column( - width = 3, - div( - class = "rectangle-red" - ) - ), - column( - width = 7, - p( - HTML( - paste( - tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -75px", " = ≥ 5% of loci missing") - ) - ) - ) - ) - ) - ), - column( - width = 3, - fluidRow( - column( - width = 3, - div( - class = "rectangle-green" - ) - ), - column( - width = 9, - p( - HTML( - paste( - tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -105px", " = locus contains multiple variants") - ) - ) - ) - ) - ) - ) - ) ), column( width = 3, @@ -551,51 +465,7 @@ ui <- dashboardPage( br(), br(), br(), - pickerInput( - inputId = "select_cgmlst", - label = NULL, - choices = list( - "Acinetobacter baumanii", - "Bacillus anthracis", - "Bordetella pertussis", - "Brucella melitensis", - "Brucella spp.", - "Burkholderia mallei (FLI)", - "Burkholderia mallei (RKI)", - "Burkholderia pseudomallei", - "Campylobacter jejuni/coli", - "Clostridioides difficile", - "Clostridium perfringens", - "Corynebacterium diphtheriae", - "Cronobacter sakazakii/malonaticus", - "Enterococcus faecalis", - "Enterococcus faecium", - "Escherichia coli", - "Francisella tularensis", - "Klebsiella oxytoca sensu lato", - "Klebsiella pneumoniae sensu lato", - "Legionella pneumophila", - "Listeria monocytogenes", - "Mycobacterium tuberculosis complex", - "Mycobacteroides abscessus", - "Mycoplasma gallisepticum", - "Paenibacillus larvae", - "Pseudomonas aeruginosa", - "Salmonella enterica", - "Serratia marcescens", - "Staphylococcus aureus", - "Staphylococcus capitis", - "Streptococcus pyogenes" - ), - width = "300px", - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = FALSE - ) + uiOutput("scheme_selector") ), column( width = 2, @@ -615,8 +485,28 @@ ui <- dashboardPage( icon = icon("download") ), shinyjs::hidden( - div(id = "loading", - HTML('')) + div( + id = "downloading", + HTML( + paste0( + "", + "Downloading scheme", + '' + ) + ) + ) + ), + shinyjs::hidden( + div( + id = "hashing", + HTML( + paste0( + "", + "Hashing scheme", + '' + ) + ) + ) ) ) ), @@ -5951,15 +5841,15 @@ server <- function(input, output, session) { block_db = FALSE, load_selected = TRUE, no_na_switch = FALSE, - first_look = FALSE) # reactive variables related to local database + first_look = FALSE, + status = "") # reactive variables related to local database Typing <- reactiveValues(table = data.frame(), single_path = data.frame(), progress = 0, progress_format_start = 0, progress_format_end = 0, - result_list = NULL, - status = "") # reactive variables related to typing process + result_list = NULL) # reactive variables related to typing process Screening <- reactiveValues(status = "idle", picker_status = TRUE, @@ -7948,12 +7838,190 @@ server <- function(input, output, session) { output$db_entries_table <- renderUI({ if(!is.null(DB$data)) { if(between(nrow(DB$data), 1, 30)) { - rHandsontableOutput("db_entries") + fluidRow( + column( + width = 12, + rHandsontableOutput("db_entries") + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-blue" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px", " = included for analyses") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-orange" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -45px", " = duplicated assembly name") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-red" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -75px", " = ≥ 5% of loci missing") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-green" + ) + ), + column( + width = 9, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -105px", " = locus contains multiple variants") + ) + ) + ) + ) + ) + ) + ) } else { - addSpinner( - rHandsontableOutput("db_entries"), - spin = "dots", - color = "#ffffff" + fluidRow( + column( + width = 12, + addSpinner( + rHandsontableOutput("db_entries"), + spin = "dots", + color = "#ffffff" + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-blue" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px", " = included for analyses") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-orange" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -45px", " = duplicated assembly name") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-red" + ) + ), + column( + width = 7, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -75px", " = ≥ 5% of loci missing") + ) + ) + ) + ) + ) + ), + column( + width = 3, + fluidRow( + column( + width = 3, + div( + class = "rectangle-green" + ) + ), + column( + width = 9, + p( + HTML( + paste( + tags$span(style="color: white; font-size: 12px; position: relative; bottom: -10px; margin-left: -105px", " = locus contains multiple variants") + ) + ) + ) + ) + ) + ) ) } } @@ -9565,6 +9633,106 @@ server <- function(input, output, session) { ### Conditional UI Elements rendering ---- + # Scheme selector UI + output$scheme_selector <- renderUI( + if(!is.null(DB$scheme)) { + pickerInput( + inputId = "select_cgmlst", + label = NULL, + choices = list( + "Acinetobacter baumanii", + "Bacillus anthracis", + "Bordetella pertussis", + "Brucella melitensis", + "Brucella spp.", + "Burkholderia mallei (FLI)", + "Burkholderia mallei (RKI)", + "Burkholderia pseudomallei", + "Campylobacter jejuni/coli", + "Clostridioides difficile", + "Clostridium perfringens", + "Corynebacterium diphtheriae", + "Cronobacter sakazakii/malonaticus", + "Enterococcus faecalis", + "Enterococcus faecium", + "Escherichia coli", + "Francisella tularensis", + "Klebsiella oxytoca sensu lato", + "Klebsiella pneumoniae sensu lato", + "Legionella pneumophila", + "Listeria monocytogenes", + "Mycobacterium tuberculosis complex", + "Mycobacteroides abscessus", + "Mycoplasma gallisepticum", + "Paenibacillus larvae", + "Pseudomonas aeruginosa", + "Salmonella enterica", + "Serratia marcescens", + "Staphylococcus aureus", + "Staphylococcus capitis", + "Streptococcus pyogenes" + ), + width = "300px", + selected = DB$scheme, + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = FALSE + ) + } else { + pickerInput( + inputId = "select_cgmlst", + label = NULL, + choices = list( + "Acinetobacter baumanii", + "Bacillus anthracis", + "Bordetella pertussis", + "Brucella melitensis", + "Brucella spp.", + "Burkholderia mallei (FLI)", + "Burkholderia mallei (RKI)", + "Burkholderia pseudomallei", + "Campylobacter jejuni/coli", + "Clostridioides difficile", + "Clostridium perfringens", + "Corynebacterium diphtheriae", + "Cronobacter sakazakii/malonaticus", + "Enterococcus faecalis", + "Enterococcus faecium", + "Escherichia coli", + "Francisella tularensis", + "Klebsiella oxytoca sensu lato", + "Klebsiella pneumoniae sensu lato", + "Legionella pneumophila", + "Listeria monocytogenes", + "Mycobacterium tuberculosis complex", + "Mycobacteroides abscessus", + "Mycoplasma gallisepticum", + "Paenibacillus larvae", + "Pseudomonas aeruginosa", + "Salmonella enterica", + "Serratia marcescens", + "Staphylococcus aureus", + "Staphylococcus capitis", + "Streptococcus pyogenes" + ), + width = "300px", + selected = NULL, + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = FALSE + ) + } + + ) + # Contro custom variables table output$cust_var_select <- renderUI({ if(nrow(DB$cust_var) > 5) { @@ -11550,6 +11718,7 @@ server <- function(input, output, session) { ## Download cgMLST ---- observe({ + req(input$select_cgmlst) if (input$select_cgmlst == "Acinetobacter baumanii") { species <- "Abaumannii1907" Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") @@ -11743,22 +11912,10 @@ server <- function(input, output, session) { log_print(paste0("Started download of scheme for ", Scheme$folder_name)) shinyjs::hide("download_cgMLST") - shinyjs::show("loading") - - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    Downloading scheme...")), - style = "color:white;") - ) - ) - ) + shinyjs::show("downloading") show_toast( - title = "Download started", + title = paste("Downloading", input$select_cgmlst, "scheme"), type = "success", position = "bottom-end", timer = 5000 @@ -11802,6 +11959,16 @@ server <- function(input, output, session) { ) log_print("Hashing downloaded database") + shinyjs::show("hashing") + shinyjs::hide("downloading") + + show_toast( + title = paste("Hashing of", input$select_cgmlst, "started"), + type = "success", + position = "bottom-end", + timer = 5000 + ) + # Hash temporary folder hash_database(file.path(DB$database, Scheme$folder_name, @@ -11913,7 +12080,7 @@ server <- function(input, output, session) { DB$exist <- length(dir_ls(DB$database)) == 0 shinyjs::show("download_cgMLST") - shinyjs::hide("loading") + shinyjs::hide("hashing") output$statustext <- renderUI( fluidRow( @@ -11957,6 +12124,7 @@ server <- function(input, output, session) { # Download Target Info (CSV Table) observe({ + req(input$select_cgmlst) input$download_cgMLST scheme_overview <- read_html(Scheme$link_scheme) %>% diff --git a/www/body.css b/www/body.css index ef35f62..c3c3df1 100644 --- a/www/body.css +++ b/www/body.css @@ -606,12 +606,12 @@ i.far.fa-pen-to-square { /* Database */ - #db_entries > div > div > div > div > table > tbody > tr > td, - #db_distancematrix > div > div > div > div > table > tbody > tr > td, - #table_missing_values > div > div > div > div > table > tbody > tr > td, - #multi_select_table > div > div > div > div > table > tbody > tr > td, - #multi_typing_result_table > div > div > div > div > table > tbody > tr > td, - #typing_result_table > div > div > div > div > table > tbody > tr > td { +#db_entries > div > div > div > div > table > tbody > tr > td, +#db_distancematrix > div > div > div > div > table > tbody > tr > td, +#table_missing_values > div > div > div > div > table > tbody > tr > td, +#multi_select_table > div > div > div > div > table > tbody > tr > td, +#multi_typing_result_table > div > div > div > div > table > tbody > tr > td, +#typing_result_table > div > div > div > div > table > tbody > tr > td { color: black !important; } From fb822131e8433d95a3f6708037daa06a98117bc6 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 15:27:34 +0200 Subject: [PATCH 66/75] Small fix in Gene Screening conditional UI --- App.R | 184 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 94 insertions(+), 90 deletions(-) diff --git a/App.R b/App.R index e836b2c..9f57ace 100644 --- a/App.R +++ b/App.R @@ -7843,6 +7843,7 @@ server <- function(input, output, session) { width = 12, rHandsontableOutput("db_entries") ), + br(), column( width = 3, fluidRow( @@ -7938,6 +7939,7 @@ server <- function(input, output, session) { color = "#ffffff" ) ), + br(), column( width = 3, fluidRow( @@ -22866,110 +22868,114 @@ server <- function(input, output, session) { # Conditionally render table selectiom interface output$gs_table_selection <- renderUI({ - req(DB$data, input$gs_view) - if(input$gs_view == "Table") { - fluidRow( - column(1), - column( - width = 10, - div(class = "loci_table", - dataTableOutput("gs_isolate_table")) + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + req(DB$data, input$gs_view) + if(input$gs_view == "Table") { + fluidRow( + column(1), + column( + width = 10, + div(class = "loci_table", + dataTableOutput("gs_isolate_table")) + ) ) - ) + } else {NULL} } else {NULL} }) # Resistance profile table output display output$gs_profile_display <- renderUI({ req(DB$data) - if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { - if(input$gs_view == "Table") { - column( - width = 10, - hr(), - fluidRow( - column( - width = 4, - p( - HTML( - paste0("", - "Gene Screening Results
", - "", - "Comprising genes for resistance, virulence, stress, etc.") + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { + if(input$gs_view == "Table") { + column( + width = 10, + hr(), + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) ) + ), + column( + width = 4, + uiOutput("gs_download") ) ), - column( - width = 4, - uiOutput("gs_download") - ) - ), - br(), - uiOutput("gs_results_table") - ) - } else { - column( - width = 10, - fluidRow( - column( - width = 4, - p( - HTML( - paste0("", - "Gene Screening Results
", - "", - "Comprising genes for resistance, virulence, stress, etc.") + br(), + uiOutput("gs_results_table") + ) + } else { + column( + width = 10, + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) ) - ) - ), - column( - width = 4, - div( - class = "gs-picker", - pickerInput( - "gs_profile_select", - "", - choices = list( - Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] - }, - Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "No")] - }, - `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] - } - ), - choicesOpt = list( - disabled = c( - rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) + ), + column( + width = 4, + div( + class = "gs-picker", + pickerInput( + "gs_profile_select", + "", + choices = list( + Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] + } + ), + choicesOpt = list( + disabled = c( + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) + ) + ), + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" ) - ), - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" ) ) + ), + column( + width = 3, + uiOutput("gs_download") ) ), - column( - width = 3, - uiOutput("gs_download") - ) - ), - br(), - uiOutput("gs_results_table") - ) - } + br(), + uiOutput("gs_results_table") + ) + } + } else {NULL} } else {NULL} }) @@ -23128,7 +23134,6 @@ server <- function(input, output, session) { # Availablity feedback output$gene_screening_info <- renderUI({ - req(DB$data) if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { p( HTML( @@ -23153,7 +23158,6 @@ server <- function(input, output, session) { }) output$gene_resistance_info <- renderUI({ - req(DB$data) if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { p( HTML( From f07f12ed7dc675a652bebf6f606069178ef154ff Mon Sep 17 00:00:00 2001 From: fpaskali Date: Tue, 20 Aug 2024 15:47:45 +0200 Subject: [PATCH 67/75] Type 2 clustering initial implementation --- App.R | 51731 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 25896 insertions(+), 25835 deletions(-) diff --git a/App.R b/App.R index d2803dc..0cd1d6b 100644 --- a/App.R +++ b/App.R @@ -1,25835 +1,25896 @@ -######## PhyloTrace ######### - -# _______________________ #### -# CRAN Packages -library(shiny) -library(R.utils) -library(igraph) -library(shinyWidgets) -library(shinydashboard) -library(dashboardthemes) -library(ggplot2) -library(ggnewscale) -library(ggplotify) -library(ape) -library(tidyverse) -library(rlang) -library(tidytree) -library(shinyFiles) -library(dplyr) -library(downloader) -library(rvest) -library(rmarkdown) -library(knitr) -library(kableExtra) -library(fs) -library(data.table) -library(zoo) -library(ggnetwork) -library(rhandsontable) -library(visNetwork) -library(proxy) -library(phangorn) -library(cowplot) -library(viridis) -library(RColorBrewer) -library(bslib) -library(bsicons) -library(DT) -library(shinyBS) -library(openssl) -library(logr) -# Bioconductor Packages -library(treeio) -library(ggtree) -library(ggtreeExtra) - -source(paste0(getwd(), "/www/resources.R")) - -options(ignore.negative.edge=TRUE) - -# User Interface ---- - -ui <- dashboardPage( - - title = "PhyloTrace 1.5.0", - - # Title - dashboardHeader( - - title = span( - div( - class = "img_logo", - img( - src = "PhyloTrace.jpg", width = 190 - ) - ) - ), - uiOutput("loaded_scheme"), - uiOutput("databasetext"), - uiOutput("statustext"), - tags$li(class = "dropdown", - tags$span(id = "currentTime", style = "color:white; font-weight:bold;")), - disable = FALSE - ), - - ## Sidebar ---- - dashboardSidebar( - tags$head(includeCSS("www/head.css")), - tags$style(includeCSS("www/body.css")), - tags$style(HTML( - "@keyframes pulsate { - 0% { transform: scale(1); } - 50% { transform: scale(1.1); } - 100% { transform: scale(1); } - } - .pulsating-button { - animation: pulsate 1s ease infinite; - } - .pulsating-button:hover { - animation: none; - }")), - br(), br(), - sidebarMenu( - id = "tabs", - sidebarMenuOutput("menu"), - uiOutput("menu_sep2"), - conditionalPanel( - "input.tabs==='db_browse_entries'", - uiOutput("entrytable_sidebar") - ), - conditionalPanel( - "input.tabs==='db_distmatrix'", - uiOutput("distmatrix_sidebar") - ), - conditionalPanel( - "input.tabs==='db_missing_values'", - uiOutput("missing_values_sidebar") - ), - conditionalPanel( - "input.tabs==='typing'", - uiOutput("typing_sidebar") - ), - conditionalPanel( - "input.tabs==='visualization'", - uiOutput("visualization_sidebar") - ), - conditionalPanel( - "input.tabs==='gs_profile'", - uiOutput("screening_sidebar") - ) - ) - ), - - dashboardBody( - tags$head(tags$link(rel = "shortcut icon", href = "favicon.ico")), - shinyjs::useShinyjs(), - - shinyDashboardThemeDIY( - ### general - appFontFamily = "Liberation Sans", - appFontColor = "#000000", - primaryFontColor = "#ffffff", - infoFontColor = "rgb(0,0,0)", - successFontColor = "rgb(0,0,0)", - warningFontColor = "rgb(0,0,0)", - dangerFontColor = "rgb(0,0,0)", - bodyBackColor = cssGradientThreeColors( - direction = "down", - colorStart = "#282f38", - colorMiddle = "#384454", - colorEnd = "#495d78", - colorStartPos = 0, - colorMiddlePos = 50, - colorEndPos = 100 - ), - - ### header - logoBackColor = "#282f38", - headerButtonBackColor = "#282f38", - headerButtonIconColor = "#18ece1", - headerButtonBackColorHover = "#282f38", - headerButtonIconColorHover = "#ffffff", - headerBackColor = "#282f38", - headerBoxShadowColor = "#aaaaaa", - headerBoxShadowSize = "0px 0px 0px", - - ### sidebar - sidebarBackColor = cssGradientThreeColors( - direction = "down", - colorStart = "#282f38", - colorMiddle = "#384454", - colorEnd = "#495d78", - colorStartPos = 0, - colorMiddlePos = 50, - colorEndPos = 100), - - sidebarPadding = 0, - sidebarMenuBackColor = "transparent", - sidebarMenuPadding = 0, - sidebarMenuBorderRadius = 0, - sidebarShadowRadius = "5px 5px 5px", - sidebarShadowColor = "#282f38", - sidebarUserTextColor = "#ffffff", - sidebarSearchBackColor = "rgb(55,72,80)", - sidebarSearchIconColor = "rgb(153,153,153)", - sidebarSearchBorderColor = "rgb(55,72,80)", - sidebarTabTextColor = "rgb(255,255,255)", - sidebarTabTextSize = 15, - sidebarTabBorderStyle = "none none solid none", - sidebarTabBorderColor = "rgb(35,106,135)", - sidebarTabBorderWidth = 0, - sidebarTabBackColorSelected = cssGradientThreeColors( - direction = "right", - colorStart = "rgba(44,222,235,1)", - colorMiddle = "rgba(44,222,235,1)", - colorEnd = "rgba(0,255,213,1)", - colorStartPos = 0, - colorMiddlePos = 30, - colorEndPos = 100 - ), - sidebarTabTextColorSelected = "rgb(0,0,0)", - sidebarTabRadiusSelected = "0px 0px 0px 0px", - sidebarTabBackColorHover = cssGradientThreeColors( - direction = "right", - colorStart = "rgba(44,222,235,1)", - colorMiddle = "rgba(44,222,235,1)", - colorEnd = "rgba(0,255,213,1)", - colorStartPos = 0, - colorMiddlePos = 30, - colorEndPos = 100 - ), - sidebarTabTextColorHover = "rgb(50,50,50)", - sidebarTabBorderStyleHover = "none none solid none", - sidebarTabBorderColorHover = "rgb(75,126,151)", - sidebarTabBorderWidthHover = 0, - sidebarTabRadiusHover = "0px 0px 0px 0px", - - ### boxes - boxBackColor = "#ffffff", - boxBorderRadius = 7, - boxShadowSize = "0px 0px 0px", - boxShadowColor = "#ffffff", - boxTitleSize = 20, - boxDefaultColor = "#00a65a", - boxPrimaryColor = "#ffffff", - boxInfoColor = "#00a65a", - boxSuccessColor = "#00a65a", - boxWarningColor = "#ffffff", - boxDangerColor = "#ffffff", - tabBoxTabColor = "#ffffff", - tabBoxTabTextSize = 14, - tabBoxTabTextColor = "rgb(0,0,0)", - tabBoxTabTextColorSelected = "rgb(0,0,0)", - tabBoxBackColor = "#ffffff", - tabBoxHighlightColor = "#ffffff", - tabBoxBorderRadius = 5, - - ### inputs - buttonBackColor = "#282F38", - buttonTextColor = "#ffffff", - buttonBorderColor = "#282F38", - buttonBorderRadius = 5, - buttonBackColorHover = cssGradientThreeColors( - direction = "right", - colorStart = "rgba(44,222,235,1)", - colorMiddle = "rgba(44,222,235,1)", - colorEnd = "rgba(0,255,213,1)", - colorStartPos = 0, - colorMiddlePos = 30, - colorEndPos = 100 - ), - buttonTextColorHover = "#000000", - buttonBorderColorHover = "transparent", - textboxBackColor = "#ffffff", - textboxBorderColor = "#ffffff", - textboxBorderRadius = 5, - textboxBackColorSelect = "#ffffff", - textboxBorderColorSelect = "#000000", - - ### tables - tableBackColor = "rgb(255,255,255)", - tableBorderColor = "rgb(240,240,240)", - tableBorderTopSize = 1, - tableBorderRowSize = 1 - ), - - uiOutput("start_message"), - - tabItems( - - ## Tab Database ---- - - ### Tab Browse Entries ---- - - tabItem( - tabName = "db_browse_entries", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Browse Local Database"), style = "color:white") - ) - ), - hr(), br(), - br(), - br(), - uiOutput("no_scheme_entries"), - uiOutput("db_no_entries"), - uiOutput("entry_table_controls"), - br(), br(), - fluidRow( - column(1), - column( - width = 8, - uiOutput("db_entries_table") - ), - column( - width = 3, - align = "left", - uiOutput("delete_box"), - uiOutput("compare_allele_box"), - uiOutput("download_entries"), - br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br() - ) - ), - br() - ), - - ### Tab Scheme Info ---- - - tabItem( - tabName = "db_schemeinfo", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Scheme Info"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - uiOutput("no_scheme_info"), - fluidRow( - column(2), - column( - width = 7, - align = "center", - fluidRow( - column( - width = 7, - align = "right", - uiOutput("scheme_header") - ), - column( - width = 2, - align = "left", - uiOutput("download_scheme_info") - ) - ), - br(), - br(), - uiOutput("scheme_info") - ) - ) - ), - - ### Tab Loci Info ---- - - tabItem( - tabName = "db_loci_info", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Loci Info"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - fluidRow( - column(1), - column( - width = 10, - align = "center", - fluidRow( - column( - width = 6, - align = "right", - uiOutput("loci_header") - ), - column( - width = 2, - align = "left", - uiOutput("download_loci") - ) - ), - br(), - div(class = "loci_table", - dataTableOutput("db_loci")) - ) - ), - br(), br(), - fluidRow( - column(1), - uiOutput("sequence_selector"), - column(1), - column( - width = 7, - br(), - uiOutput("loci_sequences") - ) - ) - ), - - ### Tab Distance Matrix ---- - - tabItem( - tabName = "db_distmatrix", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Distance Matrix"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - uiOutput("no_scheme_distancematrix"), - uiOutput("distancematrix_no_entries"), - fluidRow( - column(1), - uiOutput("distmatrix_show") - ), - br(), br() - ), - - ### Tab Missing Values ---- - - tabItem( - tabName = "db_missing_values", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Missing Values"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - fluidRow( - column( - width = 3, - uiOutput("missing_values"), - fluidRow( - column( - width = 2, - div( - class = "rectangle-red-space" - ) - ), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 75px; position: relative; bottom: -12px", " = ≥ 5% of loci missing") - ) - ) - ) - ) - ) - ), - column( - width = 8, - rHandsontableOutput("table_missing_values") - ) - ) - ), - - ## Tab Manage Schemes ---- - - tabItem( - tabName = "init", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Select cgMLST Scheme"), style = "color:white") - ) - ), - hr(), - fluidRow( - column(1), - column( - width = 3, - br(), - br(), - br(), - pickerInput( - inputId = "select_cgmlst", - label = NULL, - choices = list( - "Acinetobacter baumanii", - "Bacillus anthracis", - "Bordetella pertussis", - "Brucella melitensis", - "Brucella spp.", - "Burkholderia mallei (FLI)", - "Burkholderia mallei (RKI)", - "Burkholderia pseudomallei", - "Campylobacter jejuni/coli", - "Clostridioides difficile", - "Clostridium perfringens", - "Corynebacterium diphtheriae", - "Cronobacter sakazakii/malonaticus", - "Enterococcus faecalis", - "Enterococcus faecium", - "Escherichia coli", - "Francisella tularensis", - "Klebsiella oxytoca sensu lato", - "Klebsiella pneumoniae sensu lato", - "Legionella pneumophila", - "Listeria monocytogenes", - "Mycobacterium tuberculosis complex", - "Mycobacteroides abscessus", - "Mycoplasma gallisepticum", - "Paenibacillus larvae", - "Pseudomonas aeruginosa", - "Salmonella enterica", - "Serratia marcescens", - "Staphylococcus aureus", - "Staphylococcus capitis", - "Streptococcus pyogenes" - ), - width = "300px", - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = FALSE - ) - ), - column( - width = 2, - br(), - br(), - br(), - h5(textOutput("scheme_update_info"), style = "color: white") - ), - column( - width = 2, - br(), - br(), - br(), - actionButton( - "download_cgMLST", - label = "Download", - icon = icon("download") - ), - shinyjs::hidden( - div(id = "loading", - HTML('')) - ) - ) - ), - fluidRow( - column(1), - column( - width = 6, - align = "center", - br(), - br(), - br(), - addSpinner( - tableOutput("cgmlst_scheme"), - spin = "dots", - color = "#ffffff" - ) - ) - ) - ), - - - - ## Tab Allelic Typing ---------------------------------------------- - - - tabItem( - tabName = "typing", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Generate Allelic Profile"), style = "color:white") - ) - ), - hr(), - uiOutput("typing_no_db"), - conditionalPanel( - "input.typing_mode == 'Single'", - fluidRow( - uiOutput("initiate_typing_ui"), - uiOutput("single_typing_progress"), - column(1), - uiOutput("metadata_single_box"), - column(1), - uiOutput("start_typing_ui") - ) - ), - conditionalPanel( - "input.typing_mode == 'Multi'", - fluidRow( - uiOutput("initiate_multi_typing_ui"), - uiOutput("multi_stop"), - column(1), - uiOutput("metadata_multi_box"), - column(1), - uiOutput("start_multi_typing_ui") - ), - fluidRow( - column( - width = 6, - uiOutput("pending_typing") - ), - column( - width = 6, - uiOutput("multi_typing_results") - ) - ) - ) - ), - - - ## Tab Visualization ------------------------------------------------------- - - - tabItem( - tabName = "visualization", - fluidRow( - tags$script(src = "javascript_functions.js"), - column( - width = 12, - align = "center", - br(), - conditionalPanel( - "input.tree_algo=='Minimum-Spanning'", - uiOutput("mst_field") - ), - conditionalPanel( - "input.tree_algo=='Neighbour-Joining'", - uiOutput("nj_field") - ), - conditionalPanel( - "input.tree_algo=='UPGMA'", - uiOutput("upgma_field") - ) - ) - ), - br(), - hr(), - - ### Control panels MST ---- - conditionalPanel( - "input.tree_algo=='Minimum-Spanning'", - fluidRow( - column( - width = 4, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - height = "500px", - h3(p("Layout"), style = "color:white; position:relative; right:-15px"), - hr(), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Title"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "mst_title", - label = "", - width = "100%", - placeholder = "Plot Title" - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_title_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_title_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - numericInput( - "mst_title_size", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 40, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Subtitle"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "mst_subtitle", - label = "", - width = "100%", - placeholder = "Plot Subtitle" - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_subtitle_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_subtitle_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - numericInput( - "mst_subtitle_size", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 20, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ) - ) - ) - ), - hr(), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Legend"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_legend_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_legend_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 11, - sliderInput( - "mst_font_size", - label = h5("Font Size", style = "color:white; margin-bottom: 0px;"), - value = 18, - min = 15, - max = 30, - step = 1, - ticks = FALSE, - width = "180px" - ) - ), - column(1) - ), - br(), - fluidRow( - column( - width = 11, - sliderInput( - "mst_symbol_size", - label = h5("Key Size", style = "color:white; margin-bottom: 0px;"), - value = 20, - min = 10, - max = 30, - step = 1, - ticks = FALSE, - width = "180px" - ) - ), - column(1) - ) - ) - ) - ), - fluidRow( - column( - width = 7, - selectInput( - "mst_legend_ori", - label = "", - width = "100%", - choices = c("Left" = "left", "Right" = "right") - ) - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Background"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 12, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "mst_background_transparent", - h5(p("Transparent"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_background_color", - width = "100%", - selected = "#ffffff", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 4, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - height = "500px", - h3(p("Nodes"), style = "color:white; position:relative; right:-15px"), - hr(), - fluidRow( - column( - width = 6, - column( - width = 12, - align = "left", - h4(p("Label"), style = "color:white;") - ), - column( - width = 12, - align = "center", - div( - class = "label_sel", - uiOutput("mst_node_label") - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "node_font_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - numericInput( - "node_label_fontsize", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 14, - min = 8, - max = 30, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 10, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "mst_color_var", - h5(p("Add Variable"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 2, - bslib::tooltip( - bsicons::bs_icon("info-circle", title = "Only categorical variables can \nbe mapped to the node color", color = "white", - height = "12px", width = "12px", position = "relative", top = "27px", right = "56px"), - "Text shown in the tooltip.", - show = FALSE, - id = "mst_node_col_info" - ) - ) - ), - uiOutput("mst_color_mapping") - ) - ) - ), br() - ) - ), - hr(), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Size"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 12, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "scale_nodes", - h5(p("Scale by Duplicates"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ) - ) - ) - ) - ), - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - align = "left", - conditionalPanel( - "input.scale_nodes==true", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Range') - ) - ) - ), - conditionalPanel( - "input.scale_nodes==false", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Size') - ) - ) - ) - ), - column( - width = 9, - align = "center", - conditionalPanel( - "input.scale_nodes==true", - div( - class = "mst_scale_slider", - sliderInput( - "mst_node_scale", - label = "", - min = 1, - max = 80, - value = c(20, 40), - ticks = FALSE - ) - ) - ), - conditionalPanel( - "input.scale_nodes==false", - div( - class = "mst_scale_slider", - sliderInput( - inputId = "mst_node_size", - label = "", - min = 1, - max = 100, - value = 30, - ticks = FALSE - ) - ) - ) - ) - ), - br() - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Other Elements"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 12, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "mst_shadow", - h5(p("Show Shadow"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - fluidRow( - column( - width = 3, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Shape') - ) - ) - ), - column( - width = 9, - align = "center", - div( - class = "mst_shape_sel", - selectInput( - "mst_node_shape", - "", - choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), - `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), - selected = c("Dot" = "dot"), - width = "85%" - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 4, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - height = "500px", - h3(p("Edges"), style = "color:white; position:relative; right:-15px"), - hr(), - fluidRow( - column( - width = 6, - column( - width = 12, - align = "left", - h4(p("Label"), style = "color:white;") - ), - column( - width = 12, - align = "center", - div( - class = "label_sel", - selectInput( - "mst_edge_label", - label = "", - choices = c( - `Allelic Distance` = "weight", - Index = "index", - `Assembly ID` = "assembly_id", - `Assembly Name` = "assembly_name", - `Isolation Date` = "isolation_date", - Host = "host", - Country = "country", - City = "city" - ), - selected = c(`Allelic Distance` = "weight"), - width = "100%" - ) - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_edge_font_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_edgelabel_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - numericInput( - "mst_edge_font_size", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 18, - step = 1, - min = 8, - max = 30, - width = "80px" - ) - ) - ) - ), - br() - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - div( - class = "node_color", - colorPickr( - inputId = "mst_color_edge", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_edgecolor_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - sliderInput( - "mst_edge_opacity", - label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), - value = 0.7, - step = 0.1, - min = 0, - max = 1, - ticks = FALSE, - width = "150px" - ) - ) - ) - ) - ) - ) - ) - ) - ), - hr(style = "margin-top: 3px !important"), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Length multiplier"), style = "color:white; position: relative; right: -15px; margin-bottom: -5px") - ) - ), - column( - width = 12, - align = "left", - br(), - div( - class = "switch-mst-edges", - materialSwitch( - "mst_scale_edges", - h5(p("Scale Allelic Distance"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - fluidRow( - column( - width = 3, - align = "left", - conditionalPanel( - "input.mst_scale_edges==true", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Multiplier') - ) - ) - ), - conditionalPanel( - "input.mst_scale_edges==false", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Length') - ) - ) - ) - ), - column( - width = 9, - align = "center", - conditionalPanel( - "input.mst_scale_edges==true", - div( - class = "slider_edge", - sliderInput( - inputId = "mst_edge_length_scale", - label = NULL, - min = 1, - max = 40, - value = 15, - ticks = FALSE - ) - ) - ), - conditionalPanel( - "input.mst_scale_edges==false", - div( - class = "slider_edge", - sliderTextInput( - inputId = "mst_edge_length", - label = NULL, - choices = append(seq(0.1, 1, 0.1), 2:100), - selected = 35, - hide_min_max = FALSE - ) - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 6, - align = "left", - h4(p("Clustering"), style = "color:white; text-align: left; position: relative; right: -15px") - ), - column( - width = 2, - bslib::tooltip( - bsicons::bs_icon("info-circle", - title = "Cluster threshold according to species-specific\nComplex Type Distance (cgMLST.org)", - color = "white", height = "14px", width = "14px", - position = "relative", top = "9px", right = "28px"), - "Text shown in the tooltip.", - show = FALSE, - id = "mst_cluster_info" - ) - ) - ), - br(), - fluidRow( - column( - width = 9, - div( - class = "mst-cluster-switch", - materialSwitch( - "mst_show_clusters", - h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "mst_cluster_col_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - selectInput( - "mst_cluster_col_scale", - label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), - choices = c("Viridis", "Rainbow"), - width = "150px" - ) - ) - ) - ), - br(), - fluidRow( - column( - width = 4, - HTML( - paste( - tags$span(style='color: white; text-align: left; font-size: 14px; margin-left: 15px', 'Threshold') - ) - ) - ), - column( - width = 4, - uiOutput("mst_cluster") - ), - column( - width = 4, - actionButton( - "mst_cluster_reset", - label = "", - icon = icon("rotate") - ), - bsTooltip("mst_cluster_reset", - HTML("Reset to default Complex Type Distance"), - placement = "top", trigger = "hover") - ) - ) - ), - br(), - ) - ), br(), br(), br(), br(), br(), br() - ) - ) - ), - - ### Control Panels NJ ---- - - conditionalPanel( - "input.tree_algo=='Neighbour-Joining'", - fluidRow( - column( - width = 1, - radioGroupButtons( - inputId = "nj_controls", - label = "", - choices = c("Layout", "Label", "Elements", "Variables"), - direction = "vertical" - ) - ), - conditionalPanel( - "input.nj_controls=='Layout'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Theme"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - align = "center", - selectInput( - inputId = "nj_layout", - label = "", - choices = list( - Linear = list( - "Rectangular" = "rectangular", - "Roundrect" = "roundrect", - "Slanted" = "slanted", - "Ellipse" = "ellipse" - ), - Circular = list("Circular" = "circular", - "Inward" = "inward") - ), - selected = "rectangular", - width = "90%" - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "nj_rootedge_show", - h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_rootedge_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_rootedge_length"), - br(), - selectInput( - "nj_rootedge_line", - label = h5("Rootedge Line", style = "color:white"), - choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), - selected = c(Dotted = "solid"), - width = "100px" - ), - br(), - conditionalPanel( - "input.nj_layout=='circular'", - sliderInput( - "nj_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = -50, - max = 0, - value = -10, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_layout=='inward'", - sliderInput( - "nj_inward_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = 30, - max = 120, - value = 50, - ticks = FALSE, - width = "150px", - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-re", - materialSwitch( - "nj_ladder", - h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - colorPickr( - inputId = "nj_color", - width = "90%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - br(), - fluidRow( - column( - width = 5, - h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") - ), - column( - width = 7, - colorPickr( - inputId = "nj_bg", - width = "90%", - selected = "#ffffff", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - br() - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Title"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "nj_title", - label = "", - width = "100%", - placeholder = "Plot Title" - ), - textInput( - "nj_subtitle", - label = "", - width = "100%", - placeholder = "Plot Subtitle" - ), - br(), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "nj_title_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "nj_title_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "nj_title_size", - label = h5("Title Size", style = "color:white; margin-bottom: 0px"), - value = 30, - min = 15, - max = 40, - step = 1, - width = "80px" - ), - br(), - numericInput( - "nj_subtitle_size", - label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), - value = 20, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ), - br() - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - br(), - fluidRow( - column( - width = 3, - h5("Ratio", style = "color: white; font-size: 14px;") - ), - column( - width = 6, - align = "left", - div( - class = "ratio-sel", - selectInput( - "nj_ratio", - "", - choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "nj_size_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - sliderInput( - "nj_v", - label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "nj_h", - label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - sliderInput( - "nj_scale", - "", - min = 500, - max = 1200, - value = 800, - step = 5, - width = "95%", - ticks = FALSE - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - div( - class = "zoom-slider", - sliderInput( - "nj_zoom", - label = NULL, - min = 0.5, - max = 1.5, - step = 0.05, - value = 0.95, - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "nj_treescale_show", - h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - br() - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_treescale_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_treescale_width"), - br(), - uiOutput("nj_treescale_x"), - br(), - uiOutput("nj_treescale_y") - ) - ) - ) - ) - ) - ) - ), - column( - width = 12, - align = "left", - h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - align = "left", - prettyRadioButtons( - "nj_legend_orientation", - "", - choices = c(Horizontal = "horizontal", - Vertical = "vertical"), - selected = c(Vertical = "vertical"), - inline = FALSE - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "nj_legend_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "nj_legend_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - value = 10, - min = 5, - max = 25, - step = 1, - width = "80px" - ), - br(), - sliderInput( - "nj_legend_x", - label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), - value = 0.9, - min = -0.9, - max = 1.9, - step = 0.2, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "nj_legend_y", - label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), - value = 0.2, - min = -1.5, - max = 1.5, - step = 0.1, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_controls=='Label'", - column( - width = 4, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Tips"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 4, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "nj_tiplab_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "center", - uiOutput("nj_tiplab") - ), - column( - width = 3, - div( - class = "mat-switch-align", - materialSwitch( - "nj_align", - h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 1, - align = "right", - dropMenu( - actionBttn( - "nj_labeltext_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "nj_tiplab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - width = "150px", - ticks = FALSE - ), - br(), - conditionalPanel( - "!(input.nj_layout=='inward'|input.nj_layout=='circular')", - sliderInput( - inputId = "nj_tiplab_nudge_x", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 0, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_layout=='circular'", - sliderInput( - inputId = "nj_tiplab_position", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = -0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_layout=='inward'", - sliderInput( - inputId = "nj_tiplab_position_inw", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 1.1, - width = "150px", - ticks = FALSE - ) - ), - br(), - sliderInput( - inputId = "nj_tiplab_angle", - label = h5("Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - ticks = FALSE, - width = "150px", - ) - ), - column( - width = 6, - align = "center", - uiOutput("nj_tiplab_size"), - br(), - selectInput( - "nj_tiplab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") - ), - column( - width = 4, - align = "center", - colorPickr( - inputId = "nj_tiplab_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - br(), - div( - class = "mat-switch-geom", - materialSwitch( - "nj_geom", - h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - colorPickr( - inputId = "nj_tiplab_fill", - width = "100%", - selected = "#84D9A0", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 3, - align = "left", - dropMenu( - actionBttn( - "nj_labelformat_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_tiplab_padding"), - br(), - sliderInput( - inputId = "nj_tiplab_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.2, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Branches"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "nj_show_branch_label", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 5, - align = "center", - uiOutput("nj_branch_label") - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "nj_branch_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "nj_branchlab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 0.65, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "nj_branch_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "nj_branch_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ) - ), - column( - width = 6, - align = "center", - uiOutput("nj_branch_size"), - selectInput( - "nj_branchlab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ), - br(), - sliderInput( - "nj_branch_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.5, - width = "250px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") - ), - column( - width = 5, - colorPickr( - inputId = "nj_branch_label_color", - width = "100%", - selected = "#FFB7B7", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 6, - textInput( - "nj_new_label_name", - "", - placeholder = "New Label" - ) - ), - column( - width = 3, - actionButton( - "nj_add_new_label", - "", - icon = icon("plus") - ) - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "nj_custom_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_custom_labelsize"), - br(), - uiOutput("nj_sliderInput_y"), - br(), - uiOutput("nj_sliderInput_x") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 6, - uiOutput("nj_custom_label_select") - ), - column( - width = 4, - uiOutput("nj_del_label"), - ) - ), - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_cust_label_save") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_controls=='Elements'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "nj_tippoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_tippoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "nj_tippoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 0.5, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("nj_tippoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "nj_tippoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - conditionalPanel( - "input.nj_tipshape_mapping_show==false", - selectInput( - "nj_tippoint_shape", - "", - width = "100%", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ) - ), - conditionalPanel( - "input.nj_tipshape_mapping_show==true", - h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "nj_nodepoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_nodepoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "nj_nodepoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 1, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("nj_nodepoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "nj_nodepoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - selectInput( - "nj_nodepoint_shape", - "", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Tiles"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 5, - div( - class = "sel-tile-number", - selectInput( - "nj_tile_number", - "", - choices = 1:5, - width = "70px" - ) - ) - ), - column( - width = 7, - align = "right", - dropMenu( - actionBttn( - "nj_tile_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - conditionalPanel( - "input.nj_tile_num == 1", - sliderInput( - "nj_fruit_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - sliderInput( - "nj_fruit_alpha_2", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - sliderInput( - "nj_fruit_alpha_3", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - sliderInput( - "nj_fruit_alpha_4", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - sliderInput( - "nj_fruit_alpha_5", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 1", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width2"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_2"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width3"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_3"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width4"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_4"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width5"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_5"), - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 3, - h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") - ), - column( - width = 6, - align = "center", - textInput( - "nj_heatmap_title", - label = "", - value = "Heatmap", - placeholder = "Heatmap" - ) - ), - column( - width = 3, - align = "right", - dropMenu( - actionBttn( - "nj_heatmap_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_colnames_angle"), - br(), - uiOutput("nj_colnames_y") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") - ), - column( - width = 7, - uiOutput("nj_heatmap_width") - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") - ), - column( - width = 7, - uiOutput("nj_heatmap_offset") - ) - ), - br(), br() - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - div( - class = "mat-switch", - materialSwitch( - "nj_nodelabel_show", - h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") - ), - column( - width = 9, - uiOutput("nj_parentnode") - ) - ), - uiOutput("nj_clade_scale"), - fluidRow( - column( - width = 5, - h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - div( - class = "sel-clade", - selectInput( - "nj_clade_type", - "", - choices = c("Rect" = "rect", - "Round" = "roundrect"), - selected = c("Round" = "roundrect") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_controls=='Variables'", - column( - width = 7, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - align = "center", - h4(p("Element"), style = "color:white; margin-bottom: 20px") - ), - column( - width = 3, - align = "center", - h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") - ), - column( - width = 6, - align = "center", - h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") - ) - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_mapping_show", - h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_color_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("nj_tiplab_scale") - ), - uiOutput("nj_tiplab_mapping_info"), - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_tipcolor_mapping_show", - h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_tipcolor_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("nj_tippoint_scale") - ), - uiOutput("nj_tipcolor_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_tipshape_mapping_show", - h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_tipshape_mapping") - ), - column( - width = 3, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') - ) - ) - ), - uiOutput("nj_tipshape_mapping_info") - ), - fluidRow( - column( - width = 3, - fluidRow( - column( - width = 8, - conditionalPanel( - "input.nj_tile_num == 1", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_1", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_2", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_3", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_4", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_5", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - column( - width = 4, - align = "left", - div( - class = "tile-sel", - selectInput( - "nj_tile_num", - "", - choices = 1:5, - width = "50px" - ) - ) - ) - ) - ), - column( - width = 3, - align = "center", - conditionalPanel( - "input.nj_tile_num == 1", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable") - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable2") - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable3") - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable4") - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable5") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 1", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_1") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_2") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_3") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_4") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_5") - ) - ) - ), - uiOutput("nj_fruit_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_heatmap_show", - h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_heatmap_sel") - ), - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_heatmap_scale") - ) - ), - uiOutput("nj_heatmap_mapping_info") - ) - ) - ) - ) - ) - ), - br(), br(), br(), br(), br(), br() - ), - - ### Control Panels UPGMA ---- - - conditionalPanel( - "input.tree_algo=='UPGMA'", - fluidRow( - column( - width = 1, - radioGroupButtons( - inputId = "upgma_controls", - label = "", - choices = c("Layout", "Label", "Elements", "Variables"), - direction = "vertical" - ) - ), - conditionalPanel( - "input.upgma_controls=='Layout'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Theme"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - align = "center", - selectInput( - inputId = "upgma_layout", - label = "", - choices = list( - Linear = list( - "Rectangular" = "rectangular", - "Roundrect" = "roundrect", - "Slanted" = "slanted", - "Ellipse" = "ellipse" - ), - Circular = list("Circular" = "circular", - "Inward" = "inward") - ), - selected = "rectangular", - width = "90%" - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "upgma_rootedge_show", - h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_rootedge_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_rootedge_length"), - br(), - selectInput( - "upgma_rootedge_line", - label = h5("Rootedge Line", style = "color:white"), - choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), - selected = c(Dotted = "solid"), - width = "100px" - ), - br(), - conditionalPanel( - "input.upgma_layout=='circular'", - sliderInput( - "upgma_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = -50, - max = 0, - value = -10, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_layout=='inward'", - sliderInput( - "upgma_inward_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = 30, - max = 120, - value = 50, - ticks = FALSE, - width = "150px", - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-re", - materialSwitch( - "upgma_ladder", - h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - colorPickr( - inputId = "upgma_color", - width = "90%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - br(), - fluidRow( - column( - width = 5, - h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") - ), - column( - width = 7, - colorPickr( - inputId = "upgma_bg", - width = "90%", - selected = "#ffffff", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Title"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "upgma_title", - label = "", - width = "100%", - placeholder = "Plot Title" - ), - textInput( - "upgma_subtitle", - label = "", - width = "100%", - placeholder = "Plot Subtitle" - ), - br(), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "upgma_title_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "upgma_title_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "upgma_title_size", - label = h5("Title Size", style = "color:white; margin-bottom: 0px"), - value = 30, - min = 15, - max = 40, - step = 1, - width = "80px" - ), - br(), - numericInput( - "upgma_subtitle_size", - label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), - value = 20, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - br(), - fluidRow( - column( - width = 3, - h5("Ratio", style = "color: white; font-size: 14px;") - ), - column( - width = 6, - align = "left", - div( - class = "ratio-sel", - selectInput( - "upgma_ratio", - "", - choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "upgma_size_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - sliderInput( - "upgma_v", - label = "Vertical Position", - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "upgma_h", - label = "Horizontal Position", - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - sliderInput( - "upgma_scale", - "", - min = 500, - max = 1200, - value = 800, - step = 5, - width = "95%", - ticks = FALSE - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - div( - class = "zoom-slider", - sliderInput( - "upgma_zoom", - label = NULL, - min = 0.5, - max = 1.5, - step = 0.05, - value = 0.95, - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "upgma_treescale_show", - h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - br() - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_treescale_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_treescale_width"), - br(), - uiOutput("upgma_treescale_x"), - br(), - uiOutput("upgma_treescale_y") - ) - ) - ) - ) - ) - ) - ), - column( - width = 12, - align = "left", - h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - align = "left", - prettyRadioButtons( - "upgma_legend_orientation", - "", - choices = c(Horizontal = "horizontal", - Vertical = "vertical"), - selected = c(Vertical = "vertical"), - inline = FALSE - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "upgma_legend_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "upgma_legend_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - value = 10, - min = 5, - max = 25, - step = 1, - width = "80px" - ), - br(), - sliderInput( - "upgma_legend_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - value = 0.9, - min = -0.9, - max = 1.9, - step = 0.2, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "upgma_legend_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - value = 0.2, - min = -1.5, - max = 1.5, - step = 0.1, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_controls=='Label'", - column( - width = 4, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Tips"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 4, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "upgma_tiplab_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "center", - uiOutput("upgma_tiplab") - ), - column( - width = 3, - div( - class = "mat-switch-align", - materialSwitch( - "upgma_align", - h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 1, - align = "right", - dropMenu( - actionBttn( - "upgma_labeltext_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "upgma_tiplab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - width = "150px", - ticks = FALSE - ), - br(), - conditionalPanel( - "!(input.upgma_layout=='inward'|input.upgma_layout=='circular')", - sliderInput( - inputId = "upgma_tiplab_nudge_x", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 0, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_layout=='circular'", - sliderInput( - inputId = "upgma_tiplab_position", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = -0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_layout=='inward'", - sliderInput( - inputId = "upgma_tiplab_position_inw", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 1.1, - width = "150px", - ticks = FALSE - ) - ), - br(), - sliderInput( - inputId = "upgma_tiplab_angle", - label = h5("Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - ticks = FALSE, - width = "150px", - ) - ), - column( - width = 6, - align = "center", - uiOutput("upgma_tiplab_size"), - br(), - selectInput( - "upgma_tiplab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") - ), - column( - width = 4, - align = "center", - colorPickr( - inputId = "upgma_tiplab_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - br(), - div( - class = "mat-switch-geom", - materialSwitch( - "upgma_geom", - h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - colorPickr( - inputId = "upgma_tiplab_fill", - width = "100%", - selected = "#84D9A0", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 3, - align = "left", - dropMenu( - actionBttn( - "upgma_labelformat_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_tiplab_padding"), - br(), - sliderInput( - inputId = "upgma_tiplab_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.2, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Branches"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "upgma_show_branch_label", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 5, - align = "center", - uiOutput("upgma_branch_label") - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "upgma_branch_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "upgma_branchlab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 0.65, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "upgma_branch_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "upgma_branch_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ) - ), - column( - width = 6, - align = "center", - uiOutput("upgma_branch_size"), - selectInput( - "upgma_branchlab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ), - br(), - sliderInput( - "upgma_branch_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.5, - width = "250px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") - ), - column( - width = 5, - colorPickr( - inputId = "upgma_branch_label_color", - width = "100%", - selected = "#FFB7B7", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ), - br(), br() - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 6, - textInput( - "upgma_new_label_name", - "", - placeholder = "New Label" - ) - ), - column( - width = 3, - actionButton( - "upgma_add_new_label", - "", - icon = icon("plus") - ) - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "upgma_custom_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_custom_labelsize"), - br(), - uiOutput("upgma_sliderInput_y"), - br(), - uiOutput("upgma_sliderInput_x") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 6, - uiOutput("upgma_custom_label_select") - ), - column( - width = 4, - uiOutput("upgma_del_label"), - ) - ), - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_cust_label_save") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_controls=='Elements'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "upgma_tippoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_tippoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "upgma_tippoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 0.5, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("upgma_tippoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "upgma_tippoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - conditionalPanel( - "input.upgma_tipshape_mapping_show==false", - selectInput( - "upgma_tippoint_shape", - "", - width = "100%", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ) - ), - conditionalPanel( - "input.upgma_tipshape_mapping_show==true", - h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") - ), - br() - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "upgma_nodepoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_nodepoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "upgma_nodepoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 1, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("upgma_nodepoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "upgma_nodepoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - selectInput( - "upgma_nodepoint_shape", - "", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ), - br() - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Tiles"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 5, - div( - class = "sel-tile-number", - selectInput( - "upgma_tile_number", - "", - choices = 1:5, - width = "70px" - ) - ) - ), - column( - width = 7, - align = "right", - dropMenu( - actionBttn( - "upgma_tile_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - conditionalPanel( - "input.upgma_tile_num == 1", - sliderInput( - "upgma_fruit_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - sliderInput( - "upgma_fruit_alpha_2", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - sliderInput( - "upgma_fruit_alpha_3", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - sliderInput( - "upgma_fruit_alpha_4", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - sliderInput( - "upgma_fruit_alpha_5", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 1", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width2"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_2"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width3"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_3"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width4"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_4"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width5"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_5"), - br() - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 3, - h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") - ), - column( - width = 6, - align = "center", - textInput( - "upgma_heatmap_title", - label = "", - value = "Heatmap", - placeholder = "Heatmap" - ) - ), - column( - width = 3, - align = "right", - dropMenu( - actionBttn( - "upgma_heatmap_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_colnames_angle"), - br(), - uiOutput("upgma_colnames_y") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") - ), - column( - width = 7, - uiOutput("upgma_heatmap_width") - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") - ), - column( - width = 7, - uiOutput("upgma_heatmap_offset") - ) - ), - br(), br() - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - div( - class = "mat-switch", - materialSwitch( - "upgma_nodelabel_show", - h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") - ), - column( - width = 9, - uiOutput("upgma_parentnode") - ) - ), - uiOutput("upgma_clade_scale"), - fluidRow( - column( - width = 5, - h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - div( - class = "sel-clade", - selectInput( - "upgma_clade_type", - "", - choices = c("Rect" = "rect", - "Round" = "roundrect"), - selected = c("Round" = "roundrect") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_controls=='Variables'", - column( - width = 7, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - align = "center", - h4(p("Element"), style = "color:white; margin-bottom: 20px") - ), - column( - width = 3, - align = "center", - h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") - ), - column( - width = 6, - align = "center", - h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") - ) - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_mapping_show", - h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_color_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tiplab_scale") - ), - uiOutput("upgma_tiplab_mapping_info"), - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tipcolor_mapping_show", - h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tipcolor_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tippoint_scale") - ), - uiOutput("upgma_tipcolor_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tipshape_mapping_show", - h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tipshape_mapping") - ), - column( - width = 3, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') - ) - ) - ), - uiOutput("upgma_tipshape_mapping_info") - ), - fluidRow( - column( - width = 3, - fluidRow( - column( - width = 8, - conditionalPanel( - "input.upgma_tile_num == 1", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_1", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_2", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_3", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_4", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_5", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - column( - width = 4, - align = "left", - div( - class = "tile-sel", - selectInput( - "upgma_tile_num", - "", - choices = 1:5, - width = "50px" - ) - ) - ) - ) - ), - column( - width = 3, - align = "center", - conditionalPanel( - "input.upgma_tile_num == 1", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable2") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable3") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable4") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable5") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 1", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_1") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_2") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_3") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_4") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_5") - ) - ) - ), - uiOutput("upgma_fruit_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_heatmap_show", - h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_heatmap_sel") - ), - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_heatmap_scale") - ) - ), - uiOutput("upgma_heatmap_mapping_info") - ) - ) - ) - ) - ) - ), - br(), br(), br(), br(), br(), br() - ) - ), - - ## Tab Utilities ------------------------------------------------------- - - tabItem( - tabName = "utilities", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Utilities"), style = "color:white") - ) - ), - br(), - hr(), - column( - width = 5, - align = "left", - shinyDirButton( - "hash_dir", - "Choose folder with .fasta files", - title = "Locate folder with loci", - buttonType = "default", - style = "border-color: white; margin: 10px; min-width: 200px; text-align: center" - ), - actionButton("hash_start", "Start Hashing", icon = icon("circle-play")), - shinyjs::hidden( - div(id = "hash_loading", - HTML('')) - ) - ) - # br(), - # actionButton( - # "backup_database", - # "Create backup", - # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - # ), - # br(), - # actionButton( - # "import_db_backup", - # "Restore backup", - # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - # ) - ), - - - ## Tab Screening ------------------------------------------------------- - - tabItem( - tabName = "gs_screening", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Screening"), style = "color:white; margin-bottom: -20px;") - ), - column( - width = 7, - align = "left", - uiOutput("gene_screening_info") - ) - ), - br(), - hr(), - fluidRow( - uiOutput("screening_interface") - ) - ), - - ## Tab Resistance Profile ------------------------------------------------------- - - tabItem( - tabName = "gs_profile", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Browse Entries"), style = "color:white; margin-bottom: -20px") - ), - column( - width = 7, - align = "left", - uiOutput("gene_resistance_info") - ) - ), - br(), - hr(), - br(), br(), - uiOutput("gs_table_selection"), - fluidRow( - column(1), - uiOutput("gs_profile_display") - ) - ) - ) # End tabItems - ) # End dashboardPage -) # end UI - -# _______________________ #### - -# Server ---- - -server <- function(input, output, session) { - - phylotraceVersion <- paste("1.5.0") - - #TODO Enable this, or leave disabled - # Kill server on session end - session$onSessionEnded( function() { - stopApp() - }) - - # Disable various user inputs (visualization control) - shinyjs::disable('mst_edge_label') - - ## Functions ---- - - # Function to read and format FASTA sequences - format_fasta <- function(filepath) { - fasta <- readLines(filepath) - formatted_fasta <- list() - current_sequence <- "" - - for (line in fasta) { - if (startsWith(line, ">")) { - if (current_sequence != "") { - formatted_fasta <- append(formatted_fasta, list(current_sequence)) - current_sequence <- "" - } - formatted_fasta <- append(formatted_fasta, list(line)) - } else { - current_sequence <- paste0(current_sequence, line) - } - } - if (current_sequence != "") { - formatted_fasta <- append(formatted_fasta, list(current_sequence)) - } - - formatted_fasta - } - - # Function to color-code the bases in a sequence - color_sequence <- function(sequence) { - sequence <- gsub("A", "A", sequence) - sequence <- gsub("T", "T", sequence) - sequence <- gsub("G", "G", sequence) - sequence <- gsub("C", "C", sequence) - sequence - } - - # Function to log messages to logfile - log_message <- function(log_file, message, append = TRUE) { - cat(format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "-", message, "\n", file = log_file, append = append) - } - - # Modified gheatmap function - gheatmap.mod <- function(p, data, offset=0, width=1, low="green", high="red", color="white", - colnames=TRUE, colnames_position="bottom", colnames_angle=0, colnames_level=NULL, - colnames_offset_x = 0, colnames_offset_y = 0, font.size=4, family="", hjust=0.5, legend_title = "value", - colnames_color = "black") { - - colnames_position %<>% match.arg(c("bottom", "top")) - variable <- value <- lab <- y <- NULL - - ## if (is.null(width)) { - ## width <- (p$data$x %>% range %>% diff)/30 - ## } - - ## convert width to width of each cell - width <- width * (p$data$x %>% range(na.rm=TRUE) %>% diff) / ncol(data) - - isTip <- x <- y <- variable <- value <- from <- to <- NULL - - ## handle the display of heatmap on collapsed nodes - ## https://github.com/GuangchuangYu/ggtree/issues/242 - ## extract data on leaves (& on collapsed internal nodes) - ## (the latter is extracted only when the input data has data on collapsed - ## internal nodes) - df <- p$data - nodeCo <- intersect(df %>% filter(is.na(x)) %>% - select(.data$parent, .data$node) %>% unlist(), - df %>% filter(!is.na(x)) %>% - select(.data$parent, .data$node) %>% unlist()) - labCo <- df %>% filter(.data$node %in% nodeCo) %>% - select(.data$label) %>% unlist() - selCo <- intersect(labCo, rownames(data)) - isSel <- df$label %in% selCo - - df <- df[df$isTip | isSel, ] - start <- max(df$x, na.rm=TRUE) + offset - - dd <- as.data.frame(data) - ## dd$lab <- rownames(dd) - i <- order(df$y) - - ## handle collapsed tree - ## https://github.com/GuangchuangYu/ggtree/issues/137 - i <- i[!is.na(df$y[i])] - - lab <- df$label[i] - ## dd <- dd[lab, , drop=FALSE] - ## https://github.com/GuangchuangYu/ggtree/issues/182 - dd <- dd[match(lab, rownames(dd)), , drop = FALSE] - - - dd$y <- sort(df$y) - dd$lab <- lab - ## dd <- melt(dd, id=c("lab", "y")) - dd <- gather(dd, variable, value, -c(lab, y)) - - i <- which(dd$value == "") - if (length(i) > 0) { - dd$value[i] <- NA - } - if (is.null(colnames_level)) { - dd$variable <- factor(dd$variable, levels=colnames(data)) - } else { - dd$variable <- factor(dd$variable, levels=colnames_level) - } - V2 <- start + as.numeric(dd$variable) * width - mapping <- data.frame(from=dd$variable, to=V2) - mapping <- unique(mapping) - - dd$x <- V2 - dd$width <- width - dd[[".panel"]] <- factor("Tree") - if (is.null(color)) { - p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, inherit.aes=FALSE) - } else { - p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, color=color, inherit.aes=FALSE) - } - if (is(dd$value,"numeric")) { - p2 <- p2 + scale_fill_gradient(low=low, high=high, na.value=NA, name = legend_title) # "white") - } else { - p2 <- p2 + scale_fill_discrete(na.value=NA, name = legend_title) #"white") - } - - if (colnames) { - if (colnames_position == "bottom") { - y <- 0 - } else { - y <- max(p$data$y) + 1 - } - mapping$y <- y - mapping[[".panel"]] <- factor("Tree") - p2 <- p2 + geom_text(data=mapping, aes(x=to, y = y, label=from), color = colnames_color, size=font.size, family=family, inherit.aes = FALSE, - angle=colnames_angle, nudge_x=colnames_offset_x, nudge_y = colnames_offset_y, hjust=hjust) - } - - p2 <- p2 + theme(legend.position="right") - ## p2 <- p2 + guides(fill = guide_legend(override.aes = list(colour = NULL))) - - if (!colnames) { - ## https://github.com/GuangchuangYu/ggtree/issues/204 - p2 <- p2 + scale_y_continuous(expand = c(0,0)) - } - - attr(p2, "mapping") <- mapping - return(p2) - } - - # Get rhandsontable - get.entry.table.meta <- reactive({ - if(!is.null(hot_to_r(input$db_entries))){ - table <- hot_to_r(input$db_entries) - select(select(table, -13), 1:(12 + nrow(DB$cust_var))) - } - }) - - # Function to find columns with varying values - var_alleles <- function(dataframe) { - - varying_columns <- c() - - for (col in 1:ncol(dataframe)) { - unique_values <- unique(dataframe[, col]) - - if (length(unique_values) > 1) { - varying_columns <- c(varying_columns, col) - } - } - - return(varying_columns) - } - - # Functions to compute hamming distances dependent on missing value handling - hamming.dist <- function(x, y) { - sum(x != y) - } - - hamming.distIgnore <- function(x, y) { - sum( (x != y) & !is.na(x) & !is.na(y) ) - } - - hamming.distCategory <- function(x, y) { - sum((x != y | xor(is.na(x), is.na(y))) & !(is.na(x) & is.na(y))) - } - - compute.distMatrix <- function(profile, hamming.method) { - mat <- as.matrix(profile) - n <- nrow(mat) - dist_mat <- matrix(0, n, n) - for (i in 1:(n-1)) { - for (j in (i+1):n) { - dist_mat[i, j] <- hamming.method(x = mat[i, ], y = mat[j, ]) - dist_mat[j, i] <- dist_mat[i, j] - } - } - return(dist_mat) - } - - # Function to determine entry table height - table_height <- reactive({ - if (input$table_height == TRUE) { - NULL - } else {900} - }) - - # Function to determine distance matrix height - distancematrix_height <- reactive({ - if(DB$distancematrix_nrow > 33) { - 800 - } else {NULL} - }) - - # Function to missing value table height - miss.val.height <- reactive({ - if(input$miss_val_height == TRUE) { - NULL - } else {800} - }) - - #Function to check custom variable classes - column_classes <- function(df) { - sapply(df, function(x) { - if (class(x) == "numeric") { - return("cont") - } else if (class(x) == "character") { - return("categ") - } else { - return(class(x)) - } - }) - } - - # Function to hash database - hash_database <- function(folder) { - loci_files <- list.files(folder) - loci_names <- sapply(strsplit(loci_files, "[.]"), function(x) x[1]) - loci_paths <- file.path(folder, loci_files) - - hashes <- sapply(loci_paths, hash_locus) - names(hashes) <- loci_names - hashes - } - - # Function to hash a locus - hash_locus <- function(locus_path) { - locus_file <- readLines(locus_path) - seq_list <- locus_file[seq(2, length(locus_file), 3)] - seq_hash <- sha256(seq_list) - seq_idx <- paste0(">", seq_hash) - - locus_file[seq(1, length(locus_file), 3)] <- seq_idx - writeLines(locus_file, locus_path) - - seq_hash - } - - # Get locus hashes - get_locus_hashes <- function(locus_path) { - locus_file <- readLines(locus_path) - hash_list <- locus_file[seq(1, length(locus_file), 3)] - hash_list <- sapply(strsplit(hash_list, "[>]"), function(x) x[2]) - } - - extract_seq <- function(locus_path, hashes) { - locus_file <- readLines(locus_path) - hash_list <- sapply(strsplit(locus_file[seq(1, length(locus_file), 3)], "[>]"), function(x) x[2]) - seq_list <- locus_file[seq(2, length(locus_file), 3)] - seq_idx <- hash_list %in% hashes - - list( - idx = hash_list[seq_idx], - seq = seq_list[seq_idx] - ) - } - - add_new_sequences <- function(locus_path, sequences) { - locus_file <- file(locus_path, open = "a+") - for (i in seq_along(sequences$idx)) { - writeLines(c("", paste0(">", sequences$idx[i]), sequences$seq[i]), locus_file) - } - close(locus_file) - } - - # Compute clusters to use in visNetwork - compute_clusters <- function(nodes, edges, threshold) { - groups <- rep(0, length(nodes$id)) - - edges_table <- data.frame( - from = edges$from, - to = edges$to, - weight = edges$weight - ) - - count <- 0 - while (any(groups == 0)) { - group_na <- groups == 0 - labels <- nodes$id[group_na] - - cluster <- nodes$id[group_na][1] # Initialize with 1 label - while (!is_empty(labels)) { - sub_tb <- edges_table[(edges_table$from %in% cluster | edges_table$to %in% cluster) & edges_table$weight <= threshold,] - - if (nrow(sub_tb) == 0 | length(unique(c(sub_tb$from, sub_tb$to))) == length(cluster)) { - count <- count + 1 - groups[nodes$id %in% cluster] <- paste("Group", count) - break - } else { - cluster <- unique(c(sub_tb$from, sub_tb$to)) - } - } - } - groups - } - - # Check gene screening status - check_status <- function(isolate) { - iso_name <- gsub(".zip", "", basename(isolate)) - if(file.exists(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", iso_name, "status.txt"))) { - if(str_detect(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", iso_name, "status.txt"))[1], - "successfully")) { - return("success") - } else { - return("fail") - } - } else {return("unfinished")} - } - - # Reset gene screening status - remove.screening.status <- function(isolate) { - if(file.exists(file.path(DB$database, - gsub(" ", "_", DB$scheme), - "Isolates", - isolate, - "status.txt"))) { - file.remove( - file.path(DB$database, - gsub(" ", "_", DB$scheme), - "Isolates", - isolate, - "status.txt") - ) - } - } - - # Truncate hashes - truncHash <- function(hash) { - if(!is.na(hash)) { - paste0(str_sub(hash, 1, 4), "...", str_sub(hash, nchar(hash) - 3, nchar(hash))) - } else {NA} - } - - # Function to check for duplicate isolate IDs for multi typing start - dupl_mult_id <- reactive({ - req(Typing$multi_sel_table) - if(!is.null(DB$data)) { - selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] - selection$Files - } else {""} - }) - - # Function to check single typing log file - check_new_entry <- reactive({ - - invalidateLater(5000, session) - - if(!is.null(DB$database)) { - if(file_exists(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds"))) { - - Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) - - if(is.null(DB$data)) { - if(nrow(Database[["Typing"]]) >= 1) { - TRUE - } else {FALSE} - } else { - if(nrow(DB$data) < nrow(Database[["Typing"]])) { - TRUE - } else { - FALSE - } - } - } else {FALSE} - } - }) - - # Render Entry Table Highlights - - diff_allele <- reactive({ - if (!is.null(DB$data) & !is.null(input$compare_select) & !is.null(DB$cust_var)) { - var_alleles(select(DB$data, input$compare_select)) + (13 + nrow(DB$cust_var)) - } - }) - - err_thresh <- reactive({ - if (!is.null(DB$data) & !is.null(DB$number_loci)) { - which(as.numeric(DB$data[["Errors"]]) >= (DB$number_loci * 0.05)) - } - }) - - err_thresh_na <- reactive({ - if (!is.null(DB$na_table) & !is.null(DB$number_loci)) { - which(as.numeric(DB$na_table[["Errors"]]) >= (DB$number_loci * 0.05)) - } - }) - - true_rows <- reactive({ - if (!is.null(DB$data)) { - which(DB$data$Include == TRUE) - } - }) - - duplicated_names <- reactive({ - if (!is.null(DB$meta)) { - which(duplicated(DB$meta$`Assembly Name`) | duplicated(DB$meta$`Assembly Name`, fromLast = TRUE)) - } - }) - - duplicated_ids <- reactive({ - if (!is.null(DB$meta)) { - which(duplicated(DB$meta$`Assembly ID`) | duplicated(DB$meta$`Assembly ID`, fromLast = TRUE)) - } - }) - - # _______________________ #### - - ## Startup ---- - shinyjs::addClass(selector = "body", class = "sidebar-collapse") - shinyjs::removeClass(selector = "body", class = "sidebar-toggle") - - output$messageMenu <- renderText({ - HTML(format(Sys.time(), "%Y-%m-%d %H:%M:%S %Z")) - }) - - # Initiate logging - if(!dir_exists(paste0(getwd(), "/logs"))) { - dir_create(paste0(getwd(), "/logs")) - } - - logfile <- file.path(paste0(getwd(), "/logs/phylotrace.log")) - - log <- log_open(logfile, logdir = FALSE) - - log_print("Session started") - - # Clear screening file - if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { - file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) - } - - if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { - file.remove(paste0(getwd(), "/execute/screening/error.txt")) - } - - # Declare reactive variables - Startup <- reactiveValues(sidebar = TRUE, - header = TRUE) # reactive variables related to startup process - - DB <- reactiveValues(data = NULL, - block_db = FALSE, - load_selected = TRUE, - no_na_switch = FALSE, - first_look = FALSE) # reactive variables related to local database - - Typing <- reactiveValues(table = data.frame(), - single_path = data.frame(), - progress = 0, - progress_format_start = 0, - progress_format_end = 0, - result_list = NULL, - status = "") # reactive variables related to typing process - - Screening <- reactiveValues(status = "idle", - picker_status = TRUE, - first_result = NULL) # reactive variables related to gene screening - - Vis <- reactiveValues(cluster = NULL, - metadata = list(), - custom_label_nj = data.frame(), - nj_label_pos_y = list(), - nj_label_pos_x = list(), - nj_label_size = list(), - custom_label_upgma = data.frame(), - upgma_label_pos_y = list(), - upgma_label_pos_x = list(), - upgma_label_size = list()) # reactive variables related to visualization - - Report <- reactiveValues() # reactive variables related to report functions - - Scheme <- reactiveValues() # reactive variables related to scheme functions - - # Load last used database if possible - if(paste0(getwd(), "/execute/last_db.rds") %in% dir_ls(paste0(getwd(), "/execute"))) { - DB$last_db <- TRUE - } - - # Locate local Database - observe({ - shinyDirChoose(input, - "db_location", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session) - - if(!is.null(DB$select_new)) { - if(DB$select_new == FALSE) { - if(DB$block_db == FALSE) { - DB$database <- as.character( - parseDirPath( - roots = c(Home = path_home(), Root = "/"), - input$db_location - ) - ) - - DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present - - DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available - } - - } else if (DB$select_new == TRUE) { - DB$database <- paste0(DB$new_database, "/Database") - - } - } else { - if(!is.null(DB$last_db) & file.exists(paste0(getwd(), "/execute/last_db.rds"))) { - - DB$database <- readRDS(paste0(getwd(), "/execute/last_db.rds")) - - if(dir_exists(DB$database)) { - DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present - - DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available - } - } - } - }) - - ### Set up typing environment ---- - - # Null typing progress trackers - writeLines("0", paste0(getwd(), "/logs/script_log.txt")) - writeLines("0\n", paste0(getwd(), "/logs/progress.txt")) - - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - } - - # Reset typing feedback values - Typing$pending <- FALSE - Typing$multi_started <- FALSE - Typing$multi_help <- FALSE - saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) - Typing$last_success <- "0" # Null last multi typing success name - Typing$last_failure <- "0" # Null last multi typing failure name - - ### Landing page UI ---- - observe({ - if (Startup$sidebar == FALSE) { - shinyjs::removeClass(selector = "body", class = "sidebar-collapse") - shinyjs::addClass(selector = "body", class = "sidebar-toggle") - } - }) - - output$start_message <- renderUI({ - column( - width = 12, - align = "center", - br(), br(), br(), br(), br(), br(), - div( - class = "image", - imageOutput("imageOutput") - ), - br(), br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 16px;', 'Proceed by loading a compatible local database or create a new one.') - ) - ) - ), - br(), - fluidRow( - column( - width = 6, - align = "right", - shinyDirButton( - "db_location", - "Browse", - icon = icon("folder-open"), - title = "Locate the database folder", - buttonType = "default", - root = path_home() - ) - ), - column( - width = 6, - align = "left", - shinyDirButton( - "create_new_db", - "Create New", - icon = icon("plus"), - title = "Choose location for new PhyloTrace database", - buttonType = "default", - root = path_home() - ) - ) - ), - br(), br(), - fluidRow( - column( - width = 12, - align = "center", - uiOutput("load_db"), - br(), br(), br(), br(), br(), br(), br() - ) - ) - ) - }) - - # User selection new db or load db - observeEvent(input$create_new_db, { - log_print("Input create_new_db") - DB$select_new <- TRUE - }) - - observeEvent(input$db_location, { - log_print("Input db_location") - DB$select_new <- FALSE - }) - - # Load db & scheme selection UI - output$load_db <- renderUI({ - if(!is.null(DB$select_new)) { - if(length(DB$new_database) > 0 & DB$select_new) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px;', - HTML( - paste( - 'New database will be created in', - DB$new_database - ) - ) - ) - ), - br(), - actionButton( - "load", - "Create", - class = "load-start" - ) - ) - } else if(length(DB$available) > 0 & !(DB$select_new)) { - if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Selected:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), - p( - HTML( - paste( - tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', - 'Warning: Folder contains invalid elements.') - ) - ) - ), - br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } else { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Selected:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } - } - } else if((!is.null(DB$last_db)) & (!is.null(DB$available))) { - if (DB$last_db == TRUE & (length(DB$available) > 0)) { - if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Last used:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), - p( - HTML( - paste( - tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', - 'Warning: Folder contains invalid elements.') - ) - ) - ), - br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } else { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Last used:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } - } else if (DB$last_db == TRUE & (length(DB$available) == 0)) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Last used:', DB$database) - ) - ) - ), - br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } - } - }) - - output$imageOutput <- renderImage({ - # Path to your PNG image with a transparent background - image_path <- paste0(getwd(), "/www/PhyloTrace.png") - - # Use HTML to display the image with the tag - list(src = image_path, - height = 180) - }, deleteFile = FALSE) - - ### Load app event ---- - - observeEvent(input$load, { - - # Reset reactive screening variables - output$screening_start <- NULL - output$screening_result_sel <- NULL - output$screening_result <- NULL - output$screening_fail <- NULL - Screening$status_df <- NULL - Screening$choices <- NULL - Screening$picker_status <- TRUE - Screening$status <- "idle" - Screening$first_result <- NULL - if(!is.null(input$screening_select)) { - if(!is.null(DB$data)) { - updatePickerInput(session, "screening_select", selected = character(0)) - } - } - - log_print("Input load") - - # set typing start control variable - Typing$reload <- TRUE - - # reset typing status on start( - if(Typing$status == "Finalized") {Typing$status <- "Inactive"} - if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} - - #### Render status bar ---- - observe({ - req(DB$scheme) - - if(is.null(input$scheme_position)) { - output$loaded_scheme <- renderUI({ - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Selected scheme:   ", - DB$scheme, - "")), - style = "color:white;") - ) - ) - }) - } - - if(!is.null(input$scheme_position)) { - output$loaded_scheme <- renderUI({ - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Selected scheme:   ", - DB$scheme, - "")), - style = "color:white;"), - div( - class = "reload-bttn", - style = paste0("margin-left:", 30 + input$scheme_position, "px; position: relative; top: -24px;"), - actionButton( - "reload_db", - label = "", - icon = icon("rotate") - ) - ) - ) - ) - }) - } - }) - - observe({ - if(!is.null(DB$database)){ - if(nchar(DB$database) > 60) { - database <- paste0(substring(DB$database, first = 1, last = 60), "...") - } else { - database <- DB$database - } - output$databasetext <- renderUI({ - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Database:   ", - database, - "")), - style = "color:white;") - ), - if(nchar(database) > 60) {bsTooltip("databasetext", - HTML(DB$database), - placement = "bottom", - trigger = "hover")} - ) - }) - } - }) - - observe({ - if(!is.null(DB$database)) { - if(Typing$status == "Finalized"){ - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    typing finalized")), - style = "color:white;") - ) - ) - ) - } else if(Typing$status == "Attaching"){ - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    evaluating typing results")), - style = "color:white;") - ) - ) - ) - } else if(Typing$status == "Processing") { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    pending typing")), - style = "color:white;") - ) - ) - ) - } else if(Screening$status == "started") { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    pending gene screening")), - style = "color:white;") - ) - ) - ) - } else if(Screening$status == "finished") { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    gene screening finalized")), - style = "color:white;") - ) - ) - ) - } else { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    ready")), - style = "color:white;") - ) - ) - ) - } - } - }) - - # Null single typing status - if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - Typing$progress <- 0 - - Typing$progress_format <- 900000 - - output$single_typing_progress <- NULL - - output$typing_fin <- NULL - - output$single_typing_results <- NULL - - output$typing_formatting <- NULL - - Typing$single_path <- data.frame() - - # reset results file - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - # Resetting single typing progress logfile bar - con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") - - cat("0\n", file = con) - - close(con) - } - } - - shinyjs::runjs( - 'if(document.querySelector("#loaded_scheme > div > li > span") !== null) { - // Select the span element - let spanElement = document.querySelector("#loaded_scheme > div > li > span"); - - // Get the bounding rectangle of the span element - let rect = spanElement.getBoundingClientRect(); - - // Extract the width - let width = rect.width; - - Shiny.setInputValue("scheme_position", width); - }' - ) - - # Load app elements based on database availability and missing value presence - if(!is.null(DB$select_new)) { - if(DB$select_new & (paste0(DB$new_database, "/Database") %in% dir_ls(DB$new_database))) { - - log_print("Directory already contains a database") - - show_toast( - title = "Directory already contains a database", - type = "error", - position = "bottom-end", - timer = 6000 - ) - DB$load_selected <- FALSE - - } else if(DB$select_new | (DB$select_new == FALSE & is.null(input$scheme_db))) { - - log_print(paste0("New database created in ", DB$new_database)) - - DB$check_new_entries <- TRUE - DB$data <- NULL - DB$meta_gs <- NULL - DB$meta <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_trunc <- NULL - DB$allelic_profile_true <- NULL - - # null Distance matrix, entry table and plots - output$db_distancematrix <- NULL - output$db_entries_table <- NULL - output$tree_mst <- NULL - output$tree_nj <- NULL - output$tree_upgma <- NULL - - # null report values - Report$report_list_mst <- list() - Report$report_list_nj <- list() - Report$report_list_upgma <- list() - - # null plots - Vis$nj <- NULL - Vis$upgma <- NULL - Vis$ggraph_1 <- NULL - - removeModal() - - #### Render Menu Items ---- - - Startup$sidebar <- FALSE - Startup$header <- FALSE - - output$menu_sep2 <- renderUI(hr()) - - # Hide start message - output$start_message <- NULL - - DB$load_selected <- FALSE - - # Declare database path - DB$database <- file.path(DB$new_database, "Database") - - # Set database availability screening variables to present database - DB$block_db <- TRUE - DB$select_new <- FALSE - - # Render menu with Manage Schemes as start tab and no Missing values tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - # Dont render these elements - output$db_no_entries <- NULL - output$distancematrix_no_entries <- NULL - output$db_entries <- NULL - output$edit_index <- NULL - output$edit_scheme_d <- NULL - output$edit_entries <- NULL - output$compare_select <- NULL - output$delete_select <- NULL - output$del_bttn <- NULL - output$compare_allele_box <- NULL - output$download_entries <- NULL - output$missing_values <- NULL - output$delete_box <- NULL - output$missing_values_sidebar <- NULL - output$distmatrix_sidebar <- NULL - output$download_scheme_info <- NULL - output$download_loci <- NULL - output$entry_table_controls <- NULL - output$multi_stop <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - output$pending_typing <- NULL - output$multi_typing_results <- NULL - output$single_typing_progress <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - } - } else { - log_print(paste0("Loading existing ", input$scheme_db, " database from ", DB$database)) - } - - if(DB$load_selected == TRUE) { - - if(gsub(" ", "_", input$scheme_db) %in% schemes) { #Check if selected scheme valid - - # Save database path for next start - saveRDS(DB$database, paste0(getwd(), "/execute/last_db.rds")) - - DB$check_new_entries <- TRUE - DB$data <- NULL - DB$meta_gs <- NULL - DB$meta <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_trunc <- NULL - DB$allelic_profile_true <- NULL - DB$scheme <- input$scheme_db - - # null Distance matrix, entry table and plots - output$db_distancematrix <- NULL - output$db_entries_table <- NULL - output$tree_mst <- NULL - output$tree_nj <- NULL - output$tree_upgma <- NULL - - # null typing initiation UI - output$multi_stop <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - output$pending_typing <- NULL - output$multi_typing_results <- NULL - output$single_typing_progress <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - # null report values - Report$report_list_mst <- list() - Report$report_list_nj <- list() - Report$report_list_upgma <- list() - - # null plots - Vis$nj <- NULL - Vis$upgma <- NULL - Vis$ggraph_1 <- NULL - - removeModal() - - #### Render Menu Items ---- - - Startup$sidebar <- FALSE - Startup$header <- FALSE - - output$menu_sep2 <- renderUI(hr()) - - # Hide start message - output$start_message <- NULL - - if(any(grepl(gsub(" ", "_", DB$scheme), dir_ls(DB$database)))) { - - if(!any(grepl("alleles", dir_ls(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme)))))) { - - log_print("Missing loci files") - - # Show message that loci files are missing - showModal( - modalDialog( - paste0("Whoops! No loci files are present in the local ", - DB$scheme, - " folder. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } else if (!any(grepl("scheme_info.html", dir_ls(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme)))))) { - - output$download_scheme_info <- NULL - - log_print("Scheme info file missing") - - # Show message that scheme info is missing - showModal( - modalDialog( - paste0("Whoops! Scheme info of the local ", - DB$scheme, - " database is missing. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - } else if (!any(grepl("targets.csv", dir_ls(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme)))))) { - - # Dont render target download button - output$download_loci <- NULL - - log_print("Missing loci info (targets.csv)") - - # Show message that scheme info is missing - showModal( - modalDialog( - paste0("Whoops! Loci info of the local ", - DB$scheme, - " database is missing. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - } else { - # Produce Scheme Info Table - schemeinfo <- - read_html(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/scheme_info.html" - )) %>% - html_table(header = FALSE) %>% - as.data.frame(stringsAsFactors = FALSE) - names(schemeinfo) <- NULL - DB$schemeinfo <- schemeinfo - number_loci <- as.vector(DB$schemeinfo[6, 2]) - DB$number_loci <- as.numeric(gsub(",", "", number_loci)) - - # Produce Loci Info table - DB$loci_info <- read.csv( - file.path(DB$database, gsub(" ", "_", DB$scheme), "targets.csv"), - header = TRUE, - sep = "\t", - row.names = NULL, - colClasses = c( - "NULL", - "character", - "character", - "integer", - "integer", - "character", - "integer", - "NULL" - ) - ) - - # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme - if(DB$number_loci > length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { - - log_print(paste0("Loci files are missing in the local ", DB$scheme, " folder")) - - # Show message that loci files are missing - showModal( - modalDialog( - paste0("Whoops! Some loci files are missing in the local ", - DB$scheme, - " folder. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - } else { - ###### Alle checks bestanden -> Laden der DTB - # If typed entries present - if (any(grepl("Typing.rds", dir_ls(paste0( - DB$database, "/", gsub(" ", "_", DB$scheme) - ))))) { - - # Load database from files - Database <- readRDS(file.path(DB$database, - gsub(" ", "_", DB$scheme), - "Typing.rds")) - - DB$data <- Database[["Typing"]] - - if(!is.null(DB$data)){ - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - } else { - DB$cust_var <- data.frame() - } - } - - DB$change <- FALSE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - - # Null pipe - con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") - - cat("0\n", file = con) - - # Close the file connection - close(con) - - # Reset other reactive typing variables - Typing$progress_format_end <- 0 - Typing$progress_format_start <- 0 - Typing$pending_format <- 0 - Typing$entry_added <- 0 - Typing$progress <- 0 - Typing$progress_format <- 900000 - output$single_typing_progress <- NULL - output$typing_fin <- NULL - output$single_typing_results <- NULL - output$typing_formatting <- NULL - Typing$single_path <- data.frame() - - # Null multi typing feedback variable - Typing$reset <- TRUE - - # Check need for new missing vlaue display - if(DB$first_look == TRUE) { - if(sum(apply(DB$data, 1, anyNA)) >= 1) { - DB$no_na_switch <- TRUE - } else { - DB$no_na_switch <- FALSE - } - } - - DB$first_look <- TRUE - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - if(!anyNA(DB$allelic_profile)) { - - # no NA's -> dont render missing values sidebar elements - output$missing_values_sidebar <- NULL - - # Render menu if no NA's present - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } else { - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries", - selected = TRUE - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } - - # Render custom variable display - output$show_cust_var <- renderTable( - width = "100%", - { - if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { - if(nrow(DB$cust_var) > 5) { - low <- -4 - high <- 0 - for (i in 1:input$cust_var_select) { - low <- low + 5 - if((nrow(DB$cust_var) %% 5) != 0) { - if(i == ceiling(nrow(DB$cust_var) / 5 )) { - high <- high + nrow(DB$cust_var) %% 5 - } else { - high <- high + 5 - } - } else { - high <- high + 5 - } - } - DB$cust_var[low:high,] - } else { - DB$cust_var - } - } else if (!is.null(DB$cust_var)) { - DB$cust_var - } - }) - - # render visualization sidebar elements - observe({ - Vis$tree_algo <- input$tree_algo - }) - - output$visualization_sidebar <- renderUI({ - if(!is.null(DB$data)) { - column( - width = 12, - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - prettyRadioButtons( - "tree_algo", - choices = c("Minimum-Spanning", "Neighbour-Joining", "UPGMA"), - label = "", - selected = if(!is.null(Vis$tree_algo)){Vis$tree_algo} else {"Minimum-Spanning"} - ), - ) - ), - br(), - fluidRow( - column( - width = 12, - align = "center", - tags$div( - id = "button-wrapper", - actionButton( - "create_tree", - h5("Create Tree", style = "position: relative; left: 15px; color: white; font-size: 15px;"), - width = "100%" - ), - tags$img( - src = "phylo.png", - alt = "icon", - class = "icon" - ) - ) - ) - ), - br(), - hr(), - conditionalPanel( - "input.tree_algo=='Minimum-Spanning'", - fluidRow( - column( - width = 12, - align = "left", - br(), - HTML( - paste( - tags$span(style='color: white; font-size: 16px; margin-left: 15px', "Sizing") - ) - ) - ) - ), - fluidRow( - column( - width = 12, - radioGroupButtons( - "mst_ratio", - "", - choiceNames = c("16:10", "16:9", "4:3"), - choiceValues = c((16/10), (16/9), (4/3)), - width = "100%" - ), - br(), - sliderInput( - "mst_scale", - "", - min = 500, - max = 1200, - step = 5, - value = 800, - width = "95%", - ticks = FALSE - ) - ) - ), - br(), - hr(), - fluidRow( - column( - width = 12, - column( - width = 5, - align = "left", - conditionalPanel( - "input.mst_plot_format=='jpeg'", - actionBttn( - "save_plot_jpeg", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - conditionalPanel( - "input.mst_plot_format=='png'", - actionBttn( - "save_plot_png", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - conditionalPanel( - "input.mst_plot_format=='bmp'", - actionBttn( - "save_plot_bmp", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - conditionalPanel( - "input.mst_plot_format=='html'", - downloadBttn( - "save_plot_html", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ) - ), - column( - width = 7, - div( - style = "max-width: 150px", - class = "format", - selectInput( - inputId = "mst_plot_format", - label = "", - choices = c("html", "jpeg", "png", "bmp") - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.tree_algo=='Neighbour-Joining'", - fluidRow( - column( - width = 12, - column( - width = 5, - align = "left", - downloadBttn( - "download_nj", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - column( - width = 7, - div( - style = "max-width: 150px", - class = "format", - selectInput( - inputId = "filetype_nj", - label = "", - choices = c("png", "jpeg", "bmp", "svg") - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.tree_algo=='UPGMA'", - fluidRow( - column( - width = 12, - column( - width = 5, - align = "left", - downloadBttn( - "download_upgma", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - column( - width = 7, - div( - style = "max-width: 150px", - class = "format", - selectInput( - inputId = "filetype_upgma", - label = "", - choices = c("png", "jpeg", "bmp", "svg") - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 6, - align = "left", - br(), - actionButton( - "create_rep", - "Print Report" - ) - ) - ) - ) - } - }) - - # Render entry table sidebar elements - output$entrytable_sidebar <- renderUI({ - if(!is.null(DB$data)) { - column( - width = 12, - align = "center", - br(), - fluidRow( - column(1), - column( - width = 10, - align = "left", - if(nrow(DB$data) > 40) { - div( - class = "mat-switch-db-tab", - materialSwitch( - "table_height", - h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - } - ) - ), - br(), br(), - fluidRow( - column( - width = 12, - HTML( - paste( - tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Custom Variables') - ) - ) - ) - ), - fluidRow( - column( - width = 8, - textInput( - "new_var_name", - label = "", - placeholder = "New Variable" - ) - ), - column( - width = 2, - actionButton( - "add_new_variable", - "", - icon = icon("plus") - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "textinput_var", - selectInput( - "del_which_var", - "", - DB$cust_var$Variable - ) - ) - ), - column( - width = 2, - align = "left", - actionButton( - "delete_new_variable", - "", - icon = icon("minus") - ) - ) - ), - br(), - fluidRow( - column(1), - column( - width = 4, - uiOutput("cust_var_info") - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - tableOutput("show_cust_var") - ) - ), - fluidRow( - column(4), - column( - width = 7, - align = "center", - uiOutput("cust_var_select") - ) - ) - ) - } - }) - - # Render missing values sidebar elements - output$missing_values_sidebar <- renderUI({ - column( - width = 12, - fluidRow( - column( - width = 12, - br(), - materialSwitch( - "miss_val_height", - h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - br() - ), - fluidRow( - column( - width = 6, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -23px; right: -15px', - 'Download CSV') - ) - ) - ), - column( - width = 4, - downloadBttn( - "download_na_matrix", - style = "simple", - label = "", - size = "sm", - icon = icon("download") - ) - ) - ) - ) - }) - - # Render scheme info download button - output$download_loci <- renderUI({ - column( - 12, - downloadBttn( - "download_loci_info", - style = "simple", - label = "", - size = "sm", - icon = icon("download"), - color = "primary" - ), - bsTooltip("download_loci_info_bttn", HTML("Save loci information
(without sequence)"), placement = "top", trigger = "hover") - ) - }) - - # Render scheme info download button - output$download_scheme_info <- renderUI({ - downloadBttn( - "download_schemeinfo", - style = "simple", - label = "", - size = "sm", - icon = icon("download"), - color = "primary" - ) - }) - - # Render distance matrix sidebar - output$distmatrix_sidebar <- renderUI({ - column( - width = 12, - align = "left", - fluidRow( - column( - width = 12, - align = "center", - selectInput( - "distmatrix_label", - label = "", - choices = c("Index", "Assembly Name", "Assembly ID"), - selected = c("Assembly Name"), - width = "100%" - ), - br() - ) - ), - div( - class = "mat-switch-dmatrix", - materialSwitch( - "distmatrix_true", - h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - div( - class = "mat-switch-dmatrix", - materialSwitch( - "distmatrix_triangle", - h5(p("Show Upper Triangle"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - div( - class = "mat-switch-dmatrix-last", - materialSwitch( - "distmatrix_diag", - h5(p("Show Diagonal"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - fluidRow( - column( - width = 6, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: 37px; right: -15px', - 'Download CSV') - ) - ) - ), - column( - width = 4, - downloadBttn( - "download_distmatrix", - style = "simple", - label = "", - size = "sm", - icon = icon("download") - ) - ) - ) - ) - }) - - # Render select input to choose displayed loci - output$compare_select <- renderUI({ - - if(nrow(DB$data) == 1) { - HTML( - paste( - tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to compare") - ) - ) - } else { - if(!is.null(input$compare_difference)) { - if (input$compare_difference == FALSE) { - pickerInput( - inputId = "compare_select", - label = "", - width = "85%", - choices = names(DB$allelic_profile), - selected = names(DB$allelic_profile)[1:20], - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - } else { - pickerInput( - inputId = "compare_select", - label = "", - width = "85%", - choices = names(DB$allelic_profile), - selected = names(DB$allelic_profile)[var_alleles(DB$allelic_profile)], - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - } - } - } - }) - - #### Render Entry Data Table ---- - output$db_entries_table <- renderUI({ - if(!is.null(DB$data)) { - if(between(nrow(DB$data), 1, 30)) { - rHandsontableOutput("db_entries") - } else { - addSpinner( - rHandsontableOutput("db_entries"), - spin = "dots", - color = "#ffffff" - ) - } - } - }) - - if (!is.null(DB$data)) { - - observe({ - - if (!is.null(DB$data)) { - if (nrow(DB$data) == 1) { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else if (between(nrow(DB$data), 2, 40)) { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - highlightCol = TRUE, - highlightRow = TRUE, - contextMenu = FALSE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - valign = "htMiddle", - halign = "htCenter", - readOnly = TRUE) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - strict = TRUE, - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }" - ) %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names()- 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } else { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - rowHeaders = NULL, - height = table_height(), - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - readOnly = TRUE, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - height = table_height(), - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", halign = "htCenter") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } - } - - # Dynamic save button when rhandsontable changes or new entries - output$edit_entry_table <- renderUI({ - if(check_new_entry() & DB$check_new_entries) { - Typing$reload <- FALSE - fluidRow( - column( - width = 8, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', - 'New entries - reload database') - ) - ) - ), - column( - width = 4, - actionButton( - "load", - "", - icon = icon("rotate"), - class = "pulsating-button" - ) - ) - ) - } else if(Typing$status == "Attaching") { - fluidRow( - column( - width = 11, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', 'No database changes possible - pending entry addition') - ) - ) - ), - column( - width = 1, - HTML(paste('')) - ) - ) - } else if((DB$change == TRUE) | !identical(get.entry.table.meta(), select(DB$meta, -13))) { - - if(!is.null(input$db_entries)) { - fluidRow( - column( - width = 5, - HTML( - paste( - tags$span(style='color: white; font-size: 16px; position: absolute; bottom: -30px; right: -5px', 'Confirm changes') - ) - ) - ), - column( - width = 3, - actionButton( - "edit_button", - "", - icon = icon("bookmark"), - class = "pulsating-button" - ) - ), - column( - width = 4, - actionButton( - "undo_changes", - "Undo", - icon = icon("repeat") - ) - ) - ) - } - } else {NULL} - }) - - }) - - # Hide no entry message - output$db_no_entries <- NULL - output$distancematrix_no_entries <- NULL - - } else { - - # If database loading not successful dont show entry table - output$db_entries_table <- NULL - output$entry_table_controls <- NULL - } - - # Render Entry table controls - output$entry_table_controls <- renderUI({ - fluidRow( - column(1), - column( - width = 3, - align = "center", - fluidRow( - column( - width = 4, - align = "center", - actionButton( - "sel_all_entries", - "Select All", - icon = icon("check") - ) - ), - column( - width = 4, - align = "left", - actionButton( - "desel_all_entries", - "Deselect All", - icon = icon("xmark") - ) - ) - ) - ), - column( - width = 3, - uiOutput("edit_entry_table") - ) - ) - }) - - #### Render Distance Matrix ---- - observe({ - if(!is.null(DB$data)) { - - if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { - output$db_distancematrix <- NULL - - if( (sum(duplicated(DB$meta$`Assembly Name`)) > 0) & (sum(duplicated(DB$meta$`Assembly ID`)) == 0) ) { - duplicated_txt <- paste0( - paste( - paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), - DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] - ), - "
" - ) - } else if ( (sum(duplicated(DB$meta$`Assembly ID`)) > 0) & (sum(duplicated(DB$meta$`Assembly Name`)) == 0) ){ - duplicated_txt <- paste0( - paste( - paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), - DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] - ), - "
" - ) - } else { - duplicated_txt <- c( - paste0( - paste( - paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), - DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] - ), - "
" - ), - paste0( - paste( - paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), - DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] - ), - "
" - ) - ) - } - - output$distancematrix_duplicated <- renderUI({ - column( - width = 12, - tags$span(style = "font-size: 15; color: white", - "Change duplicated entry names to display distance matrix."), - br(), br(), br(), - actionButton("change_entries", "Go to Entry Table", class = "btn btn-default"), - br(), br(), br(), - tags$span( - style = "font-size: 15; color: white", - HTML( - append( - "Duplicated:", - append( - "
", - duplicated_txt - ) - ) - ) - ) - ) - }) - } else { - output$distancematrix_duplicated <- NULL - if(!is.null(DB$data) & !is.null(DB$allelic_profile) & !is.null(DB$allelic_profile_true) & !is.null(DB$cust_var) & !is.null(input$distmatrix_label) & !is.null(input$distmatrix_diag) & !is.null(input$distmatrix_triangle)) { - output$db_distancematrix <- renderRHandsontable({ - rhandsontable(hamming_df(), - digits = 1, - readOnly = TRUE, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE, - height = distancematrix_height(), rowHeaders = NULL) %>% - hot_heatmap(renderer = paste0(" - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - heatmapScale = chroma.scale(['#17F556', '#ED6D47']); - - if (instance.heatmap[col]) { - mn = ", DB$matrix_min, "; - mx = ", DB$matrix_max, "; - - pt = (parseInt(value, 10) - mn) / (mx - mn); - - td.style.backgroundColor = heatmapScale(pt).hex(); - } - }")) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1:(dim(DB$ham_matrix)[1]+1), - halign = "htCenter", - valign = "htMiddle") %>% - hot_col(1, renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - td.style.background = '#F0F0F0' - }" - ) - }) - } - } - - # Render Distance Matrix UI - - output$distmatrix_show <- renderUI({ - if(!is.null(DB$data)) { - if(nrow(DB$data) > 1) { - column( - width = 10, - uiOutput("distancematrix_duplicated"), - div( - class = "distmatrix", - rHandsontableOutput("db_distancematrix") - ) - ) - } else { - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to display a distance matrix.") - ) - ) - ), - br(), - br() - ) - } - } - }) - - } - }) - - - # Render delete entry box UI - output$delete_box <- renderUI({ - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - column( - width = 12, - align = "center", - h3(p("Delete Entries"), style = "color:white") - ) - ), - hr(), - fluidRow( - column( - width = 2, - offset = 1, - align = "right", - br(), - h5("Index", style = "color:white; margin-bottom: 0px;") - ), - column( - width = 6, - align = "center", - uiOutput("delete_select") - ), - column( - width = 2, - align = "center", - br(), - uiOutput("del_bttn") - ) - ), - br() - ) - }) - - # Render loci comparison box UI - output$compare_allele_box <- renderUI({ - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - column( - width = 12, - align = "center", - h3(p("Compare Loci"), style = "color:white") - ) - ), - hr(), - column( - width = 12, - align = "center", - br(), - uiOutput("compare_select"), - br(), - column(2), - column( - width = 10, - align = "left", - uiOutput("compare_difference_box") - ) - ), - br() - ) - }) - - # Render entry table download box UI - output$download_entries <- renderUI({ - fluidRow( - column( - width = 12, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - column( - width = 12, - align = "center", - h3(p("Download Table"), style = "color:white") - ) - ), - hr(), - fluidRow( - column(2), - column( - width = 10, - align = "left", - br(), - div( - class = "mat-switch-db", - materialSwitch( - "download_table_include", - h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - div( - class = "mat-switch-db", - materialSwitch( - "download_table_loci", - h5(p("Include Displayed Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - br(), - ) - ), - fluidRow( - column( - width = 12, - align = "center", - downloadBttn( - "download_entry_table", - style = "simple", - label = "", - size = "sm", - icon = icon("download"), - color = "primary" - ) - ) - ), - br() - ) - ), - column( - width = 12, - fluidRow( - column( - width = 2, - div( - class = "rectangle-blue" - ), - div( - class = "rectangle-orange" - ), - div( - class = "rectangle-red" - ), - div( - class = "rectangle-green" - ) - ), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -12px", " = included for analyses") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -13px", " = duplicated name/ID") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -14px", " = ≥ 5% of loci missing") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -15px", " = locus contains multiple variants") - ) - ) - ), - ) - ) - ) - ) - }) - - # Render entry deletion select input - output$delete_select <- renderUI({ - pickerInput("select_delete", - label = "", - choices = DB$data[, "Index"], - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE) - }) - - # Render delete entry button - output$del_bttn <- renderUI({ - actionBttn( - "del_button", - label = "", - color = "danger", - size = "sm", - style = "material-circle", - icon = icon("xmark") - ) - }) - - #### Missing Values UI ---- - - # Missing values calculations and table - observe({ - - if (!is.null(DB$allelic_profile)) { - NA_table <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) != 0] - - NA_table <- NA_table[rowSums(is.na(NA_table)) != 0,] - - NA_table[is.na(NA_table)] <- "NA" - - NA_table <- NA_table %>% - cbind("Assembly Name" = DB$meta[rownames(NA_table),]$`Assembly Name`) %>% - cbind("Errors" = DB$meta[rownames(NA_table),]$Errors) %>% - relocate("Assembly Name", "Errors") - - DB$na_table <- NA_table - - if(!is.null(input$miss_val_height)) { - if(nrow(DB$na_table) < 31) { - output$table_missing_values <- renderRHandsontable({ - rhandsontable( - DB$na_table, - readOnly = TRUE, - rowHeaders = NULL, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE, - error_highlight = err_thresh_na() - 1 - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% - hot_col(2, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } else { - output$table_missing_values <- renderRHandsontable({ - rhandsontable( - DB$na_table, - readOnly = TRUE, - rowHeaders = NULL, - height = miss.val.height(), - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE, - error_highlight = err_thresh() - 1 - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% - hot_col(2, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } - } - } - - }) - - # Render missing value informatiojn box UI - output$missing_values <- renderUI({ - div( - class = "miss_val_box", - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - div( - class = "white", - column( - width = 12, - align = "left", - br(), - HTML( - paste0("There are ", - strong(as.character(sum(is.na(DB$data)))), - " unsuccessful allele allocations (NA). ", - strong(sum(sapply(DB$allelic_profile, anyNA))), - " out of ", - strong(ncol(DB$allelic_profile)), - " total loci in this scheme contain NA's (", - strong(round((sum(sapply(DB$allelic_profile, anyNA)) / ncol(DB$allelic_profile) * 100), 1)), - " %). ", - "Decide how these missing values should be treated:") - - ), - br() - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "left", - br(), - prettyRadioButtons( - "na_handling", - "", - choiceNames = c("Ignore missing values for pairwise comparison", - "Omit loci with missing values for all assemblies", - "Treat missing values as allele variant"), - choiceValues = c("ignore_na", "omit", "category"), - shape = "curve", - selected = c("ignore_na") - ), - br() - ) - ) - ) - ) - }) - - } else { - #if no typed assemblies present - - # null underlying database - - DB$data <- NULL - DB$meta <- NULL - DB$meta_gs <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_trunc <- NULL - DB$allelic_profile_true <- NULL - - # Render menu without missing values tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - selected = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - observe({ - if(is.null(DB$data)) { - if(check_new_entry()) { - output$db_no_entries <- renderUI( - column( - width = 12, - fluidRow( - column(1), - column( - width = 3, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 15px; position: absolute; bottom: -30px; right: -5px', 'New entries - reload database') - ) - ) - ), - column( - width = 4, - actionButton( - "load", - "", - icon = icon("rotate"), - class = "pulsating-button" - ) - ) - ) - ) - ) - } else { - output$db_no_entries <- renderUI( - column( - width = 12, - fluidRow( - column(1), - column( - width = 11, - align = "left", - HTML( - paste( - "", - "No Entries for this scheme available.\n", - "Type a genome in the section Allelic Typing and add the result to the local database.", - sep = '
' - ) - ) - ) - ) - ) - ) - } - } - }) - - output$distancematrix_no_entries <- renderUI( - fluidRow( - column(1), - column( - width = 11, - align = "left", - HTML(paste( - "", - "No Entries for this scheme available.", - "Type a genome in the section Allelic Typing and add the result to the local database.", - sep = '
' - )) - ) - ) - ) - - output$db_entries <- NULL - output$edit_index <- NULL - output$edit_scheme_d <- NULL - output$edit_entries <- NULL - output$compare_select <- NULL - output$delete_select <- NULL - output$del_bttn <- NULL - output$compare_allele_box <- NULL - output$download_entries <- NULL - output$missing_values <- NULL - output$delete_box <- NULL - output$entry_table_controls <- NULL - output$multi_stop <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - output$pending_typing <- NULL - output$multi_typing_results <- NULL - output$single_typing_progress <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - } - } - } - } - } else { - - log_print("Invalid scheme folder") - show_toast( - title = "Invalid scheme folder", - type = "warning", - position = "bottom-end", - timer = 4000 - ) - } - } - - }) - - # _______________________ #### - - ## Database ---- - - ### Conditional UI Elements rendering ---- - - # Contro custom variables table - output$cust_var_select <- renderUI({ - if(nrow(DB$cust_var) > 5) { - selectInput( - "cust_var_select", - "", - choices = 1:ceiling(nrow(DB$cust_var) / 5 ) - ) - } - }) - - output$cust_var_info <- renderUI({ - if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { - if(nrow(DB$cust_var) > 5) { - low <- -4 - high <- 0 - for (i in 1:input$cust_var_select) { - low <- low + 5 - if((nrow(DB$cust_var) %% 5) != 0) { - if(i == ceiling(nrow(DB$cust_var) / 5 )) { - high <- high + nrow(DB$cust_var) %% 5 - } else { - high <- high + 5 - } - } else { - high <- high + 5 - } - } - h5(paste0("Showing ", low, " to ", high," of ", nrow(DB$cust_var), " variables"), style = "color: white; font-size: 10px;") - } - } - }) - - # Message on Database tabs if no scheme available yet - observe({ - if(!is.null(DB$exist)) { - if(DB$exist){ - - # Message for tab Browse Entries - output$no_scheme_entries <- renderUI({ - fluidRow( - column(1), - column( - width = 4, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'No scheme available.') - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'Download a scheme first and type assemblies in the section Allelic Typing.') - ) - ) - ) - ) - ) - }) - - # Message for Tab Scheme Info - output$no_scheme_info <- renderUI({ - fluidRow( - column(1), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'No scheme available.') - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'Download a scheme first and type assemblies in the section Allelic Typing.') - ) - ) - ) - ) - ) - }) - - # Message for Tab Distance Matrix - output$no_scheme_distancematrix <- renderUI({ - fluidRow( - column(1), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'No scheme available.') - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'Download a scheme first and type assemblies in the section Allelic Typing.') - ) - ) - ) - ) - ) - }) - - } else { - output$no_scheme_entries <- NULL - output$no_scheme_info <- NULL - output$no_scheme_distancematrix <- NULL - } - } - - }) - - observe({ - # Conditional Missing Values Tab - if(!is.null(DB$allelic_profile)) { - if(anyNA(DB$allelic_profile)) { - if(DB$no_na_switch == FALSE) { - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - selected = TRUE, - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } - - } else { - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } - } - - }) - - observe({ - - if (!is.null(DB$available)) { - output$scheme_db <- renderUI({ - if (length(DB$available) > 5) { - selectInput( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} - ) - } else { - prettyRadioButtons( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} - ) - } - }) - - if (!is.null(DB$schemeinfo)) { - - output$scheme_info <- renderTable({ - DB$schemeinfo - }) - - output$scheme_header <- renderUI(h3(p("cgMLST Scheme"), style = "color:white")) - - } else { - - output$scheme_info <- NULL - output$scheme_header <- NULL - - } - - if (!is.null(DB$loci_info)) { - loci_info <- DB$loci_info - names(loci_info)[6] <- "Allele Count" - - output$db_loci <- renderDataTable( - loci_info, - selection = "single", - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - )) - ) - - output$loci_header <- renderUI(h3(p("Loci"), style = "color:white")) - - } else { - output$db_loci <- NULL - output$loci_header <- NULL - } - } - }) - - # If only one entry available disable varying loci checkbox - - output$compare_difference_box <- renderUI({ - if(!is.null(DB$data)) { - if(nrow(DB$data) > 1) { - div( - class = "mat-switch-db", - materialSwitch( - "compare_difference", - h5(p("Only Varying Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - } - } - }) - - ### Database Events ---- - - # Invalid entries table input - observe({ - req(DB$data, input$db_entries) - if (isTRUE(input$invalid_date)) { - show_toast( - title = "Invalid date", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - DB$inhibit_change <- TRUE - } else if (isTRUE(input$empty_name)) { - show_toast( - title = "Empty name", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - DB$inhibit_change <- TRUE - } else if (isTRUE(input$empty_id)) { - show_toast( - title = "Empty ID", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - DB$inhibit_change <- TRUE - } else { - DB$inhibit_change <- FALSE - } - }) - - # Change scheme - observeEvent(input$reload_db, { - log_print("Input reload_db") - - if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { - show_toast( - title = "Pending Multi Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(Screening$status == "started") { - show_toast( - title = "Pending Screening", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - showModal( - modalDialog( - selectInput( - "scheme_db", - label = "", - choices = DB$available, - selected = DB$scheme), - title = "Select a local database to load.", - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("load", "Load", class = "btn btn-default") - ) - ) - ) - } - }) - - # Create new database - observe({ - shinyDirChoose(input, - "create_new_db", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session) - - if(!is.null(input$create_new_db)) { - DB$new_database <- as.character( - parseDirPath( - roots = c(Home = path_home(), Root = "/"), - input$create_new_db - ) - ) - } - }) - - # Undo db changes - observeEvent(input$undo_changes, { - log_print("Input undo_changes") - - DB$inhibit_change <- FALSE - - Data <- readRDS(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/Typing.rds" - )) - - DB$data <- Data[["Typing"]] - - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - } else { - DB$cust_var <- data.frame() - } - - DB$change <- FALSE - DB$count <- 0 - DB$no_na_switch <- TRUE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - DB$deleted_entries <- character(0) - - observe({ - if (!is.null(DB$data)) { - if (nrow(DB$data) == 1) { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else if (between(nrow(DB$data), 1, 40)) { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - highlightCol = TRUE, - highlightRow = TRUE, - contextMenu = FALSE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - valign = "htMiddle", - halign = "htCenter", - readOnly = TRUE) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - strict = TRUE, - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }" - ) %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names()- 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } else { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - rowHeaders = NULL, - height = table_height(), - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - readOnly = TRUE, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - height = table_height(), - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", halign = "htCenter") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } - } - }) - }) - - observe({ - if(!is.null(DB$data)){ - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - - } else { - DB$cust_var <- data.frame() - } - } - }) - - DB$count <- 0 - - observeEvent(input$add_new_variable, { - log_print("Input add_new_variable") - - if(nchar(input$new_var_name) > 12) { - log_print("Add variable; max. 10 character") - show_toast( - title = "Max. 10 characters", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - if (input$new_var_name == "") { - log_print("Add variable; min. 1 character") - show_toast( - title = "Min. 1 character", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - if(trimws(input$new_var_name) %in% names(DB$meta)) { - log_print("Add variable; name already existing") - show_toast( - title = "Variable name already existing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - showModal( - modalDialog( - selectInput( - "new_var_type", - label = "", - choices = c("Categorical (character)", - "Continous (numeric)")), - title = paste0("Select Data Type"), - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_new_var", "Confirm", class = "btn btn-default") - ) - ) - ) - } - } - } - }) - - observeEvent(input$conf_new_var, { - log_print("Input conf_new_var") - - # User feedback variables - removeModal() - DB$count <- DB$count + 1 - DB$change <- TRUE - - # Format variable name - name <- trimws(input$new_var_name) - - if(input$new_var_type == "Categorical (character)") { - DB$data <- DB$data %>% - mutate("{name}" := character(nrow(DB$data)), .after = 13) - - DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "categ")) - } else { - DB$data <- DB$data %>% - mutate("{name}" := numeric(nrow(DB$data)), .after = 13) - - DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "cont")) - } - - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - - log_print(paste0("New custom variable added: ", input$new_var_name)) - - show_toast( - title = paste0("Variable ", trimws(input$new_var_name), " added"), - type = "success", - position = "bottom-end", - timer = 6000 - ) - - }) - - observeEvent(input$delete_new_variable, { - log_print("Input delete_new_variable") - - if (input$del_which_var == "") { - log_print("Delete custom variables; no custom variable") - show_toast( - title = "No custom variables", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - showModal( - modalDialog( - paste0( - "Confirmation will lead to irreversible deletion of the custom ", - input$del_which_var, - " variable. Continue?" - ), - title = "Delete custom variables", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_var_del", "Delete", class = "btn btn-danger") - ) - ) - ) - } - }) - - observeEvent(input$conf_var_del, { - log_print("Input conf_var_del") - - DB$change <- TRUE - - removeModal() - - if(DB$count >= 1) { - DB$count <- DB$count - 1 - } - - show_toast( - title = paste0("Variable ", input$del_which_var, " removed"), - type = "warning", - position = "bottom-end", - timer = 6000 - ) - - log_print(paste0("Variable ", input$del_which_var, " removed")) - - DB$cust_var <- DB$cust_var[-which(DB$cust_var$Variable == input$del_which_var),] - DB$data <- select(DB$data, -(input$del_which_var)) - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - }) - - # Select all button - - observeEvent(input$sel_all_entries, { - log_print("Input sel_all_entries") - - DB$data$Include <- TRUE - }) - - observeEvent(input$desel_all_entries, { - log_print("Input desel_all_entries") - - DB$data$Include <- FALSE - }) - - # Switch to entry table - - observeEvent(input$change_entries, { - log_print("Input change_entries") - - removeModal() - updateTabItems(session, "tabs", selected = "db_browse_entries") - }) - - #### Save Missing Value as CSV ---- - - output$download_na_matrix <- downloadHandler( - filename = function() { - log_print(paste0("Save missing values table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv"))) - paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv") - }, - content = function(file) { - download_matrix <- hot_to_r(input$table_missing_values) - write.csv(download_matrix, file, sep = ",", row.names=FALSE, quote=FALSE) - } - ) - - #### Save scheme info table as CSV ---- - - output$download_schemeinfo <- downloadHandler( - filename = function() { - log_print(paste0("Save scheme info table ", paste0(gsub(" ", "_", DB$scheme), "_scheme.csv"))) - - paste0(gsub(" ", "_", DB$scheme), "_scheme.csv") - }, - content = function(file) { - pub_index <- which(DB$schemeinfo[,1] == "Publications") - write.table( - DB$schemeinfo[1:(pub_index-1),], - file, - sep = ";", - row.names = FALSE, - quote = FALSE - ) - } - ) - - #### Save Loci info table as CSV ---- - - output$download_loci_info <- downloadHandler( - filename = function() { - log_print(paste0("Save loci info table ", paste0(gsub(" ", "_", DB$scheme), "_Loci.csv"))) - - paste0(gsub(" ", "_", DB$scheme), "_Loci.csv") - }, - content = function(file) { - write.table( - DB$loci_info, - file, - sep = ";", - row.names = FALSE, - quote = FALSE - ) - } - ) - - #### Save entry table as CSV ---- - - output$download_entry_table <- downloadHandler( - filename = function() { - log_print(paste0("Save entry table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv"))) - - paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv") - }, - content = function(file) { - download_matrix <- hot_to_r(input$db_entries) - - if (input$download_table_include == TRUE) { - download_matrix <- download_matrix[which(download_matrix$Include == TRUE),] - } - - if (input$download_table_loci == FALSE) { - download_matrix <- select(download_matrix, 1:(13 + nrow(DB$cust_var))) - } - - write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) - } - ) - - # Save Edits Button - - observeEvent(input$edit_button, { - if(nrow(hot_to_r(input$db_entries)) > nrow(DB$data)) { - show_toast( - title = "Invalid rows entered. Saving not possible.", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - if(!isTRUE(DB$inhibit_change)) { - log_print("Input edit_button") - - showModal( - modalDialog( - if(length(DB$deleted_entries > 0)) { - paste0( - "Overwriting previous metadata of local ", - DB$scheme, - " database. Deleted entries will be irreversibly removed. Continue?" - ) - } else { - paste0( - "Overwriting previous metadata of local ", - DB$scheme, - " database. Continue?" - ) - }, - title = "Save Database", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_db_save", "Save", class = "btn btn-default") - ) - ) - ) - } else { - log_print("Input edit_button, invalid values.") - show_toast( - title = "Invalid values entered. Saving not possible.", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } - }) - - observeEvent(input$Cancel, { - log_print("Input Cancel") - removeModal() - }) - - observeEvent(input$conf_db_save, { - log_print("Input conf_db_save") - - # Remove isolate assembly file if present - if(!is.null(DB$remove_iso)) { - if(length(DB$remove_iso) > 0) { - lapply(DB$remove_iso, unlink, recursive = TRUE, force = FALSE, expand = TRUE) - } - } - DB$remove_iso <- NULL - - Data <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) - - if ((ncol(Data[["Typing"]]) - 13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_vars_pre <- select(Data[["Typing"]], - 14:(ncol(Data[["Typing"]]) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - cust_vars_pre <- names(cust_vars_pre) - } else { - cust_vars_pre <- character() - } - - Data[["Typing"]] <- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) - - meta_hot <- hot_to_r(input$db_entries) - - if(length(DB$deleted_entries > 0)) { - - meta_hot <- mutate(meta_hot, Index = as.character(1:nrow(DB$data))) - - Data[["Typing"]] <- mutate(Data[["Typing"]][-as.numeric(DB$deleted_entries), ], - meta_hot, .before = 1) - rownames(Data[["Typing"]]) <- Data[["Typing"]]$Index - } else { - Data[["Typing"]] <- mutate(Data[["Typing"]], meta_hot, .before = 1) - } - - # Ensure correct logical data type - Data[["Typing"]][["Include"]] <- as.logical(Data[["Typing"]][["Include"]]) - saveRDS(Data, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - # Load database from files - Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - DB$data <- Database[["Typing"]] - - if(!is.null(DB$data)){ - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - } else { - DB$cust_var <- data.frame() - } - } - - DB$change <- FALSE - DB$count <- 0 - DB$no_na_switch <- TRUE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - DB$deleted_entries <- character(0) - - removeModal() - - show_toast( - title = "Database successfully saved", - type = "success", - position = "bottom-end", - timer = 4000 - ) - }) - - observeEvent(input$del_button, { - log_print("Input del_button") - - if (length(input$select_delete) < 1) { - log_print("Delete entries; no entry selected") - show_toast( - title = "No entry selected", - type = "warning", - position = "bottom-end", - timer = 4000 - ) - } else if((readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") | - (tail(readLogFile(), 1) != "0")) { - log_print("Delete entries; pending typing") - - show_toast( - title = "Pending Typing", - type = "warning", - position = "bottom-end", - timer = 4000 - ) - } else { - if( (length(input$select_delete) - nrow(DB$data) ) == 0) { - showModal( - modalDialog( - paste0("Deleting will lead to removal of all entries and assemblies from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?"), - easyClose = TRUE, - title = "Deleting Entries", - footer = tagList( - modalButton("Cancel"), - actionButton("conf_delete_all", "Delete", class = "btn btn-danger") - ) - ) - ) - } else { - showModal( - modalDialog( - paste0( - "Confirmation will lead to irreversible removal of selected entries and the respectively saved assembly. Continue?" - ), - title = "Deleting Entries", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton( - "conf_delete", - "Delete", - class = "btn btn-danger") - ) - ) - ) - } - } - }) - - observeEvent(input$conf_delete_all, { - log_print("Input conf_delete_all") - - # remove file with typing data - file.remove(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - unlink(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates"), recursive = TRUE, force = FALSE, expand =TRUE) - - showModal( - modalDialog( - selectInput( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}}), - title = "All entries have been removed. Select a local database to load.", - footer = tagList( - actionButton("load", "Load", class = "btn btn-default") - ) - ) - ) - - }) - - DB$deleted_entries <- character(0) - - observeEvent(input$conf_delete, { - - log_print("Input conf_delete") - - # Get isolates selected for deletion - DB$deleted_entries <- append(DB$deleted_entries, DB$data$Index[as.numeric(input$select_delete)]) - - # Set reactive status variables - DB$no_na_switch <- TRUE - DB$change <- TRUE - DB$check_new_entries <- FALSE - - # Set isolate directory deletion variables - isopath <- dir_ls(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates")) - DB$remove_iso <- isopath[which(basename(isopath) == DB$data$`Assembly ID`[as.numeric(input$select_delete)])] - - # Reload updated database reactive variables - DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - - # User feedback - removeModal() - - if(length(input$select_delete) > 1) { - show_toast( - title = "Entries deleted", - type = "success", - position = "bottom-end", - timer = 4000 - ) - } else { - show_toast( - title = "Entry deleted", - type = "success", - position = "bottom-end", - timer = 4000 - ) - } - }) - - - ### Distance Matrix ---- - - hamming_df <- reactive({ - if(input$distmatrix_true == TRUE) { - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - - allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - - hamming_mat <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) - - } else if(input$na_handling == "ignore_na"){ - hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) - - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) - - } - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) - } - } else { - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - hamming_mat <- compute.distMatrix(allelic_profile_noNA, hamming.dist) - } else if(input$na_handling == "ignore_na"){ - hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distIgnore) - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distCategory) - } - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.dist) - } - } - - # Extreme values for distance matrix heatmap display - DB$matrix_min <- min(hamming_mat, na.rm = TRUE) - DB$matrix_max <- max(hamming_mat, na.rm = TRUE) - - if(input$distmatrix_triangle == FALSE) { - hamming_mat[upper.tri(hamming_mat, diag = !input$distmatrix_diag)] <- NA - } - - # Row- and colnames change - if(input$distmatrix_true == TRUE) { - rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label][which(DB$data$Include == TRUE),]) - } else { - rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label]) - } - colnames(hamming_mat) <- rownames(hamming_mat) - - mode(hamming_mat) <- "integer" - - DB$ham_matrix <- hamming_mat %>% - as.data.frame() %>% - mutate(Index = colnames(hamming_mat)) %>% - relocate(Index) - DB$distancematrix_nrow <- nrow(DB$ham_matrix) - - DB$ham_matrix - }) - - output$download_distmatrix <- downloadHandler( - filename = function() { - paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Distance_Matrix.csv") - }, - content = function(file) { - download_matrix <- hot_to_r(input$db_distancematrix) - download_matrix[is.na(download_matrix)] <- "" - write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) - } - ) - - # _______________________ #### - - ## Locus sequences ---- - - observe({ - if(!is.null(DB$database) & !is.null(DB$scheme)) { - DB$loci <- list.files( - path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), - pattern = "\\.(fasta|fa|fna)$", - full.names = TRUE - ) - } - }) - - output$loci_sequences <- renderUI({ - req(input$db_loci_rows_selected, DB$database, DB$scheme, input$seq_sel) - - DB$loci <- list.files( - path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), - pattern = "\\.(fasta|fa|fna)$", - full.names = TRUE - ) - - fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) - - seq <- fasta[[which(fasta == paste0(">", gsub("Allele ", "", sub(" -.*", "", input$seq_sel)))) + 1]] - - DB$seq <- seq - - column( - width = 12, - HTML( - paste( - tags$span(style='color: white; font-size: 15px; position: relative; top: -15px; left: -50px', - sub(" -.*", "", input$seq_sel)) - ) - ), - tags$pre(HTML(color_sequence(seq)), class = "sequence") - ) - }) - - output$sequence_selector <- renderUI({ - if(!is.null(input$db_loci_rows_selected)) { - - req(input$db_loci_rows_selected, DB$database, DB$scheme) - - DB$loci <- list.files( - path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), - pattern = "\\.(fasta|fa|fna)$", - full.names = TRUE - ) - - fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) - - seq_names <- c() - for (i in seq_along(fasta)) { - if (startsWith(fasta[[i]], ">")) { - name <- sub(">", "", fasta[[i]]) - seq_names <- c(seq_names, name) - } - } - - var_count <- table(DB$allelic_profile[gsub(".fasta", "", (basename(DB$loci[input$db_loci_rows_selected])))]) - - vec <- prop.table(var_count) - - perc <- sapply(unname(vec), scales::percent, accuracy = 0.1) - - names(perc) <- names(vec) - - choices <- seq_names - - present <- which(choices %in% names(vec)) - absent <- which(!(choices %in% names(vec))) - - choices[present] <- paste0("Allele ", choices[present], " - ", unname(var_count), " times in DB (", unname(perc), ")") - - choices[absent] <- paste0("Allele ", choices[absent], " - not present") - - choices <- c(choices[present], choices[absent]) - - names(choices) <- sapply(choices, function(x) { - x <- strsplit(x, " ")[[1]] - x[2] <- paste0(substr(x[2], 1, 4), "...", substr(x[2], nchar(x[2])-3, nchar(x[2]))) - paste(x, collapse = " ") - }) - - column( - width = 3, - selectInput( - "seq_sel", - h5("Select Variant", style = "color:white;"), - choices = choices, - width = "80%" - ), - br(), - fluidRow( - column( - width = 8, - align = "left", - actionButton("copy_seq", "Copy Sequence", - icon = icon("copy")), - bsTooltip("copy_seq", "Copy the variant sequence
to clipboard", placement = "top", trigger = "hover") - ) - ), - br(), - fluidRow( - column( - width = 8, - align = "left", - downloadBttn( - "get_locus", - style = "simple", - label = "Save .fasta", - size = "sm", - icon = icon("download") - ), - bsTooltip("get_locus_bttn", "Save locus file with all variants", placement = "top", trigger = "hover") - ) - ), - br(), br(), br(), br(), br(), br(), br() - ) - } - }) - - observeEvent(input$copy_seq, { - if(!is.null(DB$seq)) { - session$sendCustomMessage("txt", DB$seq) - } - show_toast( - title = "Copied sequence", - type = "success", - position = "bottom-end", - timer = 3000 - ) - }) - - output$get_locus <- downloadHandler( - filename = function() { - fname <- basename(DB$loci[input$db_loci_rows_selected]) - log_print(paste0("Get locus fasta ", fname)) - fname - }, - content = function(file) { - cont <- readLines(DB$loci[input$db_loci_rows_selected]) - writeLines(cont, file) - } - ) - - # _______________________ #### - - ## Download cgMLST ---- - - observe({ - if (input$select_cgmlst == "Acinetobacter baumanii") { - species <- "Abaumannii1907" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- Scheme$folder_name <- "Acinetobacter_baumanii" - } else if (input$select_cgmlst == "Bacillus anthracis") { - species <- "Banthracis1917" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Bacillus_anthracis" - } else if (input$select_cgmlst == "Bordetella pertussis") { - species <- "Bpertussis1917" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Bordetella_pertussis" - } else if (input$select_cgmlst == "Brucella melitensis") { - species <- "Bmelitensis1912" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Brucella_melitensis" - } else if (input$select_cgmlst == "Brucella spp.") { - species <- "Brucella1914" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Brucella_spp" - } else if (input$select_cgmlst == "Burkholderia mallei (FLI)") { - species <- "Bmallei_fli1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Burkholderia_mallei_FLI" - } else if (input$select_cgmlst == "Burkholderia mallei (RKI)") { - species <- "Bmallei_rki1909" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Burkholderia_mallei_RKI" - } else if (input$select_cgmlst == "Burkholderia pseudomallei") { - species <- "Bpseudomallei1906" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Burkholderia_pseudomallei" - } else if (input$select_cgmlst == "Campylobacter jejuni/coli") { - species <- "Cjejuni1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Campylobacter_jejuni_coli" - } else if (input$select_cgmlst == "Clostridioides difficile") { - species <- "Cdifficile1905" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Clostridioides_difficile" - } else if (input$select_cgmlst == "Clostridium perfringens") { - species <- "Cperfringens1907" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Clostridium_perfringens" - } else if (input$select_cgmlst == "Corynebacterium diphtheriae") { - species <- "Cdiphtheriae1907" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Corynebacterium_diphtheriae" - } else if (input$select_cgmlst == "Cronobacter sakazakii/malonaticus") { - species <- "Csakazakii1910" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Cronobacter_sakazakii_malonaticus" - } else if (input$select_cgmlst == "Enterococcus faecalis") { - species <- "Efaecalis1912" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Enterococcus_faecalis" - } else if (input$select_cgmlst == "Enterococcus faecium") { - species <- "Efaecium1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Enterococcus_faecium" - } else if (input$select_cgmlst == "Escherichia coli") { - species <- "Ecoli1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Escherichia_coli" - } else if (input$select_cgmlst == "Francisella tularensis") { - species <- "Ftularensis1913" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Francisella_tularensis" - } else if (input$select_cgmlst == "Klebsiella oxytoca sensu lato") { - species <- "Koxytoca717" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Klebsiella_oxytoca_sensu_lato" - } else if (input$select_cgmlst == "Klebsiella pneumoniae sensu lato") { - species <- "Kpneumoniae1909" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Klebsiella_pneumoniae_sensu_lato" - } else if (input$select_cgmlst == "Legionella pneumophila") { - species <- "Lpneumophila1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Legionella_pneumophila" - } else if (input$select_cgmlst == "Listeria monocytogenes") { - species <- "Lmonocytogenes1910" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Listeria_monocytogenes" - } else if (input$select_cgmlst == "Mycobacterium tuberculosis complex") { - species <- "Mtuberculosis1909" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Mycobacterium_tuberculosis_complex" - } else if (input$select_cgmlst == "Mycobacteroides abscessus") { - species <- "Mabscessus1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Mycobacteroides_abscessus" - } else if (input$select_cgmlst == "Mycoplasma gallisepticum") { - species <- "Mgallisepticum1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Mycoplasma_gallisepticum" - } else if (input$select_cgmlst == "Paenibacillus larvae") { - species <- "Plarvae1902" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Paenibacillus_larvae" - } else if (input$select_cgmlst == "Pseudomonas aeruginosa") { - species <- "Paeruginosa1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Pseudomonas_aeruginosa" - } else if (input$select_cgmlst == "Salmonella enterica") { - species <- "Senterica1913" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Salmonella_enterica" - } else if (input$select_cgmlst == "Serratia marcescens") { - species <- "Smarcescens1912" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Serratia_marcescens" - } else if (input$select_cgmlst == "Staphylococcus aureus") { - species <- "Saureus1908" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Staphylococcus_aureus" - } else if (input$select_cgmlst == "Staphylococcus capitis") { - species <- "Scapitis1905" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Staphylococcus_capitis" - } else if (input$select_cgmlst == "Streptococcus pyogenes") { - species <- "Spyogenes1904" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Streptococcus_pyogenes" - } - }) - - observeEvent(input$download_cgMLST, { - log_print(paste0("Started download of scheme for ", Scheme$folder_name)) - - shinyjs::hide("download_cgMLST") - shinyjs::show("loading") - - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    Downloading scheme...")), - style = "color:white;") - ) - ) - ) - - show_toast( - title = "Download started", - type = "success", - position = "bottom-end", - timer = 5000 - ) - - if(length(DB$available) == 0) { - saveRDS(DB$new_database, paste0(getwd(), "/execute/new_db.rds")) - dir.create(file.path(readRDS(paste0(getwd(), "/execute/new_db.rds")), "Database"), recursive = TRUE) - } - - DB$load_selected <- TRUE - - # Check if .downloaded_schemes folder exists and if not create it - if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { - dir.create(file.path(DB$database, ".downloaded_schemes"), recursive = TRUE) - } - - # Check if remains of old temporary folder exists and remove them - if (dir.exists(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")))) { - unlink(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")), recursive = TRUE) - } - - # Download Loci Fasta Files - options(timeout = 600) - - tryCatch({ - download.file(Scheme$link_cgmlst, - file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip"))) - "Download successful!" - }, error = function(e) { - paste("Error: ", e$message) - }) - - # Unzip the scheme in temporary folder - unzip( - zipfile = file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")), - exdir = file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp") - ) - ) - - log_print("Hashing downloaded database") - # Hash temporary folder - hash_database(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"))) - - # Get list from local database - local_db_filelist <- list.files(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"))) - if (!is_empty(local_db_filelist)) { - # Get list from temporary database - tmp_db_filelist <- list.files(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"))) - - # Find the difference (extra files in local database) - local_db_extra <- setdiff(local_db_filelist, tmp_db_filelist) - - # Copy extra files to temporary folder - file.copy(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), local_db_extra), - file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"))) - - # Check differences in file pairs - local_db_hashes <- tools::md5sum(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), - local_db_filelist)) - tmp_db_hashes <- tools::md5sum(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"), - local_db_filelist)) - - diff_files <- local_db_hashes %in% tmp_db_hashes - diff_loci <- names(local_db_hashes)[diff_files == FALSE] - diff_loci <- sapply(strsplit(diff_loci, "/"), function(x) x[length(x)]) - - # Check locus hashes - for (locus in diff_loci) { - local_db_hashes <- get_locus_hashes(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), - locus)) - tmp_db_hashes <- get_locus_hashes(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"), - locus)) - diff_hashes <- setdiff(local_db_hashes, tmp_db_hashes) - - sequences <- extract_seq(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), - locus), diff_hashes) - if (!is_empty(sequences$idx) && !is_empty(sequences$seq) && - length(sequences$idx) == length(sequences$seq)) { - add_new_sequences(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"), - locus), sequences) - } - } - } - - unlink(file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) - - file.rename(file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp")), - file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"))) - - # Download Scheme Info - download( - Scheme$link_scheme, - dest = file.path(DB$database, Scheme$folder_name, "scheme_info.html"), - mode = "wb" - ) - - # Download Loci Info - download( - Scheme$link_targets, - dest = file.path(DB$database, Scheme$folder_name, "targets.csv"), - mode = "wb" - ) - - # Send downloaded scheme to database browser overview - DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) - - Scheme$target_table <- read.csv( - file.path(DB$database, Scheme$folder_name, "targets.csv"), - header = TRUE, - sep = "\t", - row.names = NULL, - colClasses = c( - "NULL", - "character", - "character", - "integer", - "integer", - "character", - "integer", - "NULL" - ) - ) - - DB$exist <- length(dir_ls(DB$database)) == 0 - - shinyjs::show("download_cgMLST") - shinyjs::hide("loading") - - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    ready")), - style = "color:white;") - ) - ) - ) - - show_toast( - title = "Download successful", - type = "success", - position = "bottom-end", - timer = 5000 - ) - - log_print("Download successful") - - showModal( - modalDialog( - selectInput( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {input$select_cgmlst} else {DB$available[1]}}), - title = "Select a local database to load.", - footer = tagList( - actionButton("load", "Load", class = "btn btn-default") - ) - ) - ) - }) - - # Download Target Info (CSV Table) - observe({ - input$download_cgMLST - - scheme_overview <- read_html(Scheme$link_scheme) %>% - html_table(header = FALSE) %>% - as.data.frame(stringsAsFactors = FALSE) - - last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], - format = "%B %d, %Y, %H:%M %p") - names(scheme_overview) <- NULL - - last_file_change <- format( - file.info(file.path(DB$database, - ".downloaded_schemes", - paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") - - output$cgmlst_scheme <- renderTable({scheme_overview}) - output$scheme_update_info <- renderText({ - req(last_file_change) - if (last_file_change < last_scheme_change) { - "(Newer scheme available \u274c)" - } else { - "(Scheme is up-to-date \u2705)" - } - }) - }) - - # _______________________ #### - - ## Visualization ---- - - # Render placeholder image - - output$placeholder <- renderImage({ - # Path to your PNG image with a transparent background - image_path <- paste0(getwd(), "/www/PhyloTrace.png") - - # Use HTML to display the image with the tag - list(src = image_path, - height = 180) - }, deleteFile = FALSE) - - # Render tree plot fields - - output$nj_field <- renderUI( - fluidRow( - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br() - ) - ) - - output$mst_field <- renderUI( - fluidRow( - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br() - ) - ) - - output$upgma_field <- renderUI( - fluidRow( - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br() - ) - ) - - ### Render Visualization Controls ---- - - #### NJ and UPGMA controls ---- - - # Control enable/disable of variable mapping inputs - observe({ - shinyjs::toggleState(id = "nj_color_mapping", condition = isTRUE(input$nj_mapping_show)) - shinyjs::toggleState(id = "nj_tiplab_scale", condition = isTRUE(input$nj_mapping_show)) - shinyjs::toggleState(id = "upgma_color_mapping", condition = isTRUE(input$upgma_mapping_show)) - shinyjs::toggleState(id = "upgma_tiplab_scale", condition = isTRUE(input$upgma_mapping_show)) - - shinyjs::toggleState(id = "nj_tipcolor_mapping", condition = isTRUE(input$nj_tipcolor_mapping_show)) - shinyjs::toggleState(id = "nj_tippoint_scale", condition = isTRUE(input$nj_tipcolor_mapping_show)) - shinyjs::toggleState(id = "upgma_tipcolor_mapping", condition = isTRUE(input$upgma_tipcolor_mapping_show)) - shinyjs::toggleState(id = "upgma_tippoint_scale", condition = isTRUE(input$upgma_tipcolor_mapping_show)) - - shinyjs::toggleState(id = "nj_tipshape_mapping", condition = isTRUE(input$nj_tipshape_mapping_show)) - shinyjs::toggleState(id = "upgma_tipshape_mapping", condition = isTRUE(input$upgma_tipshape_mapping_show)) - - shinyjs::toggleState(id = "nj_fruit_variable", condition = isTRUE(input$nj_tiles_show_1)) - shinyjs::toggleState(id = "upgma_fruit_variable", condition = isTRUE(input$upgma_tiles_show_1)) - shinyjs::toggleState(id = "nj_fruit_variable_2", condition = isTRUE(input$nj_tiles_show_2)) - shinyjs::toggleState(id = "upgma_fruit_variable_2", condition = isTRUE(input$upgma_tiles_show_2)) - shinyjs::toggleState(id = "nj_fruit_variable_3", condition = isTRUE(input$nj_tiles_show_3)) - shinyjs::toggleState(id = "upgma_fruit_variable_3", condition = isTRUE(input$upgma_tiles_show_3)) - shinyjs::toggleState(id = "nj_fruit_variable_4", condition = isTRUE(input$nj_tiles_show_4)) - shinyjs::toggleState(id = "upgma_fruit_variable_4", condition = isTRUE(input$upgma_tiles_show_4)) - shinyjs::toggleState(id = "nj_fruit_variable_5", condition = isTRUE(input$nj_tiles_show_5)) - shinyjs::toggleState(id = "upgma_fruit_variable_5", condition = isTRUE(input$upgma_tiles_show_5)) - shinyjs::toggleState(id = "nj_tiles_scale_1", condition = isTRUE(input$nj_tiles_show_1)) - shinyjs::toggleState(id = "upgma_tiles_scale_1", condition = isTRUE(input$upgma_tiles_show_1)) - shinyjs::toggleState(id = "nj_tiles_scale_2", condition = isTRUE(input$nj_tiles_show_2)) - shinyjs::toggleState(id = "upgma_tiles_scale_2", condition = isTRUE(input$upgma_tiles_show_2)) - shinyjs::toggleState(id = "nj_tiles_scale_3", condition = isTRUE(input$nj_tiles_show_3)) - shinyjs::toggleState(id = "upgma_tiles_scale_3", condition = isTRUE(input$upgma_tiles_show_3)) - shinyjs::toggleState(id = "nj_tiles_scale_4", condition = isTRUE(input$nj_tiles_show_4)) - shinyjs::toggleState(id = "upgma_tiles_scale_4", condition = isTRUE(input$upgma_tiles_show_4)) - shinyjs::toggleState(id = "nj_tiles_scale_5", condition = isTRUE(input$nj_tiles_show_5)) - shinyjs::toggleState(id = "upgma_tiles_scale_5", condition = isTRUE(input$upgma_tiles_show_5)) - - shinyjs::toggleState(id = "nj_heatmap_sel", condition = isTRUE(input$nj_heatmap_show)) - shinyjs::toggleState(id = "nj_heatmap_scale", condition = isTRUE(input$nj_heatmap_show)) - shinyjs::toggleState(id = "upgma_heatmap_sel", condition = isTRUE(input$upgma_heatmap_show)) - shinyjs::toggleState(id = "upgma_heatmap_scale", condition = isTRUE(input$upgma_heatmap_show)) - }) - - # Size scaling NJ - observe({ - req(input$nj_ratio) - if(input$nj_ratio == "1.6") { - updateSliderInput(session, "nj_scale", - step = 5, value = 800, min = 500, max = 1200) - } else if(input$nj_ratio == "1.77777777777778") { - updateSliderInput(session, "nj_scale", - step = 9, value = 801, min = 504, max = 1197) - } else if(input$nj_ratio == "1.33333333333333"){ - updateSliderInput(session, "nj_scale", - step = 3, value = 801, min = 501, max = 1200) - } - }) - - # Size scaling UPGMA - observe({ - req(input$upgma_ratio) - if(input$upgma_ratio == "1.6") { - updateSliderInput(session, "upgma_scale", - step = 5, value = 800, min = 500, max = 1200) - } else if(input$upgma_ratio == "1.77777777777778") { - updateSliderInput(session, "upgma_scale", - step = 9, value = 801, min = 504, max = 1197) - } else if(input$upgma_ratio == "1.33333333333333"){ - updateSliderInput(session, "upgma_scale", - step = 3, value = 801, min = 501, max = 1200) - } - }) - - # Size scaling MST - observe({ - req(input$mst_ratio) - if(input$mst_ratio == "1.6") { - updateSliderInput(session, "mst_scale", - step = 5, value = 800, min = 500, max = 1200) - } else if(input$mst_ratio == "1.77777777777778") { - updateSliderInput(session, "mst_scale", - step = 9, value = 801, min = 504, max = 1197) - } else if(input$mst_ratio == "1.33333333333333"){ - updateSliderInput(session, "mst_scale", - step = 3, value = 801, min = 501, max = 1200) - } - }) - - # Custom Labels - - # Add custom label - observeEvent(input$nj_add_new_label, { - - if(nchar(input$nj_new_label_name) > 0) { - if(!(input$nj_new_label_name %in% Vis$custom_label_nj)) { - Vis$custom_label_nj <- rbind(Vis$custom_label_nj, input$nj_new_label_name) - if(!(nrow(Vis$custom_label_nj) == 1)) { - updateSelectInput(session, "nj_custom_label_sel", selected = input$nj_new_label_name) - } - } else { - show_toast( - title = "Label already exists", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } else { - show_toast( - title = "Min. 1 character", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - - observeEvent(input$upgma_add_new_label, { - - if(nchar(input$upgma_new_label_name) > 0) { - if(!(input$upgma_new_label_name %in% Vis$custom_label_upgma)) { - Vis$custom_label_upgma <- rbind(Vis$custom_label_upgma, input$upgma_new_label_name) - if(!(nrow(Vis$custom_label_upgma) == 1)) { - updateSelectInput(session, "upgma_custom_label_sel", selected = input$upgma_new_label_name) - } - } else { - show_toast( - title = "Label already exists", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } else { - show_toast( - title = "Min. 1 character", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - - # Delete custom label - observeEvent(input$nj_del_label, { - - if(nrow(Vis$custom_label_nj) > 1) { - Vis$custom_label_nj <- Vis$custom_label_nj[-which(Vis$custom_label_nj[,1] == input$nj_custom_label_sel), , drop = FALSE] - } else if (nrow(Vis$custom_label_nj) == 1) { - Vis$nj_label_pos_x <- list() - Vis$nj_label_pos_y <- list() - Vis$nj_label_size <- list() - Vis$custom_label_nj <- data.frame() - } - }) - - observeEvent(input$upgma_del_label, { - - if(nrow(Vis$custom_label_upgma) > 1) { - Vis$custom_label_upgma <- Vis$custom_label_upgma[-which(Vis$custom_label_upgma[,1] == input$upgma_custom_label_sel), , drop = FALSE] - } else if (nrow(Vis$custom_label_upgma) == 1) { - Vis$upgma_label_pos_x <- list() - Vis$upgma_label_pos_y <- list() - Vis$upgma_label_size <- list() - Vis$custom_label_upgma <- data.frame() - } - }) - - # Select custom labels - output$nj_custom_label_select <- renderUI({ - if(nrow(Vis$custom_label_nj) > 0) { - selectInput( - "nj_custom_label_sel", - "", - choices = Vis$custom_label_nj[,1] - ) - } - }) - - output$upgma_custom_label_select <- renderUI({ - if(nrow(Vis$custom_label_upgma) > 0) { - selectInput( - "upgma_custom_label_sel", - "", - choices = Vis$custom_label_upgma[,1] - ) - } - }) - - # Select custom labels - output$nj_cust_label_save <- renderUI({ - if(nrow(Vis$custom_label_nj) > 0) { - actionButton( - "nj_cust_label_save", - "Apply" - ) - } else { - column( - width = 12, - br(), br(), br(), br(), br(), br(), - h5("test", style = "color: transparent; margin-bottom: 3px") - ) - } - }) - - output$upgma_cust_label_save <- renderUI({ - if(nrow(Vis$custom_label_upgma) > 0) { - actionButton( - "upgma_cust_label_save", - "Apply" - ) - } else { - column( - width = 12, - br(), br(), br(), br(), br(), br(), - h5("test", style = "color: transparent; margin-bottom: 3px") - ) - } - }) - - # Custom Label Size - output$nj_custom_labelsize <- renderUI({ - if(length(Vis$custom_label_nj) > 0) { - if(!is.null(Vis$nj_label_size[[input$nj_custom_label_sel]])) { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, - value = Vis$nj_label_size[[input$nj_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, value = 5, - width = "150px") - } - } - }) - - output$upgma_custom_labelsize <- renderUI({ - if(length(Vis$custom_label_upgma) > 0) { - if(!is.null(Vis$upgma_label_size[[input$upgma_custom_label_sel]])) { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, - value = Vis$upgma_label_size[[input$upgma_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, value = 5, - width = "150px") - } - } - }) - - # Render slider input based on selected label - output$nj_sliderInput_y <- renderUI({ - if(length(Vis$custom_label_nj) > 0) { - if(!is.null(Vis$nj_label_pos_y[[input$nj_custom_label_sel]])) { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$nj_label_pos_y[[input$nj_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = sum(DB$data$Include), step = 1, ticks = F, - value = sum(DB$data$Include) / 2, - width = "150px") - } - } - }) - - output$upgma_sliderInput_y <- renderUI({ - if(length(Vis$custom_label_upgma) > 0) { - if(!is.null(Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]])) { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = sum(DB$data$Include), step = 1, ticks = F, - value = sum(DB$data$Include) / 2, - width = "150px") - } - } - }) - - output$nj_sliderInput_x <- renderUI({ - if(length(Vis$custom_label_nj) > 0) { - if(!is.null(Vis$nj_label_pos_x[[input$nj_custom_label_sel]])) { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$nj_label_pos_x[[input$nj_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = round(Vis$nj_max_x, 0), step = 1, ticks = F, - value = round(Vis$nj_max_x / 2, 0), - width = "150px") - } - } - }) - - output$upgma_sliderInput_x <- renderUI({ - if(length(Vis$custom_label_upgma) > 0) { - if(!is.null(Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]])) { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = round(Vis$upgma_max_x, 0), step = 1, ticks = F, - value = round(Vis$upgma_max_x / 2, 0), - width = "150px") - } - } - }) - - # Apply custom label changes - observeEvent(input$nj_cust_label_save, { - - if(!is.null(Vis$nj_label_pos_y) & - !is.null(Vis$nj_label_pos_x) & - !is.null(Vis$nj_label_size) & - !is.null(input$nj_custom_label_sel)) { - Vis$nj_label_pos_y[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_y")]] - Vis$nj_label_pos_x[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_x")]] - Vis$nj_label_size[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_size")]] - } - }) - - observeEvent(input$upgma_cust_label_save, { - - if(!is.null(Vis$upgma_label_pos_y) & - !is.null(Vis$upgma_label_pos_x) & - !is.null(Vis$upgma_label_size) & - !is.null(input$upgma_custom_label_sel)) { - Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_y")]] - Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_x")]] - Vis$upgma_label_size[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_size")]] - } - }) - - # Show delete custom label button if custam label added - output$nj_del_label <- renderUI({ - if(nrow(Vis$custom_label_nj) > 0) { - actionButton( - "nj_del_label", - "", - icon = icon("minus") - ) - } else {NULL} - }) - - output$upgma_del_label <- renderUI({ - if(nrow(Vis$custom_label_upgma) > 0) { - actionButton( - "upgma_del_label", - "", - icon = icon("minus") - ) - } else {NULL} - }) - - # Mapping value number information - output$nj_tiplab_mapping_info <- renderUI({ - if(!is.null(input$nj_color_mapping) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_color_mapping]))) { - if(input$nj_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_color_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$upgma_tiplab_mapping_info <- renderUI({ - if(!is.null(input$upgma_color_mapping) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) { - if(input$upgma_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_color_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$nj_tipcolor_mapping_info <- renderUI({ - if(!is.null(input$nj_tipcolor_mapping) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) { - if(input$nj_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tipcolor_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$upgma_tipcolor_mapping_info <- renderUI({ - if(!is.null(input$upgma_tipcolor_mapping) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) { - if(input$upgma_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tipcolor_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$nj_tipshape_mapping_info <- renderUI({ - if(!is.null(input$nj_tipshape_mapping) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) { - column( - width = 3, - h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) > 6) { - column( - width = 3, - h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$upgma_tipshape_mapping_info <- renderUI({ - if(!is.null(input$upgma_tipshape_mapping) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) { - column( - width = 3, - h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) > 6) { - column( - width = 3, - h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$nj_fruit_mapping_info <- renderUI({ - if(input$nj_tile_num == 1) { - if(!is.null(input$nj_fruit_variable) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable]))) { - if(input$nj_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_1", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 2) { - if(!is.null(input$nj_fruit_variable_2) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) { - if(input$nj_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_2", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 3) { - if(!is.null(input$nj_fruit_variable_3) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) { - if(input$nj_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_3", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 4) { - if(!is.null(input$nj_fruit_variable_4) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) { - if(input$nj_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_4", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 5) { - if(!is.null(input$nj_fruit_variable_5) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) { - if(input$nj_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_5", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } - }) - - output$upgma_fruit_mapping_info <- renderUI({ - if(input$upgma_tile_num == 1) { - if(!is.null(input$upgma_fruit_variable) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) { - if(input$upgma_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_1", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 2) { - if(!is.null(input$upgma_fruit_variable_2) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) { - if(input$upgma_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_2", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 3) { - if(!is.null(input$upgma_fruit_variable_3) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) { - if(input$upgma_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_3", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 4) { - if(!is.null(input$upgma_fruit_variable_4) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) { - if(input$upgma_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_4", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 5) { - if(!is.null(input$upgma_fruit_variable_5) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) { - if(input$upgma_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_5", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } - }) - - output$nj_heatmap_mapping_info <- renderUI({ - if(!is.null(input$nj_heatmap_select) & (!is.null(Vis$meta_nj))) { - if (any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { - column( - width = 3, - h5("Heatmap with categorical and continous values not possible", - style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") - ) - } else { - if(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { - if(input$nj_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_heatmap_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { - column( - width = 3, - h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } - } else {NULL} - }) - - output$upgma_heatmap_mapping_info <- renderUI({ - if(!is.null(input$upgma_heatmap_select) & (!is.null(Vis$meta_upgma))) { - if (any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { - column( - width = 3, - h5("Heatmap with categorical and continous values not possible", - style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") - ) - } else { - if(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { - if(input$upgma_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_heatmap_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { - column( - width = 3, - h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } - } else {NULL} - }) - - # Tiles offset - output$nj_fruit_offset_circ <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ", - label = "", - min = min, - max = max, - step= step, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.1 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.05 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ", - label = "", - min = min, - max = max, - step= step, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ", - label = "", - min = -0.2, - max = 0.2, - step= 0.05, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_2 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_2", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_2", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_2 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_2", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_2", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_3 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_3", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_3", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_3 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_3", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_3", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_4 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_4", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_4", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_4 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_4", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_4", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_5 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_5", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_5", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_5 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_5", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_5", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - # For Layout change update tiles offset position - observeEvent(input$nj_layout, { - - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } else { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } - - updateSliderInput(session, "nj_fruit_offset_circ", min = min, step = step, max = max) - updateSliderInput(session, "nj_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "nj_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "nj_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "nj_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) - }) - - observeEvent(input$upgma_layout, { - - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } else { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } - - updateSliderInput(session, "upgma_fruit_offset_circ", min = min, step = step, max = max) - updateSliderInput(session, "upgma_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "upgma_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "upgma_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "upgma_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) - }) - - # Heatmap width - output$nj_heatmap_width <- renderUI({ - if(!is.null(input$nj_heatmap_select)) { - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - - sliderInput( - "nj_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = width, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = 0.1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_heatmap_width <- renderUI({ - if(!is.null(input$upgma_heatmap_select)) { - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - - sliderInput( - "upgma_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = width, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = 0.1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - }) - - # Update value if new variables added - observeEvent(input$nj_heatmap_select, { - - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "nj_heatmap_width", value = width) - }) - - observeEvent(input$upgma_heatmap_select, { - - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "upgma_heatmap_width", value = width) - }) - - # Update value if layout changed - observeEvent(input$nj_layout, { - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "nj_heatmap_width", value = width) - }) - - observeEvent(input$upgma_layout, { - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "upgma_heatmap_width", value = width) - }) - - # Heatmap column titles position - observeEvent(input$nj_layout, { - if(!(input$nj_layout == "inward" | input$nj_layout == "circular")) { - updateSliderInput(session, "nj_colnames_y", value = -1) - } else { - updateSliderInput(session, "nj_colnames_y", value = 0) - } - }) - - observeEvent(input$upgma_layout, { - if(!(input$upgma_layout == "inward" | input$upgma_layout == "circular")) { - updateSliderInput(session, "upgma_colnames_y", value = -1) - } else { - updateSliderInput(session, "upgma_colnames_y", value = 0) - } - }) - - output$nj_colnames_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - if(input$nj_layout == "inward" | input$nj_layout == "circular") { - min <- 0 - val <- 0 - } else { - val <- -1 - if((sum(DB$data$Include) * -0.1) > -2) { - min <- -2 - } else { - min <- round(sum(DB$data$Include) * -0.1, 0) - } - } - sliderInput( - "nj_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = min, - max = sum(DB$data$Include), - value = val, - step = 1, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = -10, - max = 10, - value = 0, - step = 1, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_colnames_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { - min <- 0 - val <- 0 - } else { - val <- -1 - if((sum(DB$data$Include) * -0.1) > -2) { - min <- -2 - } else { - min <- round(sum(DB$data$Include) * -0.1, 0) - } - } - sliderInput( - "upgma_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = min, - max = sum(DB$data$Include), - value = val, - step = 1, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = -10, - max = 10, - value = 0, - step = 1, - width = "150px", - ticks = FALSE - ) - } - }) - - # Heatmap column titles angle - output$nj_colnames_angle <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - angle <- 90 - } else {angle <- -90} - sliderInput( - "nj_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = angle, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_colnames_angle <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - angle <- 90 - } else {angle <- -90} - sliderInput( - "upgma_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = angle, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - # Change heatmap column titles angle and label align when switching layout - observeEvent(input$nj_layout, { - if(input$nj_layout == "circular" | input$nj_layout == "inward"){ - angle <- 90 - val <- TRUE - } else { - angle <- -90 - val <- FALSE - } - updateSwitchInput(session, "nj_align", value = val) - updateSliderInput(session, "nj_colnames_angle", value = angle) - }) - - observeEvent(input$upgma_layout, { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward"){ - angle <- 90 - val <- TRUE - } else { - angle <- -90 - val <- FALSE - } - updateSwitchInput(session, "upgma_align", value = val) - updateSliderInput(session, "upgma_colnames_angle", value = angle) - }) - - # Tile number selector update each other - observeEvent(input$nj_tile_num, { - updateSelectInput(session, "nj_tile_number", selected = input$nj_tile_num) - }) - - observeEvent(input$nj_tile_number, { - updateSelectInput(session, "nj_tile_num", selected = input$nj_tile_number) - }) - - observeEvent(input$upgma_tile_num, { - updateSelectInput(session, "upgma_tile_number", selected = input$upgma_tile_num) - }) - - observeEvent(input$upgma_tile_number, { - updateSelectInput(session, "upgma_tile_num", selected = input$upgma_tile_number) - }) - - # Clade coloring - output$nj_clade_scale <- renderUI({ - if(length(input$nj_parentnode) <= 1) { - fluidRow( - column( - width = 5, - h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "nj_clade_scale", - selected = "#D0F221", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ) - ) - } else { - fluidRow( - column( - width = 5, - h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - div( - class = "sel-clade-scale", - selectInput( - "nj_clade_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - ) - ) - } - }) - - output$upgma_clade_scale <- renderUI({ - if(length(input$upgma_parentnode) <= 1) { - fluidRow( - column( - width = 5, - h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "upgma_clade_scale", - selected = "#D0F221", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ) - ) - } else { - fluidRow( - column( - width = 5, - h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - div( - class = "sel-clade-scale", - selectInput( - "upgma_clade_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - ) - ) - } - }) - - # Heatmap variable color scale - output$nj_heatmap_scale <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_heatmap_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_heatmap_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_heatmap_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Paired" - ) - ) - } - } - }) - - output$upgma_heatmap_scale <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_heatmap_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_heatmap_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_heatmap_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Paired" - ) - ) - } - } - }) - - # Tiles variable color scale - output$nj_tiles_scale_1 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_1", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_1", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_1", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_1 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_1", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_1", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_1", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_2 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_2", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_2", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_2", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_2 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_2", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_2", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_2", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_3 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_3", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_3", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_3", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_3 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_3", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_3", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_3", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_4 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_4])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_4", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { - shinyjs::disabled(selectInput( - "nj_tiles_scale_4", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - )) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_4", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_4 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_4", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_4", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_4", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_5 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_5", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_5", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_5", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_5 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_5", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_5", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_5", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - # Tip Labels Variable Color Scale - output$nj_tiplab_scale <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiplab_scale", - "", - selectize = FALSE, - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiplab_scale", - "", - selectize = FALSE, - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiplab_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - } - } - }) - - output$upgma_tiplab_scale <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiplab_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiplab_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiplab_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - } - } - }) - - # Tippoint Scale - output$nj_tippoint_scale <- renderUI({ - if(!is.null(Vis$meta_nj)) { - if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - } - } else { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - }) - - output$upgma_tippoint_scale <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ), - selected = c("Viridis" = "viridis") - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - } - } else { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - }) - - # Clade Highlights - output$nj_parentnode <- renderUI({ - if(!is.null(Vis$nj_parentnodes)) { - pickerInput( - "nj_parentnode", - label = "", - choices = sort(unique(as.numeric(Vis$nj_parentnodes))), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } else { - pickerInput( - "nj_parentnode", - label = "", - choices = c(), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } - }) - - output$upgma_parentnode <- renderUI({ - if(!is.null(Vis$upgma_parentnodes)) { - pickerInput( - "upgma_parentnode", - label = "", - choices = sort(unique(as.numeric(Vis$upgma_parentnodes))), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } else { - pickerInput( - "upgma_parentnode", - label = "", - choices = c(), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } - }) - - # Branch label size - output$nj_branch_size <- renderUI( - numericInput( - "nj_branch_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 2, - max = 10, - step = 0.5, - value = Vis$branch_size_nj, - width = "80px" - ) - ) - - output$upgma_branch_size <- renderUI( - numericInput( - "upgma_branch_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 2, - max = 10, - step = 0.5, - value = Vis$branch_size_upgma, - width = "80px" - ) - ) - - # Tippanel size - output$nj_tiplab_padding <- renderUI( - if(!is.null(Vis$tiplab_padding_nj)) { - sliderInput( - inputId = "nj_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = Vis$tiplab_padding_nj, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "nj_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = 0.2, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - ) - - output$upgma_tiplab_padding <- renderUI( - if(!is.null(Vis$tiplab_padding_upgma)) { - sliderInput( - inputId = "upgma_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = Vis$tiplab_padding_upgma, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "upgma_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = 0.2, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - ) - - # Nodepoint size - output$nj_nodepoint_size <- renderUI( - if(!is.null(Vis$nodepointsize_nj)) { - sliderInput( - inputId = "nj_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = Vis$nodepointsize_nj, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "nj_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = 2.5, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } - ) - - output$upgma_nodepoint_size <- renderUI( - if(!is.null(Vis$nodepointsize_upgma)) { - sliderInput( - inputId = "upgma_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = Vis$nodepointsize_upgma, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "upgma_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = 2.5, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } - ) - - # Tippoint size - output$nj_tippoint_size <- renderUI( - if(!is.null(Vis$tippointsize_nj)) { - sliderInput( - inputId = "nj_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = Vis$tippointsize_nj, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "nj_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = 4, - width = "150px", - ticks = FALSE - ) - } - ) - - output$upgma_tippoint_size <- renderUI( - if(!is.null(Vis$tippointsize_upgma)) { - sliderInput( - inputId = "upgma_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = Vis$tippointsize_upgma, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "upgma_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = 4, - width = "150px", - ticks = FALSE - ) - } - ) - - # Tiplabel size - output$nj_tiplab_size <- renderUI( - if(!is.null(Vis$labelsize_nj)) { - numericInput( - "nj_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = Vis$labelsize_nj, - width = "80px" - ) - } else { - numericInput( - "nj_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = 4, - width = "80px" - ) - } - ) - - output$upgma_tiplab_size <- renderUI( - if(!is.null(Vis$labelsize_upgma)) { - numericInput( - "upgma_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = Vis$labelsize_upgma, - width = "80px" - ) - } else { - numericInput( - "upgma_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = 4, - width = "80px" - ) - } - ) - - # Rootedge length - output$nj_rootedge_length <- renderUI({ - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.02, 0) < 1) { - min <- 1 - } else { - min <- round(ceiling(Vis$nj_max_x) * 0.02, 0) - } - max <- round(ceiling(Vis$nj_max_x) * 0.2, 0) - sliderInput( - "nj_rootedge_length", - label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), - min = min, - max = max, - value = round(ceiling(Vis$nj_max_x) * 0.05, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_rootedge_length", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_rootedge_length <- renderUI({ - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.02, 0) < 1) { - min <- 1 - } else { - min <- round(ceiling(Vis$upgma_max_x) * 0.02, 0) - } - max <- round(ceiling(Vis$upgma_max_x) * 0.2, 0) - sliderInput( - "upgma_rootedge_length", - label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), - min = min, - max = max, - value = round(ceiling(Vis$upgma_max_x) * 0.05, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_rootedge_length", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - # Treescale - output$nj_treescale_width <- renderUI({ - if(!is.null(Vis$nj_max_x)) { - numericInput( - "nj_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = round(ceiling(Vis$nj_max_x) * 0.1, 0), - min = 1, - max = round(floor(Vis$nj_max_x) * 0.5, 0), - step = 1, - width = "80px" - ) - } else { - numericInput( - "nj_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = 2, - min = 1, - max = 10, - step = 1, - width = "80px" - ) - } - }) - - output$upgma_treescale_width <- renderUI({ - if(!is.null(Vis$upgma_max_x)) { - numericInput( - "upgma_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = round(ceiling(Vis$upgma_max_x) * 0.1, 0), - min = 1, - max = round(floor(Vis$upgma_max_x) * 0.5, 0), - step = 1, - width = "80px" - ) - } else { - numericInput( - "upgma_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = 2, - min = 1, - max = 10, - step = 1, - width = "80px" - ) - } - }) - - output$nj_treescale_x <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(ceiling(Vis$nj_min_x) < 1) { - floor <- 1 - } else { - floor <- ceiling(Vis$nj_min_x) - } - sliderInput( - "nj_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = floor, - max = round(floor(Vis$nj_max_x)), - value = round(ceiling(Vis$nj_max_x) * 0.2, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_treescale_x <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(ceiling(Vis$upgma_min_x) < 1) { - floor <- 1 - } else { - floor <- ceiling(Vis$upgma_min_x) - } - sliderInput( - "upgma_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = floor, - max = round(floor(Vis$upgma_max_x)), - value = round(ceiling(Vis$upgma_max_x) * 0.2, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_treescale_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - sliderInput( - "nj_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = sum(DB$data$Include), - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 10, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_treescale_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - sliderInput( - "upgma_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = sum(DB$data$Include), - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 10, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - ### Heatmap - # Heatmap picker - output$nj_heatmap_sel <- renderUI({ - if(!is.null(Vis$meta_nj)) { - meta <- select(Vis$meta_nj, -c(taxa, Index, `Assembly ID`, `Assembly Name`, - Scheme, `Typing Date`, Successes, Errors)) - - # Identify numeric columns - numeric_columns <- sapply(meta, is.numeric) - - numeric_column_names <- names(meta[numeric_columns]) - - non_numeric_column_names <- names(meta)[!numeric_columns] - - choices <- list() - - # Add Continuous list only if there are numeric columns - if (length(numeric_column_names) > 0) { - choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) - } - - # Add Diverging list - choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) - - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "nj_heatmap_select", - label = "", - width = "100%", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else {choices}, - options = list( - `dropdown-align-center` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - ) - } else { - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "nj_heatmap_select", - label = "", - width = "100%", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - multiple = TRUE - ) - ) - ) - } - }) - - output$upgma_heatmap_sel <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - meta <- select(Vis$meta_upgma, -c(taxa, Index, `Assembly ID`, `Assembly Name`, - Scheme, `Typing Date`, Successes, Errors)) - - # Identify numeric columns - numeric_columns <- sapply(meta, is.numeric) - - numeric_column_names <- names(meta[numeric_columns]) - - non_numeric_column_names <- names(meta)[!numeric_columns] - - choices <- list() - - # Add Continuous list only if there are numeric columns - if (length(numeric_column_names) > 0) { - choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) - } - - # Add Diverging list - choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) - - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "upgma_heatmap_select", - label = "", - width = "100%", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else {choices}, - options = list( - `dropdown-align-center` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - ) - } else { - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "upgma_heatmap_select", - label = "", - width = "100%", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - multiple = TRUE - ) - ) - ) - } - }) - - # Heatmap offset - output$nj_heatmap_offset <- renderUI({ - if(!is.null(Vis$nj_max_x)) { - sliderInput( - "nj_heatmap_offset", - label = "", - min = 0, - max = round(ceiling(Vis$nj_max_x)*1.5, 0), - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_heatmap_offset", - label = "", - min = 0, - max = 10, - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_heatmap_offset <- renderUI({ - if(!is.null(Vis$upgma_max_x)) { - sliderInput( - "upgma_heatmap_offset", - label = "", - min = 0, - max = round(ceiling(Vis$upgma_max_x)*1.5, 0), - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_heatmap_offset", - label = "", - min = 0, - max = 10, - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - ### Tiling - # Geom Fruit select Variable - output$nj_fruit_variable <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable2 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_2", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_2", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable3 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_3", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_3", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable4 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_4", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_4", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable5 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_5", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_5", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable2 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_2", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_2", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable3 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled(selectInput( - "upgma_fruit_variable_3", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - )) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_3", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable4 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_4", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_4", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable5 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_5", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_5", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - # Geom Fruit Width - output$nj_fruit_width <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width2 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_2", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width3 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_3", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width4 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_4", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width5 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_5", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width2 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_2", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width3 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_3", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width4 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_4", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width5 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_5", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - # For Layout change update tiles - observeEvent(input$nj_layout, { - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } - - updateSliderInput(session, "nj_fruit_width_circ", value = width) - updateSliderInput(session, "nj_fruit_width_circ_2", value = width) - updateSliderInput(session, "nj_fruit_width_circ_3", value = width) - updateSliderInput(session, "nj_fruit_width_circ_4", value = width) - updateSliderInput(session, "nj_fruit_width_circ_5", value = width) - } - }) - - observeEvent(input$upgma_layout, { - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } - - updateSliderInput(session, "upgma_fruit_width_circ", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_2", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_3", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_4", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_5", value = width) - } - }) - - # Tip color mapping - output$nj_tipcolor_mapping <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_tipcolor_mapping", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(City = "City"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tipcolor_mapping", - "", - choices = c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(City = "City") - ) - ) - } - }) - - output$upgma_tipcolor_mapping <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_tipcolor_mapping", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(City = "City"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tipcolor_mapping", - "", - choices = c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(City = "City") - ) - ) - } - }) - - # Tip shape Mapping - output$nj_tipshape_mapping <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_tipshape_mapping", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tipshape_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } - }) - - output$upgma_tipshape_mapping <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_tipshape_mapping", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tipshape_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } - }) - - # Branch label - output$nj_branch_label <- renderUI({ - if(!is.null(Vis$meta_nj)) { - selectInput( - "nj_branch_label", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - } else { - selectInput( - "nj_branch_label", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - } - }) - - output$upgma_branch_label <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - selectInput( - "upgma_branch_label", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - } else { - selectInput( - "upgma_branch_label", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - } - }) - - # Color mapping - output$nj_color_mapping <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_color_mapping", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(Country = "Country"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_color_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(Country = "Country"), - width = "100%" - ) - ) - } - }) - - output$upgma_color_mapping <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_color_mapping", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(Country = "Country"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_color_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(Country = "Country"), - width = "100%" - ) - ) - } - }) - - # Tip labels - output$nj_tiplab <- renderUI({ - if(!is.null(Vis$meta_nj)) { - selectInput( - "nj_tiplab", - label = "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } else { - selectInput( - "nj_tiplab", - label = "", - choices = c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } - }) - - output$upgma_tiplab <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - selectInput( - "upgma_tiplab", - label = "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } else { - selectInput( - "upgma_tiplab", - label = "", - choices = c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } - }) - - #### MST controls ---- - - # Clustering UI - output$mst_cluster <- renderUI({ - req(DB$schemeinfo) - numericInput( - inputId = "mst_cluster_threshold", - label = NULL, - value = as.numeric(DB$schemeinfo[7, 2]), - min = 1, - max = 99 - ) - }) - - # MST color mapping - output$mst_color_mapping <- renderUI({ - if(input$mst_color_var == FALSE) { - fluidRow( - column( - width = 7, - div( - class = "node_color", - colorPickr( - inputId = "mst_color_node", - width = "100%", - selected = "#B2FACA", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_node_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - numericInput( - "node_opacity", - label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), - value = 1, - step = 0.1, - min = 0, - max = 1, - width = "80px" - ) - ) - ) - ) - } else { - fluidRow( - column( - width = 9, - div( - class = "mst_col_sel", - selectInput( - "mst_col_var", - label = "", - choices = if(any(DB$cust_var[DB$cust_var$Variable[which(DB$cust_var$Variable %in% c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]))],]$Type != "categ")) { - selection <- c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]) - cust_vars <- DB$cust_var$Variable[which(DB$cust_var$Variable %in% selection)] - selection[-which(selection == cust_vars[DB$cust_var[cust_vars,]$Type != "categ"])] - } else {c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)])}, - width = "100%" - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "mst_col_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - selectInput( - "mst_col_scale", - label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), - choices = c("Viridis", "Rainbow"), - width = "150px" - ), - br(), br(), br(), br() - ) - ) - ) - } - }) - - observeEvent(input$mst_color_var, { - - if(input$mst_color_var == TRUE) { - updateSelectizeInput(session, inputId = "mst_node_shape", choices = c("Pie Nodes" = "custom")) - updateSelectizeInput(session, inputId = "mst_node_label", choices = c("Assembly Name")) - } else { - updateSelectizeInput(session, inputId = "mst_node_shape", - choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), - `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), - selected = c("Dot" = "dot")) - updateSelectizeInput(session, inputId = "mst_node_label", - choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], - selected = "Assembly Name") - } - }) - - # MST node labels - output$mst_node_label <- renderUI({ - selectInput( - "mst_node_label", - label = "", - choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], - selected = "Assembly Name", - width = "100%" - ) - }) - - ### Plot Reactives ---- - - #### MST ---- - - mst_tree <- reactive({ - data <- toVisNetworkData(Vis$ggraph_1) - data$nodes <- mutate(data$nodes, - label = label_mst(), - value = mst_node_scaling(), - opacity = node_opacity()) - - ctxRendererJS <- htmlwidgets::JS("({ctx, id, x, y, state: { selected, hover }, style, font, label, metadata}) => { - var pieData = JSON.parse(metadata); - var radius = style.size; - var centerX = x; - var centerY = y; - var total = pieData.reduce((sum, slice) => sum + slice.value, 0) - var startAngle = 0; - - const drawNode = () => { - // Set shadow properties - if (style.shadow) { - var shadowSize = style.shadowSize; - ctx.shadowColor = style.shadowColor; - ctx.shadowBlur = style.shadowSize; - ctx.shadowOffsetX = style.shadowX; - ctx.shadowOffsetY = style.shadowY; - - ctx.beginPath(); - ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); - ctx.fill(); - - ctx.shadowColor = 'transparent'; - ctx.shadowBlur = 0; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - } - - pieData.forEach(slice => { - var sliceAngle = 2 * Math.PI * (slice.value / total); - ctx.beginPath(); - ctx.moveTo(centerX, centerY); - ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle); - ctx.closePath(); - ctx.fillStyle = slice.color; - ctx.fill(); - if (pieData.length > 1) { - ctx.strokeStyle = 'black'; - ctx.lineWidth = 1; - ctx.stroke(); - } - startAngle += sliceAngle; - }); - - // Draw a border - ctx.beginPath(); - ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); - ctx.strokeStyle = 'black'; - ctx.lineWidth = 1; - ctx.stroke(); - }; - drawLabel = () => { - //Draw the label - var lines = label.split(`\n`); - var lineHeight = font.size; - ctx.font = `${font.size}px ${font.face}`; - ctx.fillStyle = font.color; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - lines.forEach((line, index) => { - ctx.fillText(line, centerX, - centerY + radius + (index + 1) * lineHeight); - }) - } - - return { - drawNode, - drawExternalLabel: drawLabel, - nodeDimensions: { width: 2 * radius, height: 2 * radius }, - }; - }") - - Vis$var_cols <- NULL - - # Generate pie charts as nodes - if(input$mst_color_var == TRUE & (!is.null(input$mst_col_var))) { - - group <- character(nrow(data$nodes)) - for (i in 1:length(unique(Vis$meta_mst[[input$mst_col_var]]))) { - group[i] <- unique(Vis$meta_mst[[input$mst_col_var]])[i] - } - - data$nodes <- cbind(data$nodes, data.frame(metadata = character(nrow(data$nodes)))) - - if(length(which(data$nodes$group == "")) != 0) { - data$nodes$group[which(data$nodes$group == "")] <- data$nodes$group[1] - } - - if(is.null(input$mst_col_scale)) { - Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), - color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) - } else if (input$mst_col_scale == "Rainbow") { - Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), - color = rainbow(length(unique(Vis$meta_mst[[input$mst_col_var]])))) - } else if (input$mst_col_scale == "Viridis") { - Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), - color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) - } - - for(i in 1:nrow(data$nodes)) { - - iso_subset <- strsplit(data$nodes$label[i], split = "\n")[[1]] - variable <- Vis$meta_mst[[input$mst_col_var]] - values <- variable[which(Vis$meta_mst$`Assembly Name` %in% iso_subset)] - - for(j in 1:length(unique(values))) { - - share <- sum(unique(values)[j] == values) / length(values) * 100 - color <- Vis$var_cols$color[Vis$var_cols$value == unique(values)[j]] - - if(j == 1) { - pie_vec <- paste0('{"value":', share,',"color":"', color,'"}') - } else { - pie_vec <- paste0(pie_vec, ',{"value":', share,',"color":"', color,'"}') - } - } - - data$nodes$metadata[i] <- paste0('[', pie_vec, ']') - } - } - - data$edges <- mutate(data$edges, - length = if(input$mst_scale_edges == FALSE) { - input$mst_edge_length - } else { - data$edges$weight * input$mst_edge_length_scale - }, - label = as.character(data$edges$weight), - opacity = input$mst_edge_opacity) - - if (input$mst_show_clusters) { - data$nodes$group <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) - } - - visNetwork_graph <- visNetwork(data$nodes, data$edges, - main = mst_title(), - background = mst_background_color(), - submain = mst_subtitle()) %>% - visNodes(size = mst_node_size(), - shape = input$mst_node_shape, - shadow = input$mst_shadow, - color = mst_color_node(), - ctxRenderer = ctxRendererJS, - scaling = list(min = mst_node_size_min(), - max = mst_node_size_max()), - font = list(color = node_font_color(), - size = input$node_label_fontsize)) %>% - visEdges(color = mst_color_edge(), - font = list(color = mst_edge_font_color(), - size = mst_edge_font_size(), - strokeWidth = 4)) %>% - visOptions(collapse = TRUE) %>% - visInteraction(hover = TRUE) %>% - visLayout(randomSeed = 1) %>% - visLegend(useGroups = FALSE, - zoom = TRUE, - width = legend_width(), - position = input$mst_legend_ori, - ncol = legend_col(), - addNodes = mst_legend()) - - if (input$mst_show_clusters) { - if (input$mst_cluster_col_scale == "Viridis") { - color_palette <- viridis(length(unique(data$nodes$group))) - } else { - color_palette <- rainbow(length(unique(data$nodes$group))) - } - - for (i in 1:length(unique(data$nodes$group))) { - visNetwork_graph <- visNetwork_graph %>% - visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) - } - } - visNetwork_graph - }) - - # MST legend - legend_col <- reactive({ - if(!is.null(Vis$var_cols)) { - if(nrow(Vis$var_cols) > 10) { - 3 - } else if(nrow(Vis$var_cols) > 5) { - 2 - } else { - 1 - } - } else {1} - }) - - mst_legend <- reactive({ - if(is.null(Vis$var_cols)) { - NULL - } else { - legend <- Vis$var_cols - names(legend)[1] <- "label" - mutate(legend, shape = "dot", - font.color = input$mst_legend_color, - size = input$mst_symbol_size, - font.size = input$mst_font_size) - } - }) - - # Set MST legend width - legend_width <- reactive({ - 0.2 - }) - - # Set MST node shape - mst_node_shape <- reactive({ - if(input$mst_node_shape == "Pie Nodes"){ - "dot" - } else if(input$mst_node_shape %in% c("circle", "database", "box", "text")) { - shinyjs::disable('scale_nodes') - updateCheckboxInput(session, "scale_nodes", value = FALSE) - shinyjs::disable('mst_node_size') - shinyjs::disable('mst_node_scale') - input$mst_node_shape - } else { - shinyjs::enable('scale_nodes') - shinyjs::enable('mst_node_size') - shinyjs::enable('mst_node_scale') - input$mst_node_shape - } - }) - - # Set MST label - label_mst <- reactive({ - Vis$unique_meta[, colnames(Vis$unique_meta) %in% input$mst_node_label] - }) - - # Set node color - mst_color_node <- reactive({ - input$mst_color_node - }) - - # Node Label Color - node_font_color <- reactive({ - input$node_font_color - }) - - - # Node Size Scaling - mst_node_scaling <- reactive({ - if(input$scale_nodes == TRUE){ - Vis$unique_meta$size - } else {NULL} - }) - - # Node Size Min/May - mst_node_size_min <- reactive({ - input$mst_node_scale[1] - }) - - mst_node_size_max <- reactive({ - input$mst_node_scale[2] - }) - - # Node Size - mst_node_size <- reactive({ - input$mst_node_size - }) - - # Node Alpha/Opacity - node_opacity <- reactive({ - input$node_opacity - }) - - # Set Title - mst_title <- reactive({ - if(!is.null(input$mst_title)) { - if(nchar(input$mst_title) < 1) { - list(text = "title", - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_title_size), "px", - "; color: ", as.character(mst_background_color())) - ) - } else { - list(text = input$mst_title, - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_title_size), "px", - "; color: ", as.character(input$mst_title_color)) - ) - } - } else { - list(text = "title", - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_title_size), "px", - "; color: ", as.character(mst_background_color())) - ) - } - }) - - # Set Subtitle - mst_subtitle <- reactive({ - list(text = input$mst_subtitle, - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_subtitle_size), "px", - "; color: ", as.character(input$mst_subtitle_color)) - ) - }) - - # Background color - - mst_background_color <- reactive({ - if(input$mst_background_transparent == TRUE) { - 'rgba(0, 0, 0, 0)' - } else{ - input$mst_background_color - } - }) - - # Edge font color - mst_edge_font_color <- reactive({ - input$mst_edge_font_color - }) - - # Edge color - mst_color_edge <- reactive({ - input$mst_color_edge - }) - - # Edge font size - mst_edge_font_size <- reactive({ - input$mst_edge_font_size - }) - - #### NJ ---- - - nj_tree <- reactive({ - - # Convert negative edges - Vis$nj[["edge.length"]] <- abs(Vis$nj[["edge.length"]]) - - if(input$nj_nodelabel_show == TRUE) { - ggtree(Vis$nj, alpha = 0.2, layout = layout_nj()) + - geom_nodelab(aes(label = node), color = "#29303A", size = nj_tiplab_size() + 1, hjust = 0.7) + - nj_limit() + - nj_inward() - } else { - tree <- - ggtree(Vis$nj, - color = input$nj_color, - layout = layout_nj(), - ladderize = input$nj_ladder) %<+% Vis$meta_nj + - nj_clades() + - nj_tiplab() + - nj_tiplab_scale() + - new_scale_color() + - nj_limit() + - nj_inward() + - nj_label_branch() + - nj_treescale() + - nj_nodepoint() + - nj_tippoint() + - nj_tippoint_scale() + - new_scale_color() + - nj_clip_label() + - nj_rootedge() + - ggtitle(label = input$nj_title, - subtitle = input$nj_subtitle) + - theme_tree(bgcolor = input$nj_bg) + - theme(plot.title = element_text(colour = input$nj_title_color, - size = input$nj_title_size), - plot.subtitle = element_text(colour = input$nj_title_color, - size = input$nj_subtitle_size), - legend.background = element_rect(fill = input$nj_bg), - legend.direction = input$nj_legend_orientation, - legend.title = element_text(color = input$nj_color, - size = input$nj_legend_size*1.2), - legend.title.align = 0.5, - legend.position = nj_legend_pos(), - legend.text = element_text(color = input$nj_color, - size = input$nj_legend_size), - legend.key = element_rect(fill = input$nj_bg), - legend.box.spacing = unit(1.5, "cm"), - legend.key.size = unit(0.05*input$nj_legend_size, 'cm'), - plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) + - new_scale_fill() + - nj_fruit() + - nj_gradient() + - new_scale_fill() + - nj_fruit2() + - nj_gradient2() + - new_scale_fill() + - nj_fruit3() + - nj_gradient3() + - new_scale_fill() + - nj_fruit4() + - nj_gradient4() + - new_scale_fill() + - nj_fruit5() + - nj_gradient5() + - new_scale_fill() - - # Add custom labels - if(length(Vis$custom_label_nj) > 0) { - - for(i in Vis$custom_label_nj[,1]) { - - if(!is.null(Vis$nj_label_pos_x[[i]])) { - x_pos <- Vis$nj_label_pos_x[[i]] - } else { - x_pos <- round(Vis$nj_max_x / 2, 0) - } - - if(!is.null(Vis$nj_label_pos_y[[i]])) { - y_pos <- Vis$nj_label_pos_y[[i]] - } else { - y_pos <- sum(DB$data$Include) / 2 - } - - if(!is.null(Vis$nj_label_size[[i]])) { - size <- Vis$nj_label_size[[i]] - } else { - size <- 5 - } - - tree <- tree + annotate("text", - x = x_pos, - y = y_pos, - label = i, - size = size) - } - } - - # Add heatmap - if(input$nj_heatmap_show == TRUE & length(input$nj_heatmap_select) > 0) { - if (!(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)))) { - tree <- gheatmap.mod(tree, - data = select(Vis$meta_nj, input$nj_heatmap_select), - offset = nj_heatmap_offset(), - width = nj_heatmap_width(), - legend_title = input$nj_heatmap_title, - colnames_angle = -nj_colnames_angle(), - colnames_offset_y = nj_colnames_y(), - colnames_color = input$nj_color) + - nj_heatmap_scale() - } - } - - # Sizing control - Vis$nj_plot <- ggplotify::as.ggplot(tree, - scale = input$nj_zoom, - hjust = input$nj_h, - vjust = input$nj_v) - - Vis$nj_true <- TRUE - - # Correct background color if zoomed out - cowplot::ggdraw(Vis$nj_plot) + - theme(plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) - } - }) - - # Heatmap width - nj_heatmap_width <- reactive({ - if(!is.null(input$nj_heatmap_width)) { - input$nj_heatmap_width - } else { - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - 1.5 - } - } - } else { - if(length_input < 3) { - 0.3 - } else if (length_input >= 3 && length_input <= 27) { - min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - 3 - } - } - } - }) - - # Heatmap column titles position - nj_colnames_y <- reactive({ - if(!is.null(input$nj_colnames_y)) { - input$nj_colnames_y - } else { - if(input$nj_layout == "inward" | input$nj_layout == "circular") { - 0 - } else {-1} - } - }) - - # Heatmap column titles angle - nj_colnames_angle <- reactive({ - if(!is.null(input$nj_colnames_angle)) { - input$nj_colnames_angle - } else { - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "inward" | input$nj_layout == "circular") { - 90 - } else {-90} - } else {-90} - } - }) - - # Heatmap scale - nj_heatmap_scale <- reactive({ - if(!is.null(input$nj_heatmap_scale) & !is.null(input$nj_heatmap_div_mid)) { - if(input$nj_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_heatmap_div_mid == "Zero") { - midpoint <- 0 - } else if(input$nj_heatmap_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$nj_heatmap_scale)[1], - mid = brewer.pal(3, input$nj_heatmap_scale)[2], - high = brewer.pal(3, input$nj_heatmap_scale)[3], - midpoint = midpoint, - name = input$nj_heatmap_title) - } else { - if(input$nj_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { - if(input$nj_heatmap_scale == "magma") { - scale_fill_viridis(option = "A", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "inferno") { - scale_fill_viridis(option = "B", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "plasma") { - scale_fill_viridis(option = "C", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "viridis") { - scale_fill_viridis(option = "D", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "cividis") { - scale_fill_viridis(option = "E", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "rocket") { - scale_fill_viridis(option = "F", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "mako") { - scale_fill_viridis(option = "G", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "turbo") { - scale_fill_viridis(option = "H", - name = input$nj_heatmap_title) - } - } else { - if(input$nj_heatmap_scale == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H", - name = input$nj_heatmap_title) - } - } - } else { - scale_fill_brewer(palette = input$nj_heatmap_scale, - name = input$nj_heatmap_title) - } - } - } - }) - - # Tippoint Scale - nj_tippoint_scale <- reactive({ - if(!is.null(input$nj_tippoint_scale) & !is.null(input$nj_tipcolor_mapping_div_mid)) { - if(input$nj_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tipcolor_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$nj_tipcolor_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$nj_tippoint_scale)[1], - mid = brewer.pal(3, input$nj_tippoint_scale)[2], - high = brewer.pal(3, input$nj_tippoint_scale)[3], - midpoint = midpoint) - } else { - if(input$nj_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { - if(input$nj_tippoint_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$nj_tippoint_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$nj_tippoint_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$nj_tippoint_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$nj_tippoint_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$nj_tippoint_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$nj_tippoint_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$nj_tippoint_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$nj_tippoint_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tippoint_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tippoint_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tippoint_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tippoint_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tippoint_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tippoint_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tippoint_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$nj_tippoint_scale) - } - } - } - }) - - # Tiplab Scale - nj_tiplab_scale <- reactive({ - if(!is.null(input$nj_tiplab_scale) & !is.null(input$nj_color_mapping_div_mid)) { - if(input$nj_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_color_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$nj_color_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$nj_tiplab_scale)[1], - mid = brewer.pal(3, input$nj_tiplab_scale)[2], - high = brewer.pal(3, input$nj_tiplab_scale)[3], - midpoint = midpoint) - } else { - if(input$nj_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { - if(input$nj_tiplab_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$nj_tiplab_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$nj_tiplab_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$nj_tiplab_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$nj_tiplab_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$nj_tiplab_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$nj_tiplab_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$nj_tiplab_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$nj_tiplab_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiplab_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiplab_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiplab_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiplab_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiplab_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiplab_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiplab_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$nj_tiplab_scale) - } - } - } - }) - - # Clade Highlight - nj_clades <- reactive({ - if(!is.null(input$nj_parentnode)) { - if(!length(input$nj_parentnode) == 0) { - if(length(input$nj_parentnode) == 1) { - fill <- input$nj_clade_scale - } else if (length(input$nj_parentnode) == 2) { - if(startsWith(input$nj_clade_scale, "#")) { - fill <- brewer.pal(3, "Set1")[1:2] - } else { - fill <- brewer.pal(3, input$nj_clade_scale)[1:2] - } - } else { - fill <- brewer.pal(length(input$nj_parentnode), input$nj_clade_scale) - } - geom_hilight(node = as.numeric(input$nj_parentnode), - fill = fill, - type = input$nj_clade_type, - to.bottom = TRUE - ) - } else {NULL} - } - }) - - # Legend Position - nj_legend_pos <- reactive({ - if(!is.null(input$nj_legend_x) & !is.null(input$nj_legend_y)) { - c(input$nj_legend_x, input$nj_legend_y) - } else { - c(0.1, 1) - } - }) - - # Heatmap offset - nj_heatmap_offset <- reactive({ - if(is.null(input$nj_heatmap_offset)) { - 0 - } else {input$nj_heatmap_offset} - }) - - # Tiles fill color gradient - nj_gradient <- reactive({ - if(!is.null(input$nj_tiles_show_1) & - !is.null(input$nj_fruit_variable) & - !is.null(input$nj_tiles_scale_1) & - !is.null(input$nj_tiles_mapping_div_mid_1)) { - if(input$nj_tiles_show_1 == TRUE) { - if(input$nj_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_1 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_1 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_1)[1], - mid = brewer.pal(3, input$nj_tiles_scale_1)[2], - high = brewer.pal(3, input$nj_tiles_scale_1)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { - if(input$nj_tiles_scale_1 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_1 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_1 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_1 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_1 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_1 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_1 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_1 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_1 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_1 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_1 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_1 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_1 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_1 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_1 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_1 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_1) - } - } - } else {NULL} - } - }) - - nj_gradient2 <- reactive({ - if(!is.null(input$nj_tiles_show_2) & - !is.null(input$nj_fruit_variable_2) & - !is.null(input$nj_tiles_scale_2) & - !is.null(input$nj_tiles_mapping_div_mid_2)) { - if(input$nj_tiles_show_2 == TRUE) { - if(input$nj_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_2 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_2 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_2)[1], - mid = brewer.pal(3, input$nj_tiles_scale_2)[2], - high = brewer.pal(3, input$nj_tiles_scale_2)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { - if(input$nj_tiles_scale_2 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_2 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_2 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_2 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_2 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_2 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_2 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_2 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_2 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_2 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_2 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_2 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_2 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_2 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_2 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_2 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_2) - } - } - } else {NULL} - } - }) - - nj_gradient3 <- reactive({ - if(!is.null(input$nj_tiles_show_3) & - !is.null(input$nj_fruit_variable_3) & - !is.null(input$nj_tiles_scale_3 & - !is.null(input$nj_tiles_mapping_div_mid_3))) { - if(input$nj_tiles_show_3 == TRUE) { - if(input$nj_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_3 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_3 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) - } - scale_fill_gradient3(low = brewer.pal(3, input$nj_tiles_scale_3)[1], - mid = brewer.pal(3, input$nj_tiles_scale_3)[2], - high = brewer.pal(3, input$nj_tiles_scale_3)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { - if(input$nj_tiles_scale_3 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_3 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_3 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_3 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_3 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_3 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_3 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_3 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_3 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_3 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_3 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_3 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_3 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_3 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_3 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_3 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_3) - } - } - } else {NULL} - } - }) - - nj_gradient4 <- reactive({ - if(!is.null(input$nj_tiles_show_4) & - !is.null(input$nj_fruit_variable_4) & - !is.null(input$nj_tiles_scale_4) & - !is.null(input$nj_tiles_mapping_div_mid_4)) { - if(input$nj_tiles_show_4 == TRUE) { - if(input$nj_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_4 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_4 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) - } - scale_fill_gradient4(low = brewer.pal(3, input$nj_tiles_scale_4)[1], - mid = brewer.pal(3, input$nj_tiles_scale_4)[2], - high = brewer.pal(3, input$nj_tiles_scale_4)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { - if(input$nj_tiles_scale_4 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_4 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_4 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_4 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_4 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_4 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_4 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_4 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_4 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_4 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_4 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_4 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_4 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_4 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_4 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_4 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_4) - } - } - } else {NULL} - } - }) - - nj_gradient5 <- reactive({ - if(!is.null(input$nj_tiles_show_5) & - !is.null(input$nj_fruit_variable_5) & - !is.null(input$nj_tiles_scale_5) & - !is.null(input$nj_tiles_mapping_div_mid_5)) { - if(input$nj_tiles_show_5 == TRUE) { - if(input$nj_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_5 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_5 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) - } - scale_fill_gradient5(low = brewer.pal(3, input$nj_tiles_scale_5)[1], - mid = brewer.pal(3, input$nj_tiles_scale_5)[2], - high = brewer.pal(3, input$nj_tiles_scale_5)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { - if(input$nj_tiles_scale_5 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_5 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_5 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_5 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_5 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_5 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_5 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_5 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_5 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_5 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_5 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_5 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_5 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_5 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_5 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_5 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_5) - } - } - } else {NULL} - } - }) - - # No label clip off for linear NJ tree - nj_clip_label <- reactive({ - if(!(input$nj_layout == "circular" | input$nj_layout == "inward")) { - coord_cartesian(clip = "off") - } else {NULL} - }) - - # Geom Fruit - nj_fruit <- reactive({ - if((!is.null(input$nj_tiles_show_1)) & - (!is.null(input$nj_fruit_variable)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ)) & - (!is.null(input$nj_fruit_width_circ)) & - (!is.null(input$nj_fruit_alpha))) { - if(input$nj_tiles_show_1 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = input$nj_fruit_offset_circ, - width = input$nj_fruit_width_circ, - alpha = input$nj_fruit_alpha - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = input$nj_fruit_offset_circ, - width = input$nj_fruit_width_circ, - alpha = input$nj_fruit_alpha - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_1 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = 0, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = 0, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Geom Fruit - nj_fruit2 <- reactive({ - if((!is.null(input$nj_tiles_show_2)) & - (!is.null(input$nj_fruit_variable_2)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_2)) & - (!is.null(input$nj_fruit_width_circ_2)) & - (!is.null(input$nj_fruit_alpha_2))) { - if(input$nj_tiles_show_2 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), - offset = input$nj_fruit_offset_circ_2, - width = input$nj_fruit_width_circ_2, - alpha = input$nj_fruit_alpha_2 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), - offset = input$nj_fruit_offset_circ_2, - width = input$nj_fruit_width_circ_2, - alpha = input$nj_fruit_alpha_2 - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_2 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - nj_fruit3 <- reactive({ - if((!is.null(input$nj_tiles_show_3)) & - (!is.null(input$nj_fruit_variable_3)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_3)) & - (!is.null(input$nj_fruit_width_circ_3)) & - (!is.null(input$nj_fruit_alpha_3))) { - if(input$nj_tiles_show_3 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), - offset = input$nj_fruit_offset_circ_3, - width = input$nj_fruit_width_circ_3, - alpha = input$nj_fruit_alpha_3 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), - offset = input$nj_fruit_offset_circ_3, - width = input$nj_fruit_width_circ_3, - alpha = input$nj_fruit_alpha_3 - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_3 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - nj_fruit4 <- reactive({ - if((!is.null(input$nj_tiles_show_4)) & - (!is.null(input$nj_fruit_variable_4)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_4)) & - (!is.null(input$nj_fruit_width_circ_4)) & - (!is.null(input$nj_fruit_alpha_4))) { - if(input$nj_tiles_show_4 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), - offset = input$nj_fruit_offset_circ_4, - width = input$nj_fruit_width_circ_4, - alpha = input$nj_fruit_alpha_4 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), - offset = input$nj_fruit_offset_circ_4, - width = input$nj_fruit_width_circ_4, - alpha = input$nj_fruit_alpha_4 - ) - } - } else { - if(input$nj_tiles_show_4 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - } - }) - - nj_fruit5 <- reactive({ - if((!is.null(input$nj_tiles_show_5)) & - (!is.null(input$nj_fruit_variable_5)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_5)) & - (!is.null(input$nj_fruit_width_circ_5)) & - (!is.null(input$nj_fruit_alpha_5))) { - if(input$nj_tiles_show_5 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), - offset = input$nj_fruit_offset_circ_5, - width = input$nj_fruit_width_circ_5, - alpha = input$nj_fruit_alpha_5 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), - offset = input$nj_fruit_offset_circ_5, - width = input$nj_fruit_width_circ_5, - alpha = input$nj_fruit_alpha_5 - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_5 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Xlim - nj_limit <- reactive({ - if(input$nj_layout == "circular") { - xlim(input$nj_xlim, NA) - } else {NULL} - }) - - # Treescale - nj_treescale <- reactive({ - if(!input$nj_layout == "circular") { - if(input$nj_treescale_show == TRUE) { - geom_treescale(x = nj_treescale_x(), - y = nj_treescale_y(), - width = nj_treescale_width(), - color = input$nj_color, - fontsize = 4) - } else {NULL} - } else {NULL} - }) - - # Treescale Y Position - nj_treescale_y <- reactive({ - if(is.null(input$nj_treescale_y)) { - 0 - } else {input$nj_treescale_y} - }) - - # Treescale X Position - nj_treescale_x <- reactive({ - if(is.null(input$nj_treescale_x)) { - round(ceiling(Vis$nj_max_x) * 0.2, 0) - } else {input$nj_treescale_x} - }) - - # Treescale width - nj_treescale_width <- reactive({ - if(!is.null(input$nj_treescale_width)) { - input$nj_treescale_width - } else { - round(ceiling(Vis$nj_max_x) * 0.1, 0) - } - }) - - # Label branches - nj_label_branch <- reactive({ - if(!input$nj_layout == "circular" | !input$nj_layout == "inward") { - if(input$nj_show_branch_label == TRUE) { - geom_label( - aes( - x=!!sym("branch"), - label= !!sym(input$nj_branch_label)), - fill = input$nj_branch_label_color, - size = nj_branch_size(), - label.r = unit(input$nj_branch_labelradius, "lines"), - nudge_x = input$nj_branch_x, - nudge_y = input$nj_branch_y, - fontface = input$nj_branchlab_fontface, - alpha = input$nj_branchlab_alpha - ) - } else {NULL} - } else {NULL} - }) - - # Branch label size - nj_branch_size <- reactive({ - if(!is.null(input$nj_branch_size)) { - input$nj_branch_size - } else { - Vis$branch_size_nj - } - }) - - # Rootedge - nj_rootedge <- reactive({ - if(input$nj_rootedge_show == TRUE) { - if(is.null(input$nj_rootedge_length)) { - geom_rootedge(rootedge = round(ceiling(Vis$nj_max_x) * 0.05, 0), - linetype = input$nj_rootedge_line) - } else { - geom_rootedge(rootedge = input$nj_rootedge_length, - linetype = input$nj_rootedge_line) - } - } else {NULL} - }) - - # Tippoints - nj_tippoint <- reactive({ - if(input$nj_tippoint_show == TRUE | input$nj_tipcolor_mapping_show == TRUE | input$nj_tipshape_mapping_show == TRUE) { - if(input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == FALSE) { - geom_tippoint( - aes(color = !!sym(input$nj_tipcolor_mapping)), - alpha = input$nj_tippoint_alpha, - shape = input$nj_tippoint_shape, - size = nj_tippoint_size() - ) - } else if (input$nj_tipcolor_mapping_show == FALSE & input$nj_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$nj_tipshape_mapping)), - alpha = input$nj_tippoint_alpha, - color = input$nj_tippoint_color, - size = nj_tippoint_size() - ) - } else if (input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$nj_tipshape_mapping), - color = !!sym(input$nj_tipcolor_mapping)), - alpha = input$nj_tippoint_alpha, - size = nj_tippoint_size() - ) - } else { - geom_tippoint( - alpha = input$nj_tippoint_alpha, - colour = input$nj_tippoint_color, - fill = input$nj_tippoint_color, - shape = input$nj_tippoint_shape, - size = nj_tippoint_size() - ) - } - } else {NULL} - }) - - # Nodepoints - nj_nodepoint <- reactive({ - if(input$nj_nodepoint_show == TRUE) { - geom_nodepoint( - alpha = input$nj_nodepoint_alpha, - color = input$nj_nodepoint_color, - shape = input$nj_nodepoint_shape, - size = nj_nodepoint_size() - ) - } else {NULL} - }) - - # Nodepoint size - nj_nodepoint_size <- reactive({ - if(!is.null(input$nj_nodepoint_size)) { - input$nj_nodepoint_size - } else { - Vis$nodepointsize_nj - } - }) - - # NJ circular or not - nj_tiplab <- reactive({ - if(input$nj_tiplab_show == TRUE) { - if(input$nj_layout == "circular") { - if(input$nj_mapping_show == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position), - check.overlap = input$nj_tiplab_overlap - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - color = input$nj_tiplab_color, - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position), - check.overlap = input$nj_tiplab_overlap - ) - } - } else if (input$nj_layout == "inward") { - if(input$nj_mapping_show == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position_inw), - check.overlap = input$nj_tiplab_overlap - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - color = input$nj_tiplab_color, - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position_inw), - check.overlap = input$nj_tiplab_overlap - ) - } - } else { - if(input$nj_mapping_show == TRUE) { - if(input$nj_geom == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap, - label.padding = unit(nj_tiplab_padding(), "lines"), - label.r = unit(input$nj_tiplab_labelradius, "lines"), - fill = input$nj_tiplab_fill - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap - ) - } - } else { - if(input$nj_geom == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - color = input$nj_tiplab_color, - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap, - label.padding = unit(nj_tiplab_padding(), "lines"), - label.r = unit(input$nj_tiplab_labelradius, "lines"), - fill = input$nj_tiplab_fill - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - color = input$nj_tiplab_color, - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap - ) - } - } - } - } else {NULL} - }) - - # Tip panel size - nj_tiplab_padding <- reactive({ - if(!is.null(input$nj_tiplab_padding)) { - input$nj_tiplab_padding - } else { - Vis$tiplab_padding_nj - } - }) - - # Tiplab size - nj_tiplab_size <- reactive({ - if(!is.null(input$nj_tiplab_size)) { - input$nj_tiplab_size - } else { - Vis$labelsize_nj - } - }) - - # Tippoint size - nj_tippoint_size <- reactive({ - if(!is.null(input$nj_tippoint_size)) { - input$nj_tippoint_size - } else { - Vis$tippointsize_nj - } - }) - - # Show Label Panels? - nj_geom <- reactive({ - if(input$nj_geom == TRUE) { - "label" - } else {"text"} - }) - - # NJ Tiplab color - nj_mapping_tiplab <- reactive({ - if(input$nj_mapping_show == TRUE) { - if(!is.null(input$nj_tiplab)) { - aes(label = !!sym(input$nj_tiplab), - color = !!sym(input$nj_color_mapping)) - } else { - aes(label = !!sym("Assembly Name"), - color = !!sym(input$nj_color_mapping)) - } - } else { - if(!is.null(input$nj_tiplab)) { - aes(label = !!sym(input$nj_tiplab)) - } else { - aes(label = !!sym("Assembly Name")) - } - } - }) - - # NJ Tree Layout - layout_nj <- reactive({ - if(input$nj_layout == "inward") { - "circular" - } else {input$nj_layout} - }) - - # NJ inward circular - nj_inward <- reactive({ - if (input$nj_layout == "inward") { - layout_inward_circular(xlim = input$nj_inward_xlim) - } else { - NULL - } - }) - - #### UPGMA ---- - - upgma_tree <- reactive({ - if(input$upgma_nodelabel_show == TRUE) { - ggtree(Vis$upgma, alpha = 0.2, layout = layout_upgma()) + - geom_nodelab(aes(label = node), color = "#29303A", size = upgma_tiplab_size() + 1, hjust = 0.7) + - upgma_limit() + - upgma_inward() - } else { - tree <- - ggtree(Vis$upgma, - color = input$upgma_color, - layout = layout_upgma(), - ladderize = input$upgma_ladder) %<+% Vis$meta_upgma + - upgma_tiplab() + - upgma_tiplab_scale() + - new_scale_color() + - upgma_limit() + - upgma_inward() + - upgma_label_branch() + - upgma_treescale() + - upgma_nodepoint() + - upgma_tippoint() + - upgma_tippoint_scale() + - new_scale_color() + - upgma_clip_label() + - upgma_rootedge() + - upgma_clades() + - ggtitle(label = input$upgma_title, - subtitle = input$upgma_subtitle) + - theme_tree(bgcolor = input$upgma_bg) + - theme(plot.title = element_text(colour = input$upgma_title_color, - size = input$upgma_title_size), - plot.subtitle = element_text(colour = input$upgma_title_color, - size = input$upgma_subtitle_size), - legend.background = element_rect(fill = input$upgma_bg), - legend.direction = input$upgma_legend_orientation, - legend.title = element_text(color = input$upgma_color, - size = input$upgma_legend_size*1.2), - legend.title.align = 0.5, - legend.position = upgma_legend_pos(), - legend.text = element_text(color = input$upgma_color, - size = input$upgma_legend_size), - legend.key = element_rect(fill = input$upgma_bg), - legend.box.spacing = unit(1.5, "cm"), - legend.key.size = unit(0.05*input$upgma_legend_size, 'cm'), - plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) + - new_scale_fill() + - upgma_fruit() + - upgma_gradient() + - new_scale_fill() + - upgma_fruit2() + - upgma_gradient2() + - new_scale_fill() + - upgma_fruit3() + - upgma_gradient3() + - new_scale_fill() + - upgma_fruit4() + - upgma_gradient4() + - new_scale_fill() + - upgma_fruit5() + - upgma_gradient5() + - new_scale_fill() - - # Add custom labels - if(length(Vis$custom_label_upgma) > 0) { - - for(i in Vis$custom_label_upgma[,1]) { - - if(!is.null(Vis$upgma_label_pos_x[[i]])) { - x_pos <- Vis$upgma_label_pos_x[[i]] - } else { - x_pos <- round(Vis$upgma_max_x / 2, 0) - } - - if(!is.null(Vis$upgma_label_pos_y[[i]])) { - y_pos <- Vis$upgma_label_pos_y[[i]] - } else { - y_pos <- sum(DB$data$Include) / 2 - } - - if(!is.null(Vis$upgma_label_size[[i]])) { - size <- Vis$upgma_label_size[[i]] - } else { - size <- 5 - } - - tree <- tree + annotate("text", - x = x_pos, - y = y_pos, - label = i, - size = size) - } - } - - # Add heatmap - if(input$upgma_heatmap_show == TRUE & length(input$upgma_heatmap_select) > 0) { - if (!(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)))) { - tree <- gheatmap.mod(tree, - data = select(Vis$meta_upgma, input$upgma_heatmap_select), - offset = upgma_heatmap_offset(), - width = upgma_heatmap_width(), - legend_title = input$upgma_heatmap_title, - colnames_angle = -upgma_colnames_angle(), - colnames_offset_y = upgma_colnames_y(), - colnames_color = input$upgma_color) + - upgma_heatmap_scale() - } - } - - # Sizing control - Vis$upgma_plot <- ggplotify::as.ggplot(tree, - scale = input$upgma_zoom, - hjust = input$upgma_h, - vjust = input$upgma_v) - - # Correct background color if zoomed out - cowplot::ggdraw(Vis$upgma_plot) + - theme(plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) - } - }) - - # Heatmap width - upgma_heatmap_width <- reactive({ - if(!is.null(input$upgma_heatmap_width)) { - input$upgma_heatmap_width - } else { - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - 1.5 - } - } - } else { - if(length_input < 3) { - 0.3 - } else if (length_input >= 3 && length_input <= 27) { - min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - 3 - } - } - } - }) - - # Heatmap column titles position - upgma_colnames_y <- reactive({ - if(!is.null(input$upgma_colnames_y)) { - input$upgma_colnames_y - } else { - if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { - 0 - } else {-1} - } - }) - - # Heatmap column titles angle - upgma_colnames_angle <- reactive({ - if(!is.null(input$upgma_colnames_angle)) { - input$upgma_colnames_angle - } else { - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { - 90 - } else {-90} - } else {-90} - } - }) - - # Heatmap scale - upgma_heatmap_scale <- reactive({ - if(!is.null(input$upgma_heatmap_scale) & !is.null(input$upgma_heatmap_div_mid)) { - if(input$upgma_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_heatmap_div_mid == "Zero") { - midpoint <- 0 - } else if(input$upgma_heatmap_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$upgma_heatmap_scale)[1], - mid = brewer.pal(3, input$upgma_heatmap_scale)[2], - high = brewer.pal(3, input$upgma_heatmap_scale)[3], - midpoint = midpoint, - name = input$upgma_heatmap_title) - } else { - if(input$upgma_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { - if(input$upgma_heatmap_scale == "magma") { - scale_fill_viridis(option = "A", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "inferno") { - scale_fill_viridis(option = "B", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "plasma") { - scale_fill_viridis(option = "C", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "viridis") { - scale_fill_viridis(option = "D", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "cividis") { - scale_fill_viridis(option = "E", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "rocket") { - scale_fill_viridis(option = "F", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "mako") { - scale_fill_viridis(option = "G", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "turbo") { - scale_fill_viridis(option = "H", - name = input$upgma_heatmap_title) - } - } else { - if(input$upgma_heatmap_scale == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H", - name = input$upgma_heatmap_title) - } - } - } else { - scale_fill_brewer(palette = input$upgma_heatmap_scale, - name = input$upgma_heatmap_title) - } - } - } - }) - - # Tippoint Scale - upgma_tippoint_scale <- reactive({ - if(!is.null(input$upgma_tippoint_scale) & !is.null(input$upgma_tipcolor_mapping_div_mid)) { - if(input$upgma_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tipcolor_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$upgma_tipcolor_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$upgma_tippoint_scale)[1], - mid = brewer.pal(3, input$upgma_tippoint_scale)[2], - high = brewer.pal(3, input$upgma_tippoint_scale)[3], - midpoint = midpoint) - } else { - if(input$upgma_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { - if(input$upgma_tippoint_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$upgma_tippoint_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$upgma_tippoint_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$upgma_tippoint_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$upgma_tippoint_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$upgma_tippoint_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$upgma_tippoint_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$upgma_tippoint_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$upgma_tippoint_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tippoint_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tippoint_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tippoint_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tippoint_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tippoint_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tippoint_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tippoint_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$upgma_tippoint_scale) - } - } - } - }) - - # Tiplab Scale - upgma_tiplab_scale <- reactive({ - if(!is.null(input$upgma_tiplab_scale) & !is.null(input$upgma_color_mapping_div_mid)) { - if(input$upgma_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_color_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$upgma_color_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$upgma_tiplab_scale)[1], - mid = brewer.pal(3, input$upgma_tiplab_scale)[2], - high = brewer.pal(3, input$upgma_tiplab_scale)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { - if(input$upgma_tiplab_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$upgma_tiplab_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$upgma_tiplab_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$upgma_tiplab_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$upgma_tiplab_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$upgma_tiplab_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$upgma_tiplab_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$upgma_tiplab_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$upgma_tiplab_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiplab_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiplab_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiplab_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiplab_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiplab_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiplab_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiplab_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$upgma_tiplab_scale) - } - } - } - }) - - # Clade Highlight - upgma_clades <- reactive({ - if(!is.null(input$upgma_parentnode)) { - if(!length(input$upgma_parentnode) == 0) { - if(length(input$upgma_parentnode) == 1) { - fill <- input$upgma_clade_scale - } else if (length(input$upgma_parentnode) == 2) { - if(startsWith(input$upgma_clade_scale, "#")) { - fill <- brewer.pal(3, "Set1")[1:2] - } else { - fill <- brewer.pal(3, input$upgma_clade_scale)[1:2] - } - } else { - fill <- brewer.pal(length(input$upgma_parentnode), input$upgma_clade_scale) - } - geom_hilight(node = as.numeric(input$upgma_parentnode), - fill = fill, - type = input$upgma_clade_type, - to.bottom = TRUE) - } else {NULL} - } - }) - - # Legend Position - upgma_legend_pos <- reactive({ - if(!is.null(input$upgma_legend_x) & !is.null(input$upgma_legend_y)) { - c(input$upgma_legend_x, input$upgma_legend_y) - } else { - c(0.1, 1) - } - }) - - # Heatmap offset - upgma_heatmap_offset <- reactive({ - if(is.null(input$upgma_heatmap_offset)) { - 0 - } else {input$upgma_heatmap_offset} - }) - - # Tiles fill color gradient - upgma_gradient <- reactive({ - if(!is.null(input$upgma_tiles_show_1) & - !is.null(input$upgma_fruit_variable) & - !is.null(input$upgma_tiles_scale_1) & - !is.null(input$upgma_tiles_mapping_div_mid_1)) { - if(input$upgma_tiles_show_1 == TRUE) { - if(input$upgma_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_1 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_1 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_1)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_1)[2], - high = brewer.pal(3, input$upgma_tiles_scale_1)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { - if(input$upgma_tiles_scale_1 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_1 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_1 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_1 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_1 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_1 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_1 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_1 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_1 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_1 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_1 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_1 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_1 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_1 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_1 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_1 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_1) - } - } - } else {NULL} - } - }) - - upgma_gradient2 <- reactive({ - if(!is.null(input$upgma_tiles_show_2) & - !is.null(input$upgma_fruit_variable_2) & - !is.null(input$upgma_tiles_scale_2) & - !is.null(input$upgma_tiles_mapping_div_mid_2)) { - if(input$upgma_tiles_show_2 == TRUE) { - if(input$upgma_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_2 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_2 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_2)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_2)[2], - high = brewer.pal(3, input$upgma_tiles_scale_2)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { - if(input$upgma_tiles_scale_2 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_2 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_2 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_2 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_2 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_2 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_2 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_2 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_2 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_2 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_2 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_2 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_2 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_2 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_2 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_2 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_2) - } - } - } else {NULL} - } - }) - - upgma_gradient3 <- reactive({ - if(!is.null(input$upgma_tiles_show_3) & - !is.null(input$upgma_fruit_variable_3) & - !is.null(input$upgma_tiles_scale_3) & - !is.null(input$upgma_tiles_mapping_div_mid_3)) { - if(input$upgma_tiles_show_3 == TRUE) { - if(input$upgma_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_3 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_3 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) - } - scale_fill_gradient3(low = brewer.pal(3, input$upgma_tiles_scale_3)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_3)[2], - high = brewer.pal(3, input$upgma_tiles_scale_3)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { - if(input$upgma_tiles_scale_3 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_3 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_3 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_3 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_3 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_3 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_3 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_3 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_3 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_3 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_3 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_3 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_3 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_3 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_3 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_3 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_3) - } - } - } else {NULL} - } - }) - - upgma_gradient4 <- reactive({ - if(!is.null(input$upgma_tiles_show_4) & - !is.null(input$upgma_fruit_variable_4) & - !is.null(input$upgma_tiles_scale_4) & - !is.null(input$upgma_tiles_mapping_div_mid_4)) { - if(input$upgma_tiles_show_4 == TRUE) { - if(input$upgma_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_4 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_4 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) - } - scale_fill_gradient4(low = brewer.pal(3, input$upgma_tiles_scale_4)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_4)[2], - high = brewer.pal(3, input$upgma_tiles_scale_4)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { - if(input$upgma_tiles_scale_4 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_4 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_4 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_4 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_4 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_4 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_4 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_4 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_4 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_4 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_4 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_4 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_4 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_4 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_4 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_4 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_4) - } - } - } else {NULL} - } - }) - - upgma_gradient5 <- reactive({ - if(!is.null(input$upgma_tiles_show_5) & - !is.null(input$upgma_fruit_variable_5) & - !is.null(input$upgma_tiles_scale_5) & - !is.null(input$upgma_tiles_mapping_div_mid_5)) { - if(input$upgma_tiles_show_5 == TRUE) { - if(input$upgma_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_5 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_5 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) - } - scale_fill_gradient5(low = brewer.pal(3, input$upgma_tiles_scale_5)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_5)[2], - high = brewer.pal(3, input$upgma_tiles_scale_5)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { - if(input$upgma_tiles_scale_5 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_5 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_5 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_5 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_5 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_5 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_5 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_5 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_5 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_5 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_5 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_5 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_5 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_5 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_5 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_5 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_5) - } - } - } else {NULL} - } - }) - - # No label clip off for linear upgma tree - upgma_clip_label <- reactive({ - if(!(input$upgma_layout == "circular" | input$upgma_layout == "inward")) { - coord_cartesian(clip = "off") - } else {NULL} - }) - - # Geom Fruit - upgma_fruit <- reactive({ - if((!is.null(input$upgma_tiles_show_1)) & - (!is.null(input$upgma_fruit_variable)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ)) & - (!is.null(input$upgma_fruit_width_circ)) & - (!is.null(input$upgma_fruit_alpha))) { - if(input$upgma_tiles_show_1 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = input$upgma_fruit_offset_circ, - width = input$upgma_fruit_width_circ, - alpha = input$upgma_fruit_alpha - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = input$upgma_fruit_offset_circ, - width = input$upgma_fruit_width_circ, - alpha = input$upgma_fruit_alpha - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_1 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = 0, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = 0, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Geom Fruit - upgma_fruit2 <- reactive({ - if((!is.null(input$upgma_tiles_show_2)) & - (!is.null(input$upgma_fruit_variable_2)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_2)) & - (!is.null(input$upgma_fruit_width_circ_2)) & - (!is.null(input$upgma_fruit_alpha_2))) { - if(input$upgma_tiles_show_2 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), - offset = input$upgma_fruit_offset_circ_2, - width = input$upgma_fruit_width_circ_2, - alpha = input$upgma_fruit_alpha_2 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), - offset = input$upgma_fruit_offset_circ_2, - width = input$upgma_fruit_width_circ_2, - alpha = input$upgma_fruit_alpha_2 - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_2 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - upgma_fruit3 <- reactive({ - if((!is.null(input$upgma_tiles_show_3)) & - (!is.null(input$upgma_fruit_variable_3)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_3)) & - (!is.null(input$upgma_fruit_width_circ_3)) & - (!is.null(input$upgma_fruit_alpha_3))) { - if(input$upgma_tiles_show_3 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), - offset = input$upgma_fruit_offset_circ_3, - width = input$upgma_fruit_width_circ_3, - alpha = input$upgma_fruit_alpha_3 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), - offset = input$upgma_fruit_offset_circ_3, - width = input$upgma_fruit_width_circ_3, - alpha = input$upgma_fruit_alpha_3 - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_3 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - upgma_fruit4 <- reactive({ - if((!is.null(input$upgma_tiles_show_4)) & - (!is.null(input$upgma_fruit_variable_4)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_4)) & - (!is.null(input$upgma_fruit_width_circ_4)) & - (!is.null(input$upgma_fruit_alpha_4))) { - if(input$upgma_tiles_show_4 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), - offset = input$upgma_fruit_offset_circ_4, - width = input$upgma_fruit_width_circ_4, - alpha = input$upgma_fruit_alpha_4 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), - offset = input$upgma_fruit_offset_circ_4, - width = input$upgma_fruit_width_circ_4, - alpha = input$upgma_fruit_alpha_4 - ) - } - } else { - if(input$upgma_tiles_show_4 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - } - }) - - upgma_fruit5 <- reactive({ - if((!is.null(input$upgma_tiles_show_5)) & - (!is.null(input$upgma_fruit_variable_5)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_5)) & - (!is.null(input$upgma_fruit_width_circ_5)) & - (!is.null(input$upgma_fruit_alpha_5))) { - if(input$upgma_tiles_show_5 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), - offset = input$upgma_fruit_offset_circ_5, - width = input$upgma_fruit_width_circ_5, - alpha = input$upgma_fruit_alpha_5 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), - offset = input$upgma_fruit_offset_circ_5, - width = input$upgma_fruit_width_circ_5, - alpha = input$upgma_fruit_alpha_5 - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_5 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Xlim - upgma_limit <- reactive({ - if(input$upgma_layout == "circular") { - xlim(input$upgma_xlim, NA) - } else {NULL} - }) - - # Treescale - upgma_treescale <- reactive({ - if(!input$upgma_layout == "circular") { - if(input$upgma_treescale_show == TRUE) { - geom_treescale(x = upgma_treescale_x(), - y = upgma_treescale_y(), - width = upgma_treescale_width(), - color = input$upgma_color, - fontsize = 4) - } else {NULL} - } else {NULL} - }) - - # Treescale Y Position - upgma_treescale_y <- reactive({ - if(is.null(input$upgma_treescale_y)) { - 0 - } else {input$upgma_treescale_y} - }) - - # Treescale X Position - upgma_treescale_x <- reactive({ - if(is.null(input$upgma_treescale_x)) { - round(ceiling(Vis$upgma_max_x) * 0.2, 0) - } else {input$upgma_treescale_x} - }) - - # Treescale width - upgma_treescale_width <- reactive({ - if(!is.null(input$upgma_treescale_width)) { - input$upgma_treescale_width - } else { - round(ceiling(Vis$upgma_max_x) * 0.1, 0) - } - }) - - # Label branches - upgma_label_branch <- reactive({ - if(!input$upgma_layout == "circular" | !input$upgma_layout == "inward") { - if(input$upgma_show_branch_label == TRUE) { - geom_label( - aes( - x=!!sym("branch"), - label= !!sym(input$upgma_branch_label)), - fill = input$upgma_branch_label_color, - size = upgma_branch_size(), - label.r = unit(input$upgma_branch_labelradius, "lines"), - nudge_x = input$upgma_branch_x, - nudge_y = input$upgma_branch_y, - fontface = input$upgma_branchlab_fontface, - alpha = input$upgma_branchlab_alpha - ) - } else {NULL} - } else {NULL} - }) - - # Branch label size - upgma_branch_size <- reactive({ - if(!is.null(input$upgma_branch_size)) { - input$upgma_branch_size - } else { - Vis$branch_size_upgma - } - }) - - # Rootedge - upgma_rootedge <- reactive({ - if(input$upgma_rootedge_show == TRUE) { - if(is.null(input$upgma_rootedge_length)) { - geom_rootedge(rootedge = round(ceiling(Vis$upgma_max_x) * 0.05, 0), - linetype = input$upgma_rootedge_line) - } else { - geom_rootedge(rootedge = input$upgma_rootedge_length, - linetype = input$upgma_rootedge_line) - } - } else {NULL} - }) - - # Tippoints - upgma_tippoint <- reactive({ - if(input$upgma_tippoint_show == TRUE | input$upgma_tipcolor_mapping_show == TRUE | input$upgma_tipshape_mapping_show == TRUE) { - if(input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == FALSE) { - geom_tippoint( - aes(color = !!sym(input$upgma_tipcolor_mapping)), - alpha = input$upgma_tippoint_alpha, - shape = input$upgma_tippoint_shape, - size = upgma_tippoint_size() - ) - } else if (input$upgma_tipcolor_mapping_show == FALSE & input$upgma_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$upgma_tipshape_mapping)), - alpha = input$upgma_tippoint_alpha, - color = input$upgma_tippoint_color, - size = upgma_tippoint_size() - ) - } else if (input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$upgma_tipshape_mapping), - color = !!sym(input$upgma_tipcolor_mapping)), - alpha = input$upgma_tippoint_alpha, - size = upgma_tippoint_size() - ) - } else { - geom_tippoint( - alpha = input$upgma_tippoint_alpha, - colour = input$upgma_tippoint_color, - fill = input$upgma_tippoint_color, - shape = input$upgma_tippoint_shape, - size = upgma_tippoint_size() - ) - } - } else {NULL} - }) - - # Nodepoints - upgma_nodepoint <- reactive({ - if(input$upgma_nodepoint_show == TRUE) { - geom_nodepoint( - alpha = input$upgma_nodepoint_alpha, - color = input$upgma_nodepoint_color, - shape = input$upgma_nodepoint_shape, - size = upgma_nodepoint_size() - ) - } else {NULL} - }) - - # Nodepoint size - upgma_nodepoint_size <- reactive({ - if(!is.null(input$upgma_nodepoint_size)) { - input$upgma_nodepoint_size - } else { - Vis$nodepointsize_upgma - } - }) - - # upgma circular or not - upgma_tiplab <- reactive({ - if(input$upgma_tiplab_show == TRUE) { - if(input$upgma_layout == "circular") { - if(input$upgma_mapping_show == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position), - check.overlap = input$upgma_tiplab_overlap - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - color = input$upgma_tiplab_color, - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position), - check.overlap = input$upgma_tiplab_overlap - ) - } - } else if (input$upgma_layout == "inward") { - if(input$upgma_mapping_show == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position_inw), - check.overlap = input$upgma_tiplab_overlap - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - color = input$upgma_tiplab_color, - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position_inw), - check.overlap = input$upgma_tiplab_overlap - ) - } - } else { - if(input$upgma_mapping_show == TRUE) { - if(input$upgma_geom == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap, - label.padding = unit(upgma_tiplab_padding(), "lines"), - label.r = unit(input$upgma_tiplab_labelradius, "lines"), - fill = input$upgma_tiplab_fill - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap - ) - } - } else { - if(input$upgma_geom == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - color = input$upgma_tiplab_color, - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap, - label.padding = unit(upgma_tiplab_padding(), "lines"), - label.r = unit(input$upgma_tiplab_labelradius, "lines"), - fill = input$upgma_tiplab_fill - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - color = input$upgma_tiplab_color, - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap - ) - } - } - } - } else {NULL} - }) - - # Tip panel size - upgma_tiplab_padding <- reactive({ - if(!is.null(input$upgma_tiplab_padding)) { - input$upgma_tiplab_padding - } else { - Vis$tiplab_padding_upgma - } - }) - - # Tiplab size - upgma_tiplab_size <- reactive({ - if(!is.null(input$upgma_tiplab_size)) { - input$upgma_tiplab_size - } else { - Vis$labelsize_upgma - } - }) - - # Tippoint size - upgma_tippoint_size <- reactive({ - if(!is.null(input$upgma_tippoint_size)) { - input$upgma_tippoint_size - } else { - Vis$tippointsize_upgma - } - }) - - # Show Label Panels? - upgma_geom <- reactive({ - if(input$upgma_geom == TRUE) { - "label" - } else {"text"} - }) - - # upgma Tiplab color - upgma_mapping_tiplab <- reactive({ - if(input$upgma_mapping_show == TRUE) { - if(!is.null(input$upgma_tiplab)) { - aes(label = !!sym(input$upgma_tiplab), - color = !!sym(input$upgma_color_mapping)) - } else { - aes(label = !!sym("Assembly Name"), - color = !!sym(input$upgma_color_mapping)) - } - } else { - if(!is.null(input$upgma_tiplab)) { - aes(label = !!sym(input$upgma_tiplab)) - } else { - aes(label = !!sym("Assembly Name")) - } - } - }) - - # upgma Tree Layout - layout_upgma <- reactive({ - if(input$upgma_layout == "inward") { - "circular" - } else {input$upgma_layout} - }) - - # upgma inward circular - upgma_inward <- reactive({ - if (input$upgma_layout == "inward") { - layout_inward_circular(xlim = input$upgma_inward_xlim) - } else { - NULL - } - }) - - ### Save MST Plot ---- - output$save_plot_html <- downloadHandler( - filename = function() { - log_print(paste0("Save MST;", paste0("MST_", Sys.Date(), ".html"))) - paste0("MST_", Sys.Date(), ".html") - }, - content = function(file) { - mst_tree() %>% visSave(file = file, background = mst_background_color()) - } - ) - - ### Save NJ Plot ---- - - # Define download handler to save the plot - - output$download_nj <- downloadHandler( - filename = function() { - log_print(paste0("Save NJ;", paste0("NJ_", Sys.Date(), ".", input$filetype_nj))) - paste0("NJ_", Sys.Date(), ".", input$filetype_nj) - }, - content = function(file) { - if (input$filetype_nj == "png") { - png(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) - print(nj_tree()) - dev.off() - } else if (input$filetype_nj == "jpeg") { - jpeg(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) - print(nj_tree()) - dev.off() - } else if (input$filetype_nj == "svg") { - plot <- print(nj_tree()) - ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio))/96, - height = as.numeric(input$nj_scale)/96)) - } else if (input$filetype_nj == "bmp") { - bmp(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) - print(nj_tree()) - dev.off() - } - } - ) - - ### Save UPGMA Plot ---- - - # Define download handler to save the plot - - output$download_upgma <- downloadHandler( - filename = function() { - log_print(paste0("Save UPGMA;", paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma))) - paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma) - }, - content = function(file) { - if (input$filetype_upgma == "png") { - png(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) - print(upgma_tree()) - dev.off() - } else if (input$filetype_upgma == "jpeg") { - jpeg(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) - print(upgma_tree()) - dev.off() - } else if (input$filetype_upgma == "svg") { - plot <- print(upgma_tree()) - ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio))/96, - height = as.numeric(input$upgma_scale)/96)) - } else if (input$filetype_upgma == "bmp") { - bmp(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) - print(upgma_tree()) - dev.off() - } - } - ) - - ### Reactive Events ---- - - # MST cluster reset button - observeEvent(input$mst_cluster_reset, { - if(!is.null(DB$schemeinfo)) - updateNumericInput(session, "mst_cluster_threshold", value = as.numeric(DB$schemeinfo[7, 2])) - }) - - # Shut off "Align Labels" control for UPGMA trees - shinyjs::disable('upgma_align') - shinyjs::disable('upgma_tiplab_linesize') - shinyjs::disable('upgma_tiplab_linetype') - - # Conditional disabling of control elemenmts - observe({ - - # Tiles for inward layout - if(input$nj_layout == "inward") { - shinyjs::disable('nj_tiles_show') - shinyjs::disable('nj_tiles_show_2') - shinyjs::disable('nj_tiles_show_3') - shinyjs::disable('nj_tiles_show_4') - shinyjs::disable('nj_tiles_show_5') - shinyjs::disable('nj_fruit_variable') - shinyjs::disable('nj_fruit_variable_2') - shinyjs::disable('nj_fruit_variable_3') - shinyjs::disable('nj_fruit_variable_4') - shinyjs::disable('nj_fruit_variable_5') - shinyjs::disable('nj_fruit_width') - shinyjs::disable('nj_fruit_width_2') - shinyjs::disable('nj_fruit_width_3') - shinyjs::disable('nj_fruit_width_4') - shinyjs::disable('nj_fruit_width_5') - shinyjs::disable('nj_fruit_offset') - shinyjs::disable('nj_fruit_offset_2') - shinyjs::disable('nj_fruit_offset_3') - shinyjs::disable('nj_fruit_offset_4') - shinyjs::disable('nj_fruit_offset_5') - } else { - shinyjs::enable('nj_tiles_show') - shinyjs::enable('nj_tiles_show_2') - shinyjs::enable('nj_tiles_show_3') - shinyjs::enable('nj_tiles_show_4') - shinyjs::enable('nj_tiles_show_5') - shinyjs::enable('nj_fruit_variable') - shinyjs::enable('nj_fruit_variable_2') - shinyjs::enable('nj_fruit_variable_3') - shinyjs::enable('nj_fruit_variable_4') - shinyjs::enable('nj_fruit_variable_5') - shinyjs::enable('nj_fruit_width') - shinyjs::enable('nj_fruit_width_2') - shinyjs::enable('nj_fruit_width_3') - shinyjs::enable('nj_fruit_width_4') - shinyjs::enable('nj_fruit_width_5') - shinyjs::enable('nj_fruit_offset') - shinyjs::enable('nj_fruit_offset_2') - shinyjs::enable('nj_fruit_offset_3') - shinyjs::enable('nj_fruit_offset_4') - shinyjs::enable('nj_fruit_offset_5') - } - - if(input$upgma_layout == "inward") { - shinyjs::disable('upgma_tiles_show') - shinyjs::disable('upgma_tiles_show_2') - shinyjs::disable('upgma_tiles_show_3') - shinyjs::disable('upgma_tiles_show_4') - shinyjs::disable('upgma_tiles_show_5') - shinyjs::disable('upgma_fruit_variable') - shinyjs::disable('upgma_fruit_variable_2') - shinyjs::disable('upgma_fruit_variable_3') - shinyjs::disable('upgma_fruit_variable_4') - shinyjs::disable('upgma_fruit_variable_5') - shinyjs::disable('upgma_fruit_width') - shinyjs::disable('upgma_fruit_width_2') - shinyjs::disable('upgma_fruit_width_3') - shinyjs::disable('upgma_fruit_width_4') - shinyjs::disable('upgma_fruit_width_5') - shinyjs::disable('upgma_fruit_offset') - shinyjs::disable('upgma_fruit_offset_2') - shinyjs::disable('upgma_fruit_offset_3') - shinyjs::disable('upgma_fruit_offset_4') - shinyjs::disable('upgma_fruit_offset_5') - } else { - shinyjs::enable('upgma_tiles_show') - shinyjs::enable('upgma_tiles_show_2') - shinyjs::enable('upgma_tiles_show_3') - shinyjs::enable('upgma_tiles_show_4') - shinyjs::enable('upgma_tiles_show_5') - shinyjs::enable('upgma_fruit_variable') - shinyjs::enable('upgma_fruit_variable_2') - shinyjs::enable('upgma_fruit_variable_3') - shinyjs::enable('upgma_fruit_variable_4') - shinyjs::enable('upgma_fruit_variable_5') - shinyjs::enable('upgma_fruit_width') - shinyjs::enable('upgma_fruit_width_2') - shinyjs::enable('upgma_fruit_width_3') - shinyjs::enable('upgma_fruit_width_4') - shinyjs::enable('upgma_fruit_width_5') - shinyjs::enable('upgma_fruit_offset') - shinyjs::enable('upgma_fruit_offset_2') - shinyjs::enable('upgma_fruit_offset_3') - shinyjs::enable('upgma_fruit_offset_4') - shinyjs::enable('upgma_fruit_offset_5') - } - - # Shut off branch labels for NJ and UPGMA plots for circular layout - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - shinyjs::disable('nj_show_branch_label') - } else { - shinyjs::enable('nj_show_branch_label') - } - - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - shinyjs::disable('upgma_show_branch_label') - } else { - shinyjs::enable('upgma_show_branch_label') - } - }) - - #### Generate Plot ---- - - hamming_nj <- reactive({ - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - - allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - - compute.distMatrix(allelic_profile_noNA_true, hamming.dist) - - } else if(input$na_handling == "ignore_na"){ - compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) - - } else { - compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) - } - - } else {compute.distMatrix(DB$allelic_profile_true, hamming.dist)} - }) - - hamming_mst <- reactive({ - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - - allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - - dist <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) - - } else if (input$na_handling == "ignore_na") { - dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) - } else { - dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) - } - } else { - dist <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) - } - - # Find indices of pairs with a distance of 0 - zero_distance_pairs <- as.data.frame(which(as.matrix(dist) == 0, arr.ind = TRUE)) - - zero_distance_pairs <- zero_distance_pairs[zero_distance_pairs$row != zero_distance_pairs$col, ] - - if(nrow(zero_distance_pairs) > 0) { - - # Sort each row so that x <= y - df_sorted <- t(apply(zero_distance_pairs, 1, function(row) sort(row))) - - # Remove duplicate rows - df_unique <- as.data.frame(unique(df_sorted)) - - colnames(df_unique) <- c("col", "row") - - # get metadata in df - vector_col <- character(0) - count <- 1 - for (i in df_unique$col) { - vector_col[count] <- Vis$meta_mst$`Assembly Name`[i] - count <- count + 1 - } - - vector_row <- character(0) - count <- 1 - for (i in df_unique$row) { - vector_row[count] <- Vis$meta_mst$`Assembly Name`[i] - count <- count + 1 - } - - col_id <- character(0) - count <- 1 - for (i in df_unique$col) { - col_id[count] <- Vis$meta_mst$`Assembly ID`[i] - count <- count + 1 - } - - row_id <- character(0) - count <- 1 - for (i in df_unique$row) { - row_id[count] <- Vis$meta_mst$`Assembly ID`[i] - count <- count + 1 - } - - col_index <- character(0) - count <- 1 - for (i in df_unique$col) { - col_index[count] <- Vis$meta_mst$Index[i] - count <- count + 1 - } - - row_index <- character(0) - count <- 1 - for (i in df_unique$row) { - row_index[count] <- Vis$meta_mst$Index[i] - count <- count + 1 - } - - col_date <- character(0) - count <- 1 - for (i in df_unique$col) { - col_date[count] <- Vis$meta_mst$`Isolation Date`[i] - count <- count + 1 - } - - row_date <- character(0) - count <- 1 - for (i in df_unique$row) { - row_date[count] <- Vis$meta_mst$`Isolation Date`[i] - count <- count + 1 - } - - col_host <- character(0) - count <- 1 - for (i in df_unique$col) { - col_host[count] <- Vis$meta_mst$Host[i] - count <- count + 1 - } - - row_host <- character(0) - count <- 1 - for (i in df_unique$row) { - row_host[count] <- Vis$meta_mst$Host[i] - count <- count + 1 - } - - col_country <- character(0) - count <- 1 - for (i in df_unique$col) { - col_country[count] <- Vis$meta_mst$Country[i] - count <- count + 1 - } - - row_country <- character(0) - count <- 1 - for (i in df_unique$row) { - row_country[count] <- Vis$meta_mst$Country[i] - count <- count + 1 - } - - col_city <- character(0) - count <- 1 - for (i in df_unique$col) { - col_city[count] <- Vis$meta_mst$City[i] - count <- count + 1 - } - - row_city <- character(0) - count <- 1 - for (i in df_unique$row) { - row_city[count] <- Vis$meta_mst$City[i] - count <- count + 1 - } - - df_unique <- cbind(df_unique, col_name = vector_col, row_name = vector_row, - col_index = col_index, row_index = row_index, col_id = col_id, - row_id = row_id, col_date = col_date, row_date = row_date, - col_host = col_host, row_host = row_host, col_country = col_country, - row_country = row_country, col_city = col_city, row_city = row_city) - - # Add groups - grouped_df <- df_unique %>% - group_by(col) %>% - mutate(group_id = cur_group_id()) - - # Merge groups - name <- character(0) - index <- character(0) - id <- character(0) - count <- 1 - for (i in grouped_df$group_id) { - name[count] <- paste(unique(append(grouped_df$col_name[which(grouped_df$group_id == i)], - grouped_df$row_name[which(grouped_df$group_id == i)])), - collapse = "\n") - - id[count] <- paste(unique(append(grouped_df$col_id[which(grouped_df$group_id == i)], - grouped_df$row_id[which(grouped_df$group_id == i)])), - collapse = "\n") - - index[count] <- paste(unique(append(grouped_df$col_index[which(grouped_df$group_id == i)], - grouped_df$row_index[which(grouped_df$group_id == i)])), - collapse = "\n") - - count <- count + 1 - } - - merged_names <- cbind(grouped_df, "Index" = index, "Assembly Name" = name, "Assembly ID" = id) - - # remove duplicate groups - - final <- merged_names[!duplicated(merged_names$group_id), ] - - final_cleaned <- final[!(final$col_name %in% final$row_name),] - - final_cleaned <- select(final_cleaned, 3, 17:20) - - # adapt metadata - Date_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - Date <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - Date <- append(Date, Vis$meta_mst$`Isolation Date`[which(Vis$meta_mst$Index == i)]) - } - Date_merged <- append(Date_merged, paste(Date, collapse = "\n")) - } - - Host_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - Host <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - Host <- append(Host, Vis$meta_mst$Host[which(Vis$meta_mst$Index == i)]) - } - Host_merged <- append(Host_merged, paste(Host, collapse = "\n")) - } - - Country_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - Country <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - Country <- append(Country, Vis$meta_mst$Country[which(Vis$meta_mst$Index == i)]) - } - Country_merged <- append(Country_merged, paste(Country, collapse = "\n")) - } - - City_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - City <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - City <- append(City, Vis$meta_mst$City[which(Vis$meta_mst$Index == i)]) - } - City_merged <- append(City_merged, paste(City, collapse = "\n")) - } - - final_meta <- cbind(final_cleaned, "Isolation Date" = Date_merged, - "Host" = Host_merged, "Country" = Country_merged, "City" = City_merged) - - - # Merging with original data frame / allelic profile - - allelic_profile_true <- DB$allelic_profile_true - meta_true <- Vis$meta_mst - - rownames(allelic_profile_true) <- Vis$meta_mst$`Assembly Name` - rownames(meta_true) <- Vis$meta_mst$`Assembly Name` - - omit <- unique(append(df_unique$col_name, df_unique$row_name)) %in% final_cleaned$col_name - - omit_id <- unique(append(df_unique$col_name, df_unique$row_name))[!omit] - - remove <- !(rownames(allelic_profile_true) %in% omit_id) - - allelic_profile_clean <- allelic_profile_true[remove, ] - - meta_clean <- meta_true[remove, ] - - # substitute meta assembly names with group names - - count <- 1 - for(i in which(rownames(meta_clean) %in% final_meta$col_name)) { - meta_clean$Index[i] <- final_meta$Index[count] - meta_clean$`Assembly Name`[i] <- final_meta$`Assembly Name`[count] - meta_clean$`Assembly ID`[i] <- final_meta$`Assembly ID`[count] - meta_clean$`Isolation Date`[i] <- final_meta$`Isolation Date`[count] - meta_clean$Host[i] <- final_meta$Host[count] - meta_clean$Country[i] <- final_meta$Country[count] - meta_clean$City[i] <- final_meta$City[count] - count <- count + 1 - } - - # Metadata completion - # get group size - - size_vector <- numeric(0) - for(i in 1:nrow(meta_clean)) { - if (str_count(meta_clean$`Assembly Name`[i], "\n") == 0) { - size_vector[i] <- 1 - } else { - size_vector[i] <- str_count(meta_clean$`Assembly Name`[i], "\n") +1 - } - } - - meta_clean <- mutate(meta_clean, size = size_vector) - - # get font size dependent on group size - - font_size <- numeric(nrow(meta_clean)) - - for (i in 1:length(font_size)) { - if(meta_clean$size[i] < 3) { - font_size[i] <- 12 - } else { - font_size[i] <- 11 - } - } - - # get v-align dependent on group size - valign <- numeric(nrow(meta_clean)) - - for (i in 1:length(valign)) { - if(meta_clean$size[i] == 1) { - valign[i] <- -30 - } else if(meta_clean$size[i] == 2) { - valign[i] <- -38 - } else if(meta_clean$size[i] == 3) { - valign[i] <- -46 - } else if(meta_clean$size[i] == 4) { - valign[i] <- -54 - } else if(meta_clean$size[i] == 5) { - valign[i] <- -62 - } else if(meta_clean$size[i] > 5) { - valign[i] <- -70 - } - } - - Vis$unique_meta <- meta_clean %>% - cbind(font_size = font_size, valign = valign) - - # final dist calculation - - if(anyNA(DB$allelic_profile)){ - if(input$na_handling == "omit") { - allelic_profile_clean_noNA_names <- allelic_profile_clean[, colSums(is.na(allelic_profile_clean)) == 0] - compute.distMatrix(allelic_profile_clean_noNA_names, hamming.dist) - } else if (input$na_handling == "ignore_na") { - compute.distMatrix(allelic_profile_clean, hamming.distIgnore) - } else { - compute.distMatrix(allelic_profile_clean, hamming.distCategory) - } - } else {compute.distMatrix(allelic_profile_clean, hamming.dist)} - - - } else { - font_size <- rep(12, nrow(Vis$meta_mst)) - valign <- rep(-30, nrow(Vis$meta_mst)) - size <- rep(1, nrow(Vis$meta_mst)) - Vis$unique_meta <- Vis$meta_mst %>% - cbind(size , font_size, valign) - - dist - } - - }) - - observeEvent(input$create_tree, { - log_print("Input create_tree") - - if(is.null(DB$data)) { - log_print("Missing data") - - show_toast( - title = "Missing data", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else if(nrow(DB$allelic_profile_true) < 3) { - log_print("Min. of 3 entries required for visualization") - - show_toast( - title = "Min. of 3 entries required for visualization", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - - if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { - log_print("Duplicated assemblies") - - dup_name <- which(duplicated(DB$meta_true$`Assembly Name`)) - dup_id <- which(duplicated(DB$meta_true$`Assembly ID`)) - - showModal( - modalDialog( - if((length(dup_name) + length(dup_id)) == 1) { - if(length(dup_name) == 1) { - HTML(paste0("Entry #", dup_name, - " contains a duplicated assembly name:", "

", - DB$meta_true$`Assembly Name`[dup_name])) - } else { - HTML(paste0("Entry #", dup_id, - " contains a duplicated assembly ID:", "

", - DB$meta_true$`Assembly ID`[dup_id])) - } - } else { - if(length(dup_name) == 0) { - HTML(c("Entries contain duplicated IDs

", - paste0(unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) - } else if(length(dup_id) == 0) { - HTML(c("Entries contain duplicated names

", - paste0(unique(DB$meta_true$`Assembly Name`[dup_name]), "
"))) - } else { - HTML(c("Entries contain duplicated names and IDs

", - paste0("Name: ", unique(DB$meta_true$`Assembly Name`[dup_name]), "
"), - paste0("ID: ", unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) - } - }, - title = "Duplicate entries", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("change_entries", "Go to Entry Table", class = "btn btn-default") - ) - ) - ) - } else { - - set.seed(1) - - if (input$tree_algo == "Neighbour-Joining") { - - log_print("Rendering NJ tree") - - output$nj_field <- renderUI({ - addSpinner( - plotOutput("tree_nj", width = paste0(as.character(as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), "px"), height = paste0(as.character(input$nj_scale), "px")), - spin = "dots", - color = "#ffffff" - ) - }) - - Vis$meta_nj <- select(DB$meta_true, -2) - - if(length(unique(gsub(" ", "_", colnames(Vis$meta_nj)))) < length(gsub(" ", "_", colnames(Vis$meta_nj)))) { - show_toast( - title = "Conflicting Custom Variable Names", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - # Create phylogenetic tree data - Vis$nj <- ape::nj(hamming_nj()) - - # Create phylogenetic tree meta data - Vis$meta_nj <- mutate(Vis$meta_nj, taxa = Index) %>% - relocate(taxa) - - # Get number of included entries calculate start values for tree - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_nj <- 5.5 - Vis$tippointsize_nj <- 5.5 - Vis$nodepointsize_nj <- 4 - Vis$tiplab_padding_nj <- 0.25 - Vis$branch_size_nj <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_nj <- 5 - Vis$tippointsize_nj <- 5 - Vis$nodepointsize_nj <- 3.5 - Vis$tiplab_padding_nj <- 0.2 - Vis$branch_size_nj <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_nj <- 4.5 - Vis$tippointsize_nj <- 4.5 - Vis$nodepointsize_nj <- 3 - Vis$tiplab_padding_nj <- 0.15 - Vis$branch_size_nj <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_nj <- 4 - Vis$tippointsize_nj <- 4 - Vis$nodepointsize_nj <- 2.5 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_nj <- 3.5 - Vis$tippointsize_nj <- 3.5 - Vis$nodepointsize_nj <- 2 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 2.5 - } else { - Vis$labelsize_nj <- 3 - Vis$tippointsize_nj <- 3 - Vis$nodepointsize_nj <- 1.5 - Vis$tiplab_padding_nj <- 0.05 - Vis$branch_size_nj <- 2 - } - } else { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_nj <- 5 - Vis$tippointsize_nj <- 5 - Vis$nodepointsize_nj <- 4 - Vis$tiplab_padding_nj <- 0.25 - Vis$branch_size_nj <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_nj <- 4.5 - Vis$tippointsize_nj <- 4.5 - Vis$nodepointsize_nj <- 3.5 - Vis$tiplab_padding_nj <- 0.2 - Vis$branch_size_nj <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_nj <- 4 - Vis$tippointsize_nj <- 4 - Vis$nodepointsize_nj <- 3 - Vis$tiplab_padding_nj <- 0.15 - Vis$branch_size_nj <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_nj <- 3.5 - Vis$tippointsize_nj <- 3.5 - Vis$nodepointsize_nj <- 2.5 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_nj <- 3 - Vis$tippointsize_nj <- 3 - Vis$nodepointsize_nj <- 2 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 2.5 - } else { - Vis$labelsize_nj <- 2.5 - Vis$tippointsize_nj <- 2.5 - Vis$nodepointsize_nj <- 1.5 - Vis$tiplab_padding_nj <- 0.05 - Vis$branch_size_nj <- 2 - } - } - } else { - Vis$labelsize_nj <- 4 - Vis$tippointsize_nj <- 4 - Vis$nodepointsize_nj <- 2.5 - Vis$tiplab_padding_nj <- 0.2 - Vis$branch_size_nj <- 3.5 - } - - Vis$nj_tree <- ggtree(Vis$nj) - - # Get upper and lower end of x range - Vis$nj_max_x <- max(Vis$nj_tree$data$x) - Vis$nj_min_x <- min(Vis$nj_tree$data$x) - - # Get parent node numbers - Vis$nj_parentnodes <- Vis$nj_tree$data$parent - - # Update visualization control inputs - if(!is.null(input$nj_tiplab_size)) { - updateNumericInput(session, "nj_tiplab_size", value = Vis$labelsize_nj) - } - if(!is.null(input$nj_tippoint_size)) { - updateSliderInput(session, "nj_tippoint_size", value = Vis$tippointsize_nj) - } - if(!is.null(input$nj_nodepoint_size)) { - updateSliderInput(session, "nj_nodepoint_size", value = Vis$nodepointsize_nj) - } - if(!is.null(input$nj_tiplab_padding)) { - updateSliderInput(session, "nj_tiplab_padding", value = Vis$tiplab_padding_nj) - } - if(!is.null(input$nj_branch_size)) { - updateNumericInput(session, "nj_branch_size", value = Vis$branch_size_nj) - } - if(!is.null(input$nj_treescale_width)) { - updateNumericInput(session, "nj_treescale_width", value = round(ceiling(Vis$nj_max_x) * 0.1, 0)) - } - if(!is.null(input$nj_rootedge_length)) { - updateSliderInput(session, "nj_rootedge_length", value = round(ceiling(Vis$nj_max_x) * 0.05, 0)) - } - - output$tree_nj <- renderPlot({ - nj_tree() - }) - - Vis$nj_true <- TRUE - } - } else if (input$tree_algo == "UPGMA") { - - log_print("Rendering UPGMA tree") - - output$upgma_field <- renderUI({ - addSpinner( - plotOutput("tree_upgma", width = paste0(as.character(as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), "px"), height = paste0(as.character(input$upgma_scale), "px")), - spin = "dots", - color = "#ffffff" - ) - }) - - Vis$meta_upgma <- select(DB$meta_true, -2) - - if(length(unique(gsub(" ", "_", colnames(Vis$meta_upgma)))) < length(gsub(" ", "_", colnames(Vis$meta_upgma)))) { - show_toast( - title = "Conflicting Custom Variable Names", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - # Create phylogenetic tree data - Vis$upgma <- phangorn::upgma(hamming_nj()) - - # Create phylogenetic tree meta data - Vis$meta_upgma <- mutate(Vis$meta_upgma, taxa = Index) %>% - relocate(taxa) - - # Get number of included entries calculate start values for tree - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_upgma <- 5.5 - Vis$tippointsize_upgma <- 5.5 - Vis$nodepointsize_upgma <- 4 - Vis$tiplab_padding_upgma <- 0.25 - Vis$branch_size_upgma <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_upgma <- 5 - Vis$tippointsize_upgma <- 5 - Vis$nodepointsize_upgma <- 3.5 - Vis$tiplab_padding_upgma <- 0.2 - Vis$branch_size_upgma <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_upgma <- 4.5 - Vis$tippointsize_upgma <- 4.5 - Vis$nodepointsize_upgma <- 3 - Vis$tiplab_padding_upgma <- 0.15 - Vis$branch_size_upgma <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_upgma <- 4 - Vis$tippointsize_upgma <- 4 - Vis$nodepointsize_upgma <- 2.5 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_upgma <- 3.5 - Vis$tippointsize_upgma <- 3.5 - Vis$nodepointsize_upgma <- 2 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 2.5 - } else { - Vis$labelsize_upgma <- 3 - Vis$tippointsize_upgma <- 3 - Vis$nodepointsize_upgma <- 1.5 - Vis$tiplab_padding_upgma <- 0.05 - Vis$branch_size_upgma <- 2 - } - } else { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_upgma <- 5 - Vis$tippointsize_upgma <- 5 - Vis$nodepointsize_upgma <- 4 - Vis$tiplab_padding_upgma <- 0.25 - Vis$branch_size_upgma <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_upgma <- 4.5 - Vis$tippointsize_upgma <- 4.5 - Vis$nodepointsize_upgma <- 3.5 - Vis$tiplab_padding_upgma <- 0.2 - Vis$branch_size_upgma <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_upgma <- 4 - Vis$tippointsize_upgma <- 4 - Vis$nodepointsize_upgma <- 3 - Vis$tiplab_padding_upgma <- 0.15 - Vis$branch_size_upgma <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_upgma <- 3.5 - Vis$tippointsize_upgma <- 3.5 - Vis$nodepointsize_upgma <- 2.5 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_upgma <- 3 - Vis$tippointsize_upgma <- 3 - Vis$nodepointsize_upgma <- 2 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 2.5 - } else { - Vis$labelsize_upgma <- 2.5 - Vis$tippointsize_upgma <- 2.5 - Vis$nodepointsize_upgma <- 1.5 - Vis$tiplab_padding_upgma <- 0.05 - Vis$branch_size_upgma <- 2 - } - } - } else { - Vis$labelsize_upgma <- 4 - Vis$tippointsize_upgma <- 4 - Vis$nodepointsize_upgma <- 2.5 - Vis$tiplab_padding_upgma <- 0.2 - Vis$branch_size_upgma <- 3.5 - } - - Vis$upgma_tree <- ggtree(Vis$upgma) - - # Get upper and lower end of x range - Vis$upgma_max_x <- max(Vis$upgma_tree$data$x) - Vis$upgma_min_x <- min(Vis$upgma_tree$data$x) - - # Get parent node numbers - Vis$upgma_parentnodes <- Vis$upgma_tree$data$parent - - # Update visualization control inputs - if(!is.null(input$upgma_tiplab_size)) { - updateNumericInput(session, "upgma_tiplab_size", value = Vis$labelsize_upgma) - } - if(!is.null(input$upgma_tippoint_size)) { - updateSliderInput(session, "upgma_tippoint_size", value = Vis$tippointsize_upgma) - } - if(!is.null(input$upgma_nodepoint_size)) { - updateSliderInput(session, "upgma_nodepoint_size", value = Vis$nodepointsize_upgma) - } - if(!is.null(input$upgma_tiplab_padding)) { - updateSliderInput(session, "upgma_tiplab_padding", value = Vis$tiplab_padding_upgma) - } - if(!is.null(input$upgma_branch_size)) { - updateNumericInput(session, "upgma_branch_size", value = Vis$branch_size_upgma) - } - if(!is.null(input$upgma_treescale_width)) { - updateNumericInput(session, "upgma_treescale_width", value = round(ceiling(Vis$upgma_max_x) * 0.1, 0)) - } - if(!is.null(input$upgma_rootedge_length)) { - updateSliderInput(session, "upgma_rootedge_length", value = round(ceiling(Vis$upgma_max_x) * 0.05, 0)) - } - - output$tree_upgma <- renderPlot({ - upgma_tree() - }) - - Vis$upgma_true <- TRUE - } - } else { - - log_print("Rendering MST graph") - - output$mst_field <- renderUI({ - if(input$mst_background_transparent == TRUE) { - visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")) - } else { - addSpinner( - visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")), - spin = "dots", - color = "#ffffff" - ) - } - }) - - if(nrow(DB$meta_true) > 100) { - - log_print("Over 100 isolates in MST graph") - - show_toast( - title = "Computation might take a while", - type = "warning", - position = "bottom-end", - timer = 10000 - ) - } - - meta_mst <- DB$meta_true - Vis$meta_mst <- meta_mst - - # prepare igraph object - Vis$ggraph_1 <- hamming_mst() |> - as.matrix() |> - graph.adjacency(weighted = TRUE) |> - igraph::mst() - - output$tree_mst <- renderVisNetwork({ - mst_tree() - }) - - Vis$mst_true <- TRUE - } - } - } - }) - - # _______________________ #### - - ## Report ---- - - observe({ - if(!is.null(DB$data)) { - if(!is.null(input$tree_algo)) { - if(input$tree_algo == "Minimum-Spanning") { - shinyjs::disable("rep_plot_report") - updateCheckboxInput(session, "rep_plot_report", value = FALSE) - } else { - shinyjs::enable("rep_plot_report") - } - } - } - }) - - ### Report creation UI ---- - - observeEvent(input$create_rep, { - - if((input$tree_algo == "Minimum-Spanning" & isTRUE(Vis$mst_true)) | - (input$tree_algo == "UPGMA" & isTRUE(Vis$upgma_true)) | - (input$tree_algo == "Neighbour-Joining" & isTRUE(Vis$nj_true))) { - # Get currently selected missing value handling option - if(input$na_handling == "ignore_na") { - na_handling <- "Ignore missing values for pairwise comparison" - } else if(input$na_handling == "omit") { - na_handling <- "Omit loci with missing values for all assemblies" - } else if(input$na_handling == "category") { - na_handling <- "Treat missing values as allele variant" - } - - extra_var <- character() - if(input$tree_algo == "Minimum-Spanning") { - shinyjs::runjs("mstReport();") - if(isTRUE(input$mst_color_var)) { - extra_var <- c(extra_var, input$mst_col_var) - } - } else if(input$tree_algo == "Neighbour-Joining") { - if(isTRUE(input$nj_mapping_show)) { - extra_var <- c(extra_var, input$nj_color_mapping) - } - if(isTRUE(input$nj_tipcolor_mapping_show)) { - extra_var <- c(extra_var, input$nj_tipcolor_mapping) - } - if(isTRUE(input$nj_tipshape_mapping_show)) { - extra_var <- c(extra_var, input$nj_tipshape_mapping) - } - if(isTRUE(input$nj_tiles_show_1)) { - extra_var <- c(extra_var, input$nj_fruit_variable) - } - if(isTRUE(input$nj_tiles_show_2)) { - extra_var <- c(extra_var, input$nj_fruit_variable_2) - } - if(isTRUE(input$nj_tiles_show_3)) { - extra_var <- c(extra_var, input$nj_fruit_variable_3) - } - if(isTRUE(input$nj_tiles_show_4)) { - extra_var <- c(extra_var, input$nj_fruit_variable_4) - } - if(isTRUE(input$nj_tiles_show_5)) { - extra_var <- c(extra_var, input$nj_fruit_variable_5) - } - if(isTRUE(input$nj_heatmap_show)) { - extra_var <- c(extra_var, input$nj_heatmap_select) - } - } else if(input$tree_algo == "UPGMA") { - if(isTRUE(input$UPGMA_mapping_show)) { - extra_var <- c(extra_var, input$UPGMA_color_mapping) - } - if(isTRUE(input$UPGMA_tipcolor_mapping_show)) { - extra_var <- c(extra_var, input$UPGMA_tipcolor_mapping) - } - if(isTRUE(input$UPGMA_tipshape_mapping_show)) { - extra_var <- c(extra_var, input$UPGMA_tipshape_mapping) - } - if(isTRUE(input$UPGMA_tiles_show_1)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable) - } - if(isTRUE(input$UPGMA_tiles_show_2)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_2) - } - if(isTRUE(input$UPGMA_tiles_show_3)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_3) - } - if(isTRUE(input$UPGMA_tiles_show_4)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_4) - } - if(isTRUE(input$UPGMA_tiles_show_5)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_5) - } - if(isTRUE(input$UPGMA_heatmap_show)) { - extra_var <- c(extra_var, input$UPGMA_heatmap_select) - } - } - - showModal( - modalDialog( - fluidRow( - column( - width = 12, - fluidRow( - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color:black; font-size: 15px; font-weight: 900', 'General') - ) - ) - ), - column( - width = 3, - align = "left", - checkboxInput( - "rep_general", - label = "", - value = TRUE - ) - ) - ), - fluidRow( - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - checkboxInput( - "rep_date_general", - label = h5("Date", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 7, - dateInput( - "mst_date_general_select", - "", - max = Sys.Date() - ) - ) - ), - fluidRow( - column( - width = 3, - checkboxInput( - "rep_operator_general", - label = h5("Operator", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - textInput( - "mst_operator_general_select", - "" - ) - ) - ), - fluidRow( - column( - width = 3, - checkboxInput( - "rep_institute_general", - label = h5("Institute", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - textInput( - "mst_institute_general_select", - "" - ) - ) - ), - fluidRow( - column( - width = 3, - checkboxInput( - "rep_comm_general", - label = h5("Comment", style = "color:black;") - ) - ), - column( - width = 8, - textAreaInput( - inputId = "mst_comm_general_select", - label = "", - width = "100%", - height = "60px", - cols = NULL, - rows = NULL, - placeholder = NULL, - resize = "vertical" - ) - ) - ) - ) - ), - hr(), - fluidRow( - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Isolate Table') - ) - ) - ), - column( - width = 3, - align = "left", - checkboxInput( - "rep_entrytable", - label = "", - value = TRUE - ) - ), - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Include Plot') - ) - ) - ), - column( - width = 1, - align = "left", - checkboxInput( - "rep_plot_report", - label = "", - value = TRUE - ) - ) - ), - fluidRow( - column( - width = 6, - align = "left", - div( - class = "rep_tab_sel", - pickerInput("select_rep_tab", - label = "", - choices = names(DB$meta)[-2], - selected = c("Assembly Name", "Scheme", "Isolation Date", - "Host", "Country", "City", extra_var), - options = list( - size = 10, - `actions-box` = TRUE, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE) - ) - ) - ), - hr(), - fluidRow( - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Analysis Parameter') - ) - ) - ), - column( - width = 3, - align = "left", - checkboxInput( - "rep_analysis", - label = "", - value = TRUE - ) - ) - ), - fluidRow( - column( - width = 6, - align = "left", - fluidRow( - column( - width = 4, - checkboxInput( - "rep_cgmlst_analysis", - label = h5("Scheme", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic', DB$scheme) - ) - ) - ) - ), - fluidRow( - column( - width = 4, - checkboxInput( - "rep_tree_analysis", - label = h5("Tree", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic', input$tree_algo) - ) - ) - ) - ) - ), - column( - width = 6, - align = "left", - fluidRow( - column(2), - column( - width = 4, - checkboxInput( - "rep_distance", - label = h5("Distance", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 5, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic', 'Hamming') - ) - ) - ) - ), - fluidRow( - column(2), - column( - width = 4, - checkboxInput( - "rep_version", - label = h5("Version", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 5, - align = "right", - HTML( - paste( - tags$span(style='color:black; position: relative; top: 17px; font-style: italic', phylotraceVersion) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 3, - align = "left", - checkboxInput( - "rep_missval", - label = h5("NA handling", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 7, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic; right: 35px;', na_handling) - ) - ) - ) - ) - ) - ), - title = "cgMLST Report Generation", - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - downloadBttn( - "download_report", - style = "simple", - label = "Save", - size = "sm", - icon = icon("download") - ) - ) - ) - ) - } else { - show_toast( - title = "No tree created", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - - observe({ - if(!is.null(input$rep_general)) { - if(isFALSE(input$rep_general)) { - shinyjs::disable('rep_date_general') - shinyjs::disable('rep_operator_general') - shinyjs::disable('rep_institute_general') - shinyjs::disable('rep_comm_general') - shinyjs::disable('mst_date_general_select') - shinyjs::disable('mst_operator_general_select') - shinyjs::disable('mst_institute_general_select') - shinyjs::disable('mst_comm_general_select') - } else { - shinyjs::enable('rep_date_general') - shinyjs::enable('rep_operator_general') - shinyjs::enable('rep_institute_general') - shinyjs::enable('rep_comm_general') - shinyjs::enable('mst_date_general_select') - shinyjs::enable('mst_operator_general_select') - shinyjs::enable('mst_institute_general_select') - shinyjs::enable('mst_comm_general_select') - } - } - - if(!is.null(input$rep_analysis)) { - if(isFALSE(input$rep_analysis)) { - shinyjs::disable('rep_cgmlst_analysis') - shinyjs::disable('rep_tree_analysis') - shinyjs::disable('rep_distance') - shinyjs::disable('rep_missval') - shinyjs::disable('rep_version') - } else { - shinyjs::enable('rep_cgmlst_analysis') - shinyjs::enable('rep_tree_analysis') - shinyjs::enable('rep_distance') - shinyjs::enable('rep_missval') - shinyjs::enable('rep_version') - } - } - - if(length(input$select_rep_tab) > 0) { - updateCheckboxInput(session, "rep_entrytable", value = TRUE) - } else { - updateCheckboxInput(session, "rep_entrytable", value = FALSE) - } - }) - - ### Save Report ---- - - #### Get Report elements ---- - - observe({ - if(!is.null(DB$data)){ - if(!is.null(input$tree_algo)) { - req(c(input$rep_entrytable, input$rep_general, - input$rep_date_general, input$rep_operator_general, - input$rep_institute_general, input$rep_comm_general, - input$rep_analysis, input$rep_cgmlst_analysis, - input$rep_tree_analysis, input$rep_distance, - input$rep_missval, input$rep_version, - input$rep_plot_report, input$select_rep_tab)) - Report$report_df <- data.frame(Element = c("entry_table", "general_show", - "general_date", "operator", - "institute", "comment", - "analysis_show", "scheme", - "tree", "distance", "na_handling", "version", - "plot"), - Include = c(input$rep_entrytable, input$rep_general, - input$rep_date_general, input$rep_operator_general, - input$rep_institute_general, input$rep_comm_general, - input$rep_analysis, input$rep_cgmlst_analysis, - input$rep_tree_analysis, input$rep_distance, - input$rep_missval, input$rep_version, - input$rep_plot_report)) - } - } - }) - - #### Get Report values ---- - - observeEvent(input$create_tree, { - if(input$tree_algo == "Minimum-Spanning") { - Report$report_list_mst <- list(entry_table = DB$meta_true, - scheme = DB$schemeinfo, - tree = input$tree_algo, - na_handling = if(anyNA(DB$allelic_profile_true)){input$na_handling} else {NULL}, - distance = "Hamming Distances", - version = c(phylotraceVersion, "2.5.1"), - plot = "MST") - } else if(input$tree_algo == "Neighbour-Joining") { - Report$report_list_nj <- list(entry_table = DB$meta_true, - scheme = DB$schemeinfo, - tree = input$tree_algo, - na_handling = input$na_handling, - distance = "Hamming Distances", - version = c(phylotraceVersion, "2.5.1"), - plot = "NJ") - } else { - Report$report_list_upgma <- list(entry_table = DB$meta_true, - scheme = DB$schemeinfo, - tree = input$tree_algo, - na_handling = input$na_handling, - distance = "Hamming Distances", - version = c(phylotraceVersion, "2.5.1"), - plot = "UPGMA") - } - }) - - # Save plot for Report - plot.report <- reactive({ - if(input$tree_algo == "Neighbour-Joining") { - jpeg(paste0(getwd(), "/Report/NJ.jpeg"), width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) - print(nj_tree()) - dev.off() - } else if(input$tree_algo == "UPGMA") { - jpeg(paste0(getwd(), "/Report/UPGMA.jpeg"), width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) - print(upgma_tree()) - dev.off() - } else if (input$tree_algo == "Minimum-Spanning") { - shinyjs::runjs("mstReport();") - decoded_data <- base64enc::base64decode(input$canvas_data) - writeBin(decoded_data, paste0(getwd(), "/Report/MST.jpg")) - } - }) - - #### Event Save Report ---- - output$download_report <- downloadHandler( - filename = function() { - if(input$tree_algo == "Minimum-Spanning") { - paste0("MST_Report_", Sys.Date(), ".html") - } else if(input$tree_algo == "Neighbour-Joining") { - paste0("NJ_Report_", Sys.Date(), ".html") - } else {paste0("UPGMA_Report_", Sys.Date(), ".html")} - }, - content = function(file) { - if(input$tree_algo == "Minimum-Spanning") { - plot.report() - - report <- c(Report$report_list_mst, - "general_date" = as.character(input$mst_date_general_select), - "operator" = input$mst_operator_general_select, - "institute" = input$mst_institute_general_select, - "comment" = input$mst_comm_general_select, - "report_df" = Report$report_df) - - report[["table_columns"]] <- input$select_rep_tab - - # Save data to an RDS file if any elements were selected - if (!is.null(report)) { - - log_print("Creating MST report") - - saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) - - rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) - - file.copy(paste0(getwd(), "/Report/Report.html"), file) - } else { - log_print("Creating MST report failed (report is null)") - } - } else if(input$tree_algo == "Neighbour-Joining") { - plot.report() - report <- c(Report$report_list_nj, - "general_date" = as.character(input$mst_date_general_select), - "operator" = input$mst_operator_general_select, - "institute" = input$mst_institute_general_select, - "comment" = input$mst_comm_general_select, - "report_df" = Report$report_df) - - report[["table_columns"]] <- input$select_rep_tab - - # Save data to an RDS file if any elements were selected - if (!is.null(report)) { - log_print("Creating NJ report") - - saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) - - rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) - - file.copy(paste0(getwd(), "/Report/Report.html"), file) - } else { - log_print("Creating NJ report failed (report is null)") - } - - } else { - plot.report() - report <- c(Report$report_list_upgma, - "general_date" = as.character(input$mst_date_general_select), - "operator" = input$mst_operator_general_select, - "institute" = input$mst_institute_general_select, - "comment" = input$mst_comm_general_select, - "report_df" = Report$report_df) - - report[["table_columns"]] <- input$select_rep_tab - - # Save data to an RDS file if any elements were selected - if (!is.null(report)) { - log_print("Creating UPGMA report") - - saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) - - rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) - - file.copy(paste0(getwd(), "/Report/Report.html"), file) - } else { - log_print("Creating UPGMA report failed (report is null)") - } - - } - removeModal() - } - ) - - - # _______________________ #### - - ## Gene Screening ---- - - ### Render UI Elements ---- - - # Rendering results table - output$gs_results_table <- renderUI({ - req(DB$data) - if(!is.null(Screening$selected_isolate)) { - if(length(Screening$selected_isolate) > 0) { - fluidRow( - div(class = "loci_table", - DT::dataTableOutput("gs_profile_table")), - br(), - HTML( - paste0("", - 'RSL = Reference Sequence Length  |  ', - '%CRS = % Coverage of Reference Sequence  |  ', - '%IRS = % Identity to Reference Sequence  |  ', - 'ACS = Accession of Closest Sequence  |  ', - 'NCS = Name of Closest Sequence') - - ) - ) - } else { - fluidRow( - br(), br(), - p( - HTML( - paste0("", - 'Select entry from the table to display resistance profile') - - ) - ) - ) - } - } else { - fluidRow( - br(), br(), - p( - HTML( - paste0("", - 'Select entry from the table to display resistance profile') - - ) - ) - ) - } - }) - - # Gene screening download button - output$gs_download <- renderUI({ - req(DB$data) - if(!is.null(Screening$selected_isolate)) { - if(length(Screening$selected_isolate) > 0) { - fluidRow( - downloadBttn( - "download_resistance_profile", - style = "simple", - label = "Profile Table", - size = "sm", - icon = icon("download"), - color = "primary" - ), - bsTooltip("download_resistance_profile_bttn", - HTML(paste0("Save resistance profile table for
", - Screening$selected_isolate)), - placement = "bottom", trigger = "hover") - ) - } else {NULL} - } else {NULL} - }) - - # Conditionally render table selectiom interface - output$gs_table_selection <- renderUI({ - req(DB$data, input$gs_view) - if(input$gs_view == "Table") { - fluidRow( - column(1), - column( - width = 10, - div(class = "loci_table", - dataTableOutput("gs_isolate_table")) - ) - ) - } else {NULL} - }) - - # Resistance profile table output display - output$gs_profile_display <- renderUI({ - req(DB$data) - if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { - if(input$gs_view == "Table") { - column( - width = 10, - hr(), - fluidRow( - column( - width = 4, - p( - HTML( - paste0("", - "Gene Screening Results
", - "", - "Comprising genes for resistance, virulence, stress, etc.") - ) - ) - ), - column( - width = 4, - uiOutput("gs_download") - ) - ), - br(), - uiOutput("gs_results_table") - ) - } else { - column( - width = 10, - fluidRow( - column( - width = 4, - p( - HTML( - paste0("", - "Gene Screening Results
", - "", - "Comprising genes for resistance, virulence, stress, etc.") - ) - ) - ), - column( - width = 4, - div( - class = "gs-picker", - pickerInput( - "gs_profile_select", - "", - choices = list( - Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] - }, - Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "No")] - }, - `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] - } - ), - choicesOpt = list( - disabled = c( - rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) - ) - ), - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ) - ) - ) - ), - column( - width = 3, - uiOutput("gs_download") - ) - ), - br(), - uiOutput("gs_results_table") - ) - } - } else {NULL} - }) - - # Screening sidebar - output$screening_sidebar <- renderUI({ - req(DB$data) - if(!is.null(DB$meta_gs)) { - column( - width = 12, - align = "center", - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Toggle View') - ) - ) - ), - radioGroupButtons( - inputId = "gs_view", - choices = c("Picker", "Table"), - selected = "Picker", - checkIcon = list( - yes = icon("square-check"), - no = icon("square") - ) - ), - br() - ) - } else {NULL} - }) - - # Resistance profile table - observe({ - req(DB$meta_gs, Screening$selected_isolate, DB$database, DB$scheme, DB$data) - - if(length(Screening$selected_isolate) > 0 & any(Screening$selected_isolate %in% DB$data$`Assembly ID`)) { - iso_select <- Screening$selected_isolate - iso_path <- file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", - iso_select, "resProfile.tsv") - - res_profile <- read.delim(iso_path) - - colnames(res_profile) <- c( - "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", - "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", - "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", - "Alignment Length", "ACS", "Name of Closest Sequence", "HMM ID", "HMM Description") - - Screening$res_profile <- res_profile %>% - relocate(c("Gene Symbol", "Sequence Name", "Element Subtype", "Class", - "Subclass", "Scope", "Contig ID", "Target Length", "Alignment Length", - "Start", "Stop", "Strand")) - - # Generate gene profile table - output$gs_profile_table <- DT::renderDataTable( - Screening$res_profile, - selection = "single", - rownames= FALSE, - options = list(pageLength = 10, scrollX = TRUE, - autoWidth = TRUE, - columnDefs = list(list(width = '400px', targets = c("Sequence Name", - "Name of Closest Sequence"))), - columnDefs = list(list(width = 'auto', targets = "_all")), - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - )) - ) - } else { - output$gs_profile_table <- NULL - } - }) - - #Resistance profile selection table - observe({ - req(DB$meta, DB$data) - output$gs_isolate_table <- renderDataTable( - select(DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ], -c(3, 4, 10, 11, 12)), - selection = "single", - rownames= FALSE, - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - )) - ) - }) - - observe({ - req(input$screening_res_sel, DB$database, DB$scheme, DB$data) - if(!is.null(Screening$status_df) & - !is.null(input$screening_res_sel) & - !is.null(Screening$status_df$status) & - !is.null(Screening$status_df$isolate)) { - if(length(input$screening_res_sel) > 0) { - if(any(Screening$status_df$isolate == input$screening_res_sel)) { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { - results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", - input$screening_res_sel, "resProfile.tsv")) - - output$screening_table <- renderDataTable( - select(results, c(6, 7, 8, 9, 11)), - selection = "single", - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ))) - } else {output$screening_table <- NULL} - } - } else { - output$screening_table <- NULL - } - } else { - output$screening_table <- NULL - } - - }) - - # Availablity feedback - output$gene_screening_info <- renderUI({ - req(DB$data) - if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } else { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } - }) - - output$gene_resistance_info <- renderUI({ - req(DB$data) - if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } else { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } - }) - - # Screening Interface - - output$screening_interface <- renderUI({ - req(DB$data) - if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - column( - width = 12, - fluidRow( - column(1), - column( - width = 3, - align = "center", - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Isolates for Screening') - ) - ) - ), - if(Screening$picker_status) { - div( - class = "screening_div", - pickerInput( - "screening_select", - "", - choices = list( - Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "No")] - }, - Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] - }, - `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] - } - ), - choicesOpt = list( - disabled = c( - rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) - ) - ), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - } else { - div( - class = "screening_div", - pickerInput( - "screening_select", - "", - choices = Screening$picker_choices, - selected = Screening$picker_selected, - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - }, - br(), br(), - uiOutput("genome_path_gs") - ), - column( - width = 3, - uiOutput("screening_start") - ), - column( - width = 3, - align = "center", - br(), br(), - uiOutput("screening_result_sel") - ), - column(1) - ), - fluidRow( - column(1), - column( - width = 10, - br(), br(), - uiOutput("screening_result"), - br(), br(), br(), br() - ) - ) - ) - } - }) - - ### Screening Events ---- - - observe({ - req(DB$data, input$gs_view) - if(input$gs_view == "Table") { - meta_gs <- DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ] - Screening$selected_isolate <- meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] - } else if(input$gs_view == "Picker") { - Screening$selected_isolate <- input$gs_profile_select - } - }) - - output$download_resistance_profile <- downloadHandler( - filename = function() { - log_print(paste0("Save resistance profile table ", Screening$selected_isolate, "_Profile.csv")) - - paste0(format(Sys.Date()), "_", Screening$selected_isolate, "_Profile.csv") - }, - content = function(file) { - write.table( - Screening$res_profile, - file, - sep = ";", - row.names = FALSE, - quote = FALSE - ) - } - ) - - # Reset screening - observeEvent(input$screening_reset_bttn, { - log_print("Reset gene screening") - - # reset status file - sapply(Screening$status_df$isolate, remove.screening.status) - - # set feedback variables - Screening$status <- "idle" - Screening$status_df <- NULL - Screening$choices <- NULL - Screening$picker_status <- TRUE - Screening$first_result <- NULL - - # change reactive UI - output$screening_table <- NULL - output$screening_result <- NULL - output$screening_fail <- NULL - - updatePickerInput(session, "screening_select", selected = character(0)) - - # disable isolate picker - shinyjs::runjs("$('#screening_select').prop('disabled', false);") - shinyjs::runjs("$('#screening_select').selectpicker('refresh');") - }) - - # Cancel screening - observeEvent(input$screening_cancel, { - showModal( - modalDialog( - paste0( - "Gene screening is still pending. Stopping this process will cancel the screening." - ), - title = "Reset Multi Typing", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_screening_cancel", "Stop", class = "btn btn-danger") - ) - ) - ) - }) - - observeEvent(input$conf_screening_cancel, { - log_print("Cancelled gene screening") - removeModal() - - show_toast( - title = "Gene Screening Terminated", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - - # terminate screening - system(paste("kill $(pgrep -f 'execute/screening.sh')"), wait = FALSE) - system(paste("killall -TERM tblastn"), wait = FALSE) - - # reset status file - sapply(Screening$status_df$isolate, remove.screening.status) - - # set feedback variables - Screening$status <- "idle" - Screening$status_df <- NULL - Screening$choices <- NULL - Screening$picker_status <- TRUE - Screening$first_result <- NULL - - # change reactive UI - output$screening_table <- NULL - output$screening_result <- NULL - - updatePickerInput(session, "screening_select", selected = character(0)) - - # disable isolate picker - shinyjs::runjs("$('#screening_select').prop('disabled', false);") - shinyjs::runjs("$('#screening_select').selectpicker('refresh');") - }) - - # Get selected assembly - observe({ - req(DB$data, Screening$status) - if (length(input$screening_select) < 1) { - output$genome_path_gs <- renderUI(HTML( - paste("", length(input$screening_select), " isolate(s) queried for screening") - )) - - output$screening_start <- NULL - - } else if (length(input$screening_select) > 0) { - - output$screening_start <- renderUI({ - - fluidRow( - column( - width = 12, - br(), br(), - if(length(input$screening_select) < 1) { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Select Isolate(s) for Screening"))) - ) - ) - } else if(Screening$status == "finished") { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Reset to Perform Screening Again"))) - ), - actionButton( - "screening_reset_bttn", - "Reset", - icon = icon("arrows-rotate") - ), - if(!is.null(Screening$status_df)) { - p( - HTML(paste("", - sum(Screening$status_df$status != "unfinished"), "/", - nrow(Screening$status_df), " Isolate(s) screened")) - ) - } - ) - } else if(Screening$status == "idle") { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Screening Ready"))) - ), - actionButton( - inputId = "screening_start_button", - label = "Start", - icon = icon("circle-play") - ) - ) - } else if(Screening$status == "started") { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Running Screening ..."))) - ), - fluidRow( - column(3), - column( - width = 3, - actionButton( - inputId = "screening_cancel", - label = "Terminate", - icon = icon("ban") - ) - ), - column( - width = 3, - HTML(paste('')) - ) - ), - if(!is.null(Screening$status_df)) { - p( - HTML(paste("", - sum(Screening$status_df$status != "unfinished"), "/", - nrow(Screening$status_df), " isolate(s) screened")) - ) - } - ) - } - ) - ) - }) - } else {NULL} - }) - - #### Running Screening ---- - - observeEvent(input$screening_start_button, { - - if(tail(readLogFile(), 1) != "0") { - show_toast( - title = "Pending Multi Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - log_print("Started gene screening") - - Screening$status <- "started" - Screening$picker_choices <- list( - Unscreened = if (sum(DB$data$Screened == "No") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "No")] - }, - Screened = if (sum(DB$data$Screened == "Yes") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] - }, - `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] - } - ) - Screening$picker_selected <- input$screening_select - Screening$picker_status <- FALSE - - show_toast( - title = "Gene screening started", - type = "success", - position = "bottom-end", - timer = 6000 - ) - - Screening$meta_df <- data.frame(wd = getwd(), - selected = paste( - file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", input$screening_select, - paste0(input$screening_select, ".zip")), - collapse = " "), - species = gsub(" ", "_", DB$scheme)) - - Screening$status_df <- data.frame(isolate = basename(gsub(".zip", "", str_split_1(Screening$meta_df$selected, " "))), - status = "unfinished") - - # Reset screening status - sapply(Screening$status_df$isolate, remove.screening.status) - - saveRDS(Screening$meta_df, paste0(getwd(), "/execute/screening_meta.rds")) - - # Disable pickerInput - shinyjs::delay(200, shinyjs::runjs("$('#screening_select').prop('disabled', true);")) - shinyjs::delay(200, shinyjs::runjs("$('#screening_select').selectpicker('refresh');")) - - # System execution screening.sh - system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) - } - }) - - observe({ - req(DB$data, Screening$status, input$screening_res_sel, Screening$status_df) - if(!is.null(Screening$status_df) & - !is.null(Screening$status_df$status) & - !is.null(Screening$status_df$isolate) & - !is.null(input$screening_res_sel)) { - if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { - if(any(Screening$status_df$isolate == input$screening_res_sel)) { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { - output$screening_result <- renderUI( - column( - width = 12, - hr(), br(), - dataTableOutput("screening_table") - ) - ) - } else { - output$screening_result <- renderUI( - column( - width = 12, - hr(), br(), - verbatimTextOutput("screening_fail") - ) - ) - } - } - } else { - output$screening_result <- NULL - } - } else { - output$screening_result <- NULL - } - }) - - observe({ - req(DB$data, Screening$status, input$screening_res_sel) - if(!is.null(Screening$status_df) & - !is.null(Screening$status_df$status) & - !is.null(Screening$status_df$isolate) & - !is.null(input$screening_res_sel)) { - if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { - if(any(Screening$status_df$isolate == input$screening_res_sel)) { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { - output$screening_fail <- renderPrint({ - cat(paste(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", input$screening_res_sel, "status.txt")),"\n")) - }) - } - } - } else { - output$screening_fail <- NULL - } - } else { - output$screening_fail <- NULL - } - }) - - observe({ - req(DB$data) - if(!is.null(Screening$status)) { - if(Screening$status != "idle") { - - # start status screening for user feedback - check_screening() - - if(isTRUE(Screening$first_result)) { - output$screening_result_sel <- renderUI( - column( - width = 12, - align = "center", - selectInput( - "screening_res_sel", - label = h5("Select Result", style = "color:white; margin-bottom: 28px; margin-top: -10px;"), - choices = "" - ), - if(!is.null(Screening$status_df)) { - p(HTML(paste("", - if(sum(Screening$status_df$status == "success") == 1) { - "1 success   /  " - } else { - paste0(sum(Screening$status_df$status == "success"), " successes   /  ") - }, - if(sum(Screening$status_df$status == "fail") == 1) { - "1 failure" - } else { - paste0(sum(Screening$status_df$status == "fail"), " failures") - }))) - } - ) - ) - - Screening$first_result <- FALSE - } - } else if(Screening$status == "idle") { - output$screening_result_sel <- NULL - } - } - }) - - check_screening <- reactive({ - invalidateLater(500, session) - - req(Screening$status_df) - - if(Screening$status == "started") { - - Screening$status_df$status <- sapply(Screening$status_df$isolate, check_status) - - if(any("unfinished" != Screening$status_df$status) & - !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status != "unfinished")])) { - - status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] - - Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | - Screening$status_df$status == "fail")] - - if(sum(Screening$status_df$status != "unfinished") > 0) { - if(is.null(Screening$first_result)) { - Screening$first_result <- TRUE - } - } - - if(tail(status_df$status, 1) == "success") { - - # Changing "Screened" metadata variable in database - Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - Database[["Typing"]]$Screened[which(Database[["Typing"]]["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" - - saveRDS(Database, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - DB$data$Screened[which(DB$data["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" - - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - - show_toast( - title = paste("Successful screening of", tail(Screening$choices, 1)), - type = "success", - position = "bottom-end", - timer = 6000) - - updateSelectInput(session = session, - inputId = "screening_res_sel", - choices = Screening$choices, - selected = tail(Screening$choices, 1)) - - } else if(tail(status_df$status, 1) == "fail") { - - show_toast( - title = paste("Failed screening of", tail(status_df$isolate, 1)), - type = "error", - position = "bottom-end", - timer = 6000) - - updateSelectInput(session = session, - inputId = "screening_res_sel", - choices = Screening$choices, - selected = tail(Screening$choices, 1)) - } - - if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - Screening$status <- "finished" - } - } else { - if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - Screening$status <- "finished" - } - } - - if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - Screening$status <- "finished" - } - } - }) - - - # _______________________ #### - - ## Typing ---- - - # Render Single/Multi Switch - - readLogFile <- reactive({ - invalidateLater(5000, session) - readLines(paste0(getwd(), "/logs/script_log.txt")) - }) - - # Render sidebar dependent on data presence - # No sidebar - output$typing_sidebar <- renderUI({ - if(!is.null(DB$exist)) { - if(DB$exist) { - NULL - } else { - column( - width = 12, - align = "center", - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Typing Mode') - ) - ) - ), - radioGroupButtons( - inputId = "typing_mode", - choices = c("Single", "Multi"), - selected = "Single", - checkIcon = list( - yes = icon("square-check"), - no = icon("square") - ) - ), - br() - ) - } - } - - }) - - # No db typing message - output$typing_no_db <- renderUI({ - if(!is.null(DB$exist)) { - if(DB$exist) { - column( - width = 4, - align = "left", - br(), - br(), - br(), - br(), - p( - HTML( - paste0( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 50px', 'To initiate allelic typing, a cgMLST scheme must be downloaded first.' - ) - ) - ) - ) - ) - } else {NULL} - } else {NULL} - }) - - ### Single Typing ---- - - #### Render UI Elements ---- - - # Render single typing naming issues - output$single_select_issues <- renderUI({ - req(input$assembly_id) - - if(nchar(trimws(input$assembly_id)) < 1) { - ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) - } else { - ass_id <- trimws(input$assembly_id) - } - - if(ass_id %in% unlist(DB$data["Assembly ID"])) { - HTML(paste( - '', - paste("", - "  Assembly ID already present in database."))) - } else if (ass_id == "") { - HTML(paste( - '', - paste("", - "  Empty Assembly ID."))) - } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { - HTML(paste( - '', - paste("", - "  Invalid Assembly ID. Avoid special characters."))) - } else if(grepl(" ", ass_id)) { - HTML(paste( - '', - paste("", - "  Invalid Assembly ID. Avoid empty spaces."))) - } else {HTML(paste( - '', - paste("", - "  Assembly ID compatible with local database.")))} - }) - - # Render Typing Results if finished - observe({ - if(Typing$progress_format_end == 999999) { - if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { - if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { - output$typing_result_table <- renderRHandsontable({ - Typing$typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) - Typing$typing_result_table <- mutate_all(Typing$typing_result_table, as.character) - if(nrow(Typing$typing_result_table) > 0) { - if(nrow(Typing$typing_result_table) > 15) { - rhandsontable(Typing$typing_result_table, rowHeaders = NULL, - stretchH = "all", height = 500, readOnly = TRUE, - contextMenu = FALSE) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - } else { - rhandsontable(Typing$typing_result_table, rowHeaders = NULL, - stretchH = "all", readOnly = TRUE, - contextMenu = FALSE,) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - } - } - }) - - output$single_typing_results <- renderUI({ - result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) - number_events <- nrow(result_table) - - n_new <- length(grep("New Variant", result_table$Event)) - - n_missing <- number_events - n_new - - # Show results table only if successful typing - if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { - if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { - if(number_events > 0) { - column( - width = 12, - HTML(paste("", - length(Typing$scheme_loci_f) - number_events, - "loci were assigned a variant from local scheme.")), - br(), - HTML(paste("", - n_missing, - if(n_missing == 1) " locus not assigned (NA)." else " loci not assigned (NA).")), - br(), - HTML(paste("", - n_new, - if(n_new == 1) " locus with new variant." else " loci with new variants.")), - br(), br(), - rHandsontableOutput("typing_result_table") - ) - } else { - column( - width = 12, - HTML(paste("", - length(Typing$scheme_loci_f), - "successfully assigned from local scheme.")) - ) - } - } - } - }) - - } else { - - output$single_typing_results <- NULL - - } - } else { - output$single_typing_results <- NULL - } - } - - }) - - # Render Initiate Typing UI - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - # Render Declare Metadata UI - - observe({ - if (nrow(Typing$single_path) < 1) { - output$genome_path <- renderUI(HTML( - paste("", "No file selected.") - )) - - # dont show subsequent metadata declaration and typing start UI - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - } else if (nrow(Typing$single_path) > 0) { - - if (str_detect(str_sub(Typing$single_path$name, start = -6), ".fasta") | - str_detect(str_sub(Typing$single_path$name, start = -6), ".fna") | - str_detect(str_sub(Typing$single_path$name, start = -6), ".fa")) { - - # Render selected assembly path - output$genome_path <- renderUI({ - HTML( - paste( - "", - as.character(Typing$single_path$name) - ) - ) - }) - - # Render metadata declaration box - output$metadata_single_box <- renderUI({ - - # Render placeholder - updateTextInput(session, "assembly_id", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) - updateTextInput(session, "assembly_name", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) - - column( - width = 3, - align = "center", - br(), br(), - h3(p("Declare Metadata"), style = "color:white; margin-left:-40px"), - br(), br(), - div( - class = "multi_meta_box", - box( - solidHeader = TRUE, - status = "primary", - width = "90%", - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("assembly_id", - value = "", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 12, - uiOutput("single_select_issues") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("assembly_name", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - dateInput("append_isodate", - label = "", - width = "80%", - max = Sys.Date()) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_host", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table_country", - pickerInput( - "append_country", - label = "", - choices = list("Common" = sel_countries, - "All Countries" = country_names), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "90%" - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput( - "append_city", - label = "", - width = "80%" - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - actionButton( - inputId = "conf_meta_single", - label = "Confirm" - ), - br() - ) - ), - br() - ) - ) - ) - }) - } else { - show_toast( - title = "Wrong file type (only fasta/fna/fa)", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } - }) - - # Get genome datapath - - observe({ - # Get selected Genome in Single Mode - shinyFileChoose(input, - "genome_file", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - Typing$single_path <- parseFilePaths(roots = c(Home = path_home(), Root = "/"), input$genome_file) - - }) - - #### Run blat ---- - - observeEvent(input$typing_start, { - - log_print("Input typing_start") - - if(tail(readLogFile(), 1) != "0") { - show_toast( - title = "Pending Multi Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if (Screening$status == "started") { - show_toast( - title = "Pending Gene Screening", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - if(!is.null(DB$data)) { - if(sum(apply(DB$data, 1, anyNA)) >= 1) { - DB$no_na_switch <- TRUE - } else { - DB$no_na_switch <- FALSE - } - } - - # Activate entry detection - DB$check_new_entries <- TRUE - - Typing$single_end <- FALSE - - Typing$progress_format_start <- 0 - Typing$progress_format_end <- 0 - - # Remove Initiate Typing UI - output$initiate_typing_ui <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - # status feedback - Typing$status <- "Processing" - - # Locate folder containing cgMLST scheme - search_string <- paste0(gsub(" ", "_", DB$scheme), "_alleles") - - scheme_folders <- dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme))) - - if (any(grepl(search_string, scheme_folders))) { - - # reset results file - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - } - - # blat initiate index - scheme_select <- as.character(scheme_folders[which(grepl(search_string, scheme_folders))]) - - show_toast( - title = "Typing Initiated", - type = "success", - position = "bottom-end", - timer = 6000 - ) - - log_print("Initiated single typing") - - ### Run blat Typing - - single_typing_df <- data.frame( - db_path = DB$database, - wd = getwd(), - save = input$save_assembly_st, - scheme = paste0(gsub(" ", "_", DB$scheme)), - genome = Typing$single_path$datapath, - alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", search_string) - ) - - saveRDS(single_typing_df, "execute/single_typing_df.rds") - - # Execute single typing script - system(paste("bash", paste0(getwd(), "/execute/single_typing.sh")), - wait = FALSE) - - scheme_loci <- list.files(path = scheme_select, full.names = TRUE) - - # Filter the files that have FASTA extensions - Typing$scheme_loci_f <- - scheme_loci[grep("\\.(fasta|fa|fna)$", scheme_loci, ignore.case = TRUE)] - - output$single_typing_progress <- renderUI({ - fluidRow( - br(), br(), - column(width = 1), - column( - width = 3, - h3(p("Pending Single Typing ..."), style = "color:white") - ), - br(), br(), br(), - fluidRow( - column(width = 1), - column( - width = 4, - br(), br(), br(), - fluidRow( - column( - width = 12, - uiOutput("reset_single_typing"), - HTML( - paste( - "", - as.character(Typing$single_path$name) - ) - ), - br(), br(), - progressBar( - "progress_bar", - value = 0, - display_pct = TRUE, - title = "" - ) - ) - ), - fluidRow( - column( - width = 12, - uiOutput("typing_formatting"), - uiOutput("typing_fin") - ) - ) - ), - column(1), - column( - width = 5, - br(), br(), br(), - uiOutput("single_typing_results") - ) - ) - ) - }) - } else { - log_print("Folder containing cgMLST alleles not in working directory") - - show_alert( - title = "Error", - text = paste0( - "Folder containing cgMLST alleles not in working directory.", - "\n", - "Download cgMLST Scheme for selected Organism first." - ), - type = "error" - ) - } - } - }) - - # Function to update Progress Bar - update <- reactive({ - invalidateLater(3000, session) - - # write progress in process tracker - cat( - c(length(list.files(paste0(getwd(), "/execute/blat_single/results"))), - readLines(paste0(getwd(), "/logs/progress.txt"))[-1]), - file = paste0(getwd(), "/logs/progress.txt"), - sep = "\n" - ) - - progress <- readLines(paste0(getwd(), "/logs/progress.txt")) - - # if typing with blat is finished -> "attaching" phase started - if(!is.na(progress[1])) { - if(!is.na(progress[2])) { - if(progress[2] == "888888") { - Typing$progress_format_start <- progress[2] - Typing$pending_format <- progress[2] - Typing$status <- "Attaching" - } - } - # "attaching" phase completed - if(!is.na(progress[3])) { - if(progress[3] == "999999") { - Typing$progress_format_end <- progress[3] - Typing$entry_added <- progress[3] - Typing$status <- "Finalized" - } - } - Typing$progress <- as.numeric(progress[1]) - floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) - } else { - floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) - } - }) - - # Observe Typing Progress - observe({ - - if(readLogFile()[1] == "0") { - # Update Progress Bar - updateProgressBar( - session = session, - id = "progress_bar", - value = update(), - total = 100, - title = paste0(as.character(Typing$progress), "/", length(Typing$scheme_loci_f), " loci screened") - ) - } - - if (Typing$progress_format_start == 888888) { - output$typing_formatting <- renderUI({ - column( - width = 12, - align = "center", - br(), - fluidRow( - column( - width = 6, - HTML(paste("", "Transforming data ...")) - ), - column( - width = 3, - align = "left", - HTML(paste('')) - ) - ) - ) - }) - } else { - output$typing_formatting <- NULL - } - - # Render when finalized - if (Typing$progress_format_end == 999999) { - - output$typing_formatting <- NULL - - output$typing_fin <- renderUI({ - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { - if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { - req(Typing$scheme_loci_f, Typing$typing_result_table) - if(sum(Typing$typing_result_table$Event != "New Variant") > (0.5 * length(Typing$scheme_loci_f))){ - HTML( - paste("", - sub(".*Successful", "Finished", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), - paste("", "Warning: Isolate contains large number of failed allele assignments."), - paste("", "Reset to start another typing process."), - sep = '
\n')) - } else { - HTML(paste("", - sub(".*Successful", "Successful", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), - "Reset to start another typing process.", sep = '
')) - } - } else { - HTML(paste("", - sub(".*typing", "Typing", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), - "Reset to start another typing process.", sep = '
')) - } - }, - br(), br(), - actionButton( - "reset_single_typing", - "Reset", - icon = icon("arrows-rotate") - ) - ) - ) - }) - } else { - output$typing_fin <- NULL - output$single_typing_results <- NULL - } - - }) - - #### Declare Metadata ---- - - observeEvent(input$conf_meta_single, { - - if(nchar(trimws(input$assembly_id)) < 1) { - ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) - } else { - ass_id <- trimws(input$assembly_id) - } - - if(nchar(trimws(input$assembly_name)) < 1) { - ass_name <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) - } else { - ass_name <- trimws(input$assembly_name) - } - - if(ass_id %in% unlist(DB$data["Assembly ID"])) { - show_toast( - title = "Assembly ID already present", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (isFALSE(Typing$reload)) { - show_toast( - title = "Reload Database first", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if (ass_id == "") { - show_toast( - title = "Empty Assembly ID", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { - show_toast( - title = "Invalid Assembly ID. No special characters allowed: ()/\\:*?\"<>|", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if(grepl(" ", ass_id)) { - show_toast( - title = "Empty spaces in Assembly ID not allowed", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if(Screening$status == "started") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - log_print("Single typing metadata confirmed") - - meta_info <- data.frame(assembly_id = ass_id, - assembly_name = ass_name, - cgmlst_typing = DB$scheme, - append_isodate = input$append_isodate, - append_host = trimws(input$append_host), - append_country = trimws(input$append_country), - append_city = trimws(input$append_city), - append_analysisdate = Sys.Date(), - db_directory = getwd()) - - saveRDS(meta_info, paste0( - getwd(), - "/execute/meta_info_single.rds" - )) - - show_toast( - title = "Metadata declared", - type = "success", - position = "bottom-end", - timer = 3000 - ) - - # Render Start Typing UI - output$start_typing_ui <- renderUI({ - div( - class = "multi_start_col", - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Start Typing"), style = "color:white"), - br(), - br(), - HTML( - paste( - "", - "Typing by ", - DB$scheme, - " scheme." - ) - ), - br(), br(), br(), br(), - div( - class = "save-assembly", - materialSwitch( - "save_assembly_st", - h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), - value = TRUE, - right = TRUE) - ), - HTML( - paste( - "", - "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." - ) - ), - br(), br(), br(), br(), - actionButton( - inputId = "typing_start", - label = "Start", - icon = icon("circle-play") - ) - ) - ) - }) - } - }) - - #### Events Single Typing ---- - - observeEvent(input$reset_single_typing, { - log_print("Reset single typing") - - Typing$status <- "Inactive" - - Typing$progress <- 0 - - Typing$progress_format <- 900000 - - output$single_typing_progress <- NULL - - output$typing_fin <- NULL - - output$single_typing_results <- NULL - - output$typing_formatting <- NULL - - Typing$single_path <- data.frame() - - # reset results file - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - # Resetting single typing progress logfile bar - con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") - - cat("0\n", file = con) - - close(con) - } - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - }) - - # Notification for finalized Single typing - Typing$single_end <- TRUE - Typing$progress_format_end <- 0 - - observe({ - if(Typing$single_end == FALSE) { - if (Typing$progress_format_end == 999999) { - show_toast( - title = "Single Typing finalized", - type = "success", - position = "bottom-end", - timer = 8000 - ) - Typing$single_end <- TRUE - } - } - }) - - ### Multi Typing ---- - - #### Render Multi Typing UI Elements ---- - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - # Render selection info - output$multi_select_info <- renderUI({ - - if(!is.null(Typing$multi_path)) { - if(length(Typing$multi_path) < 1) { - HTML(paste("", - "No files selected.")) - } else { - HTML(paste("", - sum(hot_to_r(input$multi_select_table)$Include == TRUE), - " files selected.")) - } - } - }) - - # Render multi selection table issues - output$multi_select_issues <- renderUI({ - req(Typing$multi_sel_table, input$multi_select_table) - if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & - any(duplicated(hot_to_r(input$multi_select_table)$Files))){ - HTML( - paste( - paste("", - "Some name(s) are already present in local database.
"), - paste("", - "Duplicated name(s).
") - ) - ) - } else if (any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & - !any(duplicated(hot_to_r(input$multi_select_table)$Files))) { - HTML( - paste("", - "Some name(s) are already present in local database.
") - ) - } else if (!any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & - any(duplicated(hot_to_r(input$multi_select_table)$Files))) { - HTML( - paste("", - "Duplicated name(s).
") - ) - } - }) - - output$multi_select_issue_info <- renderUI({ - req(Typing$multi_sel_table, input$multi_select_table) - - multi_select_table <- hot_to_r(input$multi_select_table) - - if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | - any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)])) | - any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - - if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - - if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | - any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - HTML(paste( - paste( - '', - paste("", - " Rename highlighted isolates or deselect them.
")), - paste( - '', - paste("", - " Filename(s) contain(s) empty spaces.")) - )) - } else { - HTML(paste( - '', - paste("", - " Filename(s) contain(s) empty spaces."))) - } - } else { - HTML(paste( - '', - paste("", - " Rename highlighted isolates or deselect them."))) - } - } else { - HTML(paste( - '', - paste("", - " Files ready for allelic typing."))) - } - }) - - # Render Metadata Select Box after Folder selection - observe({ - if(!is.null(Typing$multi_sel_table)) { - if (nrow(Typing$multi_sel_table) > 0) { - - output$multi_select_tab_ctrls <- renderUI( - fluidRow( - column(1), - column( - width = 2, - align = "left", - actionButton( - "sel_all_mt", - "All", - icon = icon("check") - ) - ), - column( - width = 2, - align = "left", - actionButton( - "desel_all_mt", - "None", - icon = icon("xmark") - ) - ), - column(2), - column( - width = 5, - align = "right", - br(), - uiOutput("multi_select_issues") - ) - ) - ) - - output$metadata_multi_box <- renderUI({ - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Declare Metadata"), style = "color:white;margin-left:-40px"), - br(), br(), - div( - class = "multi_meta_box", - box( - solidHeader = TRUE, - status = "primary", - width = "90%", - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - dateInput("append_isodate_multi", - label = "", - width = "80%", - max = Sys.Date()) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_host_multi", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table_country", - pickerInput( - "append_country_multi", - label = "", - choices = list("Common" = sel_countries, - "All Countries" = country_names), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "90%" - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_city_multi", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - actionButton( - inputId = "conf_meta_multi", - label = "Confirm" - ), - br(), br(), - uiOutput("multi_select_issue_info") - ) - ) - ) - ) - ) - }) - } else { - output$metadata_multi_box <- NULL - } - } - }) - - # Check if ongoing Multi Typing - Render accordingly - observe({ - # Get selected Genome in Multi Mode - shinyDirChoose(input, - "genome_file_multi", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - - Typing$multi_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi) - - files_selected <- list.files(as.character(Typing$multi_path)) - Typing$files_filtered <- files_selected[which(!endsWith(files_selected, ".gz") & - grepl("\\.fasta|\\.fna|\\.fa", files_selected))] - - Typing$multi_sel_table <- data.frame( - Include = rep(TRUE, length(Typing$files_filtered)), - Files = gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", - Typing$files_filtered), - Type = sub(".*(\\.fasta|\\.fasta\\.gz|\\.fna|\\.fna\\.gz|\\.fa|\\.fa\\.gz)$", - "\\1", Typing$files_filtered, perl = F)) - - if(nrow(Typing$multi_sel_table) > 0) { - output$multi_select_tab_ctrls <- renderUI( - fluidRow( - column(1), - column( - width = 2, - align = "left", - actionButton( - "sel_all_mt", - "All", - icon = icon("check") - ) - ), - column( - width = 2, - align = "left", - actionButton( - "desel_all_mt", - "None", - icon = icon("xmark") - ) - ), - column(2), - column( - width = 5, - align = "right", - br(), - uiOutput("multi_select_issues") - ) - ) - ) - } else { - output$multi_select_tab_ctrls <- NULL - } - - if(between(nrow(Typing$multi_sel_table), 1, 15)) { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", contextMenu = FALSE - ) %>% - hot_cols(columnSorting = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { - var hot = this.hot; - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - var highlightInvalidAndDuplicates = function(invalidValues) { - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - // Find all duplicate values - for (var i = 0; i < columnData.length; i++) { - var value = columnData[i]; - if (value !== null && value !== undefined) { - if (duplicates[value]) { - duplicates[value].push(i); - } else { - duplicates[value] = [i]; - } - } - } - - // Reset all cell backgrounds in the column - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - if (cell) { - cell.style.background = 'white'; - } - } - - // Highlight duplicates and invalid values - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - var value = columnData[i]; - if (cell) { - if (invalidValues.includes(value)) { - cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values - } else if (duplicates[value] && duplicates[value].length > 1) { - cell.style.background = '#FF7334'; // Highlight color for duplicates - } - } - } - }; - - var changefn = function(changes, source) { - if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { - highlightInvalidAndDuplicates(%s); - } - }; - - hot.addHook('afterChange', changefn); - hot.addHook('afterLoadData', function() { - highlightInvalidAndDuplicates(%s); - }); - hot.addHook('afterRender', function() { - highlightInvalidAndDuplicates(%s); - }); - - highlightInvalidAndDuplicates(%s); // Initial highlight on load - - Shiny.addCustomMessageHandler('setColumnValue', function(message) { - var colData = hot.getDataAtCol(0); - for (var i = 0; i < colData.length; i++) { - hot.setDataAtCell(i, 0, message.value); - } - hot.render(); // Re-render the table - }); - }", - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()))) - }) - - } else if(nrow(Typing$multi_sel_table) > 15) { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", height = 500, - contextMenu = FALSE - ) %>% - hot_cols(columnSorting = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { - var hot = this.hot; - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - var highlightInvalidAndDuplicates = function(invalidValues) { - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - // Find all duplicate values - for (var i = 0; i < columnData.length; i++) { - var value = columnData[i]; - if (value !== null && value !== undefined) { - if (duplicates[value]) { - duplicates[value].push(i); - } else { - duplicates[value] = [i]; - } - } - } - - // Reset all cell backgrounds in the column - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - if (cell) { - cell.style.background = 'white'; - } - } - - // Highlight duplicates and invalid values - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - var value = columnData[i]; - if (cell) { - if (invalidValues.includes(value)) { - cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values - } else if (duplicates[value] && duplicates[value].length > 1) { - cell.style.background = '#FF7334'; // Highlight color for duplicates - } - } - } - }; - - var changefn = function(changes, source) { - if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { - highlightInvalidAndDuplicates(%s); - } - }; - - hot.addHook('afterChange', changefn); - hot.addHook('afterLoadData', function() { - highlightInvalidAndDuplicates(%s); - }); - hot.addHook('afterRender', function() { - highlightInvalidAndDuplicates(%s); - }); - - highlightInvalidAndDuplicates(%s); // Initial highlight on load - - Shiny.addCustomMessageHandler('setColumnValue', function(message) { - var colData = hot.getDataAtCol(0); - for (var i = 0; i < colData.length; i++) { - hot.setDataAtCell(i, 0, message.value); - } - hot.render(); // Re-render the table - }); - }", - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()))) - - }) - - } else { - output$multi_select_table <- NULL - } - }) - - observeEvent(input$conf_meta_multi, { - - multi_select_table <- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] - - if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", multi_select_table$Files)) %in% unlist(DB$data["Assembly ID"]))) { - show_toast( - title = "Assembly ID(s) already present", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (any(duplicated(multi_select_table$Files))) { - show_toast( - title = "Duplicated filename(s)", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (any(multi_select_table$Files == "")) { - show_toast( - title = "Empty filename(s)", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (any(grepl("[()/\\:*?\"<>|]", multi_select_table$Files))) { - show_toast( - title = "Invalid filename(s). No special characters allowed: ()/\\:*?\"<>|", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (!any(multi_select_table$Include == TRUE)) { - show_toast( - title = "No files selected", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - show_toast( - title = "Empty spaces in filename(s) not allowed", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (isFALSE(Typing$reload)) { - show_toast( - title = "Reload Database first", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(Screening$status == "started") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - log_print("Multi typing metadata confirmed") - - meta_info <- data.frame(cgmlst_typing = DB$scheme, - append_isodate = trimws(input$append_isodate_multi), - append_host = trimws(input$append_host_multi), - append_country = trimws(input$append_country_multi), - append_city = trimws(input$append_city_multi), - append_analysisdate = Sys.Date(), - db_directory = getwd()) - - saveRDS(meta_info, paste0(getwd(), "/execute/meta_info.rds")) - - show_toast( - title = "Metadata declared", - type = "success", - position = "bottom-end", - timer = 3000 - ) - - output$start_multi_typing_ui <- renderUI({ - div( - class = "multi_start_col", - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Start Typing"), style = "color:white"), - br(), - br(), - HTML( - paste( - "", - "Typing by ", - DB$scheme, - " scheme." - ) - ), - br(), br(), br(), br(), - div( - class = "save-assembly", - materialSwitch( - "save_assembly_mt", - h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), - value = TRUE, - right = TRUE) - ), - HTML( - paste( - "", - "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." - ) - ), - br(), br(), br(), br(), - actionButton( - "start_typ_multi", - "Start", - icon = icon("circle-play") - ) - ) - ) - }) - } - }) - - #### Events Multi Typing ---- - - observeEvent(input$sel_all_mt, { - session$sendCustomMessage(type = "setColumnValue", message = list(value = TRUE)) - }) - - observeEvent(input$desel_all_mt, { - session$sendCustomMessage(type = "setColumnValue", message = list(value = FALSE)) - }) - - # Print Log - output$print_log <- downloadHandler( - filename = function() { - log_print(paste0("Save multi typing log ", paste("Multi_Typing_", Sys.Date(), ".txt", sep = ""))) - paste("Multi_Typing_", Sys.Date(), ".txt", sep = "") - }, - content = function(file) { - writeLines(readLines(paste0(getwd(), "/logs/script_log.txt")), file) - } - ) - - # Reset Multi Typing - observeEvent(input$reset_multi, { - if(!grepl("Multi Typing", tail(readLines(paste0(getwd(),"/logs/script_log.txt")), n = 1))) { - showModal( - modalDialog( - paste0( - "A Multi Typing process is still pending. Stopping this process will cancel the processing." - ), - title = "Reset Multi Typing", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_multi_kill", "Stop", class = "btn btn-danger") - ) - ) - ) - } else { - - log_print("Reset multi typing") - - # Reset multi typing result list - saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) - multi_help <- FALSE - Typing$result_list <- NULL - - # Null logfile - writeLines("0", paste0(getwd(), "/logs/script_log.txt")) - - # Reset User Feedback variable - Typing$pending_format <- 0 - Typing$multi_started <- FALSE - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - output$pending_typing <- NULL - output$multi_typing_results <- NULL - } - }) - - # Confirm Reset after - observeEvent(input$conf_multi_kill, { - removeModal() - - log_print("Kill multi typing") - - # Kill multi typing and reset logfile - system(paste("bash", paste0(getwd(), "/execute/kill_multi.sh")), - wait = TRUE) - - show_toast( - title = "Execution cancelled", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - - # Kill multi typing and reset logfile - writeLines("0", paste0(getwd(), "/logs/script_log.txt")) - - #Reset multi typing result list - saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) - multi_help <- FALSE - Typing$result_list <- NULL - - # Reset User Feedback variable - Typing$pending_format <- 0 - output$pending_typing <- NULL - output$multi_typing_results <- NULL - Typing$failures <- 0 - Typing$successes <- 0 - Typing$multi_started <- FALSE - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - }) - - observeEvent(input$start_typ_multi, { - log_print("Initiate multi typing") - - if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if (Screening$status == "started") { - show_toast( - title = "Pending Gene Screening", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - removeModal() - - show_toast( - title = "Multi Typing started", - type = "success", - position = "bottom-end", - timer = 10000 - ) - - Typing$new_table <- NULL - - # Remove Allelic Typing Controls - output$initiate_multi_typing_ui <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - - # Activate entry detection - DB$check_new_entries <- TRUE - - # Initiate Feedback variables - Typing$multi_started <- TRUE - Typing$pending <- TRUE - Typing$failures <- 0 - Typing$successes <- 0 - - # get selected file table - multi_select_table <- hot_to_r(input$multi_select_table) - - filenames <- paste(multi_select_table$Files[which(multi_select_table$Include == TRUE)], collapse = " ") - - files <- Typing$multi_sel_table$Files[which(multi_select_table$Include == TRUE)] - type <- Typing$multi_sel_table$Type[which(multi_select_table$Include == TRUE)] - genome_names <- paste(paste0(gsub(" ", "~", files), type), collapse = " ") - - # Start Multi Typing Script - multi_typing_df <- data.frame( - db_path = DB$database, - wd = getwd(), - save = input$save_assembly_mt, - scheme = paste0(gsub(" ", "_", DB$scheme)), - genome_folder = as.character(parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi)), - filenames = paste0(filenames, collapse= " "), - genome_names = genome_names, - alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles") - ) - - saveRDS(multi_typing_df, "execute/multi_typing_df.rds") - - # Execute multi blat script - system(paste("bash", paste0(getwd(), "/execute/multi_typing.sh")), wait = FALSE) - } - }) - - - #### User Feedback ---- - - observe({ - if(file.exists(paste0(getwd(), "/logs/script_log.txt"))) { - if(Typing$multi_started == TRUE) { - check_multi_status() - } else { - Typing$status <- "Inactive" - } - } - }) - - check_multi_status <- reactive({ - - invalidateLater(3000, session) - - log <- readLines(paste0(getwd(), "/logs/script_log.txt")) - - # Determine if Single or Multi Typing - if(str_detect(log[1], "Multi")) { - Typing$pending_mode <- "Multi" - } else { - Typing$pending_mode <- "Single" - } - - # Check typing status - if(str_detect(tail(log, 1), "Attaching")) { - Typing$status <- "Attaching" - } else if(str_detect(tail(log, 1), "Successful")) { - Typing$multi_help <- TRUE - Typing$status <- "Successful" - show_toast( - title = paste0("Successful", sub(".*Successful", "", tail(log, 1))), - type = "success", - position = "bottom-end", - timer = 8000 - ) - } else if(str_detect(tail(log, 1), "failed")) { - Typing$status <- "Failed" - show_toast( - title = sub(".* - ", "", tail(log, 1)), - type = "error", - position = "bottom-end", - timer = 8000 - ) - } else if(str_detect(tail(log, 1), "Processing")) { - Typing$status <- "Processing" - - if(any(str_detect(tail(log, 2), "Successful"))) { - - if(!identical(Typing$last_success, tail(log, 2)[1])) { - Typing$multi_help <- TRUE - show_toast( - title = paste0("Successful", sub(".*Successful", "", tail(log, 2)[1])), - type = "success", - position = "bottom-end", - timer = 8000 - ) - - Typing$last_success <- tail(log, 2)[1] - } - } else if(any(str_detect(tail(log, 2), "failed"))) { - - if(!identical(Typing$last_failure, tail(log, 2)[1])) { - - show_toast( - title = sub(".* - ", "", tail(log, 2)[1]), - type = "error", - position = "bottom-end", - timer = 8000 - ) - - Typing$last_failure <- tail(log, 2)[1] - } - } - } else if(str_detect(tail(log, 1), "finalized")) { - Typing$multi_help <- TRUE - Typing$status <- "Finalized" - - if(Typing$pending == TRUE) { - show_toast( - title = "Typing finalized", - type = "success", - position = "bottom-end", - timer = 8000 - ) - - Typing$pending <- FALSE - } - } - }) - - ##### Render Multi Typing UI Feedback ---- - - observe({ - if(!is.null(input$multi_results_picker)) { - Typing$multi_table_length <- nrow(Typing$result_list[[input$multi_results_picker]]) - } else { - Typing$multi_table_length <- NULL - } - }) - - observe({ - if(!is.null(Typing$result_list)) { - if(length(Typing$result_list) > 0) { - if(is.null(Typing$multi_table_length)) { - output$multi_typing_result_table <- renderRHandsontable({ - rhandsontable(Typing$result_list[[input$multi_results_picker]], - rowHeaders = NULL, stretchH = "all", - readOnly = TRUE, contextMenu = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - - } else { - if(Typing$multi_table_length > 15) { - output$multi_typing_result_table <- renderRHandsontable({ - rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, - stretchH = "all", height = 500, - readOnly = TRUE, contextMenu = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } else { - output$multi_typing_result_table <- renderRHandsontable({ - rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, - stretchH = "all", readOnly = TRUE, - contextMenu = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } - } - } else { - output$multi_typing_result_table <- NULL - } - } else { - output$multi_typing_result_table <- NULL - } - }) - - observe({ - if(!is.null(Typing$multi_result_status)) { - if(Typing$multi_result_status == "start" | Typing$multi_result_status == "finalized"){ - - if(Typing$multi_help == TRUE) { - Typing$result_list <- readRDS(paste0(getwd(), "/execute/event_list.rds")) - Typing$multi_help <- FALSE - } - } - } - }) - - - observe({ - #Render multi typing result feedback table - - if(!is.null(Typing$result_list)) { - if(length(Typing$result_list) > 0) { - output$multi_typing_results <- renderUI({ - column( - width = 12, - fluidRow( - column(1), - column( - width = 9, - br(), br(), - br(), br(), - br(), - div( - class = "mult_res_sel", - selectInput( - "multi_results_picker", - label = h5("Select Typing Results", style = "color:white"), - choices = names(Typing$result_list), - selected = names(Typing$result_list)[length(names(Typing$result_list))], - ) - ), - br(), br() - ) - ), - rHandsontableOutput("multi_typing_result_table") - ) - }) - } - } - }) - - observe({ - - # Render log content - output$logText <- renderPrint({ - cat(rev(paste0(tail(readLogFile(), 50), "\n"))) - }) - - output$logTextFull <- renderPrint({ - cat(rev(paste0(readLines(paste0(getwd(), "/logs/script_log.txt")), "\n"))) - }) - - # Render Pending UI - if(!grepl("Multi Typing", tail(readLogFile(), n = 1)) & grepl("Start Multi Typing", head(readLogFile(), n = 1))) { - - Typing$multi_result_status <- "start" - - output$initiate_multi_typing_ui <- NULL - - output$pending_typing <- renderUI({ - fluidRow( - fluidRow( - br(), br(), - column(width = 2), - column( - width = 4, - h3(p("Pending Typing ..."), style = "color:white"), - br(), br(), - fluidRow( - column( - width = 5, - HTML(paste('')) - ), - column( - width = 6, - align = "left", - actionButton( - "reset_multi", - "Terminate", - icon = icon("ban") - ) - ) - ), - ) - ), - br(), br(), - fluidRow( - column(width = 2), - column( - width = 10, - verbatimTextOutput("logText") - ) - ) - ) - }) - } else if(grepl("Multi Typing finalized", tail(readLogFile(), n = 1))) { - - Typing$multi_result_status <- "finalized" - - Typing$last_scheme <- NULL - - output$initiate_multi_typing_ui <- NULL - - output$pending_typing <- renderUI({ - - fluidRow( - fluidRow( - br(), br(), - column(width = 2), - column( - width = 4, - h3(p("Pending Multi Typing ..."), style = "color:white"), - br(), br(), - HTML(paste("", - paste("Typing of", sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Processing")), "assemblies finalized."), - paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Successful")), "successes."), - paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "failed")), "failures."), - "Reset to start another typing process.", - sep = '
')), - br(), br(), - fluidRow( - column( - width = 5, - actionButton( - "reset_multi", - "Reset", - icon = icon("arrows-rotate") - ) - ), - column( - width = 5, - downloadButton( - "print_log", - "Logfile", - icon = icon("floppy-disk") - ) - ) - ) - ) - ), - br(), br(), - fluidRow( - column(width = 2), - column( - width = 10, - verbatimTextOutput("logTextFull"), - ) - ) - ) - }) - } else if (!grepl("Start Multi Typing", head(readLogFile(), n = 1))){ - output$pending_typing <- NULL - Typing$multi_result_status <- "idle" - } - }) - - observe({ - # Get selected Genome in Multi Mode - shinyDirChoose(input, - "hash_dir", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - }) - - observeEvent(input$hash_start, { - dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) - if (!is_empty(list.files(dir_path)) && all(endsWith(list.files(dir_path), ".fasta"))) { - log_print("Hashing directory using utilities") - shinyjs::hide("hash_start") - shinyjs::show("hash_loading") - show_toast( - title = "Hashing started!", - type = "success", - position = "bottom-end", - timer = 6000 - ) - hash_database(dir_path) - shinyjs::hide("hash_loading") - shinyjs::show("hash_start") - show_toast( - title = "Hashing completed!", - type = "success", - position = "bottom-end", - timer = 6000 - ) - } else { - show_toast( - title = "Incorrect folder selected!", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - -} # end server - -# _______________________ #### - -# Shiny ---- - -shinyApp(ui = ui, server = server) +######## PhyloTrace ######### + +# _______________________ #### +# CRAN Packages +library(shiny) +library(R.utils) +library(igraph) +library(shinyWidgets) +library(shinydashboard) +library(dashboardthemes) +library(ggplot2) +library(ggnewscale) +library(ggplotify) +library(ape) +library(tidyverse) +library(rlang) +library(tidytree) +library(shinyFiles) +library(dplyr) +library(downloader) +library(rvest) +library(rmarkdown) +library(knitr) +library(kableExtra) +library(fs) +library(data.table) +library(zoo) +library(ggnetwork) +library(rhandsontable) +library(visNetwork) +library(proxy) +library(phangorn) +library(cowplot) +library(viridis) +library(RColorBrewer) +library(bslib) +library(bsicons) +library(DT) +library(shinyBS) +library(openssl) +library(logr) +# Bioconductor Packages +library(treeio) +library(ggtree) +library(ggtreeExtra) + +source(paste0(getwd(), "/www/resources.R")) + +options(ignore.negative.edge=TRUE) + +# User Interface ---- + +ui <- dashboardPage( + + title = "PhyloTrace 1.5.0", + + # Title + dashboardHeader( + + title = span( + div( + class = "img_logo", + img( + src = "PhyloTrace.jpg", width = 190 + ) + ) + ), + uiOutput("loaded_scheme"), + uiOutput("databasetext"), + uiOutput("statustext"), + tags$li(class = "dropdown", + tags$span(id = "currentTime", style = "color:white; font-weight:bold;")), + disable = FALSE + ), + + ## Sidebar ---- + dashboardSidebar( + tags$head(includeCSS("www/head.css")), + tags$style(includeCSS("www/body.css")), + tags$style(HTML( + "@keyframes pulsate { + 0% { transform: scale(1); } + 50% { transform: scale(1.1); } + 100% { transform: scale(1); } + } + .pulsating-button { + animation: pulsate 1s ease infinite; + } + .pulsating-button:hover { + animation: none; + }")), + br(), br(), + sidebarMenu( + id = "tabs", + sidebarMenuOutput("menu"), + uiOutput("menu_sep2"), + conditionalPanel( + "input.tabs==='db_browse_entries'", + uiOutput("entrytable_sidebar") + ), + conditionalPanel( + "input.tabs==='db_distmatrix'", + uiOutput("distmatrix_sidebar") + ), + conditionalPanel( + "input.tabs==='db_missing_values'", + uiOutput("missing_values_sidebar") + ), + conditionalPanel( + "input.tabs==='typing'", + uiOutput("typing_sidebar") + ), + conditionalPanel( + "input.tabs==='visualization'", + uiOutput("visualization_sidebar") + ), + conditionalPanel( + "input.tabs==='gs_profile'", + uiOutput("screening_sidebar") + ) + ) + ), + + dashboardBody( + tags$head(tags$link(rel = "shortcut icon", href = "favicon.ico")), + shinyjs::useShinyjs(), + + shinyDashboardThemeDIY( + ### general + appFontFamily = "Liberation Sans", + appFontColor = "#000000", + primaryFontColor = "#ffffff", + infoFontColor = "rgb(0,0,0)", + successFontColor = "rgb(0,0,0)", + warningFontColor = "rgb(0,0,0)", + dangerFontColor = "rgb(0,0,0)", + bodyBackColor = cssGradientThreeColors( + direction = "down", + colorStart = "#282f38", + colorMiddle = "#384454", + colorEnd = "#495d78", + colorStartPos = 0, + colorMiddlePos = 50, + colorEndPos = 100 + ), + + ### header + logoBackColor = "#282f38", + headerButtonBackColor = "#282f38", + headerButtonIconColor = "#18ece1", + headerButtonBackColorHover = "#282f38", + headerButtonIconColorHover = "#ffffff", + headerBackColor = "#282f38", + headerBoxShadowColor = "#aaaaaa", + headerBoxShadowSize = "0px 0px 0px", + + ### sidebar + sidebarBackColor = cssGradientThreeColors( + direction = "down", + colorStart = "#282f38", + colorMiddle = "#384454", + colorEnd = "#495d78", + colorStartPos = 0, + colorMiddlePos = 50, + colorEndPos = 100), + + sidebarPadding = 0, + sidebarMenuBackColor = "transparent", + sidebarMenuPadding = 0, + sidebarMenuBorderRadius = 0, + sidebarShadowRadius = "5px 5px 5px", + sidebarShadowColor = "#282f38", + sidebarUserTextColor = "#ffffff", + sidebarSearchBackColor = "rgb(55,72,80)", + sidebarSearchIconColor = "rgb(153,153,153)", + sidebarSearchBorderColor = "rgb(55,72,80)", + sidebarTabTextColor = "rgb(255,255,255)", + sidebarTabTextSize = 15, + sidebarTabBorderStyle = "none none solid none", + sidebarTabBorderColor = "rgb(35,106,135)", + sidebarTabBorderWidth = 0, + sidebarTabBackColorSelected = cssGradientThreeColors( + direction = "right", + colorStart = "rgba(44,222,235,1)", + colorMiddle = "rgba(44,222,235,1)", + colorEnd = "rgba(0,255,213,1)", + colorStartPos = 0, + colorMiddlePos = 30, + colorEndPos = 100 + ), + sidebarTabTextColorSelected = "rgb(0,0,0)", + sidebarTabRadiusSelected = "0px 0px 0px 0px", + sidebarTabBackColorHover = cssGradientThreeColors( + direction = "right", + colorStart = "rgba(44,222,235,1)", + colorMiddle = "rgba(44,222,235,1)", + colorEnd = "rgba(0,255,213,1)", + colorStartPos = 0, + colorMiddlePos = 30, + colorEndPos = 100 + ), + sidebarTabTextColorHover = "rgb(50,50,50)", + sidebarTabBorderStyleHover = "none none solid none", + sidebarTabBorderColorHover = "rgb(75,126,151)", + sidebarTabBorderWidthHover = 0, + sidebarTabRadiusHover = "0px 0px 0px 0px", + + ### boxes + boxBackColor = "#ffffff", + boxBorderRadius = 7, + boxShadowSize = "0px 0px 0px", + boxShadowColor = "#ffffff", + boxTitleSize = 20, + boxDefaultColor = "#00a65a", + boxPrimaryColor = "#ffffff", + boxInfoColor = "#00a65a", + boxSuccessColor = "#00a65a", + boxWarningColor = "#ffffff", + boxDangerColor = "#ffffff", + tabBoxTabColor = "#ffffff", + tabBoxTabTextSize = 14, + tabBoxTabTextColor = "rgb(0,0,0)", + tabBoxTabTextColorSelected = "rgb(0,0,0)", + tabBoxBackColor = "#ffffff", + tabBoxHighlightColor = "#ffffff", + tabBoxBorderRadius = 5, + + ### inputs + buttonBackColor = "#282F38", + buttonTextColor = "#ffffff", + buttonBorderColor = "#282F38", + buttonBorderRadius = 5, + buttonBackColorHover = cssGradientThreeColors( + direction = "right", + colorStart = "rgba(44,222,235,1)", + colorMiddle = "rgba(44,222,235,1)", + colorEnd = "rgba(0,255,213,1)", + colorStartPos = 0, + colorMiddlePos = 30, + colorEndPos = 100 + ), + buttonTextColorHover = "#000000", + buttonBorderColorHover = "transparent", + textboxBackColor = "#ffffff", + textboxBorderColor = "#ffffff", + textboxBorderRadius = 5, + textboxBackColorSelect = "#ffffff", + textboxBorderColorSelect = "#000000", + + ### tables + tableBackColor = "rgb(255,255,255)", + tableBorderColor = "rgb(240,240,240)", + tableBorderTopSize = 1, + tableBorderRowSize = 1 + ), + + uiOutput("start_message"), + + tabItems( + + ## Tab Database ---- + + ### Tab Browse Entries ---- + + tabItem( + tabName = "db_browse_entries", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Browse Local Database"), style = "color:white") + ) + ), + hr(), br(), + br(), + br(), + uiOutput("no_scheme_entries"), + uiOutput("db_no_entries"), + uiOutput("entry_table_controls"), + br(), br(), + fluidRow( + column(1), + column( + width = 8, + uiOutput("db_entries_table") + ), + column( + width = 3, + align = "left", + uiOutput("delete_box"), + uiOutput("compare_allele_box"), + uiOutput("download_entries"), + br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br() + ) + ), + br() + ), + + ### Tab Scheme Info ---- + + tabItem( + tabName = "db_schemeinfo", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Scheme Info"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + uiOutput("no_scheme_info"), + fluidRow( + column(2), + column( + width = 7, + align = "center", + fluidRow( + column( + width = 7, + align = "right", + uiOutput("scheme_header") + ), + column( + width = 2, + align = "left", + uiOutput("download_scheme_info") + ) + ), + br(), + br(), + uiOutput("scheme_info") + ) + ) + ), + + ### Tab Loci Info ---- + + tabItem( + tabName = "db_loci_info", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Loci Info"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + fluidRow( + column(1), + column( + width = 10, + align = "center", + fluidRow( + column( + width = 6, + align = "right", + uiOutput("loci_header") + ), + column( + width = 2, + align = "left", + uiOutput("download_loci") + ) + ), + br(), + div(class = "loci_table", + dataTableOutput("db_loci")) + ) + ), + br(), br(), + fluidRow( + column(1), + uiOutput("sequence_selector"), + column(1), + column( + width = 7, + br(), + uiOutput("loci_sequences") + ) + ) + ), + + ### Tab Distance Matrix ---- + + tabItem( + tabName = "db_distmatrix", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Distance Matrix"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + uiOutput("no_scheme_distancematrix"), + uiOutput("distancematrix_no_entries"), + fluidRow( + column(1), + uiOutput("distmatrix_show") + ), + br(), br() + ), + + ### Tab Missing Values ---- + + tabItem( + tabName = "db_missing_values", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Missing Values"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + fluidRow( + column( + width = 3, + uiOutput("missing_values"), + fluidRow( + column( + width = 2, + div( + class = "rectangle-red-space" + ) + ), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 75px; position: relative; bottom: -12px", " = ≥ 5% of loci missing") + ) + ) + ) + ) + ) + ), + column( + width = 8, + rHandsontableOutput("table_missing_values") + ) + ) + ), + + ## Tab Manage Schemes ---- + + tabItem( + tabName = "init", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Select cgMLST Scheme"), style = "color:white") + ) + ), + hr(), + fluidRow( + column(1), + column( + width = 3, + br(), + br(), + br(), + pickerInput( + inputId = "select_cgmlst", + label = NULL, + choices = list( + "Acinetobacter baumanii", + "Bacillus anthracis", + "Bordetella pertussis", + "Brucella melitensis", + "Brucella spp.", + "Burkholderia mallei (FLI)", + "Burkholderia mallei (RKI)", + "Burkholderia pseudomallei", + "Campylobacter jejuni/coli", + "Clostridioides difficile", + "Clostridium perfringens", + "Corynebacterium diphtheriae", + "Cronobacter sakazakii/malonaticus", + "Enterococcus faecalis", + "Enterococcus faecium", + "Escherichia coli", + "Francisella tularensis", + "Klebsiella oxytoca sensu lato", + "Klebsiella pneumoniae sensu lato", + "Legionella pneumophila", + "Listeria monocytogenes", + "Mycobacterium tuberculosis complex", + "Mycobacteroides abscessus", + "Mycoplasma gallisepticum", + "Paenibacillus larvae", + "Pseudomonas aeruginosa", + "Salmonella enterica", + "Serratia marcescens", + "Staphylococcus aureus", + "Staphylococcus capitis", + "Streptococcus pyogenes" + ), + width = "300px", + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = FALSE + ) + ), + column( + width = 2, + br(), + br(), + br(), + h5(textOutput("scheme_update_info"), style = "color: white") + ), + column( + width = 2, + br(), + br(), + br(), + actionButton( + "download_cgMLST", + label = "Download", + icon = icon("download") + ), + shinyjs::hidden( + div(id = "loading", + HTML('')) + ) + ) + ), + fluidRow( + column(1), + column( + width = 6, + align = "center", + br(), + br(), + br(), + addSpinner( + tableOutput("cgmlst_scheme"), + spin = "dots", + color = "#ffffff" + ) + ) + ) + ), + + + + ## Tab Allelic Typing ---------------------------------------------- + + + tabItem( + tabName = "typing", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Generate Allelic Profile"), style = "color:white") + ) + ), + hr(), + uiOutput("typing_no_db"), + conditionalPanel( + "input.typing_mode == 'Single'", + fluidRow( + uiOutput("initiate_typing_ui"), + uiOutput("single_typing_progress"), + column(1), + uiOutput("metadata_single_box"), + column(1), + uiOutput("start_typing_ui") + ) + ), + conditionalPanel( + "input.typing_mode == 'Multi'", + fluidRow( + uiOutput("initiate_multi_typing_ui"), + uiOutput("multi_stop"), + column(1), + uiOutput("metadata_multi_box"), + column(1), + uiOutput("start_multi_typing_ui") + ), + fluidRow( + column( + width = 6, + uiOutput("pending_typing") + ), + column( + width = 6, + uiOutput("multi_typing_results") + ) + ) + ) + ), + + + ## Tab Visualization ------------------------------------------------------- + + + tabItem( + tabName = "visualization", + fluidRow( + tags$script(src = "javascript_functions.js"), + column( + width = 12, + align = "center", + br(), + conditionalPanel( + "input.tree_algo=='Minimum-Spanning'", + uiOutput("mst_field") + ), + conditionalPanel( + "input.tree_algo=='Neighbour-Joining'", + uiOutput("nj_field") + ), + conditionalPanel( + "input.tree_algo=='UPGMA'", + uiOutput("upgma_field") + ) + ) + ), + br(), + hr(), + + ### Control panels MST ---- + conditionalPanel( + "input.tree_algo=='Minimum-Spanning'", + fluidRow( + column( + width = 4, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + height = "500px", + h3(p("Layout"), style = "color:white; position:relative; right:-15px"), + hr(), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Title"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "mst_title", + label = "", + width = "100%", + placeholder = "Plot Title" + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_title_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_title_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + numericInput( + "mst_title_size", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 40, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Subtitle"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "mst_subtitle", + label = "", + width = "100%", + placeholder = "Plot Subtitle" + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_subtitle_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_subtitle_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + numericInput( + "mst_subtitle_size", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 20, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ) + ) + ) + ), + hr(), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Legend"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_legend_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_legend_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 11, + sliderInput( + "mst_font_size", + label = h5("Font Size", style = "color:white; margin-bottom: 0px;"), + value = 18, + min = 15, + max = 30, + step = 1, + ticks = FALSE, + width = "180px" + ) + ), + column(1) + ), + br(), + fluidRow( + column( + width = 11, + sliderInput( + "mst_symbol_size", + label = h5("Key Size", style = "color:white; margin-bottom: 0px;"), + value = 20, + min = 10, + max = 30, + step = 1, + ticks = FALSE, + width = "180px" + ) + ), + column(1) + ) + ) + ) + ), + fluidRow( + column( + width = 7, + selectInput( + "mst_legend_ori", + label = "", + width = "100%", + choices = c("Left" = "left", "Right" = "right") + ) + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Background"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 12, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "mst_background_transparent", + h5(p("Transparent"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_background_color", + width = "100%", + selected = "#ffffff", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 4, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + height = "500px", + h3(p("Nodes"), style = "color:white; position:relative; right:-15px"), + hr(), + fluidRow( + column( + width = 6, + column( + width = 12, + align = "left", + h4(p("Label"), style = "color:white;") + ), + column( + width = 12, + align = "center", + div( + class = "label_sel", + uiOutput("mst_node_label") + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "node_font_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + numericInput( + "node_label_fontsize", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 14, + min = 8, + max = 30, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 10, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "mst_color_var", + h5(p("Add Variable"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 2, + bslib::tooltip( + bsicons::bs_icon("info-circle", title = "Only categorical variables can \nbe mapped to the node color", color = "white", + height = "12px", width = "12px", position = "relative", top = "27px", right = "56px"), + "Text shown in the tooltip.", + show = FALSE, + id = "mst_node_col_info" + ) + ) + ), + uiOutput("mst_color_mapping") + ) + ) + ), br() + ) + ), + hr(), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Size"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 12, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "scale_nodes", + h5(p("Scale by Duplicates"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ) + ) + ) + ) + ), + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + align = "left", + conditionalPanel( + "input.scale_nodes==true", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Range') + ) + ) + ), + conditionalPanel( + "input.scale_nodes==false", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Size') + ) + ) + ) + ), + column( + width = 9, + align = "center", + conditionalPanel( + "input.scale_nodes==true", + div( + class = "mst_scale_slider", + sliderInput( + "mst_node_scale", + label = "", + min = 1, + max = 80, + value = c(20, 40), + ticks = FALSE + ) + ) + ), + conditionalPanel( + "input.scale_nodes==false", + div( + class = "mst_scale_slider", + sliderInput( + inputId = "mst_node_size", + label = "", + min = 1, + max = 100, + value = 30, + ticks = FALSE + ) + ) + ) + ) + ), + br() + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Other Elements"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 12, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "mst_shadow", + h5(p("Show Shadow"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + fluidRow( + column( + width = 3, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Shape') + ) + ) + ), + column( + width = 9, + align = "center", + div( + class = "mst_shape_sel", + selectInput( + "mst_node_shape", + "", + choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), + `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), + selected = c("Dot" = "dot"), + width = "85%" + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 4, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + height = "500px", + h3(p("Edges"), style = "color:white; position:relative; right:-15px"), + hr(), + fluidRow( + column( + width = 6, + column( + width = 12, + align = "left", + h4(p("Label"), style = "color:white;") + ), + column( + width = 12, + align = "center", + div( + class = "label_sel", + selectInput( + "mst_edge_label", + label = "", + choices = c( + `Allelic Distance` = "weight", + Index = "index", + `Assembly ID` = "assembly_id", + `Assembly Name` = "assembly_name", + `Isolation Date` = "isolation_date", + Host = "host", + Country = "country", + City = "city" + ), + selected = c(`Allelic Distance` = "weight"), + width = "100%" + ) + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_edge_font_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_edgelabel_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + numericInput( + "mst_edge_font_size", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 18, + step = 1, + min = 8, + max = 30, + width = "80px" + ) + ) + ) + ), + br() + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + div( + class = "node_color", + colorPickr( + inputId = "mst_color_edge", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_edgecolor_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + sliderInput( + "mst_edge_opacity", + label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), + value = 0.7, + step = 0.1, + min = 0, + max = 1, + ticks = FALSE, + width = "150px" + ) + ) + ) + ) + ) + ) + ) + ) + ), + hr(style = "margin-top: 3px !important"), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Length multiplier"), style = "color:white; position: relative; right: -15px; margin-bottom: -5px") + ) + ), + column( + width = 12, + align = "left", + br(), + div( + class = "switch-mst-edges", + materialSwitch( + "mst_scale_edges", + h5(p("Scale Allelic Distance"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + fluidRow( + column( + width = 3, + align = "left", + conditionalPanel( + "input.mst_scale_edges==true", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Multiplier') + ) + ) + ), + conditionalPanel( + "input.mst_scale_edges==false", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Length') + ) + ) + ) + ), + column( + width = 9, + align = "center", + conditionalPanel( + "input.mst_scale_edges==true", + div( + class = "slider_edge", + sliderInput( + inputId = "mst_edge_length_scale", + label = NULL, + min = 1, + max = 40, + value = 15, + ticks = FALSE + ) + ) + ), + conditionalPanel( + "input.mst_scale_edges==false", + div( + class = "slider_edge", + sliderTextInput( + inputId = "mst_edge_length", + label = NULL, + choices = append(seq(0.1, 1, 0.1), 2:100), + selected = 35, + hide_min_max = FALSE + ) + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 6, + align = "left", + h4(p("Clustering"), style = "color:white; text-align: left; position: relative; right: -15px") + ), + column( + width = 2, + bslib::tooltip( + bsicons::bs_icon("info-circle", + title = "Cluster threshold according to species-specific\nComplex Type Distance (cgMLST.org)", + color = "white", height = "14px", width = "14px", + position = "relative", top = "9px", right = "28px"), + "Text shown in the tooltip.", + show = FALSE, + id = "mst_cluster_info" + ) + ) + ), + br(), + fluidRow( + column( + width = 9, + div( + class = "mst-cluster-switch", + materialSwitch( + "mst_show_clusters", + h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "mst_cluster_col_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + selectInput( + "mst_cluster_col_scale", + label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), + choices = c("Viridis", "Rainbow"), + width = "150px" + ), + selectInput( + "mst_cluster_type", + label = h5("Cluster Type", style = "color:white; margin-bottom: 0px;"), + choices = c("Type 1", "Type 2"), + width = "150px" + ) + ) + ) + ), + br(), + fluidRow( + column( + width = 4, + HTML( + paste( + tags$span(style='color: white; text-align: left; font-size: 14px; margin-left: 15px', 'Threshold') + ) + ) + ), + column( + width = 4, + uiOutput("mst_cluster") + ), + column( + width = 4, + actionButton( + "mst_cluster_reset", + label = "", + icon = icon("rotate") + ), + bsTooltip("mst_cluster_reset", + HTML("Reset to default Complex Type Distance"), + placement = "top", trigger = "hover") + ) + ) + ), + br(), + ) + ), br(), br(), br(), br(), br(), br() + ) + ) + ), + + ### Control Panels NJ ---- + + conditionalPanel( + "input.tree_algo=='Neighbour-Joining'", + fluidRow( + column( + width = 1, + radioGroupButtons( + inputId = "nj_controls", + label = "", + choices = c("Layout", "Label", "Elements", "Variables"), + direction = "vertical" + ) + ), + conditionalPanel( + "input.nj_controls=='Layout'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Theme"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + align = "center", + selectInput( + inputId = "nj_layout", + label = "", + choices = list( + Linear = list( + "Rectangular" = "rectangular", + "Roundrect" = "roundrect", + "Slanted" = "slanted", + "Ellipse" = "ellipse" + ), + Circular = list("Circular" = "circular", + "Inward" = "inward") + ), + selected = "rectangular", + width = "90%" + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "nj_rootedge_show", + h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_rootedge_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_rootedge_length"), + br(), + selectInput( + "nj_rootedge_line", + label = h5("Rootedge Line", style = "color:white"), + choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), + selected = c(Dotted = "solid"), + width = "100px" + ), + br(), + conditionalPanel( + "input.nj_layout=='circular'", + sliderInput( + "nj_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = -50, + max = 0, + value = -10, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_layout=='inward'", + sliderInput( + "nj_inward_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = 30, + max = 120, + value = 50, + ticks = FALSE, + width = "150px", + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-re", + materialSwitch( + "nj_ladder", + h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + colorPickr( + inputId = "nj_color", + width = "90%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + br(), + fluidRow( + column( + width = 5, + h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") + ), + column( + width = 7, + colorPickr( + inputId = "nj_bg", + width = "90%", + selected = "#ffffff", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + br() + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Title"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "nj_title", + label = "", + width = "100%", + placeholder = "Plot Title" + ), + textInput( + "nj_subtitle", + label = "", + width = "100%", + placeholder = "Plot Subtitle" + ), + br(), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "nj_title_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "nj_title_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "nj_title_size", + label = h5("Title Size", style = "color:white; margin-bottom: 0px"), + value = 30, + min = 15, + max = 40, + step = 1, + width = "80px" + ), + br(), + numericInput( + "nj_subtitle_size", + label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), + value = 20, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ), + br() + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + br(), + fluidRow( + column( + width = 3, + h5("Ratio", style = "color: white; font-size: 14px;") + ), + column( + width = 6, + align = "left", + div( + class = "ratio-sel", + selectInput( + "nj_ratio", + "", + choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "nj_size_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + sliderInput( + "nj_v", + label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "nj_h", + label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + sliderInput( + "nj_scale", + "", + min = 500, + max = 1200, + value = 800, + step = 5, + width = "95%", + ticks = FALSE + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + div( + class = "zoom-slider", + sliderInput( + "nj_zoom", + label = NULL, + min = 0.5, + max = 1.5, + step = 0.05, + value = 0.95, + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "nj_treescale_show", + h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + br() + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_treescale_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_treescale_width"), + br(), + uiOutput("nj_treescale_x"), + br(), + uiOutput("nj_treescale_y") + ) + ) + ) + ) + ) + ) + ), + column( + width = 12, + align = "left", + h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + align = "left", + prettyRadioButtons( + "nj_legend_orientation", + "", + choices = c(Horizontal = "horizontal", + Vertical = "vertical"), + selected = c(Vertical = "vertical"), + inline = FALSE + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "nj_legend_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "nj_legend_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + value = 10, + min = 5, + max = 25, + step = 1, + width = "80px" + ), + br(), + sliderInput( + "nj_legend_x", + label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), + value = 0.9, + min = -0.9, + max = 1.9, + step = 0.2, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "nj_legend_y", + label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), + value = 0.2, + min = -1.5, + max = 1.5, + step = 0.1, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_controls=='Label'", + column( + width = 4, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Tips"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 4, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "nj_tiplab_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "center", + uiOutput("nj_tiplab") + ), + column( + width = 3, + div( + class = "mat-switch-align", + materialSwitch( + "nj_align", + h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 1, + align = "right", + dropMenu( + actionBttn( + "nj_labeltext_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "nj_tiplab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + width = "150px", + ticks = FALSE + ), + br(), + conditionalPanel( + "!(input.nj_layout=='inward'|input.nj_layout=='circular')", + sliderInput( + inputId = "nj_tiplab_nudge_x", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 0, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_layout=='circular'", + sliderInput( + inputId = "nj_tiplab_position", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = -0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_layout=='inward'", + sliderInput( + inputId = "nj_tiplab_position_inw", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 1.1, + width = "150px", + ticks = FALSE + ) + ), + br(), + sliderInput( + inputId = "nj_tiplab_angle", + label = h5("Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + ticks = FALSE, + width = "150px", + ) + ), + column( + width = 6, + align = "center", + uiOutput("nj_tiplab_size"), + br(), + selectInput( + "nj_tiplab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") + ), + column( + width = 4, + align = "center", + colorPickr( + inputId = "nj_tiplab_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + br(), + div( + class = "mat-switch-geom", + materialSwitch( + "nj_geom", + h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + colorPickr( + inputId = "nj_tiplab_fill", + width = "100%", + selected = "#84D9A0", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 3, + align = "left", + dropMenu( + actionBttn( + "nj_labelformat_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_tiplab_padding"), + br(), + sliderInput( + inputId = "nj_tiplab_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.2, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Branches"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "nj_show_branch_label", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 5, + align = "center", + uiOutput("nj_branch_label") + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "nj_branch_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "nj_branchlab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 0.65, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "nj_branch_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "nj_branch_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ) + ), + column( + width = 6, + align = "center", + uiOutput("nj_branch_size"), + selectInput( + "nj_branchlab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ), + br(), + sliderInput( + "nj_branch_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.5, + width = "250px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") + ), + column( + width = 5, + colorPickr( + inputId = "nj_branch_label_color", + width = "100%", + selected = "#FFB7B7", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 6, + textInput( + "nj_new_label_name", + "", + placeholder = "New Label" + ) + ), + column( + width = 3, + actionButton( + "nj_add_new_label", + "", + icon = icon("plus") + ) + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "nj_custom_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_custom_labelsize"), + br(), + uiOutput("nj_sliderInput_y"), + br(), + uiOutput("nj_sliderInput_x") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 6, + uiOutput("nj_custom_label_select") + ), + column( + width = 4, + uiOutput("nj_del_label"), + ) + ), + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_cust_label_save") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_controls=='Elements'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "nj_tippoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_tippoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "nj_tippoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 0.5, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("nj_tippoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "nj_tippoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + conditionalPanel( + "input.nj_tipshape_mapping_show==false", + selectInput( + "nj_tippoint_shape", + "", + width = "100%", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ) + ), + conditionalPanel( + "input.nj_tipshape_mapping_show==true", + h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "nj_nodepoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_nodepoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "nj_nodepoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 1, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("nj_nodepoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "nj_nodepoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + selectInput( + "nj_nodepoint_shape", + "", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Tiles"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 5, + div( + class = "sel-tile-number", + selectInput( + "nj_tile_number", + "", + choices = 1:5, + width = "70px" + ) + ) + ), + column( + width = 7, + align = "right", + dropMenu( + actionBttn( + "nj_tile_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + conditionalPanel( + "input.nj_tile_num == 1", + sliderInput( + "nj_fruit_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + sliderInput( + "nj_fruit_alpha_2", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + sliderInput( + "nj_fruit_alpha_3", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + sliderInput( + "nj_fruit_alpha_4", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + sliderInput( + "nj_fruit_alpha_5", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 1", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width2"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_2"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width3"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_3"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width4"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_4"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width5"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_5"), + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 3, + h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") + ), + column( + width = 6, + align = "center", + textInput( + "nj_heatmap_title", + label = "", + value = "Heatmap", + placeholder = "Heatmap" + ) + ), + column( + width = 3, + align = "right", + dropMenu( + actionBttn( + "nj_heatmap_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_colnames_angle"), + br(), + uiOutput("nj_colnames_y") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") + ), + column( + width = 7, + uiOutput("nj_heatmap_width") + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") + ), + column( + width = 7, + uiOutput("nj_heatmap_offset") + ) + ), + br(), br() + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + div( + class = "mat-switch", + materialSwitch( + "nj_nodelabel_show", + h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") + ), + column( + width = 9, + uiOutput("nj_parentnode") + ) + ), + uiOutput("nj_clade_scale"), + fluidRow( + column( + width = 5, + h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + div( + class = "sel-clade", + selectInput( + "nj_clade_type", + "", + choices = c("Rect" = "rect", + "Round" = "roundrect"), + selected = c("Round" = "roundrect") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_controls=='Variables'", + column( + width = 7, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + align = "center", + h4(p("Element"), style = "color:white; margin-bottom: 20px") + ), + column( + width = 3, + align = "center", + h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") + ), + column( + width = 6, + align = "center", + h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") + ) + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_mapping_show", + h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_color_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("nj_tiplab_scale") + ), + uiOutput("nj_tiplab_mapping_info"), + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_tipcolor_mapping_show", + h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_tipcolor_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("nj_tippoint_scale") + ), + uiOutput("nj_tipcolor_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_tipshape_mapping_show", + h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_tipshape_mapping") + ), + column( + width = 3, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') + ) + ) + ), + uiOutput("nj_tipshape_mapping_info") + ), + fluidRow( + column( + width = 3, + fluidRow( + column( + width = 8, + conditionalPanel( + "input.nj_tile_num == 1", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_1", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_2", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_3", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_4", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_5", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + column( + width = 4, + align = "left", + div( + class = "tile-sel", + selectInput( + "nj_tile_num", + "", + choices = 1:5, + width = "50px" + ) + ) + ) + ) + ), + column( + width = 3, + align = "center", + conditionalPanel( + "input.nj_tile_num == 1", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable") + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable2") + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable3") + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable4") + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable5") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 1", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_1") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_2") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_3") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_4") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_5") + ) + ) + ), + uiOutput("nj_fruit_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_heatmap_show", + h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_heatmap_sel") + ), + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_heatmap_scale") + ) + ), + uiOutput("nj_heatmap_mapping_info") + ) + ) + ) + ) + ) + ), + br(), br(), br(), br(), br(), br() + ), + + ### Control Panels UPGMA ---- + + conditionalPanel( + "input.tree_algo=='UPGMA'", + fluidRow( + column( + width = 1, + radioGroupButtons( + inputId = "upgma_controls", + label = "", + choices = c("Layout", "Label", "Elements", "Variables"), + direction = "vertical" + ) + ), + conditionalPanel( + "input.upgma_controls=='Layout'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Theme"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + align = "center", + selectInput( + inputId = "upgma_layout", + label = "", + choices = list( + Linear = list( + "Rectangular" = "rectangular", + "Roundrect" = "roundrect", + "Slanted" = "slanted", + "Ellipse" = "ellipse" + ), + Circular = list("Circular" = "circular", + "Inward" = "inward") + ), + selected = "rectangular", + width = "90%" + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "upgma_rootedge_show", + h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_rootedge_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_rootedge_length"), + br(), + selectInput( + "upgma_rootedge_line", + label = h5("Rootedge Line", style = "color:white"), + choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), + selected = c(Dotted = "solid"), + width = "100px" + ), + br(), + conditionalPanel( + "input.upgma_layout=='circular'", + sliderInput( + "upgma_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = -50, + max = 0, + value = -10, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_layout=='inward'", + sliderInput( + "upgma_inward_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = 30, + max = 120, + value = 50, + ticks = FALSE, + width = "150px", + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-re", + materialSwitch( + "upgma_ladder", + h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + colorPickr( + inputId = "upgma_color", + width = "90%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + br(), + fluidRow( + column( + width = 5, + h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") + ), + column( + width = 7, + colorPickr( + inputId = "upgma_bg", + width = "90%", + selected = "#ffffff", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Title"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "upgma_title", + label = "", + width = "100%", + placeholder = "Plot Title" + ), + textInput( + "upgma_subtitle", + label = "", + width = "100%", + placeholder = "Plot Subtitle" + ), + br(), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "upgma_title_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "upgma_title_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "upgma_title_size", + label = h5("Title Size", style = "color:white; margin-bottom: 0px"), + value = 30, + min = 15, + max = 40, + step = 1, + width = "80px" + ), + br(), + numericInput( + "upgma_subtitle_size", + label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), + value = 20, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + br(), + fluidRow( + column( + width = 3, + h5("Ratio", style = "color: white; font-size: 14px;") + ), + column( + width = 6, + align = "left", + div( + class = "ratio-sel", + selectInput( + "upgma_ratio", + "", + choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "upgma_size_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + sliderInput( + "upgma_v", + label = "Vertical Position", + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "upgma_h", + label = "Horizontal Position", + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + sliderInput( + "upgma_scale", + "", + min = 500, + max = 1200, + value = 800, + step = 5, + width = "95%", + ticks = FALSE + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + div( + class = "zoom-slider", + sliderInput( + "upgma_zoom", + label = NULL, + min = 0.5, + max = 1.5, + step = 0.05, + value = 0.95, + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "upgma_treescale_show", + h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + br() + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_treescale_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_treescale_width"), + br(), + uiOutput("upgma_treescale_x"), + br(), + uiOutput("upgma_treescale_y") + ) + ) + ) + ) + ) + ) + ), + column( + width = 12, + align = "left", + h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + align = "left", + prettyRadioButtons( + "upgma_legend_orientation", + "", + choices = c(Horizontal = "horizontal", + Vertical = "vertical"), + selected = c(Vertical = "vertical"), + inline = FALSE + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "upgma_legend_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "upgma_legend_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + value = 10, + min = 5, + max = 25, + step = 1, + width = "80px" + ), + br(), + sliderInput( + "upgma_legend_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + value = 0.9, + min = -0.9, + max = 1.9, + step = 0.2, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "upgma_legend_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + value = 0.2, + min = -1.5, + max = 1.5, + step = 0.1, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_controls=='Label'", + column( + width = 4, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Tips"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 4, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "upgma_tiplab_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "center", + uiOutput("upgma_tiplab") + ), + column( + width = 3, + div( + class = "mat-switch-align", + materialSwitch( + "upgma_align", + h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 1, + align = "right", + dropMenu( + actionBttn( + "upgma_labeltext_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "upgma_tiplab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + width = "150px", + ticks = FALSE + ), + br(), + conditionalPanel( + "!(input.upgma_layout=='inward'|input.upgma_layout=='circular')", + sliderInput( + inputId = "upgma_tiplab_nudge_x", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 0, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_layout=='circular'", + sliderInput( + inputId = "upgma_tiplab_position", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = -0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_layout=='inward'", + sliderInput( + inputId = "upgma_tiplab_position_inw", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 1.1, + width = "150px", + ticks = FALSE + ) + ), + br(), + sliderInput( + inputId = "upgma_tiplab_angle", + label = h5("Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + ticks = FALSE, + width = "150px", + ) + ), + column( + width = 6, + align = "center", + uiOutput("upgma_tiplab_size"), + br(), + selectInput( + "upgma_tiplab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") + ), + column( + width = 4, + align = "center", + colorPickr( + inputId = "upgma_tiplab_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + br(), + div( + class = "mat-switch-geom", + materialSwitch( + "upgma_geom", + h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + colorPickr( + inputId = "upgma_tiplab_fill", + width = "100%", + selected = "#84D9A0", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 3, + align = "left", + dropMenu( + actionBttn( + "upgma_labelformat_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_tiplab_padding"), + br(), + sliderInput( + inputId = "upgma_tiplab_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.2, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Branches"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "upgma_show_branch_label", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 5, + align = "center", + uiOutput("upgma_branch_label") + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "upgma_branch_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "upgma_branchlab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 0.65, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "upgma_branch_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "upgma_branch_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ) + ), + column( + width = 6, + align = "center", + uiOutput("upgma_branch_size"), + selectInput( + "upgma_branchlab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ), + br(), + sliderInput( + "upgma_branch_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.5, + width = "250px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") + ), + column( + width = 5, + colorPickr( + inputId = "upgma_branch_label_color", + width = "100%", + selected = "#FFB7B7", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ), + br(), br() + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 6, + textInput( + "upgma_new_label_name", + "", + placeholder = "New Label" + ) + ), + column( + width = 3, + actionButton( + "upgma_add_new_label", + "", + icon = icon("plus") + ) + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "upgma_custom_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_custom_labelsize"), + br(), + uiOutput("upgma_sliderInput_y"), + br(), + uiOutput("upgma_sliderInput_x") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 6, + uiOutput("upgma_custom_label_select") + ), + column( + width = 4, + uiOutput("upgma_del_label"), + ) + ), + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_cust_label_save") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_controls=='Elements'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "upgma_tippoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_tippoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "upgma_tippoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 0.5, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("upgma_tippoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "upgma_tippoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + conditionalPanel( + "input.upgma_tipshape_mapping_show==false", + selectInput( + "upgma_tippoint_shape", + "", + width = "100%", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ) + ), + conditionalPanel( + "input.upgma_tipshape_mapping_show==true", + h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") + ), + br() + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "upgma_nodepoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_nodepoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "upgma_nodepoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 1, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("upgma_nodepoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "upgma_nodepoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + selectInput( + "upgma_nodepoint_shape", + "", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ), + br() + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Tiles"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 5, + div( + class = "sel-tile-number", + selectInput( + "upgma_tile_number", + "", + choices = 1:5, + width = "70px" + ) + ) + ), + column( + width = 7, + align = "right", + dropMenu( + actionBttn( + "upgma_tile_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + conditionalPanel( + "input.upgma_tile_num == 1", + sliderInput( + "upgma_fruit_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + sliderInput( + "upgma_fruit_alpha_2", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + sliderInput( + "upgma_fruit_alpha_3", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + sliderInput( + "upgma_fruit_alpha_4", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + sliderInput( + "upgma_fruit_alpha_5", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 1", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width2"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_2"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width3"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_3"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width4"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_4"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width5"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_5"), + br() + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 3, + h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") + ), + column( + width = 6, + align = "center", + textInput( + "upgma_heatmap_title", + label = "", + value = "Heatmap", + placeholder = "Heatmap" + ) + ), + column( + width = 3, + align = "right", + dropMenu( + actionBttn( + "upgma_heatmap_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_colnames_angle"), + br(), + uiOutput("upgma_colnames_y") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") + ), + column( + width = 7, + uiOutput("upgma_heatmap_width") + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") + ), + column( + width = 7, + uiOutput("upgma_heatmap_offset") + ) + ), + br(), br() + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + div( + class = "mat-switch", + materialSwitch( + "upgma_nodelabel_show", + h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") + ), + column( + width = 9, + uiOutput("upgma_parentnode") + ) + ), + uiOutput("upgma_clade_scale"), + fluidRow( + column( + width = 5, + h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + div( + class = "sel-clade", + selectInput( + "upgma_clade_type", + "", + choices = c("Rect" = "rect", + "Round" = "roundrect"), + selected = c("Round" = "roundrect") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_controls=='Variables'", + column( + width = 7, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + align = "center", + h4(p("Element"), style = "color:white; margin-bottom: 20px") + ), + column( + width = 3, + align = "center", + h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") + ), + column( + width = 6, + align = "center", + h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") + ) + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_mapping_show", + h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_color_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tiplab_scale") + ), + uiOutput("upgma_tiplab_mapping_info"), + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tipcolor_mapping_show", + h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tipcolor_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tippoint_scale") + ), + uiOutput("upgma_tipcolor_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tipshape_mapping_show", + h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tipshape_mapping") + ), + column( + width = 3, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') + ) + ) + ), + uiOutput("upgma_tipshape_mapping_info") + ), + fluidRow( + column( + width = 3, + fluidRow( + column( + width = 8, + conditionalPanel( + "input.upgma_tile_num == 1", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_1", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_2", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_3", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_4", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_5", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + column( + width = 4, + align = "left", + div( + class = "tile-sel", + selectInput( + "upgma_tile_num", + "", + choices = 1:5, + width = "50px" + ) + ) + ) + ) + ), + column( + width = 3, + align = "center", + conditionalPanel( + "input.upgma_tile_num == 1", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable2") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable3") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable4") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable5") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 1", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_1") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_2") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_3") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_4") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_5") + ) + ) + ), + uiOutput("upgma_fruit_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_heatmap_show", + h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_heatmap_sel") + ), + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_heatmap_scale") + ) + ), + uiOutput("upgma_heatmap_mapping_info") + ) + ) + ) + ) + ) + ), + br(), br(), br(), br(), br(), br() + ) + ), + + ## Tab Utilities ------------------------------------------------------- + + tabItem( + tabName = "utilities", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Utilities"), style = "color:white") + ) + ), + br(), + hr(), + column( + width = 5, + align = "left", + shinyDirButton( + "hash_dir", + "Choose folder with .fasta files", + title = "Locate folder with loci", + buttonType = "default", + style = "border-color: white; margin: 10px; min-width: 200px; text-align: center" + ), + actionButton("hash_start", "Start Hashing", icon = icon("circle-play")), + shinyjs::hidden( + div(id = "hash_loading", + HTML('')) + ) + ) + # br(), + # actionButton( + # "backup_database", + # "Create backup", + # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + # ), + # br(), + # actionButton( + # "import_db_backup", + # "Restore backup", + # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + # ) + ), + + + ## Tab Screening ------------------------------------------------------- + + tabItem( + tabName = "gs_screening", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Screening"), style = "color:white; margin-bottom: -20px;") + ), + column( + width = 7, + align = "left", + uiOutput("gene_screening_info") + ) + ), + br(), + hr(), + fluidRow( + uiOutput("screening_interface") + ) + ), + + ## Tab Resistance Profile ------------------------------------------------------- + + tabItem( + tabName = "gs_profile", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Browse Entries"), style = "color:white; margin-bottom: -20px") + ), + column( + width = 7, + align = "left", + uiOutput("gene_resistance_info") + ) + ), + br(), + hr(), + br(), br(), + uiOutput("gs_table_selection"), + fluidRow( + column(1), + uiOutput("gs_profile_display") + ) + ) + ) # End tabItems + ) # End dashboardPage +) # end UI + +# _______________________ #### + +# Server ---- + +server <- function(input, output, session) { + + phylotraceVersion <- paste("1.5.0") + + #TODO Enable this, or leave disabled + # Kill server on session end + session$onSessionEnded( function() { + stopApp() + }) + + # Disable various user inputs (visualization control) + shinyjs::disable('mst_edge_label') + + ## Functions ---- + + # Function to read and format FASTA sequences + format_fasta <- function(filepath) { + fasta <- readLines(filepath) + formatted_fasta <- list() + current_sequence <- "" + + for (line in fasta) { + if (startsWith(line, ">")) { + if (current_sequence != "") { + formatted_fasta <- append(formatted_fasta, list(current_sequence)) + current_sequence <- "" + } + formatted_fasta <- append(formatted_fasta, list(line)) + } else { + current_sequence <- paste0(current_sequence, line) + } + } + if (current_sequence != "") { + formatted_fasta <- append(formatted_fasta, list(current_sequence)) + } + + formatted_fasta + } + + # Function to color-code the bases in a sequence + color_sequence <- function(sequence) { + sequence <- gsub("A", "A", sequence) + sequence <- gsub("T", "T", sequence) + sequence <- gsub("G", "G", sequence) + sequence <- gsub("C", "C", sequence) + sequence + } + + # Function to log messages to logfile + log_message <- function(log_file, message, append = TRUE) { + cat(format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "-", message, "\n", file = log_file, append = append) + } + + # Modified gheatmap function + gheatmap.mod <- function(p, data, offset=0, width=1, low="green", high="red", color="white", + colnames=TRUE, colnames_position="bottom", colnames_angle=0, colnames_level=NULL, + colnames_offset_x = 0, colnames_offset_y = 0, font.size=4, family="", hjust=0.5, legend_title = "value", + colnames_color = "black") { + + colnames_position %<>% match.arg(c("bottom", "top")) + variable <- value <- lab <- y <- NULL + + ## if (is.null(width)) { + ## width <- (p$data$x %>% range %>% diff)/30 + ## } + + ## convert width to width of each cell + width <- width * (p$data$x %>% range(na.rm=TRUE) %>% diff) / ncol(data) + + isTip <- x <- y <- variable <- value <- from <- to <- NULL + + ## handle the display of heatmap on collapsed nodes + ## https://github.com/GuangchuangYu/ggtree/issues/242 + ## extract data on leaves (& on collapsed internal nodes) + ## (the latter is extracted only when the input data has data on collapsed + ## internal nodes) + df <- p$data + nodeCo <- intersect(df %>% filter(is.na(x)) %>% + select(.data$parent, .data$node) %>% unlist(), + df %>% filter(!is.na(x)) %>% + select(.data$parent, .data$node) %>% unlist()) + labCo <- df %>% filter(.data$node %in% nodeCo) %>% + select(.data$label) %>% unlist() + selCo <- intersect(labCo, rownames(data)) + isSel <- df$label %in% selCo + + df <- df[df$isTip | isSel, ] + start <- max(df$x, na.rm=TRUE) + offset + + dd <- as.data.frame(data) + ## dd$lab <- rownames(dd) + i <- order(df$y) + + ## handle collapsed tree + ## https://github.com/GuangchuangYu/ggtree/issues/137 + i <- i[!is.na(df$y[i])] + + lab <- df$label[i] + ## dd <- dd[lab, , drop=FALSE] + ## https://github.com/GuangchuangYu/ggtree/issues/182 + dd <- dd[match(lab, rownames(dd)), , drop = FALSE] + + + dd$y <- sort(df$y) + dd$lab <- lab + ## dd <- melt(dd, id=c("lab", "y")) + dd <- gather(dd, variable, value, -c(lab, y)) + + i <- which(dd$value == "") + if (length(i) > 0) { + dd$value[i] <- NA + } + if (is.null(colnames_level)) { + dd$variable <- factor(dd$variable, levels=colnames(data)) + } else { + dd$variable <- factor(dd$variable, levels=colnames_level) + } + V2 <- start + as.numeric(dd$variable) * width + mapping <- data.frame(from=dd$variable, to=V2) + mapping <- unique(mapping) + + dd$x <- V2 + dd$width <- width + dd[[".panel"]] <- factor("Tree") + if (is.null(color)) { + p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, inherit.aes=FALSE) + } else { + p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, color=color, inherit.aes=FALSE) + } + if (is(dd$value,"numeric")) { + p2 <- p2 + scale_fill_gradient(low=low, high=high, na.value=NA, name = legend_title) # "white") + } else { + p2 <- p2 + scale_fill_discrete(na.value=NA, name = legend_title) #"white") + } + + if (colnames) { + if (colnames_position == "bottom") { + y <- 0 + } else { + y <- max(p$data$y) + 1 + } + mapping$y <- y + mapping[[".panel"]] <- factor("Tree") + p2 <- p2 + geom_text(data=mapping, aes(x=to, y = y, label=from), color = colnames_color, size=font.size, family=family, inherit.aes = FALSE, + angle=colnames_angle, nudge_x=colnames_offset_x, nudge_y = colnames_offset_y, hjust=hjust) + } + + p2 <- p2 + theme(legend.position="right") + ## p2 <- p2 + guides(fill = guide_legend(override.aes = list(colour = NULL))) + + if (!colnames) { + ## https://github.com/GuangchuangYu/ggtree/issues/204 + p2 <- p2 + scale_y_continuous(expand = c(0,0)) + } + + attr(p2, "mapping") <- mapping + return(p2) + } + + # Get rhandsontable + get.entry.table.meta <- reactive({ + if(!is.null(hot_to_r(input$db_entries))){ + table <- hot_to_r(input$db_entries) + select(select(table, -13), 1:(12 + nrow(DB$cust_var))) + } + }) + + # Function to find columns with varying values + var_alleles <- function(dataframe) { + + varying_columns <- c() + + for (col in 1:ncol(dataframe)) { + unique_values <- unique(dataframe[, col]) + + if (length(unique_values) > 1) { + varying_columns <- c(varying_columns, col) + } + } + + return(varying_columns) + } + + # Functions to compute hamming distances dependent on missing value handling + hamming.dist <- function(x, y) { + sum(x != y) + } + + hamming.distIgnore <- function(x, y) { + sum( (x != y) & !is.na(x) & !is.na(y) ) + } + + hamming.distCategory <- function(x, y) { + sum((x != y | xor(is.na(x), is.na(y))) & !(is.na(x) & is.na(y))) + } + + compute.distMatrix <- function(profile, hamming.method) { + mat <- as.matrix(profile) + n <- nrow(mat) + dist_mat <- matrix(0, n, n) + for (i in 1:(n-1)) { + for (j in (i+1):n) { + dist_mat[i, j] <- hamming.method(x = mat[i, ], y = mat[j, ]) + dist_mat[j, i] <- dist_mat[i, j] + } + } + return(dist_mat) + } + + # Function to determine entry table height + table_height <- reactive({ + if (input$table_height == TRUE) { + NULL + } else {900} + }) + + # Function to determine distance matrix height + distancematrix_height <- reactive({ + if(DB$distancematrix_nrow > 33) { + 800 + } else {NULL} + }) + + # Function to missing value table height + miss.val.height <- reactive({ + if(input$miss_val_height == TRUE) { + NULL + } else {800} + }) + + #Function to check custom variable classes + column_classes <- function(df) { + sapply(df, function(x) { + if (class(x) == "numeric") { + return("cont") + } else if (class(x) == "character") { + return("categ") + } else { + return(class(x)) + } + }) + } + + # Function to hash database + hash_database <- function(folder) { + loci_files <- list.files(folder) + loci_names <- sapply(strsplit(loci_files, "[.]"), function(x) x[1]) + loci_paths <- file.path(folder, loci_files) + + hashes <- sapply(loci_paths, hash_locus) + names(hashes) <- loci_names + hashes + } + + # Function to hash a locus + hash_locus <- function(locus_path) { + locus_file <- readLines(locus_path) + seq_list <- locus_file[seq(2, length(locus_file), 3)] + seq_hash <- sha256(seq_list) + seq_idx <- paste0(">", seq_hash) + + locus_file[seq(1, length(locus_file), 3)] <- seq_idx + writeLines(locus_file, locus_path) + + seq_hash + } + + # Get locus hashes + get_locus_hashes <- function(locus_path) { + locus_file <- readLines(locus_path) + hash_list <- locus_file[seq(1, length(locus_file), 3)] + hash_list <- sapply(strsplit(hash_list, "[>]"), function(x) x[2]) + } + + extract_seq <- function(locus_path, hashes) { + locus_file <- readLines(locus_path) + hash_list <- sapply(strsplit(locus_file[seq(1, length(locus_file), 3)], "[>]"), function(x) x[2]) + seq_list <- locus_file[seq(2, length(locus_file), 3)] + seq_idx <- hash_list %in% hashes + + list( + idx = hash_list[seq_idx], + seq = seq_list[seq_idx] + ) + } + + add_new_sequences <- function(locus_path, sequences) { + locus_file <- file(locus_path, open = "a+") + for (i in seq_along(sequences$idx)) { + writeLines(c("", paste0(">", sequences$idx[i]), sequences$seq[i]), locus_file) + } + close(locus_file) + } + + # Compute clusters to use in visNetwork + compute_clusters <- function(nodes, edges, threshold) { + groups <- rep(0, length(nodes$id)) + edges_groups <- rep(0, length(edges$from)) + + edges_table <- data.frame( + from = edges$from, + to = edges$to, + weight = edges$weight + ) + + count <- 0 + while (any(groups == 0)) { + group_na <- groups == 0 + labels <- nodes$id[group_na] + + cluster <- nodes$id[group_na][1] # Initialize with 1 label + while (!is_empty(labels)) { + sub_tb <- edges_table[(edges_table$from %in% cluster | edges_table$to %in% cluster) & edges_table$weight <= threshold,] + + if (nrow(sub_tb) == 0 | length(unique(c(sub_tb$from, sub_tb$to))) == length(cluster)) { + count <- count + 1 + groups[nodes$id %in% cluster] <- paste("Group", count) + edges_groups[edges$from %in% cluster & edges$to %in% cluster] <- paste("Group", count) + break + } else { + cluster <- unique(c(sub_tb$from, sub_tb$to)) + } + } + } + list(groups = groups, + edges = edges_groups) + } + + # Check gene screening status + check_status <- function(isolate) { + iso_name <- gsub(".zip", "", basename(isolate)) + if(file.exists(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", iso_name, "status.txt"))) { + if(str_detect(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", iso_name, "status.txt"))[1], + "successfully")) { + return("success") + } else { + return("fail") + } + } else {return("unfinished")} + } + + # Reset gene screening status + remove.screening.status <- function(isolate) { + if(file.exists(file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Isolates", + isolate, + "status.txt"))) { + file.remove( + file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Isolates", + isolate, + "status.txt") + ) + } + } + + # Truncate hashes + truncHash <- function(hash) { + if(!is.na(hash)) { + paste0(str_sub(hash, 1, 4), "...", str_sub(hash, nchar(hash) - 3, nchar(hash))) + } else {NA} + } + + # Function to check for duplicate isolate IDs for multi typing start + dupl_mult_id <- reactive({ + req(Typing$multi_sel_table) + if(!is.null(DB$data)) { + selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] + selection$Files + } else {""} + }) + + # Function to check single typing log file + check_new_entry <- reactive({ + + invalidateLater(5000, session) + + if(!is.null(DB$database)) { + if(file_exists(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds"))) { + + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) + + if(is.null(DB$data)) { + if(nrow(Database[["Typing"]]) >= 1) { + TRUE + } else {FALSE} + } else { + if(nrow(DB$data) < nrow(Database[["Typing"]])) { + TRUE + } else { + FALSE + } + } + } else {FALSE} + } + }) + + # Render Entry Table Highlights + + diff_allele <- reactive({ + if (!is.null(DB$data) & !is.null(input$compare_select) & !is.null(DB$cust_var)) { + var_alleles(select(DB$data, input$compare_select)) + (13 + nrow(DB$cust_var)) + } + }) + + err_thresh <- reactive({ + if (!is.null(DB$data) & !is.null(DB$number_loci)) { + which(as.numeric(DB$data[["Errors"]]) >= (DB$number_loci * 0.05)) + } + }) + + err_thresh_na <- reactive({ + if (!is.null(DB$na_table) & !is.null(DB$number_loci)) { + which(as.numeric(DB$na_table[["Errors"]]) >= (DB$number_loci * 0.05)) + } + }) + + true_rows <- reactive({ + if (!is.null(DB$data)) { + which(DB$data$Include == TRUE) + } + }) + + duplicated_names <- reactive({ + if (!is.null(DB$meta)) { + which(duplicated(DB$meta$`Assembly Name`) | duplicated(DB$meta$`Assembly Name`, fromLast = TRUE)) + } + }) + + duplicated_ids <- reactive({ + if (!is.null(DB$meta)) { + which(duplicated(DB$meta$`Assembly ID`) | duplicated(DB$meta$`Assembly ID`, fromLast = TRUE)) + } + }) + + # _______________________ #### + + ## Startup ---- + shinyjs::addClass(selector = "body", class = "sidebar-collapse") + shinyjs::removeClass(selector = "body", class = "sidebar-toggle") + + output$messageMenu <- renderText({ + HTML(format(Sys.time(), "%Y-%m-%d %H:%M:%S %Z")) + }) + + # Initiate logging + if(!dir_exists(paste0(getwd(), "/logs"))) { + dir_create(paste0(getwd(), "/logs")) + } + + logfile <- file.path(paste0(getwd(), "/logs/phylotrace.log")) + + log <- log_open(logfile, logdir = FALSE) + + log_print("Session started") + + # Clear screening file + if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { + file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) + } + + if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { + file.remove(paste0(getwd(), "/execute/screening/error.txt")) + } + + # Declare reactive variables + Startup <- reactiveValues(sidebar = TRUE, + header = TRUE) # reactive variables related to startup process + + DB <- reactiveValues(data = NULL, + block_db = FALSE, + load_selected = TRUE, + no_na_switch = FALSE, + first_look = FALSE) # reactive variables related to local database + + Typing <- reactiveValues(table = data.frame(), + single_path = data.frame(), + progress = 0, + progress_format_start = 0, + progress_format_end = 0, + result_list = NULL, + status = "") # reactive variables related to typing process + + Screening <- reactiveValues(status = "idle", + picker_status = TRUE, + first_result = NULL) # reactive variables related to gene screening + + Vis <- reactiveValues(cluster = NULL, + metadata = list(), + custom_label_nj = data.frame(), + nj_label_pos_y = list(), + nj_label_pos_x = list(), + nj_label_size = list(), + custom_label_upgma = data.frame(), + upgma_label_pos_y = list(), + upgma_label_pos_x = list(), + upgma_label_size = list()) # reactive variables related to visualization + + Report <- reactiveValues() # reactive variables related to report functions + + Scheme <- reactiveValues() # reactive variables related to scheme functions + + # Load last used database if possible + if(paste0(getwd(), "/execute/last_db.rds") %in% dir_ls(paste0(getwd(), "/execute"))) { + DB$last_db <- TRUE + } + + # Locate local Database + observe({ + shinyDirChoose(input, + "db_location", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session) + + if(!is.null(DB$select_new)) { + if(DB$select_new == FALSE) { + if(DB$block_db == FALSE) { + DB$database <- as.character( + parseDirPath( + roots = c(Home = path_home(), Root = "/"), + input$db_location + ) + ) + + DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present + + DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available + } + + } else if (DB$select_new == TRUE) { + DB$database <- paste0(DB$new_database, "/Database") + + } + } else { + if(!is.null(DB$last_db) & file.exists(paste0(getwd(), "/execute/last_db.rds"))) { + + DB$database <- readRDS(paste0(getwd(), "/execute/last_db.rds")) + + if(dir_exists(DB$database)) { + DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present + + DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available + } + } + } + }) + + ### Set up typing environment ---- + + # Null typing progress trackers + writeLines("0", paste0(getwd(), "/logs/script_log.txt")) + writeLines("0\n", paste0(getwd(), "/logs/progress.txt")) + + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + } + + # Reset typing feedback values + Typing$pending <- FALSE + Typing$multi_started <- FALSE + Typing$multi_help <- FALSE + saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) + Typing$last_success <- "0" # Null last multi typing success name + Typing$last_failure <- "0" # Null last multi typing failure name + + ### Landing page UI ---- + observe({ + if (Startup$sidebar == FALSE) { + shinyjs::removeClass(selector = "body", class = "sidebar-collapse") + shinyjs::addClass(selector = "body", class = "sidebar-toggle") + } + }) + + output$start_message <- renderUI({ + column( + width = 12, + align = "center", + br(), br(), br(), br(), br(), br(), + div( + class = "image", + imageOutput("imageOutput") + ), + br(), br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 16px;', 'Proceed by loading a compatible local database or create a new one.') + ) + ) + ), + br(), + fluidRow( + column( + width = 6, + align = "right", + shinyDirButton( + "db_location", + "Browse", + icon = icon("folder-open"), + title = "Locate the database folder", + buttonType = "default", + root = path_home() + ) + ), + column( + width = 6, + align = "left", + shinyDirButton( + "create_new_db", + "Create New", + icon = icon("plus"), + title = "Choose location for new PhyloTrace database", + buttonType = "default", + root = path_home() + ) + ) + ), + br(), br(), + fluidRow( + column( + width = 12, + align = "center", + uiOutput("load_db"), + br(), br(), br(), br(), br(), br(), br() + ) + ) + ) + }) + + # User selection new db or load db + observeEvent(input$create_new_db, { + log_print("Input create_new_db") + DB$select_new <- TRUE + }) + + observeEvent(input$db_location, { + log_print("Input db_location") + DB$select_new <- FALSE + }) + + # Load db & scheme selection UI + output$load_db <- renderUI({ + if(!is.null(DB$select_new)) { + if(length(DB$new_database) > 0 & DB$select_new) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px;', + HTML( + paste( + 'New database will be created in', + DB$new_database + ) + ) + ) + ), + br(), + actionButton( + "load", + "Create", + class = "load-start" + ) + ) + } else if(length(DB$available) > 0 & !(DB$select_new)) { + if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Selected:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), + p( + HTML( + paste( + tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', + 'Warning: Folder contains invalid elements.') + ) + ) + ), + br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } else { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Selected:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } + } + } else if((!is.null(DB$last_db)) & (!is.null(DB$available))) { + if (DB$last_db == TRUE & (length(DB$available) > 0)) { + if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Last used:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), + p( + HTML( + paste( + tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', + 'Warning: Folder contains invalid elements.') + ) + ) + ), + br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } else { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Last used:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } + } else if (DB$last_db == TRUE & (length(DB$available) == 0)) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Last used:', DB$database) + ) + ) + ), + br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } + } + }) + + output$imageOutput <- renderImage({ + # Path to your PNG image with a transparent background + image_path <- paste0(getwd(), "/www/PhyloTrace.png") + + # Use HTML to display the image with the tag + list(src = image_path, + height = 180) + }, deleteFile = FALSE) + + ### Load app event ---- + + observeEvent(input$load, { + + # Reset reactive screening variables + output$screening_start <- NULL + output$screening_result_sel <- NULL + output$screening_result <- NULL + output$screening_fail <- NULL + Screening$status_df <- NULL + Screening$choices <- NULL + Screening$picker_status <- TRUE + Screening$status <- "idle" + Screening$first_result <- NULL + if(!is.null(input$screening_select)) { + if(!is.null(DB$data)) { + updatePickerInput(session, "screening_select", selected = character(0)) + } + } + + log_print("Input load") + + # set typing start control variable + Typing$reload <- TRUE + + # reset typing status on start( + if(Typing$status == "Finalized") {Typing$status <- "Inactive"} + if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} + + #### Render status bar ---- + observe({ + req(DB$scheme) + + if(is.null(input$scheme_position)) { + output$loaded_scheme <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Selected scheme:   ", + DB$scheme, + "")), + style = "color:white;") + ) + ) + }) + } + + if(!is.null(input$scheme_position)) { + output$loaded_scheme <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Selected scheme:   ", + DB$scheme, + "")), + style = "color:white;"), + div( + class = "reload-bttn", + style = paste0("margin-left:", 30 + input$scheme_position, "px; position: relative; top: -24px;"), + actionButton( + "reload_db", + label = "", + icon = icon("rotate") + ) + ) + ) + ) + }) + } + }) + + observe({ + if(!is.null(DB$database)){ + if(nchar(DB$database) > 60) { + database <- paste0(substring(DB$database, first = 1, last = 60), "...") + } else { + database <- DB$database + } + output$databasetext <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Database:   ", + database, + "")), + style = "color:white;") + ), + if(nchar(database) > 60) {bsTooltip("databasetext", + HTML(DB$database), + placement = "bottom", + trigger = "hover")} + ) + }) + } + }) + + observe({ + if(!is.null(DB$database)) { + if(Typing$status == "Finalized"){ + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    typing finalized")), + style = "color:white;") + ) + ) + ) + } else if(Typing$status == "Attaching"){ + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    evaluating typing results")), + style = "color:white;") + ) + ) + ) + } else if(Typing$status == "Processing") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    pending typing")), + style = "color:white;") + ) + ) + ) + } else if(Screening$status == "started") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    pending gene screening")), + style = "color:white;") + ) + ) + ) + } else if(Screening$status == "finished") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    gene screening finalized")), + style = "color:white;") + ) + ) + ) + } else { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    ready")), + style = "color:white;") + ) + ) + ) + } + } + }) + + # Null single typing status + if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + Typing$progress <- 0 + + Typing$progress_format <- 900000 + + output$single_typing_progress <- NULL + + output$typing_fin <- NULL + + output$single_typing_results <- NULL + + output$typing_formatting <- NULL + + Typing$single_path <- data.frame() + + # reset results file + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + # Resetting single typing progress logfile bar + con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") + + cat("0\n", file = con) + + close(con) + } + } + + shinyjs::runjs( + 'if(document.querySelector("#loaded_scheme > div > li > span") !== null) { + // Select the span element + let spanElement = document.querySelector("#loaded_scheme > div > li > span"); + + // Get the bounding rectangle of the span element + let rect = spanElement.getBoundingClientRect(); + + // Extract the width + let width = rect.width; + + Shiny.setInputValue("scheme_position", width); + }' + ) + + # Load app elements based on database availability and missing value presence + if(!is.null(DB$select_new)) { + if(DB$select_new & (paste0(DB$new_database, "/Database") %in% dir_ls(DB$new_database))) { + + log_print("Directory already contains a database") + + show_toast( + title = "Directory already contains a database", + type = "error", + position = "bottom-end", + timer = 6000 + ) + DB$load_selected <- FALSE + + } else if(DB$select_new | (DB$select_new == FALSE & is.null(input$scheme_db))) { + + log_print(paste0("New database created in ", DB$new_database)) + + DB$check_new_entries <- TRUE + DB$data <- NULL + DB$meta_gs <- NULL + DB$meta <- NULL + DB$meta_true <- NULL + DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL + DB$allelic_profile_true <- NULL + + # null Distance matrix, entry table and plots + output$db_distancematrix <- NULL + output$db_entries_table <- NULL + output$tree_mst <- NULL + output$tree_nj <- NULL + output$tree_upgma <- NULL + + # null report values + Report$report_list_mst <- list() + Report$report_list_nj <- list() + Report$report_list_upgma <- list() + + # null plots + Vis$nj <- NULL + Vis$upgma <- NULL + Vis$ggraph_1 <- NULL + + removeModal() + + #### Render Menu Items ---- + + Startup$sidebar <- FALSE + Startup$header <- FALSE + + output$menu_sep2 <- renderUI(hr()) + + # Hide start message + output$start_message <- NULL + + DB$load_selected <- FALSE + + # Declare database path + DB$database <- file.path(DB$new_database, "Database") + + # Set database availability screening variables to present database + DB$block_db <- TRUE + DB$select_new <- FALSE + + # Render menu with Manage Schemes as start tab and no Missing values tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + # Dont render these elements + output$db_no_entries <- NULL + output$distancematrix_no_entries <- NULL + output$db_entries <- NULL + output$edit_index <- NULL + output$edit_scheme_d <- NULL + output$edit_entries <- NULL + output$compare_select <- NULL + output$delete_select <- NULL + output$del_bttn <- NULL + output$compare_allele_box <- NULL + output$download_entries <- NULL + output$missing_values <- NULL + output$delete_box <- NULL + output$missing_values_sidebar <- NULL + output$distmatrix_sidebar <- NULL + output$download_scheme_info <- NULL + output$download_loci <- NULL + output$entry_table_controls <- NULL + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$pending_typing <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + } + } else { + log_print(paste0("Loading existing ", input$scheme_db, " database from ", DB$database)) + } + + if(DB$load_selected == TRUE) { + + if(gsub(" ", "_", input$scheme_db) %in% schemes) { #Check if selected scheme valid + + # Save database path for next start + saveRDS(DB$database, paste0(getwd(), "/execute/last_db.rds")) + + DB$check_new_entries <- TRUE + DB$data <- NULL + DB$meta_gs <- NULL + DB$meta <- NULL + DB$meta_true <- NULL + DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL + DB$allelic_profile_true <- NULL + DB$scheme <- input$scheme_db + + # null Distance matrix, entry table and plots + output$db_distancematrix <- NULL + output$db_entries_table <- NULL + output$tree_mst <- NULL + output$tree_nj <- NULL + output$tree_upgma <- NULL + + # null typing initiation UI + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$pending_typing <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + # null report values + Report$report_list_mst <- list() + Report$report_list_nj <- list() + Report$report_list_upgma <- list() + + # null plots + Vis$nj <- NULL + Vis$upgma <- NULL + Vis$ggraph_1 <- NULL + + removeModal() + + #### Render Menu Items ---- + + Startup$sidebar <- FALSE + Startup$header <- FALSE + + output$menu_sep2 <- renderUI(hr()) + + # Hide start message + output$start_message <- NULL + + if(any(grepl(gsub(" ", "_", DB$scheme), dir_ls(DB$database)))) { + + if(!any(grepl("alleles", dir_ls(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme)))))) { + + log_print("Missing loci files") + + # Show message that loci files are missing + showModal( + modalDialog( + paste0("Whoops! No loci files are present in the local ", + DB$scheme, + " folder. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } else if (!any(grepl("scheme_info.html", dir_ls(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme)))))) { + + output$download_scheme_info <- NULL + + log_print("Scheme info file missing") + + # Show message that scheme info is missing + showModal( + modalDialog( + paste0("Whoops! Scheme info of the local ", + DB$scheme, + " database is missing. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + } else if (!any(grepl("targets.csv", dir_ls(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme)))))) { + + # Dont render target download button + output$download_loci <- NULL + + log_print("Missing loci info (targets.csv)") + + # Show message that scheme info is missing + showModal( + modalDialog( + paste0("Whoops! Loci info of the local ", + DB$scheme, + " database is missing. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + } else { + # Produce Scheme Info Table + schemeinfo <- + read_html(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme), + "/scheme_info.html" + )) %>% + html_table(header = FALSE) %>% + as.data.frame(stringsAsFactors = FALSE) + names(schemeinfo) <- NULL + DB$schemeinfo <- schemeinfo + number_loci <- as.vector(DB$schemeinfo[6, 2]) + DB$number_loci <- as.numeric(gsub(",", "", number_loci)) + + # Produce Loci Info table + DB$loci_info <- read.csv( + file.path(DB$database, gsub(" ", "_", DB$scheme), "targets.csv"), + header = TRUE, + sep = "\t", + row.names = NULL, + colClasses = c( + "NULL", + "character", + "character", + "integer", + "integer", + "character", + "integer", + "NULL" + ) + ) + + # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme + if(DB$number_loci > length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { + + log_print(paste0("Loci files are missing in the local ", DB$scheme, " folder")) + + # Show message that loci files are missing + showModal( + modalDialog( + paste0("Whoops! Some loci files are missing in the local ", + DB$scheme, + " folder. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + } else { + ###### Alle checks bestanden -> Laden der DTB + # If typed entries present + if (any(grepl("Typing.rds", dir_ls(paste0( + DB$database, "/", gsub(" ", "_", DB$scheme) + ))))) { + + # Load database from files + Database <- readRDS(file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Typing.rds")) + + DB$data <- Database[["Typing"]] + + if(!is.null(DB$data)){ + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + } else { + DB$cust_var <- data.frame() + } + } + + DB$change <- FALSE + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + + # Null pipe + con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") + + cat("0\n", file = con) + + # Close the file connection + close(con) + + # Reset other reactive typing variables + Typing$progress_format_end <- 0 + Typing$progress_format_start <- 0 + Typing$pending_format <- 0 + Typing$entry_added <- 0 + Typing$progress <- 0 + Typing$progress_format <- 900000 + output$single_typing_progress <- NULL + output$typing_fin <- NULL + output$single_typing_results <- NULL + output$typing_formatting <- NULL + Typing$single_path <- data.frame() + + # Null multi typing feedback variable + Typing$reset <- TRUE + + # Check need for new missing vlaue display + if(DB$first_look == TRUE) { + if(sum(apply(DB$data, 1, anyNA)) >= 1) { + DB$no_na_switch <- TRUE + } else { + DB$no_na_switch <- FALSE + } + } + + DB$first_look <- TRUE + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + if(!anyNA(DB$allelic_profile)) { + + # no NA's -> dont render missing values sidebar elements + output$missing_values_sidebar <- NULL + + # Render menu if no NA's present + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } else { + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries", + selected = TRUE + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } + + # Render custom variable display + output$show_cust_var <- renderTable( + width = "100%", + { + if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { + if(nrow(DB$cust_var) > 5) { + low <- -4 + high <- 0 + for (i in 1:input$cust_var_select) { + low <- low + 5 + if((nrow(DB$cust_var) %% 5) != 0) { + if(i == ceiling(nrow(DB$cust_var) / 5 )) { + high <- high + nrow(DB$cust_var) %% 5 + } else { + high <- high + 5 + } + } else { + high <- high + 5 + } + } + DB$cust_var[low:high,] + } else { + DB$cust_var + } + } else if (!is.null(DB$cust_var)) { + DB$cust_var + } + }) + + # render visualization sidebar elements + observe({ + Vis$tree_algo <- input$tree_algo + }) + + output$visualization_sidebar <- renderUI({ + if(!is.null(DB$data)) { + column( + width = 12, + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + prettyRadioButtons( + "tree_algo", + choices = c("Minimum-Spanning", "Neighbour-Joining", "UPGMA"), + label = "", + selected = if(!is.null(Vis$tree_algo)){Vis$tree_algo} else {"Minimum-Spanning"} + ), + ) + ), + br(), + fluidRow( + column( + width = 12, + align = "center", + tags$div( + id = "button-wrapper", + actionButton( + "create_tree", + h5("Create Tree", style = "position: relative; left: 15px; color: white; font-size: 15px;"), + width = "100%" + ), + tags$img( + src = "phylo.png", + alt = "icon", + class = "icon" + ) + ) + ) + ), + br(), + hr(), + conditionalPanel( + "input.tree_algo=='Minimum-Spanning'", + fluidRow( + column( + width = 12, + align = "left", + br(), + HTML( + paste( + tags$span(style='color: white; font-size: 16px; margin-left: 15px', "Sizing") + ) + ) + ) + ), + fluidRow( + column( + width = 12, + radioGroupButtons( + "mst_ratio", + "", + choiceNames = c("16:10", "16:9", "4:3"), + choiceValues = c((16/10), (16/9), (4/3)), + width = "100%" + ), + br(), + sliderInput( + "mst_scale", + "", + min = 500, + max = 1200, + step = 5, + value = 800, + width = "95%", + ticks = FALSE + ) + ) + ), + br(), + hr(), + fluidRow( + column( + width = 12, + column( + width = 5, + align = "left", + conditionalPanel( + "input.mst_plot_format=='jpeg'", + actionBttn( + "save_plot_jpeg", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + conditionalPanel( + "input.mst_plot_format=='png'", + actionBttn( + "save_plot_png", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + conditionalPanel( + "input.mst_plot_format=='bmp'", + actionBttn( + "save_plot_bmp", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + conditionalPanel( + "input.mst_plot_format=='html'", + downloadBttn( + "save_plot_html", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ) + ), + column( + width = 7, + div( + style = "max-width: 150px", + class = "format", + selectInput( + inputId = "mst_plot_format", + label = "", + choices = c("html", "jpeg", "png", "bmp") + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.tree_algo=='Neighbour-Joining'", + fluidRow( + column( + width = 12, + column( + width = 5, + align = "left", + downloadBttn( + "download_nj", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + column( + width = 7, + div( + style = "max-width: 150px", + class = "format", + selectInput( + inputId = "filetype_nj", + label = "", + choices = c("png", "jpeg", "bmp", "svg") + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.tree_algo=='UPGMA'", + fluidRow( + column( + width = 12, + column( + width = 5, + align = "left", + downloadBttn( + "download_upgma", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + column( + width = 7, + div( + style = "max-width: 150px", + class = "format", + selectInput( + inputId = "filetype_upgma", + label = "", + choices = c("png", "jpeg", "bmp", "svg") + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 6, + align = "left", + br(), + actionButton( + "create_rep", + "Print Report" + ) + ) + ) + ) + } + }) + + # Render entry table sidebar elements + output$entrytable_sidebar <- renderUI({ + if(!is.null(DB$data)) { + column( + width = 12, + align = "center", + br(), + fluidRow( + column(1), + column( + width = 10, + align = "left", + if(nrow(DB$data) > 40) { + div( + class = "mat-switch-db-tab", + materialSwitch( + "table_height", + h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + } + ) + ), + br(), br(), + fluidRow( + column( + width = 12, + HTML( + paste( + tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Custom Variables') + ) + ) + ) + ), + fluidRow( + column( + width = 8, + textInput( + "new_var_name", + label = "", + placeholder = "New Variable" + ) + ), + column( + width = 2, + actionButton( + "add_new_variable", + "", + icon = icon("plus") + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "textinput_var", + selectInput( + "del_which_var", + "", + DB$cust_var$Variable + ) + ) + ), + column( + width = 2, + align = "left", + actionButton( + "delete_new_variable", + "", + icon = icon("minus") + ) + ) + ), + br(), + fluidRow( + column(1), + column( + width = 4, + uiOutput("cust_var_info") + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + tableOutput("show_cust_var") + ) + ), + fluidRow( + column(4), + column( + width = 7, + align = "center", + uiOutput("cust_var_select") + ) + ) + ) + } + }) + + # Render missing values sidebar elements + output$missing_values_sidebar <- renderUI({ + column( + width = 12, + fluidRow( + column( + width = 12, + br(), + materialSwitch( + "miss_val_height", + h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + br() + ), + fluidRow( + column( + width = 6, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -23px; right: -15px', + 'Download CSV') + ) + ) + ), + column( + width = 4, + downloadBttn( + "download_na_matrix", + style = "simple", + label = "", + size = "sm", + icon = icon("download") + ) + ) + ) + ) + }) + + # Render scheme info download button + output$download_loci <- renderUI({ + column( + 12, + downloadBttn( + "download_loci_info", + style = "simple", + label = "", + size = "sm", + icon = icon("download"), + color = "primary" + ), + bsTooltip("download_loci_info_bttn", HTML("Save loci information
(without sequence)"), placement = "top", trigger = "hover") + ) + }) + + # Render scheme info download button + output$download_scheme_info <- renderUI({ + downloadBttn( + "download_schemeinfo", + style = "simple", + label = "", + size = "sm", + icon = icon("download"), + color = "primary" + ) + }) + + # Render distance matrix sidebar + output$distmatrix_sidebar <- renderUI({ + column( + width = 12, + align = "left", + fluidRow( + column( + width = 12, + align = "center", + selectInput( + "distmatrix_label", + label = "", + choices = c("Index", "Assembly Name", "Assembly ID"), + selected = c("Assembly Name"), + width = "100%" + ), + br() + ) + ), + div( + class = "mat-switch-dmatrix", + materialSwitch( + "distmatrix_true", + h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + div( + class = "mat-switch-dmatrix", + materialSwitch( + "distmatrix_triangle", + h5(p("Show Upper Triangle"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + div( + class = "mat-switch-dmatrix-last", + materialSwitch( + "distmatrix_diag", + h5(p("Show Diagonal"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + fluidRow( + column( + width = 6, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: 37px; right: -15px', + 'Download CSV') + ) + ) + ), + column( + width = 4, + downloadBttn( + "download_distmatrix", + style = "simple", + label = "", + size = "sm", + icon = icon("download") + ) + ) + ) + ) + }) + + # Render select input to choose displayed loci + output$compare_select <- renderUI({ + + if(nrow(DB$data) == 1) { + HTML( + paste( + tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to compare") + ) + ) + } else { + if(!is.null(input$compare_difference)) { + if (input$compare_difference == FALSE) { + pickerInput( + inputId = "compare_select", + label = "", + width = "85%", + choices = names(DB$allelic_profile), + selected = names(DB$allelic_profile)[1:20], + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + } else { + pickerInput( + inputId = "compare_select", + label = "", + width = "85%", + choices = names(DB$allelic_profile), + selected = names(DB$allelic_profile)[var_alleles(DB$allelic_profile)], + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + } + } + } + }) + + #### Render Entry Data Table ---- + output$db_entries_table <- renderUI({ + if(!is.null(DB$data)) { + if(between(nrow(DB$data), 1, 30)) { + rHandsontableOutput("db_entries") + } else { + addSpinner( + rHandsontableOutput("db_entries"), + spin = "dots", + color = "#ffffff" + ) + } + } + }) + + if (!is.null(DB$data)) { + + observe({ + + if (!is.null(DB$data)) { + if (nrow(DB$data) == 1) { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else if (between(nrow(DB$data), 2, 40)) { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + highlightCol = TRUE, + highlightRow = TRUE, + contextMenu = FALSE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + valign = "htMiddle", + halign = "htCenter", + readOnly = TRUE) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + strict = TRUE, + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }" + ) %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names()- 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } else { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + rowHeaders = NULL, + height = table_height(), + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + readOnly = TRUE, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + height = table_height(), + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", halign = "htCenter") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } + } + + # Dynamic save button when rhandsontable changes or new entries + output$edit_entry_table <- renderUI({ + if(check_new_entry() & DB$check_new_entries) { + Typing$reload <- FALSE + fluidRow( + column( + width = 8, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', + 'New entries - reload database') + ) + ) + ), + column( + width = 4, + actionButton( + "load", + "", + icon = icon("rotate"), + class = "pulsating-button" + ) + ) + ) + } else if(Typing$status == "Attaching") { + fluidRow( + column( + width = 11, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', 'No database changes possible - pending entry addition') + ) + ) + ), + column( + width = 1, + HTML(paste('')) + ) + ) + } else if((DB$change == TRUE) | !identical(get.entry.table.meta(), select(DB$meta, -13))) { + + if(!is.null(input$db_entries)) { + fluidRow( + column( + width = 5, + HTML( + paste( + tags$span(style='color: white; font-size: 16px; position: absolute; bottom: -30px; right: -5px', 'Confirm changes') + ) + ) + ), + column( + width = 3, + actionButton( + "edit_button", + "", + icon = icon("bookmark"), + class = "pulsating-button" + ) + ), + column( + width = 4, + actionButton( + "undo_changes", + "Undo", + icon = icon("repeat") + ) + ) + ) + } + } else {NULL} + }) + + }) + + # Hide no entry message + output$db_no_entries <- NULL + output$distancematrix_no_entries <- NULL + + } else { + + # If database loading not successful dont show entry table + output$db_entries_table <- NULL + output$entry_table_controls <- NULL + } + + # Render Entry table controls + output$entry_table_controls <- renderUI({ + fluidRow( + column(1), + column( + width = 3, + align = "center", + fluidRow( + column( + width = 4, + align = "center", + actionButton( + "sel_all_entries", + "Select All", + icon = icon("check") + ) + ), + column( + width = 4, + align = "left", + actionButton( + "desel_all_entries", + "Deselect All", + icon = icon("xmark") + ) + ) + ) + ), + column( + width = 3, + uiOutput("edit_entry_table") + ) + ) + }) + + #### Render Distance Matrix ---- + observe({ + if(!is.null(DB$data)) { + + if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { + output$db_distancematrix <- NULL + + if( (sum(duplicated(DB$meta$`Assembly Name`)) > 0) & (sum(duplicated(DB$meta$`Assembly ID`)) == 0) ) { + duplicated_txt <- paste0( + paste( + paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), + DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] + ), + "
" + ) + } else if ( (sum(duplicated(DB$meta$`Assembly ID`)) > 0) & (sum(duplicated(DB$meta$`Assembly Name`)) == 0) ){ + duplicated_txt <- paste0( + paste( + paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), + DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] + ), + "
" + ) + } else { + duplicated_txt <- c( + paste0( + paste( + paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), + DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] + ), + "
" + ), + paste0( + paste( + paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), + DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] + ), + "
" + ) + ) + } + + output$distancematrix_duplicated <- renderUI({ + column( + width = 12, + tags$span(style = "font-size: 15; color: white", + "Change duplicated entry names to display distance matrix."), + br(), br(), br(), + actionButton("change_entries", "Go to Entry Table", class = "btn btn-default"), + br(), br(), br(), + tags$span( + style = "font-size: 15; color: white", + HTML( + append( + "Duplicated:", + append( + "
", + duplicated_txt + ) + ) + ) + ) + ) + }) + } else { + output$distancematrix_duplicated <- NULL + if(!is.null(DB$data) & !is.null(DB$allelic_profile) & !is.null(DB$allelic_profile_true) & !is.null(DB$cust_var) & !is.null(input$distmatrix_label) & !is.null(input$distmatrix_diag) & !is.null(input$distmatrix_triangle)) { + output$db_distancematrix <- renderRHandsontable({ + rhandsontable(hamming_df(), + digits = 1, + readOnly = TRUE, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE, + height = distancematrix_height(), rowHeaders = NULL) %>% + hot_heatmap(renderer = paste0(" + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + heatmapScale = chroma.scale(['#17F556', '#ED6D47']); + + if (instance.heatmap[col]) { + mn = ", DB$matrix_min, "; + mx = ", DB$matrix_max, "; + + pt = (parseInt(value, 10) - mn) / (mx - mn); + + td.style.backgroundColor = heatmapScale(pt).hex(); + } + }")) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1:(dim(DB$ham_matrix)[1]+1), + halign = "htCenter", + valign = "htMiddle") %>% + hot_col(1, renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + td.style.background = '#F0F0F0' + }" + ) + }) + } + } + + # Render Distance Matrix UI + + output$distmatrix_show <- renderUI({ + if(!is.null(DB$data)) { + if(nrow(DB$data) > 1) { + column( + width = 10, + uiOutput("distancematrix_duplicated"), + div( + class = "distmatrix", + rHandsontableOutput("db_distancematrix") + ) + ) + } else { + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to display a distance matrix.") + ) + ) + ), + br(), + br() + ) + } + } + }) + + } + }) + + + # Render delete entry box UI + output$delete_box <- renderUI({ + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + column( + width = 12, + align = "center", + h3(p("Delete Entries"), style = "color:white") + ) + ), + hr(), + fluidRow( + column( + width = 2, + offset = 1, + align = "right", + br(), + h5("Index", style = "color:white; margin-bottom: 0px;") + ), + column( + width = 6, + align = "center", + uiOutput("delete_select") + ), + column( + width = 2, + align = "center", + br(), + uiOutput("del_bttn") + ) + ), + br() + ) + }) + + # Render loci comparison box UI + output$compare_allele_box <- renderUI({ + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + column( + width = 12, + align = "center", + h3(p("Compare Loci"), style = "color:white") + ) + ), + hr(), + column( + width = 12, + align = "center", + br(), + uiOutput("compare_select"), + br(), + column(2), + column( + width = 10, + align = "left", + uiOutput("compare_difference_box") + ) + ), + br() + ) + }) + + # Render entry table download box UI + output$download_entries <- renderUI({ + fluidRow( + column( + width = 12, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + column( + width = 12, + align = "center", + h3(p("Download Table"), style = "color:white") + ) + ), + hr(), + fluidRow( + column(2), + column( + width = 10, + align = "left", + br(), + div( + class = "mat-switch-db", + materialSwitch( + "download_table_include", + h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + div( + class = "mat-switch-db", + materialSwitch( + "download_table_loci", + h5(p("Include Displayed Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + br(), + ) + ), + fluidRow( + column( + width = 12, + align = "center", + downloadBttn( + "download_entry_table", + style = "simple", + label = "", + size = "sm", + icon = icon("download"), + color = "primary" + ) + ) + ), + br() + ) + ), + column( + width = 12, + fluidRow( + column( + width = 2, + div( + class = "rectangle-blue" + ), + div( + class = "rectangle-orange" + ), + div( + class = "rectangle-red" + ), + div( + class = "rectangle-green" + ) + ), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -12px", " = included for analyses") + ) + ) + ), + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -13px", " = duplicated name/ID") + ) + ) + ), + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -14px", " = ≥ 5% of loci missing") + ) + ) + ), + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -15px", " = locus contains multiple variants") + ) + ) + ), + ) + ) + ) + ) + }) + + # Render entry deletion select input + output$delete_select <- renderUI({ + pickerInput("select_delete", + label = "", + choices = DB$data[, "Index"], + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE) + }) + + # Render delete entry button + output$del_bttn <- renderUI({ + actionBttn( + "del_button", + label = "", + color = "danger", + size = "sm", + style = "material-circle", + icon = icon("xmark") + ) + }) + + #### Missing Values UI ---- + + # Missing values calculations and table + observe({ + + if (!is.null(DB$allelic_profile)) { + NA_table <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) != 0] + + NA_table <- NA_table[rowSums(is.na(NA_table)) != 0,] + + NA_table[is.na(NA_table)] <- "NA" + + NA_table <- NA_table %>% + cbind("Assembly Name" = DB$meta[rownames(NA_table),]$`Assembly Name`) %>% + cbind("Errors" = DB$meta[rownames(NA_table),]$Errors) %>% + relocate("Assembly Name", "Errors") + + DB$na_table <- NA_table + + if(!is.null(input$miss_val_height)) { + if(nrow(DB$na_table) < 31) { + output$table_missing_values <- renderRHandsontable({ + rhandsontable( + DB$na_table, + readOnly = TRUE, + rowHeaders = NULL, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE, + error_highlight = err_thresh_na() - 1 + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% + hot_col(2, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } else { + output$table_missing_values <- renderRHandsontable({ + rhandsontable( + DB$na_table, + readOnly = TRUE, + rowHeaders = NULL, + height = miss.val.height(), + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE, + error_highlight = err_thresh() - 1 + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% + hot_col(2, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } + } + } + + }) + + # Render missing value informatiojn box UI + output$missing_values <- renderUI({ + div( + class = "miss_val_box", + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + div( + class = "white", + column( + width = 12, + align = "left", + br(), + HTML( + paste0("There are ", + strong(as.character(sum(is.na(DB$data)))), + " unsuccessful allele allocations (NA). ", + strong(sum(sapply(DB$allelic_profile, anyNA))), + " out of ", + strong(ncol(DB$allelic_profile)), + " total loci in this scheme contain NA's (", + strong(round((sum(sapply(DB$allelic_profile, anyNA)) / ncol(DB$allelic_profile) * 100), 1)), + " %). ", + "Decide how these missing values should be treated:") + + ), + br() + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "left", + br(), + prettyRadioButtons( + "na_handling", + "", + choiceNames = c("Ignore missing values for pairwise comparison", + "Omit loci with missing values for all assemblies", + "Treat missing values as allele variant"), + choiceValues = c("ignore_na", "omit", "category"), + shape = "curve", + selected = c("ignore_na") + ), + br() + ) + ) + ) + ) + }) + + } else { + #if no typed assemblies present + + # null underlying database + + DB$data <- NULL + DB$meta <- NULL + DB$meta_gs <- NULL + DB$meta_true <- NULL + DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL + DB$allelic_profile_true <- NULL + + # Render menu without missing values tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + selected = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + observe({ + if(is.null(DB$data)) { + if(check_new_entry()) { + output$db_no_entries <- renderUI( + column( + width = 12, + fluidRow( + column(1), + column( + width = 3, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 15px; position: absolute; bottom: -30px; right: -5px', 'New entries - reload database') + ) + ) + ), + column( + width = 4, + actionButton( + "load", + "", + icon = icon("rotate"), + class = "pulsating-button" + ) + ) + ) + ) + ) + } else { + output$db_no_entries <- renderUI( + column( + width = 12, + fluidRow( + column(1), + column( + width = 11, + align = "left", + HTML( + paste( + "", + "No Entries for this scheme available.\n", + "Type a genome in the section Allelic Typing and add the result to the local database.", + sep = '
' + ) + ) + ) + ) + ) + ) + } + } + }) + + output$distancematrix_no_entries <- renderUI( + fluidRow( + column(1), + column( + width = 11, + align = "left", + HTML(paste( + "", + "No Entries for this scheme available.", + "Type a genome in the section Allelic Typing and add the result to the local database.", + sep = '
' + )) + ) + ) + ) + + output$db_entries <- NULL + output$edit_index <- NULL + output$edit_scheme_d <- NULL + output$edit_entries <- NULL + output$compare_select <- NULL + output$delete_select <- NULL + output$del_bttn <- NULL + output$compare_allele_box <- NULL + output$download_entries <- NULL + output$missing_values <- NULL + output$delete_box <- NULL + output$entry_table_controls <- NULL + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$pending_typing <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + } + } + } + } + } else { + + log_print("Invalid scheme folder") + show_toast( + title = "Invalid scheme folder", + type = "warning", + position = "bottom-end", + timer = 4000 + ) + } + } + + }) + + # _______________________ #### + + ## Database ---- + + ### Conditional UI Elements rendering ---- + + # Contro custom variables table + output$cust_var_select <- renderUI({ + if(nrow(DB$cust_var) > 5) { + selectInput( + "cust_var_select", + "", + choices = 1:ceiling(nrow(DB$cust_var) / 5 ) + ) + } + }) + + output$cust_var_info <- renderUI({ + if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { + if(nrow(DB$cust_var) > 5) { + low <- -4 + high <- 0 + for (i in 1:input$cust_var_select) { + low <- low + 5 + if((nrow(DB$cust_var) %% 5) != 0) { + if(i == ceiling(nrow(DB$cust_var) / 5 )) { + high <- high + nrow(DB$cust_var) %% 5 + } else { + high <- high + 5 + } + } else { + high <- high + 5 + } + } + h5(paste0("Showing ", low, " to ", high," of ", nrow(DB$cust_var), " variables"), style = "color: white; font-size: 10px;") + } + } + }) + + # Message on Database tabs if no scheme available yet + observe({ + if(!is.null(DB$exist)) { + if(DB$exist){ + + # Message for tab Browse Entries + output$no_scheme_entries <- renderUI({ + fluidRow( + column(1), + column( + width = 4, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'No scheme available.') + ) + ) + ), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'Download a scheme first and type assemblies in the section Allelic Typing.') + ) + ) + ) + ) + ) + }) + + # Message for Tab Scheme Info + output$no_scheme_info <- renderUI({ + fluidRow( + column(1), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'No scheme available.') + ) + ) + ), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'Download a scheme first and type assemblies in the section Allelic Typing.') + ) + ) + ) + ) + ) + }) + + # Message for Tab Distance Matrix + output$no_scheme_distancematrix <- renderUI({ + fluidRow( + column(1), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'No scheme available.') + ) + ) + ), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'Download a scheme first and type assemblies in the section Allelic Typing.') + ) + ) + ) + ) + ) + }) + + } else { + output$no_scheme_entries <- NULL + output$no_scheme_info <- NULL + output$no_scheme_distancematrix <- NULL + } + } + + }) + + observe({ + # Conditional Missing Values Tab + if(!is.null(DB$allelic_profile)) { + if(anyNA(DB$allelic_profile)) { + if(DB$no_na_switch == FALSE) { + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + selected = TRUE, + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } + + } else { + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } + } + + }) + + observe({ + + if (!is.null(DB$available)) { + output$scheme_db <- renderUI({ + if (length(DB$available) > 5) { + selectInput( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} + ) + } else { + prettyRadioButtons( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} + ) + } + }) + + if (!is.null(DB$schemeinfo)) { + + output$scheme_info <- renderTable({ + DB$schemeinfo + }) + + output$scheme_header <- renderUI(h3(p("cgMLST Scheme"), style = "color:white")) + + } else { + + output$scheme_info <- NULL + output$scheme_header <- NULL + + } + + if (!is.null(DB$loci_info)) { + loci_info <- DB$loci_info + names(loci_info)[6] <- "Allele Count" + + output$db_loci <- renderDataTable( + loci_info, + selection = "single", + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + + output$loci_header <- renderUI(h3(p("Loci"), style = "color:white")) + + } else { + output$db_loci <- NULL + output$loci_header <- NULL + } + } + }) + + # If only one entry available disable varying loci checkbox + + output$compare_difference_box <- renderUI({ + if(!is.null(DB$data)) { + if(nrow(DB$data) > 1) { + div( + class = "mat-switch-db", + materialSwitch( + "compare_difference", + h5(p("Only Varying Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + } + } + }) + + ### Database Events ---- + + # Invalid entries table input + observe({ + req(DB$data, input$db_entries) + if (isTRUE(input$invalid_date)) { + show_toast( + title = "Invalid date", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + DB$inhibit_change <- TRUE + } else if (isTRUE(input$empty_name)) { + show_toast( + title = "Empty name", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + DB$inhibit_change <- TRUE + } else if (isTRUE(input$empty_id)) { + show_toast( + title = "Empty ID", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + DB$inhibit_change <- TRUE + } else { + DB$inhibit_change <- FALSE + } + }) + + # Change scheme + observeEvent(input$reload_db, { + log_print("Input reload_db") + + if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { + show_toast( + title = "Pending Multi Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Screening", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + showModal( + modalDialog( + selectInput( + "scheme_db", + label = "", + choices = DB$available, + selected = DB$scheme), + title = "Select a local database to load.", + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("load", "Load", class = "btn btn-default") + ) + ) + ) + } + }) + + # Create new database + observe({ + shinyDirChoose(input, + "create_new_db", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session) + + if(!is.null(input$create_new_db)) { + DB$new_database <- as.character( + parseDirPath( + roots = c(Home = path_home(), Root = "/"), + input$create_new_db + ) + ) + } + }) + + # Undo db changes + observeEvent(input$undo_changes, { + log_print("Input undo_changes") + + DB$inhibit_change <- FALSE + + Data <- readRDS(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme), + "/Typing.rds" + )) + + DB$data <- Data[["Typing"]] + + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + } else { + DB$cust_var <- data.frame() + } + + DB$change <- FALSE + DB$count <- 0 + DB$no_na_switch <- TRUE + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + DB$deleted_entries <- character(0) + + observe({ + if (!is.null(DB$data)) { + if (nrow(DB$data) == 1) { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else if (between(nrow(DB$data), 1, 40)) { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + highlightCol = TRUE, + highlightRow = TRUE, + contextMenu = FALSE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + valign = "htMiddle", + halign = "htCenter", + readOnly = TRUE) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + strict = TRUE, + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }" + ) %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names()- 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } else { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + rowHeaders = NULL, + height = table_height(), + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + readOnly = TRUE, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + height = table_height(), + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", halign = "htCenter") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } + } + }) + }) + + observe({ + if(!is.null(DB$data)){ + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + + } else { + DB$cust_var <- data.frame() + } + } + }) + + DB$count <- 0 + + observeEvent(input$add_new_variable, { + log_print("Input add_new_variable") + + if(nchar(input$new_var_name) > 12) { + log_print("Add variable; max. 10 character") + show_toast( + title = "Max. 10 characters", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + if (input$new_var_name == "") { + log_print("Add variable; min. 1 character") + show_toast( + title = "Min. 1 character", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + if(trimws(input$new_var_name) %in% names(DB$meta)) { + log_print("Add variable; name already existing") + show_toast( + title = "Variable name already existing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + showModal( + modalDialog( + selectInput( + "new_var_type", + label = "", + choices = c("Categorical (character)", + "Continous (numeric)")), + title = paste0("Select Data Type"), + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_new_var", "Confirm", class = "btn btn-default") + ) + ) + ) + } + } + } + }) + + observeEvent(input$conf_new_var, { + log_print("Input conf_new_var") + + # User feedback variables + removeModal() + DB$count <- DB$count + 1 + DB$change <- TRUE + + # Format variable name + name <- trimws(input$new_var_name) + + if(input$new_var_type == "Categorical (character)") { + DB$data <- DB$data %>% + mutate("{name}" := character(nrow(DB$data)), .after = 13) + + DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "categ")) + } else { + DB$data <- DB$data %>% + mutate("{name}" := numeric(nrow(DB$data)), .after = 13) + + DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "cont")) + } + + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + + log_print(paste0("New custom variable added: ", input$new_var_name)) + + show_toast( + title = paste0("Variable ", trimws(input$new_var_name), " added"), + type = "success", + position = "bottom-end", + timer = 6000 + ) + + }) + + observeEvent(input$delete_new_variable, { + log_print("Input delete_new_variable") + + if (input$del_which_var == "") { + log_print("Delete custom variables; no custom variable") + show_toast( + title = "No custom variables", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + showModal( + modalDialog( + paste0( + "Confirmation will lead to irreversible deletion of the custom ", + input$del_which_var, + " variable. Continue?" + ), + title = "Delete custom variables", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_var_del", "Delete", class = "btn btn-danger") + ) + ) + ) + } + }) + + observeEvent(input$conf_var_del, { + log_print("Input conf_var_del") + + DB$change <- TRUE + + removeModal() + + if(DB$count >= 1) { + DB$count <- DB$count - 1 + } + + show_toast( + title = paste0("Variable ", input$del_which_var, " removed"), + type = "warning", + position = "bottom-end", + timer = 6000 + ) + + log_print(paste0("Variable ", input$del_which_var, " removed")) + + DB$cust_var <- DB$cust_var[-which(DB$cust_var$Variable == input$del_which_var),] + DB$data <- select(DB$data, -(input$del_which_var)) + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + }) + + # Select all button + + observeEvent(input$sel_all_entries, { + log_print("Input sel_all_entries") + + DB$data$Include <- TRUE + }) + + observeEvent(input$desel_all_entries, { + log_print("Input desel_all_entries") + + DB$data$Include <- FALSE + }) + + # Switch to entry table + + observeEvent(input$change_entries, { + log_print("Input change_entries") + + removeModal() + updateTabItems(session, "tabs", selected = "db_browse_entries") + }) + + #### Save Missing Value as CSV ---- + + output$download_na_matrix <- downloadHandler( + filename = function() { + log_print(paste0("Save missing values table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv"))) + paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv") + }, + content = function(file) { + download_matrix <- hot_to_r(input$table_missing_values) + write.csv(download_matrix, file, sep = ",", row.names=FALSE, quote=FALSE) + } + ) + + #### Save scheme info table as CSV ---- + + output$download_schemeinfo <- downloadHandler( + filename = function() { + log_print(paste0("Save scheme info table ", paste0(gsub(" ", "_", DB$scheme), "_scheme.csv"))) + + paste0(gsub(" ", "_", DB$scheme), "_scheme.csv") + }, + content = function(file) { + pub_index <- which(DB$schemeinfo[,1] == "Publications") + write.table( + DB$schemeinfo[1:(pub_index-1),], + file, + sep = ";", + row.names = FALSE, + quote = FALSE + ) + } + ) + + #### Save Loci info table as CSV ---- + + output$download_loci_info <- downloadHandler( + filename = function() { + log_print(paste0("Save loci info table ", paste0(gsub(" ", "_", DB$scheme), "_Loci.csv"))) + + paste0(gsub(" ", "_", DB$scheme), "_Loci.csv") + }, + content = function(file) { + write.table( + DB$loci_info, + file, + sep = ";", + row.names = FALSE, + quote = FALSE + ) + } + ) + + #### Save entry table as CSV ---- + + output$download_entry_table <- downloadHandler( + filename = function() { + log_print(paste0("Save entry table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv"))) + + paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv") + }, + content = function(file) { + download_matrix <- hot_to_r(input$db_entries) + + if (input$download_table_include == TRUE) { + download_matrix <- download_matrix[which(download_matrix$Include == TRUE),] + } + + if (input$download_table_loci == FALSE) { + download_matrix <- select(download_matrix, 1:(13 + nrow(DB$cust_var))) + } + + write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) + } + ) + + # Save Edits Button + + observeEvent(input$edit_button, { + if(nrow(hot_to_r(input$db_entries)) > nrow(DB$data)) { + show_toast( + title = "Invalid rows entered. Saving not possible.", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + if(!isTRUE(DB$inhibit_change)) { + log_print("Input edit_button") + + showModal( + modalDialog( + if(length(DB$deleted_entries > 0)) { + paste0( + "Overwriting previous metadata of local ", + DB$scheme, + " database. Deleted entries will be irreversibly removed. Continue?" + ) + } else { + paste0( + "Overwriting previous metadata of local ", + DB$scheme, + " database. Continue?" + ) + }, + title = "Save Database", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_db_save", "Save", class = "btn btn-default") + ) + ) + ) + } else { + log_print("Input edit_button, invalid values.") + show_toast( + title = "Invalid values entered. Saving not possible.", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } + }) + + observeEvent(input$Cancel, { + log_print("Input Cancel") + removeModal() + }) + + observeEvent(input$conf_db_save, { + log_print("Input conf_db_save") + + # Remove isolate assembly file if present + if(!is.null(DB$remove_iso)) { + if(length(DB$remove_iso) > 0) { + lapply(DB$remove_iso, unlink, recursive = TRUE, force = FALSE, expand = TRUE) + } + } + DB$remove_iso <- NULL + + Data <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) + + if ((ncol(Data[["Typing"]]) - 13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_vars_pre <- select(Data[["Typing"]], + 14:(ncol(Data[["Typing"]]) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + cust_vars_pre <- names(cust_vars_pre) + } else { + cust_vars_pre <- character() + } + + Data[["Typing"]] <- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) + + meta_hot <- hot_to_r(input$db_entries) + + if(length(DB$deleted_entries > 0)) { + + meta_hot <- mutate(meta_hot, Index = as.character(1:nrow(DB$data))) + + Data[["Typing"]] <- mutate(Data[["Typing"]][-as.numeric(DB$deleted_entries), ], + meta_hot, .before = 1) + rownames(Data[["Typing"]]) <- Data[["Typing"]]$Index + } else { + Data[["Typing"]] <- mutate(Data[["Typing"]], meta_hot, .before = 1) + } + + # Ensure correct logical data type + Data[["Typing"]][["Include"]] <- as.logical(Data[["Typing"]][["Include"]]) + saveRDS(Data, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + # Load database from files + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + DB$data <- Database[["Typing"]] + + if(!is.null(DB$data)){ + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + } else { + DB$cust_var <- data.frame() + } + } + + DB$change <- FALSE + DB$count <- 0 + DB$no_na_switch <- TRUE + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + DB$deleted_entries <- character(0) + + removeModal() + + show_toast( + title = "Database successfully saved", + type = "success", + position = "bottom-end", + timer = 4000 + ) + }) + + observeEvent(input$del_button, { + log_print("Input del_button") + + if (length(input$select_delete) < 1) { + log_print("Delete entries; no entry selected") + show_toast( + title = "No entry selected", + type = "warning", + position = "bottom-end", + timer = 4000 + ) + } else if((readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") | + (tail(readLogFile(), 1) != "0")) { + log_print("Delete entries; pending typing") + + show_toast( + title = "Pending Typing", + type = "warning", + position = "bottom-end", + timer = 4000 + ) + } else { + if( (length(input$select_delete) - nrow(DB$data) ) == 0) { + showModal( + modalDialog( + paste0("Deleting will lead to removal of all entries and assemblies from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?"), + easyClose = TRUE, + title = "Deleting Entries", + footer = tagList( + modalButton("Cancel"), + actionButton("conf_delete_all", "Delete", class = "btn btn-danger") + ) + ) + ) + } else { + showModal( + modalDialog( + paste0( + "Confirmation will lead to irreversible removal of selected entries and the respectively saved assembly. Continue?" + ), + title = "Deleting Entries", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton( + "conf_delete", + "Delete", + class = "btn btn-danger") + ) + ) + ) + } + } + }) + + observeEvent(input$conf_delete_all, { + log_print("Input conf_delete_all") + + # remove file with typing data + file.remove(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + unlink(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates"), recursive = TRUE, force = FALSE, expand =TRUE) + + showModal( + modalDialog( + selectInput( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}}), + title = "All entries have been removed. Select a local database to load.", + footer = tagList( + actionButton("load", "Load", class = "btn btn-default") + ) + ) + ) + + }) + + DB$deleted_entries <- character(0) + + observeEvent(input$conf_delete, { + + log_print("Input conf_delete") + + # Get isolates selected for deletion + DB$deleted_entries <- append(DB$deleted_entries, DB$data$Index[as.numeric(input$select_delete)]) + + # Set reactive status variables + DB$no_na_switch <- TRUE + DB$change <- TRUE + DB$check_new_entries <- FALSE + + # Set isolate directory deletion variables + isopath <- dir_ls(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates")) + DB$remove_iso <- isopath[which(basename(isopath) == DB$data$`Assembly ID`[as.numeric(input$select_delete)])] + + # Reload updated database reactive variables + DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + + # User feedback + removeModal() + + if(length(input$select_delete) > 1) { + show_toast( + title = "Entries deleted", + type = "success", + position = "bottom-end", + timer = 4000 + ) + } else { + show_toast( + title = "Entry deleted", + type = "success", + position = "bottom-end", + timer = 4000 + ) + } + }) + + + ### Distance Matrix ---- + + hamming_df <- reactive({ + if(input$distmatrix_true == TRUE) { + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + + allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] + + hamming_mat <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) + + } else if(input$na_handling == "ignore_na"){ + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) + + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) + + } + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) + } + } else { + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + hamming_mat <- compute.distMatrix(allelic_profile_noNA, hamming.dist) + } else if(input$na_handling == "ignore_na"){ + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distIgnore) + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distCategory) + } + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.dist) + } + } + + # Extreme values for distance matrix heatmap display + DB$matrix_min <- min(hamming_mat, na.rm = TRUE) + DB$matrix_max <- max(hamming_mat, na.rm = TRUE) + + if(input$distmatrix_triangle == FALSE) { + hamming_mat[upper.tri(hamming_mat, diag = !input$distmatrix_diag)] <- NA + } + + # Row- and colnames change + if(input$distmatrix_true == TRUE) { + rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label][which(DB$data$Include == TRUE),]) + } else { + rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label]) + } + colnames(hamming_mat) <- rownames(hamming_mat) + + mode(hamming_mat) <- "integer" + + DB$ham_matrix <- hamming_mat %>% + as.data.frame() %>% + mutate(Index = colnames(hamming_mat)) %>% + relocate(Index) + DB$distancematrix_nrow <- nrow(DB$ham_matrix) + + DB$ham_matrix + }) + + output$download_distmatrix <- downloadHandler( + filename = function() { + paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Distance_Matrix.csv") + }, + content = function(file) { + download_matrix <- hot_to_r(input$db_distancematrix) + download_matrix[is.na(download_matrix)] <- "" + write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) + } + ) + + # _______________________ #### + + ## Locus sequences ---- + + observe({ + if(!is.null(DB$database) & !is.null(DB$scheme)) { + DB$loci <- list.files( + path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), + pattern = "\\.(fasta|fa|fna)$", + full.names = TRUE + ) + } + }) + + output$loci_sequences <- renderUI({ + req(input$db_loci_rows_selected, DB$database, DB$scheme, input$seq_sel) + + DB$loci <- list.files( + path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), + pattern = "\\.(fasta|fa|fna)$", + full.names = TRUE + ) + + fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) + + seq <- fasta[[which(fasta == paste0(">", gsub("Allele ", "", sub(" -.*", "", input$seq_sel)))) + 1]] + + DB$seq <- seq + + column( + width = 12, + HTML( + paste( + tags$span(style='color: white; font-size: 15px; position: relative; top: -15px; left: -50px', + sub(" -.*", "", input$seq_sel)) + ) + ), + tags$pre(HTML(color_sequence(seq)), class = "sequence") + ) + }) + + output$sequence_selector <- renderUI({ + if(!is.null(input$db_loci_rows_selected)) { + + req(input$db_loci_rows_selected, DB$database, DB$scheme) + + DB$loci <- list.files( + path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), + pattern = "\\.(fasta|fa|fna)$", + full.names = TRUE + ) + + fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) + + seq_names <- c() + for (i in seq_along(fasta)) { + if (startsWith(fasta[[i]], ">")) { + name <- sub(">", "", fasta[[i]]) + seq_names <- c(seq_names, name) + } + } + + var_count <- table(DB$allelic_profile[gsub(".fasta", "", (basename(DB$loci[input$db_loci_rows_selected])))]) + + vec <- prop.table(var_count) + + perc <- sapply(unname(vec), scales::percent, accuracy = 0.1) + + names(perc) <- names(vec) + + choices <- seq_names + + present <- which(choices %in% names(vec)) + absent <- which(!(choices %in% names(vec))) + + choices[present] <- paste0("Allele ", choices[present], " - ", unname(var_count), " times in DB (", unname(perc), ")") + + choices[absent] <- paste0("Allele ", choices[absent], " - not present") + + choices <- c(choices[present], choices[absent]) + + names(choices) <- sapply(choices, function(x) { + x <- strsplit(x, " ")[[1]] + x[2] <- paste0(substr(x[2], 1, 4), "...", substr(x[2], nchar(x[2])-3, nchar(x[2]))) + paste(x, collapse = " ") + }) + + column( + width = 3, + selectInput( + "seq_sel", + h5("Select Variant", style = "color:white;"), + choices = choices, + width = "80%" + ), + br(), + fluidRow( + column( + width = 8, + align = "left", + actionButton("copy_seq", "Copy Sequence", + icon = icon("copy")), + bsTooltip("copy_seq", "Copy the variant sequence
to clipboard", placement = "top", trigger = "hover") + ) + ), + br(), + fluidRow( + column( + width = 8, + align = "left", + downloadBttn( + "get_locus", + style = "simple", + label = "Save .fasta", + size = "sm", + icon = icon("download") + ), + bsTooltip("get_locus_bttn", "Save locus file with all variants", placement = "top", trigger = "hover") + ) + ), + br(), br(), br(), br(), br(), br(), br() + ) + } + }) + + observeEvent(input$copy_seq, { + if(!is.null(DB$seq)) { + session$sendCustomMessage("txt", DB$seq) + } + show_toast( + title = "Copied sequence", + type = "success", + position = "bottom-end", + timer = 3000 + ) + }) + + output$get_locus <- downloadHandler( + filename = function() { + fname <- basename(DB$loci[input$db_loci_rows_selected]) + log_print(paste0("Get locus fasta ", fname)) + fname + }, + content = function(file) { + cont <- readLines(DB$loci[input$db_loci_rows_selected]) + writeLines(cont, file) + } + ) + + # _______________________ #### + + ## Download cgMLST ---- + + observe({ + if (input$select_cgmlst == "Acinetobacter baumanii") { + species <- "Abaumannii1907" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- Scheme$folder_name <- "Acinetobacter_baumanii" + } else if (input$select_cgmlst == "Bacillus anthracis") { + species <- "Banthracis1917" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Bacillus_anthracis" + } else if (input$select_cgmlst == "Bordetella pertussis") { + species <- "Bpertussis1917" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Bordetella_pertussis" + } else if (input$select_cgmlst == "Brucella melitensis") { + species <- "Bmelitensis1912" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Brucella_melitensis" + } else if (input$select_cgmlst == "Brucella spp.") { + species <- "Brucella1914" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Brucella_spp" + } else if (input$select_cgmlst == "Burkholderia mallei (FLI)") { + species <- "Bmallei_fli1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Burkholderia_mallei_FLI" + } else if (input$select_cgmlst == "Burkholderia mallei (RKI)") { + species <- "Bmallei_rki1909" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Burkholderia_mallei_RKI" + } else if (input$select_cgmlst == "Burkholderia pseudomallei") { + species <- "Bpseudomallei1906" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Burkholderia_pseudomallei" + } else if (input$select_cgmlst == "Campylobacter jejuni/coli") { + species <- "Cjejuni1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Campylobacter_jejuni_coli" + } else if (input$select_cgmlst == "Clostridioides difficile") { + species <- "Cdifficile1905" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Clostridioides_difficile" + } else if (input$select_cgmlst == "Clostridium perfringens") { + species <- "Cperfringens1907" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Clostridium_perfringens" + } else if (input$select_cgmlst == "Corynebacterium diphtheriae") { + species <- "Cdiphtheriae1907" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Corynebacterium_diphtheriae" + } else if (input$select_cgmlst == "Cronobacter sakazakii/malonaticus") { + species <- "Csakazakii1910" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Cronobacter_sakazakii_malonaticus" + } else if (input$select_cgmlst == "Enterococcus faecalis") { + species <- "Efaecalis1912" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Enterococcus_faecalis" + } else if (input$select_cgmlst == "Enterococcus faecium") { + species <- "Efaecium1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Enterococcus_faecium" + } else if (input$select_cgmlst == "Escherichia coli") { + species <- "Ecoli1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Escherichia_coli" + } else if (input$select_cgmlst == "Francisella tularensis") { + species <- "Ftularensis1913" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Francisella_tularensis" + } else if (input$select_cgmlst == "Klebsiella oxytoca sensu lato") { + species <- "Koxytoca717" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Klebsiella_oxytoca_sensu_lato" + } else if (input$select_cgmlst == "Klebsiella pneumoniae sensu lato") { + species <- "Kpneumoniae1909" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Klebsiella_pneumoniae_sensu_lato" + } else if (input$select_cgmlst == "Legionella pneumophila") { + species <- "Lpneumophila1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Legionella_pneumophila" + } else if (input$select_cgmlst == "Listeria monocytogenes") { + species <- "Lmonocytogenes1910" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Listeria_monocytogenes" + } else if (input$select_cgmlst == "Mycobacterium tuberculosis complex") { + species <- "Mtuberculosis1909" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Mycobacterium_tuberculosis_complex" + } else if (input$select_cgmlst == "Mycobacteroides abscessus") { + species <- "Mabscessus1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Mycobacteroides_abscessus" + } else if (input$select_cgmlst == "Mycoplasma gallisepticum") { + species <- "Mgallisepticum1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Mycoplasma_gallisepticum" + } else if (input$select_cgmlst == "Paenibacillus larvae") { + species <- "Plarvae1902" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Paenibacillus_larvae" + } else if (input$select_cgmlst == "Pseudomonas aeruginosa") { + species <- "Paeruginosa1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Pseudomonas_aeruginosa" + } else if (input$select_cgmlst == "Salmonella enterica") { + species <- "Senterica1913" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Salmonella_enterica" + } else if (input$select_cgmlst == "Serratia marcescens") { + species <- "Smarcescens1912" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Serratia_marcescens" + } else if (input$select_cgmlst == "Staphylococcus aureus") { + species <- "Saureus1908" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Staphylococcus_aureus" + } else if (input$select_cgmlst == "Staphylococcus capitis") { + species <- "Scapitis1905" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Staphylococcus_capitis" + } else if (input$select_cgmlst == "Streptococcus pyogenes") { + species <- "Spyogenes1904" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Streptococcus_pyogenes" + } + }) + + observeEvent(input$download_cgMLST, { + log_print(paste0("Started download of scheme for ", Scheme$folder_name)) + + shinyjs::hide("download_cgMLST") + shinyjs::show("loading") + + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    Downloading scheme...")), + style = "color:white;") + ) + ) + ) + + show_toast( + title = "Download started", + type = "success", + position = "bottom-end", + timer = 5000 + ) + + if(length(DB$available) == 0) { + saveRDS(DB$new_database, paste0(getwd(), "/execute/new_db.rds")) + dir.create(file.path(readRDS(paste0(getwd(), "/execute/new_db.rds")), "Database"), recursive = TRUE) + } + + DB$load_selected <- TRUE + + # Check if .downloaded_schemes folder exists and if not create it + if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { + dir.create(file.path(DB$database, ".downloaded_schemes"), recursive = TRUE) + } + + # Check if remains of old temporary folder exists and remove them + if (dir.exists(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")))) { + unlink(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")), recursive = TRUE) + } + + # Download Loci Fasta Files + options(timeout = 600) + + tryCatch({ + download.file(Scheme$link_cgmlst, + file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip"))) + "Download successful!" + }, error = function(e) { + paste("Error: ", e$message) + }) + + # Unzip the scheme in temporary folder + unzip( + zipfile = file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")), + exdir = file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp") + ) + ) + + log_print("Hashing downloaded database") + # Hash temporary folder + hash_database(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Get list from local database + local_db_filelist <- list.files(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) + if (!is_empty(local_db_filelist)) { + # Get list from temporary database + tmp_db_filelist <- list.files(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Find the difference (extra files in local database) + local_db_extra <- setdiff(local_db_filelist, tmp_db_filelist) + + # Copy extra files to temporary folder + file.copy(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), local_db_extra), + file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Check differences in file pairs + local_db_hashes <- tools::md5sum(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + local_db_filelist)) + tmp_db_hashes <- tools::md5sum(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + local_db_filelist)) + + diff_files <- local_db_hashes %in% tmp_db_hashes + diff_loci <- names(local_db_hashes)[diff_files == FALSE] + diff_loci <- sapply(strsplit(diff_loci, "/"), function(x) x[length(x)]) + + # Check locus hashes + for (locus in diff_loci) { + local_db_hashes <- get_locus_hashes(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + locus)) + tmp_db_hashes <- get_locus_hashes(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + locus)) + diff_hashes <- setdiff(local_db_hashes, tmp_db_hashes) + + sequences <- extract_seq(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + locus), diff_hashes) + if (!is_empty(sequences$idx) && !is_empty(sequences$seq) && + length(sequences$idx) == length(sequences$seq)) { + add_new_sequences(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + locus), sequences) + } + } + } + + unlink(file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) + + file.rename(file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp")), + file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) + + # Download Scheme Info + download( + Scheme$link_scheme, + dest = file.path(DB$database, Scheme$folder_name, "scheme_info.html"), + mode = "wb" + ) + + # Download Loci Info + download( + Scheme$link_targets, + dest = file.path(DB$database, Scheme$folder_name, "targets.csv"), + mode = "wb" + ) + + # Send downloaded scheme to database browser overview + DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) + + Scheme$target_table <- read.csv( + file.path(DB$database, Scheme$folder_name, "targets.csv"), + header = TRUE, + sep = "\t", + row.names = NULL, + colClasses = c( + "NULL", + "character", + "character", + "integer", + "integer", + "character", + "integer", + "NULL" + ) + ) + + DB$exist <- length(dir_ls(DB$database)) == 0 + + shinyjs::show("download_cgMLST") + shinyjs::hide("loading") + + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    ready")), + style = "color:white;") + ) + ) + ) + + show_toast( + title = "Download successful", + type = "success", + position = "bottom-end", + timer = 5000 + ) + + log_print("Download successful") + + showModal( + modalDialog( + selectInput( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {input$select_cgmlst} else {DB$available[1]}}), + title = "Select a local database to load.", + footer = tagList( + actionButton("load", "Load", class = "btn btn-default") + ) + ) + ) + }) + + # Download Target Info (CSV Table) + observe({ + input$download_cgMLST + + scheme_overview <- read_html(Scheme$link_scheme) %>% + html_table(header = FALSE) %>% + as.data.frame(stringsAsFactors = FALSE) + + last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], + format = "%B %d, %Y, %H:%M %p") + names(scheme_overview) <- NULL + + last_file_change <- format( + file.info(file.path(DB$database, + ".downloaded_schemes", + paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") + + output$cgmlst_scheme <- renderTable({scheme_overview}) + output$scheme_update_info <- renderText({ + req(last_file_change) + if (last_file_change < last_scheme_change) { + "(Newer scheme available \u274c)" + } else { + "(Scheme is up-to-date \u2705)" + } + }) + }) + + # _______________________ #### + + ## Visualization ---- + + # Render placeholder image + + output$placeholder <- renderImage({ + # Path to your PNG image with a transparent background + image_path <- paste0(getwd(), "/www/PhyloTrace.png") + + # Use HTML to display the image with the tag + list(src = image_path, + height = 180) + }, deleteFile = FALSE) + + # Render tree plot fields + + output$nj_field <- renderUI( + fluidRow( + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br() + ) + ) + + output$mst_field <- renderUI( + fluidRow( + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br() + ) + ) + + output$upgma_field <- renderUI( + fluidRow( + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br() + ) + ) + + ### Render Visualization Controls ---- + + #### NJ and UPGMA controls ---- + + # Control enable/disable of variable mapping inputs + observe({ + shinyjs::toggleState(id = "nj_color_mapping", condition = isTRUE(input$nj_mapping_show)) + shinyjs::toggleState(id = "nj_tiplab_scale", condition = isTRUE(input$nj_mapping_show)) + shinyjs::toggleState(id = "upgma_color_mapping", condition = isTRUE(input$upgma_mapping_show)) + shinyjs::toggleState(id = "upgma_tiplab_scale", condition = isTRUE(input$upgma_mapping_show)) + + shinyjs::toggleState(id = "nj_tipcolor_mapping", condition = isTRUE(input$nj_tipcolor_mapping_show)) + shinyjs::toggleState(id = "nj_tippoint_scale", condition = isTRUE(input$nj_tipcolor_mapping_show)) + shinyjs::toggleState(id = "upgma_tipcolor_mapping", condition = isTRUE(input$upgma_tipcolor_mapping_show)) + shinyjs::toggleState(id = "upgma_tippoint_scale", condition = isTRUE(input$upgma_tipcolor_mapping_show)) + + shinyjs::toggleState(id = "nj_tipshape_mapping", condition = isTRUE(input$nj_tipshape_mapping_show)) + shinyjs::toggleState(id = "upgma_tipshape_mapping", condition = isTRUE(input$upgma_tipshape_mapping_show)) + + shinyjs::toggleState(id = "nj_fruit_variable", condition = isTRUE(input$nj_tiles_show_1)) + shinyjs::toggleState(id = "upgma_fruit_variable", condition = isTRUE(input$upgma_tiles_show_1)) + shinyjs::toggleState(id = "nj_fruit_variable_2", condition = isTRUE(input$nj_tiles_show_2)) + shinyjs::toggleState(id = "upgma_fruit_variable_2", condition = isTRUE(input$upgma_tiles_show_2)) + shinyjs::toggleState(id = "nj_fruit_variable_3", condition = isTRUE(input$nj_tiles_show_3)) + shinyjs::toggleState(id = "upgma_fruit_variable_3", condition = isTRUE(input$upgma_tiles_show_3)) + shinyjs::toggleState(id = "nj_fruit_variable_4", condition = isTRUE(input$nj_tiles_show_4)) + shinyjs::toggleState(id = "upgma_fruit_variable_4", condition = isTRUE(input$upgma_tiles_show_4)) + shinyjs::toggleState(id = "nj_fruit_variable_5", condition = isTRUE(input$nj_tiles_show_5)) + shinyjs::toggleState(id = "upgma_fruit_variable_5", condition = isTRUE(input$upgma_tiles_show_5)) + shinyjs::toggleState(id = "nj_tiles_scale_1", condition = isTRUE(input$nj_tiles_show_1)) + shinyjs::toggleState(id = "upgma_tiles_scale_1", condition = isTRUE(input$upgma_tiles_show_1)) + shinyjs::toggleState(id = "nj_tiles_scale_2", condition = isTRUE(input$nj_tiles_show_2)) + shinyjs::toggleState(id = "upgma_tiles_scale_2", condition = isTRUE(input$upgma_tiles_show_2)) + shinyjs::toggleState(id = "nj_tiles_scale_3", condition = isTRUE(input$nj_tiles_show_3)) + shinyjs::toggleState(id = "upgma_tiles_scale_3", condition = isTRUE(input$upgma_tiles_show_3)) + shinyjs::toggleState(id = "nj_tiles_scale_4", condition = isTRUE(input$nj_tiles_show_4)) + shinyjs::toggleState(id = "upgma_tiles_scale_4", condition = isTRUE(input$upgma_tiles_show_4)) + shinyjs::toggleState(id = "nj_tiles_scale_5", condition = isTRUE(input$nj_tiles_show_5)) + shinyjs::toggleState(id = "upgma_tiles_scale_5", condition = isTRUE(input$upgma_tiles_show_5)) + + shinyjs::toggleState(id = "nj_heatmap_sel", condition = isTRUE(input$nj_heatmap_show)) + shinyjs::toggleState(id = "nj_heatmap_scale", condition = isTRUE(input$nj_heatmap_show)) + shinyjs::toggleState(id = "upgma_heatmap_sel", condition = isTRUE(input$upgma_heatmap_show)) + shinyjs::toggleState(id = "upgma_heatmap_scale", condition = isTRUE(input$upgma_heatmap_show)) + }) + + # Size scaling NJ + observe({ + req(input$nj_ratio) + if(input$nj_ratio == "1.6") { + updateSliderInput(session, "nj_scale", + step = 5, value = 800, min = 500, max = 1200) + } else if(input$nj_ratio == "1.77777777777778") { + updateSliderInput(session, "nj_scale", + step = 9, value = 801, min = 504, max = 1197) + } else if(input$nj_ratio == "1.33333333333333"){ + updateSliderInput(session, "nj_scale", + step = 3, value = 801, min = 501, max = 1200) + } + }) + + # Size scaling UPGMA + observe({ + req(input$upgma_ratio) + if(input$upgma_ratio == "1.6") { + updateSliderInput(session, "upgma_scale", + step = 5, value = 800, min = 500, max = 1200) + } else if(input$upgma_ratio == "1.77777777777778") { + updateSliderInput(session, "upgma_scale", + step = 9, value = 801, min = 504, max = 1197) + } else if(input$upgma_ratio == "1.33333333333333"){ + updateSliderInput(session, "upgma_scale", + step = 3, value = 801, min = 501, max = 1200) + } + }) + + # Size scaling MST + observe({ + req(input$mst_ratio) + if(input$mst_ratio == "1.6") { + updateSliderInput(session, "mst_scale", + step = 5, value = 800, min = 500, max = 1200) + } else if(input$mst_ratio == "1.77777777777778") { + updateSliderInput(session, "mst_scale", + step = 9, value = 801, min = 504, max = 1197) + } else if(input$mst_ratio == "1.33333333333333"){ + updateSliderInput(session, "mst_scale", + step = 3, value = 801, min = 501, max = 1200) + } + }) + + # Custom Labels + + # Add custom label + observeEvent(input$nj_add_new_label, { + + if(nchar(input$nj_new_label_name) > 0) { + if(!(input$nj_new_label_name %in% Vis$custom_label_nj)) { + Vis$custom_label_nj <- rbind(Vis$custom_label_nj, input$nj_new_label_name) + if(!(nrow(Vis$custom_label_nj) == 1)) { + updateSelectInput(session, "nj_custom_label_sel", selected = input$nj_new_label_name) + } + } else { + show_toast( + title = "Label already exists", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } else { + show_toast( + title = "Min. 1 character", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + + observeEvent(input$upgma_add_new_label, { + + if(nchar(input$upgma_new_label_name) > 0) { + if(!(input$upgma_new_label_name %in% Vis$custom_label_upgma)) { + Vis$custom_label_upgma <- rbind(Vis$custom_label_upgma, input$upgma_new_label_name) + if(!(nrow(Vis$custom_label_upgma) == 1)) { + updateSelectInput(session, "upgma_custom_label_sel", selected = input$upgma_new_label_name) + } + } else { + show_toast( + title = "Label already exists", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } else { + show_toast( + title = "Min. 1 character", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + + # Delete custom label + observeEvent(input$nj_del_label, { + + if(nrow(Vis$custom_label_nj) > 1) { + Vis$custom_label_nj <- Vis$custom_label_nj[-which(Vis$custom_label_nj[,1] == input$nj_custom_label_sel), , drop = FALSE] + } else if (nrow(Vis$custom_label_nj) == 1) { + Vis$nj_label_pos_x <- list() + Vis$nj_label_pos_y <- list() + Vis$nj_label_size <- list() + Vis$custom_label_nj <- data.frame() + } + }) + + observeEvent(input$upgma_del_label, { + + if(nrow(Vis$custom_label_upgma) > 1) { + Vis$custom_label_upgma <- Vis$custom_label_upgma[-which(Vis$custom_label_upgma[,1] == input$upgma_custom_label_sel), , drop = FALSE] + } else if (nrow(Vis$custom_label_upgma) == 1) { + Vis$upgma_label_pos_x <- list() + Vis$upgma_label_pos_y <- list() + Vis$upgma_label_size <- list() + Vis$custom_label_upgma <- data.frame() + } + }) + + # Select custom labels + output$nj_custom_label_select <- renderUI({ + if(nrow(Vis$custom_label_nj) > 0) { + selectInput( + "nj_custom_label_sel", + "", + choices = Vis$custom_label_nj[,1] + ) + } + }) + + output$upgma_custom_label_select <- renderUI({ + if(nrow(Vis$custom_label_upgma) > 0) { + selectInput( + "upgma_custom_label_sel", + "", + choices = Vis$custom_label_upgma[,1] + ) + } + }) + + # Select custom labels + output$nj_cust_label_save <- renderUI({ + if(nrow(Vis$custom_label_nj) > 0) { + actionButton( + "nj_cust_label_save", + "Apply" + ) + } else { + column( + width = 12, + br(), br(), br(), br(), br(), br(), + h5("test", style = "color: transparent; margin-bottom: 3px") + ) + } + }) + + output$upgma_cust_label_save <- renderUI({ + if(nrow(Vis$custom_label_upgma) > 0) { + actionButton( + "upgma_cust_label_save", + "Apply" + ) + } else { + column( + width = 12, + br(), br(), br(), br(), br(), br(), + h5("test", style = "color: transparent; margin-bottom: 3px") + ) + } + }) + + # Custom Label Size + output$nj_custom_labelsize <- renderUI({ + if(length(Vis$custom_label_nj) > 0) { + if(!is.null(Vis$nj_label_size[[input$nj_custom_label_sel]])) { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, + value = Vis$nj_label_size[[input$nj_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, value = 5, + width = "150px") + } + } + }) + + output$upgma_custom_labelsize <- renderUI({ + if(length(Vis$custom_label_upgma) > 0) { + if(!is.null(Vis$upgma_label_size[[input$upgma_custom_label_sel]])) { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, + value = Vis$upgma_label_size[[input$upgma_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, value = 5, + width = "150px") + } + } + }) + + # Render slider input based on selected label + output$nj_sliderInput_y <- renderUI({ + if(length(Vis$custom_label_nj) > 0) { + if(!is.null(Vis$nj_label_pos_y[[input$nj_custom_label_sel]])) { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$nj_label_pos_y[[input$nj_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = sum(DB$data$Include), step = 1, ticks = F, + value = sum(DB$data$Include) / 2, + width = "150px") + } + } + }) + + output$upgma_sliderInput_y <- renderUI({ + if(length(Vis$custom_label_upgma) > 0) { + if(!is.null(Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]])) { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = sum(DB$data$Include), step = 1, ticks = F, + value = sum(DB$data$Include) / 2, + width = "150px") + } + } + }) + + output$nj_sliderInput_x <- renderUI({ + if(length(Vis$custom_label_nj) > 0) { + if(!is.null(Vis$nj_label_pos_x[[input$nj_custom_label_sel]])) { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$nj_label_pos_x[[input$nj_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = round(Vis$nj_max_x, 0), step = 1, ticks = F, + value = round(Vis$nj_max_x / 2, 0), + width = "150px") + } + } + }) + + output$upgma_sliderInput_x <- renderUI({ + if(length(Vis$custom_label_upgma) > 0) { + if(!is.null(Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]])) { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = round(Vis$upgma_max_x, 0), step = 1, ticks = F, + value = round(Vis$upgma_max_x / 2, 0), + width = "150px") + } + } + }) + + # Apply custom label changes + observeEvent(input$nj_cust_label_save, { + + if(!is.null(Vis$nj_label_pos_y) & + !is.null(Vis$nj_label_pos_x) & + !is.null(Vis$nj_label_size) & + !is.null(input$nj_custom_label_sel)) { + Vis$nj_label_pos_y[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_y")]] + Vis$nj_label_pos_x[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_x")]] + Vis$nj_label_size[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_size")]] + } + }) + + observeEvent(input$upgma_cust_label_save, { + + if(!is.null(Vis$upgma_label_pos_y) & + !is.null(Vis$upgma_label_pos_x) & + !is.null(Vis$upgma_label_size) & + !is.null(input$upgma_custom_label_sel)) { + Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_y")]] + Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_x")]] + Vis$upgma_label_size[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_size")]] + } + }) + + # Show delete custom label button if custam label added + output$nj_del_label <- renderUI({ + if(nrow(Vis$custom_label_nj) > 0) { + actionButton( + "nj_del_label", + "", + icon = icon("minus") + ) + } else {NULL} + }) + + output$upgma_del_label <- renderUI({ + if(nrow(Vis$custom_label_upgma) > 0) { + actionButton( + "upgma_del_label", + "", + icon = icon("minus") + ) + } else {NULL} + }) + + # Mapping value number information + output$nj_tiplab_mapping_info <- renderUI({ + if(!is.null(input$nj_color_mapping) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_color_mapping]))) { + if(input$nj_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_color_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$upgma_tiplab_mapping_info <- renderUI({ + if(!is.null(input$upgma_color_mapping) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) { + if(input$upgma_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_color_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$nj_tipcolor_mapping_info <- renderUI({ + if(!is.null(input$nj_tipcolor_mapping) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) { + if(input$nj_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tipcolor_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$upgma_tipcolor_mapping_info <- renderUI({ + if(!is.null(input$upgma_tipcolor_mapping) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) { + if(input$upgma_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tipcolor_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$nj_tipshape_mapping_info <- renderUI({ + if(!is.null(input$nj_tipshape_mapping) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) { + column( + width = 3, + h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) > 6) { + column( + width = 3, + h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$upgma_tipshape_mapping_info <- renderUI({ + if(!is.null(input$upgma_tipshape_mapping) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) { + column( + width = 3, + h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) > 6) { + column( + width = 3, + h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$nj_fruit_mapping_info <- renderUI({ + if(input$nj_tile_num == 1) { + if(!is.null(input$nj_fruit_variable) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable]))) { + if(input$nj_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_1", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 2) { + if(!is.null(input$nj_fruit_variable_2) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) { + if(input$nj_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_2", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 3) { + if(!is.null(input$nj_fruit_variable_3) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) { + if(input$nj_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_3", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 4) { + if(!is.null(input$nj_fruit_variable_4) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) { + if(input$nj_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_4", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 5) { + if(!is.null(input$nj_fruit_variable_5) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) { + if(input$nj_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_5", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } + }) + + output$upgma_fruit_mapping_info <- renderUI({ + if(input$upgma_tile_num == 1) { + if(!is.null(input$upgma_fruit_variable) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) { + if(input$upgma_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_1", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 2) { + if(!is.null(input$upgma_fruit_variable_2) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) { + if(input$upgma_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_2", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 3) { + if(!is.null(input$upgma_fruit_variable_3) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) { + if(input$upgma_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_3", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 4) { + if(!is.null(input$upgma_fruit_variable_4) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) { + if(input$upgma_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_4", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 5) { + if(!is.null(input$upgma_fruit_variable_5) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) { + if(input$upgma_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_5", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } + }) + + output$nj_heatmap_mapping_info <- renderUI({ + if(!is.null(input$nj_heatmap_select) & (!is.null(Vis$meta_nj))) { + if (any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { + column( + width = 3, + h5("Heatmap with categorical and continous values not possible", + style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") + ) + } else { + if(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { + if(input$nj_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_heatmap_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { + column( + width = 3, + h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } + } else {NULL} + }) + + output$upgma_heatmap_mapping_info <- renderUI({ + if(!is.null(input$upgma_heatmap_select) & (!is.null(Vis$meta_upgma))) { + if (any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { + column( + width = 3, + h5("Heatmap with categorical and continous values not possible", + style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") + ) + } else { + if(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { + if(input$upgma_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_heatmap_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { + column( + width = 3, + h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } + } else {NULL} + }) + + # Tiles offset + output$nj_fruit_offset_circ <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ", + label = "", + min = min, + max = max, + step= step, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.1 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.05 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ", + label = "", + min = min, + max = max, + step= step, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ", + label = "", + min = -0.2, + max = 0.2, + step= 0.05, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_2 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_2", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_2", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_2 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_2", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_2", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_3 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_3", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_3", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_3 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_3", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_3", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_4 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_4", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_4", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_4 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_4", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_4", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_5 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_5", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_5", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_5 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_5", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_5", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + # For Layout change update tiles offset position + observeEvent(input$nj_layout, { + + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } else { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } + + updateSliderInput(session, "nj_fruit_offset_circ", min = min, step = step, max = max) + updateSliderInput(session, "nj_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "nj_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "nj_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "nj_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) + }) + + observeEvent(input$upgma_layout, { + + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } else { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } + + updateSliderInput(session, "upgma_fruit_offset_circ", min = min, step = step, max = max) + updateSliderInput(session, "upgma_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "upgma_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "upgma_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "upgma_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) + }) + + # Heatmap width + output$nj_heatmap_width <- renderUI({ + if(!is.null(input$nj_heatmap_select)) { + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + + sliderInput( + "nj_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = width, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = 0.1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_heatmap_width <- renderUI({ + if(!is.null(input$upgma_heatmap_select)) { + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + + sliderInput( + "upgma_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = width, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = 0.1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + }) + + # Update value if new variables added + observeEvent(input$nj_heatmap_select, { + + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "nj_heatmap_width", value = width) + }) + + observeEvent(input$upgma_heatmap_select, { + + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "upgma_heatmap_width", value = width) + }) + + # Update value if layout changed + observeEvent(input$nj_layout, { + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "nj_heatmap_width", value = width) + }) + + observeEvent(input$upgma_layout, { + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "upgma_heatmap_width", value = width) + }) + + # Heatmap column titles position + observeEvent(input$nj_layout, { + if(!(input$nj_layout == "inward" | input$nj_layout == "circular")) { + updateSliderInput(session, "nj_colnames_y", value = -1) + } else { + updateSliderInput(session, "nj_colnames_y", value = 0) + } + }) + + observeEvent(input$upgma_layout, { + if(!(input$upgma_layout == "inward" | input$upgma_layout == "circular")) { + updateSliderInput(session, "upgma_colnames_y", value = -1) + } else { + updateSliderInput(session, "upgma_colnames_y", value = 0) + } + }) + + output$nj_colnames_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + if(input$nj_layout == "inward" | input$nj_layout == "circular") { + min <- 0 + val <- 0 + } else { + val <- -1 + if((sum(DB$data$Include) * -0.1) > -2) { + min <- -2 + } else { + min <- round(sum(DB$data$Include) * -0.1, 0) + } + } + sliderInput( + "nj_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = min, + max = sum(DB$data$Include), + value = val, + step = 1, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = -10, + max = 10, + value = 0, + step = 1, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_colnames_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { + min <- 0 + val <- 0 + } else { + val <- -1 + if((sum(DB$data$Include) * -0.1) > -2) { + min <- -2 + } else { + min <- round(sum(DB$data$Include) * -0.1, 0) + } + } + sliderInput( + "upgma_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = min, + max = sum(DB$data$Include), + value = val, + step = 1, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = -10, + max = 10, + value = 0, + step = 1, + width = "150px", + ticks = FALSE + ) + } + }) + + # Heatmap column titles angle + output$nj_colnames_angle <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + angle <- 90 + } else {angle <- -90} + sliderInput( + "nj_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = angle, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_colnames_angle <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + angle <- 90 + } else {angle <- -90} + sliderInput( + "upgma_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = angle, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + # Change heatmap column titles angle and label align when switching layout + observeEvent(input$nj_layout, { + if(input$nj_layout == "circular" | input$nj_layout == "inward"){ + angle <- 90 + val <- TRUE + } else { + angle <- -90 + val <- FALSE + } + updateSwitchInput(session, "nj_align", value = val) + updateSliderInput(session, "nj_colnames_angle", value = angle) + }) + + observeEvent(input$upgma_layout, { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward"){ + angle <- 90 + val <- TRUE + } else { + angle <- -90 + val <- FALSE + } + updateSwitchInput(session, "upgma_align", value = val) + updateSliderInput(session, "upgma_colnames_angle", value = angle) + }) + + # Tile number selector update each other + observeEvent(input$nj_tile_num, { + updateSelectInput(session, "nj_tile_number", selected = input$nj_tile_num) + }) + + observeEvent(input$nj_tile_number, { + updateSelectInput(session, "nj_tile_num", selected = input$nj_tile_number) + }) + + observeEvent(input$upgma_tile_num, { + updateSelectInput(session, "upgma_tile_number", selected = input$upgma_tile_num) + }) + + observeEvent(input$upgma_tile_number, { + updateSelectInput(session, "upgma_tile_num", selected = input$upgma_tile_number) + }) + + # Clade coloring + output$nj_clade_scale <- renderUI({ + if(length(input$nj_parentnode) <= 1) { + fluidRow( + column( + width = 5, + h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "nj_clade_scale", + selected = "#D0F221", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ) + ) + } else { + fluidRow( + column( + width = 5, + h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + div( + class = "sel-clade-scale", + selectInput( + "nj_clade_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + ) + ) + } + }) + + output$upgma_clade_scale <- renderUI({ + if(length(input$upgma_parentnode) <= 1) { + fluidRow( + column( + width = 5, + h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "upgma_clade_scale", + selected = "#D0F221", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ) + ) + } else { + fluidRow( + column( + width = 5, + h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + div( + class = "sel-clade-scale", + selectInput( + "upgma_clade_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + ) + ) + } + }) + + # Heatmap variable color scale + output$nj_heatmap_scale <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_heatmap_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_heatmap_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_heatmap_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Paired" + ) + ) + } + } + }) + + output$upgma_heatmap_scale <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_heatmap_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_heatmap_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_heatmap_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Paired" + ) + ) + } + } + }) + + # Tiles variable color scale + output$nj_tiles_scale_1 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_1", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_1", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_1", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_1 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_1", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_1", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_1", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_2 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_2", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_2", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_2", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_2 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_2", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_2", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_2", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_3 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_3", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_3", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_3", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_3 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_3", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_3", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_3", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_4 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_4])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_4", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { + shinyjs::disabled(selectInput( + "nj_tiles_scale_4", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + )) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_4", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_4 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_4", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_4", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_4", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_5 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_5", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_5", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_5", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_5 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_5", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_5", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_5", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + # Tip Labels Variable Color Scale + output$nj_tiplab_scale <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiplab_scale", + "", + selectize = FALSE, + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiplab_scale", + "", + selectize = FALSE, + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiplab_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + } + } + }) + + output$upgma_tiplab_scale <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiplab_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiplab_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiplab_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + } + } + }) + + # Tippoint Scale + output$nj_tippoint_scale <- renderUI({ + if(!is.null(Vis$meta_nj)) { + if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + } + } else { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + }) + + output$upgma_tippoint_scale <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ), + selected = c("Viridis" = "viridis") + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + } + } else { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + }) + + # Clade Highlights + output$nj_parentnode <- renderUI({ + if(!is.null(Vis$nj_parentnodes)) { + pickerInput( + "nj_parentnode", + label = "", + choices = sort(unique(as.numeric(Vis$nj_parentnodes))), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } else { + pickerInput( + "nj_parentnode", + label = "", + choices = c(), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } + }) + + output$upgma_parentnode <- renderUI({ + if(!is.null(Vis$upgma_parentnodes)) { + pickerInput( + "upgma_parentnode", + label = "", + choices = sort(unique(as.numeric(Vis$upgma_parentnodes))), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } else { + pickerInput( + "upgma_parentnode", + label = "", + choices = c(), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } + }) + + # Branch label size + output$nj_branch_size <- renderUI( + numericInput( + "nj_branch_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 2, + max = 10, + step = 0.5, + value = Vis$branch_size_nj, + width = "80px" + ) + ) + + output$upgma_branch_size <- renderUI( + numericInput( + "upgma_branch_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 2, + max = 10, + step = 0.5, + value = Vis$branch_size_upgma, + width = "80px" + ) + ) + + # Tippanel size + output$nj_tiplab_padding <- renderUI( + if(!is.null(Vis$tiplab_padding_nj)) { + sliderInput( + inputId = "nj_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = Vis$tiplab_padding_nj, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "nj_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = 0.2, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + ) + + output$upgma_tiplab_padding <- renderUI( + if(!is.null(Vis$tiplab_padding_upgma)) { + sliderInput( + inputId = "upgma_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = Vis$tiplab_padding_upgma, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "upgma_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = 0.2, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + ) + + # Nodepoint size + output$nj_nodepoint_size <- renderUI( + if(!is.null(Vis$nodepointsize_nj)) { + sliderInput( + inputId = "nj_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = Vis$nodepointsize_nj, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "nj_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = 2.5, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } + ) + + output$upgma_nodepoint_size <- renderUI( + if(!is.null(Vis$nodepointsize_upgma)) { + sliderInput( + inputId = "upgma_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = Vis$nodepointsize_upgma, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "upgma_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = 2.5, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } + ) + + # Tippoint size + output$nj_tippoint_size <- renderUI( + if(!is.null(Vis$tippointsize_nj)) { + sliderInput( + inputId = "nj_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = Vis$tippointsize_nj, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "nj_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = 4, + width = "150px", + ticks = FALSE + ) + } + ) + + output$upgma_tippoint_size <- renderUI( + if(!is.null(Vis$tippointsize_upgma)) { + sliderInput( + inputId = "upgma_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = Vis$tippointsize_upgma, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "upgma_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = 4, + width = "150px", + ticks = FALSE + ) + } + ) + + # Tiplabel size + output$nj_tiplab_size <- renderUI( + if(!is.null(Vis$labelsize_nj)) { + numericInput( + "nj_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = Vis$labelsize_nj, + width = "80px" + ) + } else { + numericInput( + "nj_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = 4, + width = "80px" + ) + } + ) + + output$upgma_tiplab_size <- renderUI( + if(!is.null(Vis$labelsize_upgma)) { + numericInput( + "upgma_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = Vis$labelsize_upgma, + width = "80px" + ) + } else { + numericInput( + "upgma_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = 4, + width = "80px" + ) + } + ) + + # Rootedge length + output$nj_rootedge_length <- renderUI({ + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.02, 0) < 1) { + min <- 1 + } else { + min <- round(ceiling(Vis$nj_max_x) * 0.02, 0) + } + max <- round(ceiling(Vis$nj_max_x) * 0.2, 0) + sliderInput( + "nj_rootedge_length", + label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), + min = min, + max = max, + value = round(ceiling(Vis$nj_max_x) * 0.05, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_rootedge_length", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_rootedge_length <- renderUI({ + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.02, 0) < 1) { + min <- 1 + } else { + min <- round(ceiling(Vis$upgma_max_x) * 0.02, 0) + } + max <- round(ceiling(Vis$upgma_max_x) * 0.2, 0) + sliderInput( + "upgma_rootedge_length", + label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), + min = min, + max = max, + value = round(ceiling(Vis$upgma_max_x) * 0.05, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_rootedge_length", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + # Treescale + output$nj_treescale_width <- renderUI({ + if(!is.null(Vis$nj_max_x)) { + numericInput( + "nj_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = round(ceiling(Vis$nj_max_x) * 0.1, 0), + min = 1, + max = round(floor(Vis$nj_max_x) * 0.5, 0), + step = 1, + width = "80px" + ) + } else { + numericInput( + "nj_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = 2, + min = 1, + max = 10, + step = 1, + width = "80px" + ) + } + }) + + output$upgma_treescale_width <- renderUI({ + if(!is.null(Vis$upgma_max_x)) { + numericInput( + "upgma_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = round(ceiling(Vis$upgma_max_x) * 0.1, 0), + min = 1, + max = round(floor(Vis$upgma_max_x) * 0.5, 0), + step = 1, + width = "80px" + ) + } else { + numericInput( + "upgma_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = 2, + min = 1, + max = 10, + step = 1, + width = "80px" + ) + } + }) + + output$nj_treescale_x <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(ceiling(Vis$nj_min_x) < 1) { + floor <- 1 + } else { + floor <- ceiling(Vis$nj_min_x) + } + sliderInput( + "nj_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = floor, + max = round(floor(Vis$nj_max_x)), + value = round(ceiling(Vis$nj_max_x) * 0.2, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_treescale_x <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(ceiling(Vis$upgma_min_x) < 1) { + floor <- 1 + } else { + floor <- ceiling(Vis$upgma_min_x) + } + sliderInput( + "upgma_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = floor, + max = round(floor(Vis$upgma_max_x)), + value = round(ceiling(Vis$upgma_max_x) * 0.2, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_treescale_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + sliderInput( + "nj_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = sum(DB$data$Include), + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 10, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_treescale_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + sliderInput( + "upgma_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = sum(DB$data$Include), + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 10, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + ### Heatmap + # Heatmap picker + output$nj_heatmap_sel <- renderUI({ + if(!is.null(Vis$meta_nj)) { + meta <- select(Vis$meta_nj, -c(taxa, Index, `Assembly ID`, `Assembly Name`, + Scheme, `Typing Date`, Successes, Errors)) + + # Identify numeric columns + numeric_columns <- sapply(meta, is.numeric) + + numeric_column_names <- names(meta[numeric_columns]) + + non_numeric_column_names <- names(meta)[!numeric_columns] + + choices <- list() + + # Add Continuous list only if there are numeric columns + if (length(numeric_column_names) > 0) { + choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) + } + + # Add Diverging list + choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) + + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "nj_heatmap_select", + label = "", + width = "100%", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else {choices}, + options = list( + `dropdown-align-center` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + ) + } else { + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "nj_heatmap_select", + label = "", + width = "100%", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + multiple = TRUE + ) + ) + ) + } + }) + + output$upgma_heatmap_sel <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + meta <- select(Vis$meta_upgma, -c(taxa, Index, `Assembly ID`, `Assembly Name`, + Scheme, `Typing Date`, Successes, Errors)) + + # Identify numeric columns + numeric_columns <- sapply(meta, is.numeric) + + numeric_column_names <- names(meta[numeric_columns]) + + non_numeric_column_names <- names(meta)[!numeric_columns] + + choices <- list() + + # Add Continuous list only if there are numeric columns + if (length(numeric_column_names) > 0) { + choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) + } + + # Add Diverging list + choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) + + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "upgma_heatmap_select", + label = "", + width = "100%", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else {choices}, + options = list( + `dropdown-align-center` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + ) + } else { + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "upgma_heatmap_select", + label = "", + width = "100%", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + multiple = TRUE + ) + ) + ) + } + }) + + # Heatmap offset + output$nj_heatmap_offset <- renderUI({ + if(!is.null(Vis$nj_max_x)) { + sliderInput( + "nj_heatmap_offset", + label = "", + min = 0, + max = round(ceiling(Vis$nj_max_x)*1.5, 0), + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_heatmap_offset", + label = "", + min = 0, + max = 10, + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_heatmap_offset <- renderUI({ + if(!is.null(Vis$upgma_max_x)) { + sliderInput( + "upgma_heatmap_offset", + label = "", + min = 0, + max = round(ceiling(Vis$upgma_max_x)*1.5, 0), + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_heatmap_offset", + label = "", + min = 0, + max = 10, + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + ### Tiling + # Geom Fruit select Variable + output$nj_fruit_variable <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable2 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_2", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_2", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable3 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_3", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_3", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable4 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_4", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_4", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable5 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_5", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_5", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable2 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_2", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_2", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable3 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled(selectInput( + "upgma_fruit_variable_3", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + )) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_3", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable4 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_4", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_4", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable5 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_5", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_5", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + # Geom Fruit Width + output$nj_fruit_width <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width2 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_2", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width3 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_3", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width4 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_4", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width5 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_5", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width2 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_2", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width3 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_3", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width4 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_4", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width5 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_5", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + # For Layout change update tiles + observeEvent(input$nj_layout, { + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } + + updateSliderInput(session, "nj_fruit_width_circ", value = width) + updateSliderInput(session, "nj_fruit_width_circ_2", value = width) + updateSliderInput(session, "nj_fruit_width_circ_3", value = width) + updateSliderInput(session, "nj_fruit_width_circ_4", value = width) + updateSliderInput(session, "nj_fruit_width_circ_5", value = width) + } + }) + + observeEvent(input$upgma_layout, { + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } + + updateSliderInput(session, "upgma_fruit_width_circ", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_2", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_3", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_4", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_5", value = width) + } + }) + + # Tip color mapping + output$nj_tipcolor_mapping <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_tipcolor_mapping", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(City = "City"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tipcolor_mapping", + "", + choices = c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(City = "City") + ) + ) + } + }) + + output$upgma_tipcolor_mapping <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_tipcolor_mapping", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(City = "City"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tipcolor_mapping", + "", + choices = c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(City = "City") + ) + ) + } + }) + + # Tip shape Mapping + output$nj_tipshape_mapping <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_tipshape_mapping", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tipshape_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } + }) + + output$upgma_tipshape_mapping <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_tipshape_mapping", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tipshape_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } + }) + + # Branch label + output$nj_branch_label <- renderUI({ + if(!is.null(Vis$meta_nj)) { + selectInput( + "nj_branch_label", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + } else { + selectInput( + "nj_branch_label", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + } + }) + + output$upgma_branch_label <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + selectInput( + "upgma_branch_label", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + } else { + selectInput( + "upgma_branch_label", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + } + }) + + # Color mapping + output$nj_color_mapping <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_color_mapping", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(Country = "Country"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_color_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(Country = "Country"), + width = "100%" + ) + ) + } + }) + + output$upgma_color_mapping <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_color_mapping", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(Country = "Country"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_color_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(Country = "Country"), + width = "100%" + ) + ) + } + }) + + # Tip labels + output$nj_tiplab <- renderUI({ + if(!is.null(Vis$meta_nj)) { + selectInput( + "nj_tiplab", + label = "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } else { + selectInput( + "nj_tiplab", + label = "", + choices = c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } + }) + + output$upgma_tiplab <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + selectInput( + "upgma_tiplab", + label = "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } else { + selectInput( + "upgma_tiplab", + label = "", + choices = c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } + }) + + #### MST controls ---- + + # Clustering UI + output$mst_cluster <- renderUI({ + req(DB$schemeinfo) + numericInput( + inputId = "mst_cluster_threshold", + label = NULL, + value = as.numeric(DB$schemeinfo[7, 2]), + min = 1, + max = 99 + ) + }) + + # MST color mapping + output$mst_color_mapping <- renderUI({ + if(input$mst_color_var == FALSE) { + fluidRow( + column( + width = 7, + div( + class = "node_color", + colorPickr( + inputId = "mst_color_node", + width = "100%", + selected = "#B2FACA", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_node_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + numericInput( + "node_opacity", + label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), + value = 1, + step = 0.1, + min = 0, + max = 1, + width = "80px" + ) + ) + ) + ) + } else { + fluidRow( + column( + width = 9, + div( + class = "mst_col_sel", + selectInput( + "mst_col_var", + label = "", + choices = if(any(DB$cust_var[DB$cust_var$Variable[which(DB$cust_var$Variable %in% c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]))],]$Type != "categ")) { + selection <- c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]) + cust_vars <- DB$cust_var$Variable[which(DB$cust_var$Variable %in% selection)] + selection[-which(selection == cust_vars[DB$cust_var[cust_vars,]$Type != "categ"])] + } else {c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)])}, + width = "100%" + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "mst_col_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + selectInput( + "mst_col_scale", + label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), + choices = c("Viridis", "Rainbow"), + width = "150px" + ), + br(), br(), br(), br() + ) + ) + ) + } + }) + + observeEvent(input$mst_color_var, { + + if(input$mst_color_var == TRUE) { + updateSelectizeInput(session, inputId = "mst_node_shape", choices = c("Pie Nodes" = "custom")) + updateSelectizeInput(session, inputId = "mst_node_label", choices = c("Assembly Name")) + } else { + updateSelectizeInput(session, inputId = "mst_node_shape", + choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), + `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), + selected = c("Dot" = "dot")) + updateSelectizeInput(session, inputId = "mst_node_label", + choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], + selected = "Assembly Name") + } + }) + + # MST node labels + output$mst_node_label <- renderUI({ + selectInput( + "mst_node_label", + label = "", + choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], + selected = "Assembly Name", + width = "100%" + ) + }) + + ### Plot Reactives ---- + + #### MST ---- + + mst_tree <- reactive({ + data <- toVisNetworkData(Vis$ggraph_1) + data$nodes <- mutate(data$nodes, + label = label_mst(), + value = mst_node_scaling(), + opacity = node_opacity()) + + ctxRendererJS <- htmlwidgets::JS("({ctx, id, x, y, state: { selected, hover }, style, font, label, metadata}) => { + var pieData = JSON.parse(metadata); + var radius = style.size; + var centerX = x; + var centerY = y; + var total = pieData.reduce((sum, slice) => sum + slice.value, 0) + var startAngle = 0; + + const drawNode = () => { + // Set shadow properties + if (style.shadow) { + var shadowSize = style.shadowSize; + ctx.shadowColor = style.shadowColor; + ctx.shadowBlur = style.shadowSize; + ctx.shadowOffsetX = style.shadowX; + ctx.shadowOffsetY = style.shadowY; + + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); + ctx.fill(); + + ctx.shadowColor = 'transparent'; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; + } + + pieData.forEach(slice => { + var sliceAngle = 2 * Math.PI * (slice.value / total); + ctx.beginPath(); + ctx.moveTo(centerX, centerY); + ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle); + ctx.closePath(); + ctx.fillStyle = slice.color; + ctx.fill(); + if (pieData.length > 1) { + ctx.strokeStyle = 'black'; + ctx.lineWidth = 1; + ctx.stroke(); + } + startAngle += sliceAngle; + }); + + // Draw a border + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); + ctx.strokeStyle = 'black'; + ctx.lineWidth = 1; + ctx.stroke(); + }; + drawLabel = () => { + //Draw the label + var lines = label.split(`\n`); + var lineHeight = font.size; + ctx.font = `${font.size}px ${font.face}`; + ctx.fillStyle = font.color; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + lines.forEach((line, index) => { + ctx.fillText(line, centerX, + centerY + radius + (index + 1) * lineHeight); + }) + } + + return { + drawNode, + drawExternalLabel: drawLabel, + nodeDimensions: { width: 2 * radius, height: 2 * radius }, + }; + }") + + Vis$var_cols <- NULL + + # Generate pie charts as nodes + if(input$mst_color_var == TRUE & (!is.null(input$mst_col_var))) { + + group <- character(nrow(data$nodes)) + for (i in 1:length(unique(Vis$meta_mst[[input$mst_col_var]]))) { + group[i] <- unique(Vis$meta_mst[[input$mst_col_var]])[i] + } + + data$nodes <- cbind(data$nodes, data.frame(metadata = character(nrow(data$nodes)))) + + if(length(which(data$nodes$group == "")) != 0) { + data$nodes$group[which(data$nodes$group == "")] <- data$nodes$group[1] + } + + if(is.null(input$mst_col_scale)) { + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) + } else if (input$mst_col_scale == "Rainbow") { + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + color = rainbow(length(unique(Vis$meta_mst[[input$mst_col_var]])))) + } else if (input$mst_col_scale == "Viridis") { + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) + } + + for(i in 1:nrow(data$nodes)) { + + iso_subset <- strsplit(data$nodes$label[i], split = "\n")[[1]] + variable <- Vis$meta_mst[[input$mst_col_var]] + values <- variable[which(Vis$meta_mst$`Assembly Name` %in% iso_subset)] + + for(j in 1:length(unique(values))) { + + share <- sum(unique(values)[j] == values) / length(values) * 100 + color <- Vis$var_cols$color[Vis$var_cols$value == unique(values)[j]] + + if(j == 1) { + pie_vec <- paste0('{"value":', share,',"color":"', color,'"}') + } else { + pie_vec <- paste0(pie_vec, ',{"value":', share,',"color":"', color,'"}') + } + } + + data$nodes$metadata[i] <- paste0('[', pie_vec, ']') + } + } + + data$edges <- mutate(data$edges, + length = if(input$mst_scale_edges == FALSE) { + input$mst_edge_length + } else { + data$edges$weight * input$mst_edge_length_scale + }, + label = as.character(data$edges$weight), + opacity = input$mst_edge_opacity) + + if (input$mst_show_clusters) { + clusters <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + if (input$mst_cluster_type == "Type 1") { + data$nodes$group <- clusters$group + } + } + + visNetwork_graph <- visNetwork(data$nodes, data$edges, + main = mst_title(), + background = mst_background_color(), + submain = mst_subtitle()) %>% + visNodes(size = mst_node_size(), + shape = input$mst_node_shape, + shadow = input$mst_shadow, + color = mst_color_node(), + ctxRenderer = ctxRendererJS, + scaling = list(min = mst_node_size_min(), + max = mst_node_size_max()), + font = list(color = node_font_color(), + size = input$node_label_fontsize)) %>% + visEdges(color = mst_color_edge(), + font = list(color = mst_edge_font_color(), + size = mst_edge_font_size(), + strokeWidth = 4)) %>% + visOptions(collapse = TRUE) %>% + visInteraction(hover = TRUE) %>% + visLayout(randomSeed = 1) %>% + visLegend(useGroups = FALSE, + zoom = TRUE, + width = legend_width(), + position = input$mst_legend_ori, + ncol = legend_col(), + addNodes = mst_legend()) + + if (input$mst_show_clusters) { + if (input$mst_cluster_col_scale == "Viridis") { + color_palette <- viridis(length(unique(data$nodes$group))) + } else { + color_palette <- rainbow(length(unique(data$nodes$group))) + } + + if (input$mst_cluster_type == "Type 1") { + for (i in 1:length(unique(data$nodes$group))) { + visNetwork_graph <- visNetwork_graph %>% + visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) + } + } else { + thin_edges <- data$edges + thin_edges$width <- 1 + thin_edges$color <- "black" + + thick_edges <- data$edges + thick_edges$width <- 24 + + thick_edges$color <- rep("rgba(0, 0, 0, 0)", length(data$edges$from)) + color_palette <- rainbow(length(unique(clusters$edges))) + for (i in 1:length(unique(clusters$edges))) { + print(clusters$edges) + if (unique(clusters$edges)[i] != "0") { + edge_color <- paste(col2rgb(color_palette[i]), collapse=", ") + thick_edges$color[clusters$edges == unique(clusters$edges)[i]] <- paste0("rgba(", edge_color, ", 0.5)") + } + } + merged_edges <- rbind(thick_edges, thin_edges) + data$edges <- merged_edges + visNetwork_graph <- visNetwork(data$nodes, data$edges, + main = mst_title(), + background = mst_background_color(), + submain = mst_subtitle()) %>% + visNodes(size = mst_node_size(), + shape = input$mst_node_shape, + shadow = input$mst_shadow, + color = mst_color_node(), + ctxRenderer = ctxRendererJS, + scaling = list(min = mst_node_size_min(), + max = mst_node_size_max()), + font = list(color = node_font_color(), + size = input$node_label_fontsize)) %>% + visEdges(color = mst_color_edge(), + font = list(color = mst_edge_font_color(), + size = mst_edge_font_size(), + strokeWidth = 4), + smooth = FALSE, + physics = FALSE) %>% + visOptions(collapse = TRUE) %>% + visInteraction(hover = TRUE) %>% + visLayout(randomSeed = 1) %>% + visLegend(useGroups = FALSE, + zoom = TRUE, + width = legend_width(), + position = input$mst_legend_ori, + ncol = legend_col(), + addNodes = mst_legend()) + } + } + visNetwork_graph + }) + + # MST legend + legend_col <- reactive({ + if(!is.null(Vis$var_cols)) { + if(nrow(Vis$var_cols) > 10) { + 3 + } else if(nrow(Vis$var_cols) > 5) { + 2 + } else { + 1 + } + } else {1} + }) + + mst_legend <- reactive({ + if(is.null(Vis$var_cols)) { + NULL + } else { + legend <- Vis$var_cols + names(legend)[1] <- "label" + mutate(legend, shape = "dot", + font.color = input$mst_legend_color, + size = input$mst_symbol_size, + font.size = input$mst_font_size) + } + }) + + # Set MST legend width + legend_width <- reactive({ + 0.2 + }) + + # Set MST node shape + mst_node_shape <- reactive({ + if(input$mst_node_shape == "Pie Nodes"){ + "dot" + } else if(input$mst_node_shape %in% c("circle", "database", "box", "text")) { + shinyjs::disable('scale_nodes') + updateCheckboxInput(session, "scale_nodes", value = FALSE) + shinyjs::disable('mst_node_size') + shinyjs::disable('mst_node_scale') + input$mst_node_shape + } else { + shinyjs::enable('scale_nodes') + shinyjs::enable('mst_node_size') + shinyjs::enable('mst_node_scale') + input$mst_node_shape + } + }) + + # Set MST label + label_mst <- reactive({ + Vis$unique_meta[, colnames(Vis$unique_meta) %in% input$mst_node_label] + }) + + # Set node color + mst_color_node <- reactive({ + input$mst_color_node + }) + + # Node Label Color + node_font_color <- reactive({ + input$node_font_color + }) + + + # Node Size Scaling + mst_node_scaling <- reactive({ + if(input$scale_nodes == TRUE){ + Vis$unique_meta$size + } else {NULL} + }) + + # Node Size Min/May + mst_node_size_min <- reactive({ + input$mst_node_scale[1] + }) + + mst_node_size_max <- reactive({ + input$mst_node_scale[2] + }) + + # Node Size + mst_node_size <- reactive({ + input$mst_node_size + }) + + # Node Alpha/Opacity + node_opacity <- reactive({ + input$node_opacity + }) + + # Set Title + mst_title <- reactive({ + if(!is.null(input$mst_title)) { + if(nchar(input$mst_title) < 1) { + list(text = "title", + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_title_size), "px", + "; color: ", as.character(mst_background_color())) + ) + } else { + list(text = input$mst_title, + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_title_size), "px", + "; color: ", as.character(input$mst_title_color)) + ) + } + } else { + list(text = "title", + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_title_size), "px", + "; color: ", as.character(mst_background_color())) + ) + } + }) + + # Set Subtitle + mst_subtitle <- reactive({ + list(text = input$mst_subtitle, + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_subtitle_size), "px", + "; color: ", as.character(input$mst_subtitle_color)) + ) + }) + + # Background color + + mst_background_color <- reactive({ + if(input$mst_background_transparent == TRUE) { + 'rgba(0, 0, 0, 0)' + } else{ + input$mst_background_color + } + }) + + # Edge font color + mst_edge_font_color <- reactive({ + input$mst_edge_font_color + }) + + # Edge color + mst_color_edge <- reactive({ + input$mst_color_edge + }) + + # Edge font size + mst_edge_font_size <- reactive({ + input$mst_edge_font_size + }) + + #### NJ ---- + + nj_tree <- reactive({ + + # Convert negative edges + Vis$nj[["edge.length"]] <- abs(Vis$nj[["edge.length"]]) + + if(input$nj_nodelabel_show == TRUE) { + ggtree(Vis$nj, alpha = 0.2, layout = layout_nj()) + + geom_nodelab(aes(label = node), color = "#29303A", size = nj_tiplab_size() + 1, hjust = 0.7) + + nj_limit() + + nj_inward() + } else { + tree <- + ggtree(Vis$nj, + color = input$nj_color, + layout = layout_nj(), + ladderize = input$nj_ladder) %<+% Vis$meta_nj + + nj_clades() + + nj_tiplab() + + nj_tiplab_scale() + + new_scale_color() + + nj_limit() + + nj_inward() + + nj_label_branch() + + nj_treescale() + + nj_nodepoint() + + nj_tippoint() + + nj_tippoint_scale() + + new_scale_color() + + nj_clip_label() + + nj_rootedge() + + ggtitle(label = input$nj_title, + subtitle = input$nj_subtitle) + + theme_tree(bgcolor = input$nj_bg) + + theme(plot.title = element_text(colour = input$nj_title_color, + size = input$nj_title_size), + plot.subtitle = element_text(colour = input$nj_title_color, + size = input$nj_subtitle_size), + legend.background = element_rect(fill = input$nj_bg), + legend.direction = input$nj_legend_orientation, + legend.title = element_text(color = input$nj_color, + size = input$nj_legend_size*1.2), + legend.title.align = 0.5, + legend.position = nj_legend_pos(), + legend.text = element_text(color = input$nj_color, + size = input$nj_legend_size), + legend.key = element_rect(fill = input$nj_bg), + legend.box.spacing = unit(1.5, "cm"), + legend.key.size = unit(0.05*input$nj_legend_size, 'cm'), + plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) + + new_scale_fill() + + nj_fruit() + + nj_gradient() + + new_scale_fill() + + nj_fruit2() + + nj_gradient2() + + new_scale_fill() + + nj_fruit3() + + nj_gradient3() + + new_scale_fill() + + nj_fruit4() + + nj_gradient4() + + new_scale_fill() + + nj_fruit5() + + nj_gradient5() + + new_scale_fill() + + # Add custom labels + if(length(Vis$custom_label_nj) > 0) { + + for(i in Vis$custom_label_nj[,1]) { + + if(!is.null(Vis$nj_label_pos_x[[i]])) { + x_pos <- Vis$nj_label_pos_x[[i]] + } else { + x_pos <- round(Vis$nj_max_x / 2, 0) + } + + if(!is.null(Vis$nj_label_pos_y[[i]])) { + y_pos <- Vis$nj_label_pos_y[[i]] + } else { + y_pos <- sum(DB$data$Include) / 2 + } + + if(!is.null(Vis$nj_label_size[[i]])) { + size <- Vis$nj_label_size[[i]] + } else { + size <- 5 + } + + tree <- tree + annotate("text", + x = x_pos, + y = y_pos, + label = i, + size = size) + } + } + + # Add heatmap + if(input$nj_heatmap_show == TRUE & length(input$nj_heatmap_select) > 0) { + if (!(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)))) { + tree <- gheatmap.mod(tree, + data = select(Vis$meta_nj, input$nj_heatmap_select), + offset = nj_heatmap_offset(), + width = nj_heatmap_width(), + legend_title = input$nj_heatmap_title, + colnames_angle = -nj_colnames_angle(), + colnames_offset_y = nj_colnames_y(), + colnames_color = input$nj_color) + + nj_heatmap_scale() + } + } + + # Sizing control + Vis$nj_plot <- ggplotify::as.ggplot(tree, + scale = input$nj_zoom, + hjust = input$nj_h, + vjust = input$nj_v) + + Vis$nj_true <- TRUE + + # Correct background color if zoomed out + cowplot::ggdraw(Vis$nj_plot) + + theme(plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) + } + }) + + # Heatmap width + nj_heatmap_width <- reactive({ + if(!is.null(input$nj_heatmap_width)) { + input$nj_heatmap_width + } else { + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + 1.5 + } + } + } else { + if(length_input < 3) { + 0.3 + } else if (length_input >= 3 && length_input <= 27) { + min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + 3 + } + } + } + }) + + # Heatmap column titles position + nj_colnames_y <- reactive({ + if(!is.null(input$nj_colnames_y)) { + input$nj_colnames_y + } else { + if(input$nj_layout == "inward" | input$nj_layout == "circular") { + 0 + } else {-1} + } + }) + + # Heatmap column titles angle + nj_colnames_angle <- reactive({ + if(!is.null(input$nj_colnames_angle)) { + input$nj_colnames_angle + } else { + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "inward" | input$nj_layout == "circular") { + 90 + } else {-90} + } else {-90} + } + }) + + # Heatmap scale + nj_heatmap_scale <- reactive({ + if(!is.null(input$nj_heatmap_scale) & !is.null(input$nj_heatmap_div_mid)) { + if(input$nj_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_heatmap_div_mid == "Zero") { + midpoint <- 0 + } else if(input$nj_heatmap_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$nj_heatmap_scale)[1], + mid = brewer.pal(3, input$nj_heatmap_scale)[2], + high = brewer.pal(3, input$nj_heatmap_scale)[3], + midpoint = midpoint, + name = input$nj_heatmap_title) + } else { + if(input$nj_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { + if(input$nj_heatmap_scale == "magma") { + scale_fill_viridis(option = "A", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "inferno") { + scale_fill_viridis(option = "B", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "plasma") { + scale_fill_viridis(option = "C", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "viridis") { + scale_fill_viridis(option = "D", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "cividis") { + scale_fill_viridis(option = "E", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "rocket") { + scale_fill_viridis(option = "F", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "mako") { + scale_fill_viridis(option = "G", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "turbo") { + scale_fill_viridis(option = "H", + name = input$nj_heatmap_title) + } + } else { + if(input$nj_heatmap_scale == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H", + name = input$nj_heatmap_title) + } + } + } else { + scale_fill_brewer(palette = input$nj_heatmap_scale, + name = input$nj_heatmap_title) + } + } + } + }) + + # Tippoint Scale + nj_tippoint_scale <- reactive({ + if(!is.null(input$nj_tippoint_scale) & !is.null(input$nj_tipcolor_mapping_div_mid)) { + if(input$nj_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tipcolor_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$nj_tipcolor_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$nj_tippoint_scale)[1], + mid = brewer.pal(3, input$nj_tippoint_scale)[2], + high = brewer.pal(3, input$nj_tippoint_scale)[3], + midpoint = midpoint) + } else { + if(input$nj_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { + if(input$nj_tippoint_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$nj_tippoint_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$nj_tippoint_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$nj_tippoint_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$nj_tippoint_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$nj_tippoint_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$nj_tippoint_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$nj_tippoint_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$nj_tippoint_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tippoint_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tippoint_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tippoint_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tippoint_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tippoint_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tippoint_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tippoint_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$nj_tippoint_scale) + } + } + } + }) + + # Tiplab Scale + nj_tiplab_scale <- reactive({ + if(!is.null(input$nj_tiplab_scale) & !is.null(input$nj_color_mapping_div_mid)) { + if(input$nj_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_color_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$nj_color_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$nj_tiplab_scale)[1], + mid = brewer.pal(3, input$nj_tiplab_scale)[2], + high = brewer.pal(3, input$nj_tiplab_scale)[3], + midpoint = midpoint) + } else { + if(input$nj_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { + if(input$nj_tiplab_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$nj_tiplab_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$nj_tiplab_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$nj_tiplab_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$nj_tiplab_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$nj_tiplab_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$nj_tiplab_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$nj_tiplab_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$nj_tiplab_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiplab_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiplab_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiplab_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiplab_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiplab_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiplab_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiplab_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$nj_tiplab_scale) + } + } + } + }) + + # Clade Highlight + nj_clades <- reactive({ + if(!is.null(input$nj_parentnode)) { + if(!length(input$nj_parentnode) == 0) { + if(length(input$nj_parentnode) == 1) { + fill <- input$nj_clade_scale + } else if (length(input$nj_parentnode) == 2) { + if(startsWith(input$nj_clade_scale, "#")) { + fill <- brewer.pal(3, "Set1")[1:2] + } else { + fill <- brewer.pal(3, input$nj_clade_scale)[1:2] + } + } else { + fill <- brewer.pal(length(input$nj_parentnode), input$nj_clade_scale) + } + geom_hilight(node = as.numeric(input$nj_parentnode), + fill = fill, + type = input$nj_clade_type, + to.bottom = TRUE + ) + } else {NULL} + } + }) + + # Legend Position + nj_legend_pos <- reactive({ + if(!is.null(input$nj_legend_x) & !is.null(input$nj_legend_y)) { + c(input$nj_legend_x, input$nj_legend_y) + } else { + c(0.1, 1) + } + }) + + # Heatmap offset + nj_heatmap_offset <- reactive({ + if(is.null(input$nj_heatmap_offset)) { + 0 + } else {input$nj_heatmap_offset} + }) + + # Tiles fill color gradient + nj_gradient <- reactive({ + if(!is.null(input$nj_tiles_show_1) & + !is.null(input$nj_fruit_variable) & + !is.null(input$nj_tiles_scale_1) & + !is.null(input$nj_tiles_mapping_div_mid_1)) { + if(input$nj_tiles_show_1 == TRUE) { + if(input$nj_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_1 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_1 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_1)[1], + mid = brewer.pal(3, input$nj_tiles_scale_1)[2], + high = brewer.pal(3, input$nj_tiles_scale_1)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { + if(input$nj_tiles_scale_1 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_1 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_1 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_1 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_1 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_1 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_1 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_1 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_1 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_1 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_1 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_1 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_1 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_1 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_1 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_1 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_1) + } + } + } else {NULL} + } + }) + + nj_gradient2 <- reactive({ + if(!is.null(input$nj_tiles_show_2) & + !is.null(input$nj_fruit_variable_2) & + !is.null(input$nj_tiles_scale_2) & + !is.null(input$nj_tiles_mapping_div_mid_2)) { + if(input$nj_tiles_show_2 == TRUE) { + if(input$nj_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_2 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_2 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_2)[1], + mid = brewer.pal(3, input$nj_tiles_scale_2)[2], + high = brewer.pal(3, input$nj_tiles_scale_2)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { + if(input$nj_tiles_scale_2 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_2 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_2 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_2 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_2 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_2 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_2 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_2 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_2 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_2 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_2 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_2 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_2 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_2 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_2 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_2 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_2) + } + } + } else {NULL} + } + }) + + nj_gradient3 <- reactive({ + if(!is.null(input$nj_tiles_show_3) & + !is.null(input$nj_fruit_variable_3) & + !is.null(input$nj_tiles_scale_3 & + !is.null(input$nj_tiles_mapping_div_mid_3))) { + if(input$nj_tiles_show_3 == TRUE) { + if(input$nj_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_3 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_3 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) + } + scale_fill_gradient3(low = brewer.pal(3, input$nj_tiles_scale_3)[1], + mid = brewer.pal(3, input$nj_tiles_scale_3)[2], + high = brewer.pal(3, input$nj_tiles_scale_3)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { + if(input$nj_tiles_scale_3 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_3 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_3 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_3 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_3 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_3 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_3 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_3 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_3 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_3 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_3 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_3 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_3 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_3 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_3 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_3 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_3) + } + } + } else {NULL} + } + }) + + nj_gradient4 <- reactive({ + if(!is.null(input$nj_tiles_show_4) & + !is.null(input$nj_fruit_variable_4) & + !is.null(input$nj_tiles_scale_4) & + !is.null(input$nj_tiles_mapping_div_mid_4)) { + if(input$nj_tiles_show_4 == TRUE) { + if(input$nj_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_4 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_4 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) + } + scale_fill_gradient4(low = brewer.pal(3, input$nj_tiles_scale_4)[1], + mid = brewer.pal(3, input$nj_tiles_scale_4)[2], + high = brewer.pal(3, input$nj_tiles_scale_4)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { + if(input$nj_tiles_scale_4 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_4 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_4 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_4 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_4 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_4 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_4 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_4 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_4 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_4 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_4 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_4 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_4 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_4 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_4 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_4 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_4) + } + } + } else {NULL} + } + }) + + nj_gradient5 <- reactive({ + if(!is.null(input$nj_tiles_show_5) & + !is.null(input$nj_fruit_variable_5) & + !is.null(input$nj_tiles_scale_5) & + !is.null(input$nj_tiles_mapping_div_mid_5)) { + if(input$nj_tiles_show_5 == TRUE) { + if(input$nj_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_5 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_5 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) + } + scale_fill_gradient5(low = brewer.pal(3, input$nj_tiles_scale_5)[1], + mid = brewer.pal(3, input$nj_tiles_scale_5)[2], + high = brewer.pal(3, input$nj_tiles_scale_5)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { + if(input$nj_tiles_scale_5 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_5 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_5 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_5 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_5 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_5 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_5 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_5 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_5 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_5 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_5 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_5 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_5 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_5 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_5 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_5 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_5) + } + } + } else {NULL} + } + }) + + # No label clip off for linear NJ tree + nj_clip_label <- reactive({ + if(!(input$nj_layout == "circular" | input$nj_layout == "inward")) { + coord_cartesian(clip = "off") + } else {NULL} + }) + + # Geom Fruit + nj_fruit <- reactive({ + if((!is.null(input$nj_tiles_show_1)) & + (!is.null(input$nj_fruit_variable)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ)) & + (!is.null(input$nj_fruit_width_circ)) & + (!is.null(input$nj_fruit_alpha))) { + if(input$nj_tiles_show_1 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = input$nj_fruit_offset_circ, + width = input$nj_fruit_width_circ, + alpha = input$nj_fruit_alpha + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = input$nj_fruit_offset_circ, + width = input$nj_fruit_width_circ, + alpha = input$nj_fruit_alpha + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_1 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = 0, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = 0, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Geom Fruit + nj_fruit2 <- reactive({ + if((!is.null(input$nj_tiles_show_2)) & + (!is.null(input$nj_fruit_variable_2)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_2)) & + (!is.null(input$nj_fruit_width_circ_2)) & + (!is.null(input$nj_fruit_alpha_2))) { + if(input$nj_tiles_show_2 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), + offset = input$nj_fruit_offset_circ_2, + width = input$nj_fruit_width_circ_2, + alpha = input$nj_fruit_alpha_2 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), + offset = input$nj_fruit_offset_circ_2, + width = input$nj_fruit_width_circ_2, + alpha = input$nj_fruit_alpha_2 + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_2 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + nj_fruit3 <- reactive({ + if((!is.null(input$nj_tiles_show_3)) & + (!is.null(input$nj_fruit_variable_3)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_3)) & + (!is.null(input$nj_fruit_width_circ_3)) & + (!is.null(input$nj_fruit_alpha_3))) { + if(input$nj_tiles_show_3 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), + offset = input$nj_fruit_offset_circ_3, + width = input$nj_fruit_width_circ_3, + alpha = input$nj_fruit_alpha_3 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), + offset = input$nj_fruit_offset_circ_3, + width = input$nj_fruit_width_circ_3, + alpha = input$nj_fruit_alpha_3 + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_3 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + nj_fruit4 <- reactive({ + if((!is.null(input$nj_tiles_show_4)) & + (!is.null(input$nj_fruit_variable_4)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_4)) & + (!is.null(input$nj_fruit_width_circ_4)) & + (!is.null(input$nj_fruit_alpha_4))) { + if(input$nj_tiles_show_4 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), + offset = input$nj_fruit_offset_circ_4, + width = input$nj_fruit_width_circ_4, + alpha = input$nj_fruit_alpha_4 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), + offset = input$nj_fruit_offset_circ_4, + width = input$nj_fruit_width_circ_4, + alpha = input$nj_fruit_alpha_4 + ) + } + } else { + if(input$nj_tiles_show_4 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + } + }) + + nj_fruit5 <- reactive({ + if((!is.null(input$nj_tiles_show_5)) & + (!is.null(input$nj_fruit_variable_5)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_5)) & + (!is.null(input$nj_fruit_width_circ_5)) & + (!is.null(input$nj_fruit_alpha_5))) { + if(input$nj_tiles_show_5 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), + offset = input$nj_fruit_offset_circ_5, + width = input$nj_fruit_width_circ_5, + alpha = input$nj_fruit_alpha_5 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), + offset = input$nj_fruit_offset_circ_5, + width = input$nj_fruit_width_circ_5, + alpha = input$nj_fruit_alpha_5 + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_5 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Xlim + nj_limit <- reactive({ + if(input$nj_layout == "circular") { + xlim(input$nj_xlim, NA) + } else {NULL} + }) + + # Treescale + nj_treescale <- reactive({ + if(!input$nj_layout == "circular") { + if(input$nj_treescale_show == TRUE) { + geom_treescale(x = nj_treescale_x(), + y = nj_treescale_y(), + width = nj_treescale_width(), + color = input$nj_color, + fontsize = 4) + } else {NULL} + } else {NULL} + }) + + # Treescale Y Position + nj_treescale_y <- reactive({ + if(is.null(input$nj_treescale_y)) { + 0 + } else {input$nj_treescale_y} + }) + + # Treescale X Position + nj_treescale_x <- reactive({ + if(is.null(input$nj_treescale_x)) { + round(ceiling(Vis$nj_max_x) * 0.2, 0) + } else {input$nj_treescale_x} + }) + + # Treescale width + nj_treescale_width <- reactive({ + if(!is.null(input$nj_treescale_width)) { + input$nj_treescale_width + } else { + round(ceiling(Vis$nj_max_x) * 0.1, 0) + } + }) + + # Label branches + nj_label_branch <- reactive({ + if(!input$nj_layout == "circular" | !input$nj_layout == "inward") { + if(input$nj_show_branch_label == TRUE) { + geom_label( + aes( + x=!!sym("branch"), + label= !!sym(input$nj_branch_label)), + fill = input$nj_branch_label_color, + size = nj_branch_size(), + label.r = unit(input$nj_branch_labelradius, "lines"), + nudge_x = input$nj_branch_x, + nudge_y = input$nj_branch_y, + fontface = input$nj_branchlab_fontface, + alpha = input$nj_branchlab_alpha + ) + } else {NULL} + } else {NULL} + }) + + # Branch label size + nj_branch_size <- reactive({ + if(!is.null(input$nj_branch_size)) { + input$nj_branch_size + } else { + Vis$branch_size_nj + } + }) + + # Rootedge + nj_rootedge <- reactive({ + if(input$nj_rootedge_show == TRUE) { + if(is.null(input$nj_rootedge_length)) { + geom_rootedge(rootedge = round(ceiling(Vis$nj_max_x) * 0.05, 0), + linetype = input$nj_rootedge_line) + } else { + geom_rootedge(rootedge = input$nj_rootedge_length, + linetype = input$nj_rootedge_line) + } + } else {NULL} + }) + + # Tippoints + nj_tippoint <- reactive({ + if(input$nj_tippoint_show == TRUE | input$nj_tipcolor_mapping_show == TRUE | input$nj_tipshape_mapping_show == TRUE) { + if(input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == FALSE) { + geom_tippoint( + aes(color = !!sym(input$nj_tipcolor_mapping)), + alpha = input$nj_tippoint_alpha, + shape = input$nj_tippoint_shape, + size = nj_tippoint_size() + ) + } else if (input$nj_tipcolor_mapping_show == FALSE & input$nj_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$nj_tipshape_mapping)), + alpha = input$nj_tippoint_alpha, + color = input$nj_tippoint_color, + size = nj_tippoint_size() + ) + } else if (input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$nj_tipshape_mapping), + color = !!sym(input$nj_tipcolor_mapping)), + alpha = input$nj_tippoint_alpha, + size = nj_tippoint_size() + ) + } else { + geom_tippoint( + alpha = input$nj_tippoint_alpha, + colour = input$nj_tippoint_color, + fill = input$nj_tippoint_color, + shape = input$nj_tippoint_shape, + size = nj_tippoint_size() + ) + } + } else {NULL} + }) + + # Nodepoints + nj_nodepoint <- reactive({ + if(input$nj_nodepoint_show == TRUE) { + geom_nodepoint( + alpha = input$nj_nodepoint_alpha, + color = input$nj_nodepoint_color, + shape = input$nj_nodepoint_shape, + size = nj_nodepoint_size() + ) + } else {NULL} + }) + + # Nodepoint size + nj_nodepoint_size <- reactive({ + if(!is.null(input$nj_nodepoint_size)) { + input$nj_nodepoint_size + } else { + Vis$nodepointsize_nj + } + }) + + # NJ circular or not + nj_tiplab <- reactive({ + if(input$nj_tiplab_show == TRUE) { + if(input$nj_layout == "circular") { + if(input$nj_mapping_show == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position), + check.overlap = input$nj_tiplab_overlap + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + color = input$nj_tiplab_color, + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position), + check.overlap = input$nj_tiplab_overlap + ) + } + } else if (input$nj_layout == "inward") { + if(input$nj_mapping_show == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position_inw), + check.overlap = input$nj_tiplab_overlap + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + color = input$nj_tiplab_color, + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position_inw), + check.overlap = input$nj_tiplab_overlap + ) + } + } else { + if(input$nj_mapping_show == TRUE) { + if(input$nj_geom == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap, + label.padding = unit(nj_tiplab_padding(), "lines"), + label.r = unit(input$nj_tiplab_labelradius, "lines"), + fill = input$nj_tiplab_fill + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap + ) + } + } else { + if(input$nj_geom == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + color = input$nj_tiplab_color, + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap, + label.padding = unit(nj_tiplab_padding(), "lines"), + label.r = unit(input$nj_tiplab_labelradius, "lines"), + fill = input$nj_tiplab_fill + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + color = input$nj_tiplab_color, + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap + ) + } + } + } + } else {NULL} + }) + + # Tip panel size + nj_tiplab_padding <- reactive({ + if(!is.null(input$nj_tiplab_padding)) { + input$nj_tiplab_padding + } else { + Vis$tiplab_padding_nj + } + }) + + # Tiplab size + nj_tiplab_size <- reactive({ + if(!is.null(input$nj_tiplab_size)) { + input$nj_tiplab_size + } else { + Vis$labelsize_nj + } + }) + + # Tippoint size + nj_tippoint_size <- reactive({ + if(!is.null(input$nj_tippoint_size)) { + input$nj_tippoint_size + } else { + Vis$tippointsize_nj + } + }) + + # Show Label Panels? + nj_geom <- reactive({ + if(input$nj_geom == TRUE) { + "label" + } else {"text"} + }) + + # NJ Tiplab color + nj_mapping_tiplab <- reactive({ + if(input$nj_mapping_show == TRUE) { + if(!is.null(input$nj_tiplab)) { + aes(label = !!sym(input$nj_tiplab), + color = !!sym(input$nj_color_mapping)) + } else { + aes(label = !!sym("Assembly Name"), + color = !!sym(input$nj_color_mapping)) + } + } else { + if(!is.null(input$nj_tiplab)) { + aes(label = !!sym(input$nj_tiplab)) + } else { + aes(label = !!sym("Assembly Name")) + } + } + }) + + # NJ Tree Layout + layout_nj <- reactive({ + if(input$nj_layout == "inward") { + "circular" + } else {input$nj_layout} + }) + + # NJ inward circular + nj_inward <- reactive({ + if (input$nj_layout == "inward") { + layout_inward_circular(xlim = input$nj_inward_xlim) + } else { + NULL + } + }) + + #### UPGMA ---- + + upgma_tree <- reactive({ + if(input$upgma_nodelabel_show == TRUE) { + ggtree(Vis$upgma, alpha = 0.2, layout = layout_upgma()) + + geom_nodelab(aes(label = node), color = "#29303A", size = upgma_tiplab_size() + 1, hjust = 0.7) + + upgma_limit() + + upgma_inward() + } else { + tree <- + ggtree(Vis$upgma, + color = input$upgma_color, + layout = layout_upgma(), + ladderize = input$upgma_ladder) %<+% Vis$meta_upgma + + upgma_tiplab() + + upgma_tiplab_scale() + + new_scale_color() + + upgma_limit() + + upgma_inward() + + upgma_label_branch() + + upgma_treescale() + + upgma_nodepoint() + + upgma_tippoint() + + upgma_tippoint_scale() + + new_scale_color() + + upgma_clip_label() + + upgma_rootedge() + + upgma_clades() + + ggtitle(label = input$upgma_title, + subtitle = input$upgma_subtitle) + + theme_tree(bgcolor = input$upgma_bg) + + theme(plot.title = element_text(colour = input$upgma_title_color, + size = input$upgma_title_size), + plot.subtitle = element_text(colour = input$upgma_title_color, + size = input$upgma_subtitle_size), + legend.background = element_rect(fill = input$upgma_bg), + legend.direction = input$upgma_legend_orientation, + legend.title = element_text(color = input$upgma_color, + size = input$upgma_legend_size*1.2), + legend.title.align = 0.5, + legend.position = upgma_legend_pos(), + legend.text = element_text(color = input$upgma_color, + size = input$upgma_legend_size), + legend.key = element_rect(fill = input$upgma_bg), + legend.box.spacing = unit(1.5, "cm"), + legend.key.size = unit(0.05*input$upgma_legend_size, 'cm'), + plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) + + new_scale_fill() + + upgma_fruit() + + upgma_gradient() + + new_scale_fill() + + upgma_fruit2() + + upgma_gradient2() + + new_scale_fill() + + upgma_fruit3() + + upgma_gradient3() + + new_scale_fill() + + upgma_fruit4() + + upgma_gradient4() + + new_scale_fill() + + upgma_fruit5() + + upgma_gradient5() + + new_scale_fill() + + # Add custom labels + if(length(Vis$custom_label_upgma) > 0) { + + for(i in Vis$custom_label_upgma[,1]) { + + if(!is.null(Vis$upgma_label_pos_x[[i]])) { + x_pos <- Vis$upgma_label_pos_x[[i]] + } else { + x_pos <- round(Vis$upgma_max_x / 2, 0) + } + + if(!is.null(Vis$upgma_label_pos_y[[i]])) { + y_pos <- Vis$upgma_label_pos_y[[i]] + } else { + y_pos <- sum(DB$data$Include) / 2 + } + + if(!is.null(Vis$upgma_label_size[[i]])) { + size <- Vis$upgma_label_size[[i]] + } else { + size <- 5 + } + + tree <- tree + annotate("text", + x = x_pos, + y = y_pos, + label = i, + size = size) + } + } + + # Add heatmap + if(input$upgma_heatmap_show == TRUE & length(input$upgma_heatmap_select) > 0) { + if (!(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)))) { + tree <- gheatmap.mod(tree, + data = select(Vis$meta_upgma, input$upgma_heatmap_select), + offset = upgma_heatmap_offset(), + width = upgma_heatmap_width(), + legend_title = input$upgma_heatmap_title, + colnames_angle = -upgma_colnames_angle(), + colnames_offset_y = upgma_colnames_y(), + colnames_color = input$upgma_color) + + upgma_heatmap_scale() + } + } + + # Sizing control + Vis$upgma_plot <- ggplotify::as.ggplot(tree, + scale = input$upgma_zoom, + hjust = input$upgma_h, + vjust = input$upgma_v) + + # Correct background color if zoomed out + cowplot::ggdraw(Vis$upgma_plot) + + theme(plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) + } + }) + + # Heatmap width + upgma_heatmap_width <- reactive({ + if(!is.null(input$upgma_heatmap_width)) { + input$upgma_heatmap_width + } else { + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + 1.5 + } + } + } else { + if(length_input < 3) { + 0.3 + } else if (length_input >= 3 && length_input <= 27) { + min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + 3 + } + } + } + }) + + # Heatmap column titles position + upgma_colnames_y <- reactive({ + if(!is.null(input$upgma_colnames_y)) { + input$upgma_colnames_y + } else { + if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { + 0 + } else {-1} + } + }) + + # Heatmap column titles angle + upgma_colnames_angle <- reactive({ + if(!is.null(input$upgma_colnames_angle)) { + input$upgma_colnames_angle + } else { + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { + 90 + } else {-90} + } else {-90} + } + }) + + # Heatmap scale + upgma_heatmap_scale <- reactive({ + if(!is.null(input$upgma_heatmap_scale) & !is.null(input$upgma_heatmap_div_mid)) { + if(input$upgma_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_heatmap_div_mid == "Zero") { + midpoint <- 0 + } else if(input$upgma_heatmap_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$upgma_heatmap_scale)[1], + mid = brewer.pal(3, input$upgma_heatmap_scale)[2], + high = brewer.pal(3, input$upgma_heatmap_scale)[3], + midpoint = midpoint, + name = input$upgma_heatmap_title) + } else { + if(input$upgma_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { + if(input$upgma_heatmap_scale == "magma") { + scale_fill_viridis(option = "A", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "inferno") { + scale_fill_viridis(option = "B", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "plasma") { + scale_fill_viridis(option = "C", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "viridis") { + scale_fill_viridis(option = "D", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "cividis") { + scale_fill_viridis(option = "E", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "rocket") { + scale_fill_viridis(option = "F", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "mako") { + scale_fill_viridis(option = "G", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "turbo") { + scale_fill_viridis(option = "H", + name = input$upgma_heatmap_title) + } + } else { + if(input$upgma_heatmap_scale == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H", + name = input$upgma_heatmap_title) + } + } + } else { + scale_fill_brewer(palette = input$upgma_heatmap_scale, + name = input$upgma_heatmap_title) + } + } + } + }) + + # Tippoint Scale + upgma_tippoint_scale <- reactive({ + if(!is.null(input$upgma_tippoint_scale) & !is.null(input$upgma_tipcolor_mapping_div_mid)) { + if(input$upgma_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tipcolor_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$upgma_tipcolor_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$upgma_tippoint_scale)[1], + mid = brewer.pal(3, input$upgma_tippoint_scale)[2], + high = brewer.pal(3, input$upgma_tippoint_scale)[3], + midpoint = midpoint) + } else { + if(input$upgma_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { + if(input$upgma_tippoint_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$upgma_tippoint_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$upgma_tippoint_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$upgma_tippoint_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$upgma_tippoint_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$upgma_tippoint_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$upgma_tippoint_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$upgma_tippoint_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$upgma_tippoint_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tippoint_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tippoint_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tippoint_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tippoint_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tippoint_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tippoint_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tippoint_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$upgma_tippoint_scale) + } + } + } + }) + + # Tiplab Scale + upgma_tiplab_scale <- reactive({ + if(!is.null(input$upgma_tiplab_scale) & !is.null(input$upgma_color_mapping_div_mid)) { + if(input$upgma_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_color_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$upgma_color_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$upgma_tiplab_scale)[1], + mid = brewer.pal(3, input$upgma_tiplab_scale)[2], + high = brewer.pal(3, input$upgma_tiplab_scale)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { + if(input$upgma_tiplab_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$upgma_tiplab_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$upgma_tiplab_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$upgma_tiplab_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$upgma_tiplab_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$upgma_tiplab_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$upgma_tiplab_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$upgma_tiplab_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$upgma_tiplab_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiplab_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiplab_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiplab_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiplab_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiplab_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiplab_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiplab_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$upgma_tiplab_scale) + } + } + } + }) + + # Clade Highlight + upgma_clades <- reactive({ + if(!is.null(input$upgma_parentnode)) { + if(!length(input$upgma_parentnode) == 0) { + if(length(input$upgma_parentnode) == 1) { + fill <- input$upgma_clade_scale + } else if (length(input$upgma_parentnode) == 2) { + if(startsWith(input$upgma_clade_scale, "#")) { + fill <- brewer.pal(3, "Set1")[1:2] + } else { + fill <- brewer.pal(3, input$upgma_clade_scale)[1:2] + } + } else { + fill <- brewer.pal(length(input$upgma_parentnode), input$upgma_clade_scale) + } + geom_hilight(node = as.numeric(input$upgma_parentnode), + fill = fill, + type = input$upgma_clade_type, + to.bottom = TRUE) + } else {NULL} + } + }) + + # Legend Position + upgma_legend_pos <- reactive({ + if(!is.null(input$upgma_legend_x) & !is.null(input$upgma_legend_y)) { + c(input$upgma_legend_x, input$upgma_legend_y) + } else { + c(0.1, 1) + } + }) + + # Heatmap offset + upgma_heatmap_offset <- reactive({ + if(is.null(input$upgma_heatmap_offset)) { + 0 + } else {input$upgma_heatmap_offset} + }) + + # Tiles fill color gradient + upgma_gradient <- reactive({ + if(!is.null(input$upgma_tiles_show_1) & + !is.null(input$upgma_fruit_variable) & + !is.null(input$upgma_tiles_scale_1) & + !is.null(input$upgma_tiles_mapping_div_mid_1)) { + if(input$upgma_tiles_show_1 == TRUE) { + if(input$upgma_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_1 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_1 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_1)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_1)[2], + high = brewer.pal(3, input$upgma_tiles_scale_1)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { + if(input$upgma_tiles_scale_1 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_1 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_1 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_1 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_1 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_1 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_1 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_1 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_1 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_1 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_1 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_1 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_1 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_1 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_1 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_1 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_1) + } + } + } else {NULL} + } + }) + + upgma_gradient2 <- reactive({ + if(!is.null(input$upgma_tiles_show_2) & + !is.null(input$upgma_fruit_variable_2) & + !is.null(input$upgma_tiles_scale_2) & + !is.null(input$upgma_tiles_mapping_div_mid_2)) { + if(input$upgma_tiles_show_2 == TRUE) { + if(input$upgma_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_2 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_2 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_2)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_2)[2], + high = brewer.pal(3, input$upgma_tiles_scale_2)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { + if(input$upgma_tiles_scale_2 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_2 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_2 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_2 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_2 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_2 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_2 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_2 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_2 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_2 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_2 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_2 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_2 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_2 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_2 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_2 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_2) + } + } + } else {NULL} + } + }) + + upgma_gradient3 <- reactive({ + if(!is.null(input$upgma_tiles_show_3) & + !is.null(input$upgma_fruit_variable_3) & + !is.null(input$upgma_tiles_scale_3) & + !is.null(input$upgma_tiles_mapping_div_mid_3)) { + if(input$upgma_tiles_show_3 == TRUE) { + if(input$upgma_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_3 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_3 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) + } + scale_fill_gradient3(low = brewer.pal(3, input$upgma_tiles_scale_3)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_3)[2], + high = brewer.pal(3, input$upgma_tiles_scale_3)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { + if(input$upgma_tiles_scale_3 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_3 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_3 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_3 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_3 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_3 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_3 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_3 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_3 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_3 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_3 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_3 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_3 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_3 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_3 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_3 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_3) + } + } + } else {NULL} + } + }) + + upgma_gradient4 <- reactive({ + if(!is.null(input$upgma_tiles_show_4) & + !is.null(input$upgma_fruit_variable_4) & + !is.null(input$upgma_tiles_scale_4) & + !is.null(input$upgma_tiles_mapping_div_mid_4)) { + if(input$upgma_tiles_show_4 == TRUE) { + if(input$upgma_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_4 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_4 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) + } + scale_fill_gradient4(low = brewer.pal(3, input$upgma_tiles_scale_4)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_4)[2], + high = brewer.pal(3, input$upgma_tiles_scale_4)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { + if(input$upgma_tiles_scale_4 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_4 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_4 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_4 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_4 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_4 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_4 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_4 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_4 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_4 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_4 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_4 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_4 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_4 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_4 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_4 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_4) + } + } + } else {NULL} + } + }) + + upgma_gradient5 <- reactive({ + if(!is.null(input$upgma_tiles_show_5) & + !is.null(input$upgma_fruit_variable_5) & + !is.null(input$upgma_tiles_scale_5) & + !is.null(input$upgma_tiles_mapping_div_mid_5)) { + if(input$upgma_tiles_show_5 == TRUE) { + if(input$upgma_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_5 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_5 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) + } + scale_fill_gradient5(low = brewer.pal(3, input$upgma_tiles_scale_5)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_5)[2], + high = brewer.pal(3, input$upgma_tiles_scale_5)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { + if(input$upgma_tiles_scale_5 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_5 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_5 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_5 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_5 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_5 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_5 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_5 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_5 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_5 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_5 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_5 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_5 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_5 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_5 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_5 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_5) + } + } + } else {NULL} + } + }) + + # No label clip off for linear upgma tree + upgma_clip_label <- reactive({ + if(!(input$upgma_layout == "circular" | input$upgma_layout == "inward")) { + coord_cartesian(clip = "off") + } else {NULL} + }) + + # Geom Fruit + upgma_fruit <- reactive({ + if((!is.null(input$upgma_tiles_show_1)) & + (!is.null(input$upgma_fruit_variable)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ)) & + (!is.null(input$upgma_fruit_width_circ)) & + (!is.null(input$upgma_fruit_alpha))) { + if(input$upgma_tiles_show_1 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = input$upgma_fruit_offset_circ, + width = input$upgma_fruit_width_circ, + alpha = input$upgma_fruit_alpha + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = input$upgma_fruit_offset_circ, + width = input$upgma_fruit_width_circ, + alpha = input$upgma_fruit_alpha + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_1 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = 0, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = 0, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Geom Fruit + upgma_fruit2 <- reactive({ + if((!is.null(input$upgma_tiles_show_2)) & + (!is.null(input$upgma_fruit_variable_2)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_2)) & + (!is.null(input$upgma_fruit_width_circ_2)) & + (!is.null(input$upgma_fruit_alpha_2))) { + if(input$upgma_tiles_show_2 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), + offset = input$upgma_fruit_offset_circ_2, + width = input$upgma_fruit_width_circ_2, + alpha = input$upgma_fruit_alpha_2 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), + offset = input$upgma_fruit_offset_circ_2, + width = input$upgma_fruit_width_circ_2, + alpha = input$upgma_fruit_alpha_2 + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_2 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + upgma_fruit3 <- reactive({ + if((!is.null(input$upgma_tiles_show_3)) & + (!is.null(input$upgma_fruit_variable_3)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_3)) & + (!is.null(input$upgma_fruit_width_circ_3)) & + (!is.null(input$upgma_fruit_alpha_3))) { + if(input$upgma_tiles_show_3 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), + offset = input$upgma_fruit_offset_circ_3, + width = input$upgma_fruit_width_circ_3, + alpha = input$upgma_fruit_alpha_3 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), + offset = input$upgma_fruit_offset_circ_3, + width = input$upgma_fruit_width_circ_3, + alpha = input$upgma_fruit_alpha_3 + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_3 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + upgma_fruit4 <- reactive({ + if((!is.null(input$upgma_tiles_show_4)) & + (!is.null(input$upgma_fruit_variable_4)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_4)) & + (!is.null(input$upgma_fruit_width_circ_4)) & + (!is.null(input$upgma_fruit_alpha_4))) { + if(input$upgma_tiles_show_4 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), + offset = input$upgma_fruit_offset_circ_4, + width = input$upgma_fruit_width_circ_4, + alpha = input$upgma_fruit_alpha_4 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), + offset = input$upgma_fruit_offset_circ_4, + width = input$upgma_fruit_width_circ_4, + alpha = input$upgma_fruit_alpha_4 + ) + } + } else { + if(input$upgma_tiles_show_4 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + } + }) + + upgma_fruit5 <- reactive({ + if((!is.null(input$upgma_tiles_show_5)) & + (!is.null(input$upgma_fruit_variable_5)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_5)) & + (!is.null(input$upgma_fruit_width_circ_5)) & + (!is.null(input$upgma_fruit_alpha_5))) { + if(input$upgma_tiles_show_5 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), + offset = input$upgma_fruit_offset_circ_5, + width = input$upgma_fruit_width_circ_5, + alpha = input$upgma_fruit_alpha_5 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), + offset = input$upgma_fruit_offset_circ_5, + width = input$upgma_fruit_width_circ_5, + alpha = input$upgma_fruit_alpha_5 + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_5 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Xlim + upgma_limit <- reactive({ + if(input$upgma_layout == "circular") { + xlim(input$upgma_xlim, NA) + } else {NULL} + }) + + # Treescale + upgma_treescale <- reactive({ + if(!input$upgma_layout == "circular") { + if(input$upgma_treescale_show == TRUE) { + geom_treescale(x = upgma_treescale_x(), + y = upgma_treescale_y(), + width = upgma_treescale_width(), + color = input$upgma_color, + fontsize = 4) + } else {NULL} + } else {NULL} + }) + + # Treescale Y Position + upgma_treescale_y <- reactive({ + if(is.null(input$upgma_treescale_y)) { + 0 + } else {input$upgma_treescale_y} + }) + + # Treescale X Position + upgma_treescale_x <- reactive({ + if(is.null(input$upgma_treescale_x)) { + round(ceiling(Vis$upgma_max_x) * 0.2, 0) + } else {input$upgma_treescale_x} + }) + + # Treescale width + upgma_treescale_width <- reactive({ + if(!is.null(input$upgma_treescale_width)) { + input$upgma_treescale_width + } else { + round(ceiling(Vis$upgma_max_x) * 0.1, 0) + } + }) + + # Label branches + upgma_label_branch <- reactive({ + if(!input$upgma_layout == "circular" | !input$upgma_layout == "inward") { + if(input$upgma_show_branch_label == TRUE) { + geom_label( + aes( + x=!!sym("branch"), + label= !!sym(input$upgma_branch_label)), + fill = input$upgma_branch_label_color, + size = upgma_branch_size(), + label.r = unit(input$upgma_branch_labelradius, "lines"), + nudge_x = input$upgma_branch_x, + nudge_y = input$upgma_branch_y, + fontface = input$upgma_branchlab_fontface, + alpha = input$upgma_branchlab_alpha + ) + } else {NULL} + } else {NULL} + }) + + # Branch label size + upgma_branch_size <- reactive({ + if(!is.null(input$upgma_branch_size)) { + input$upgma_branch_size + } else { + Vis$branch_size_upgma + } + }) + + # Rootedge + upgma_rootedge <- reactive({ + if(input$upgma_rootedge_show == TRUE) { + if(is.null(input$upgma_rootedge_length)) { + geom_rootedge(rootedge = round(ceiling(Vis$upgma_max_x) * 0.05, 0), + linetype = input$upgma_rootedge_line) + } else { + geom_rootedge(rootedge = input$upgma_rootedge_length, + linetype = input$upgma_rootedge_line) + } + } else {NULL} + }) + + # Tippoints + upgma_tippoint <- reactive({ + if(input$upgma_tippoint_show == TRUE | input$upgma_tipcolor_mapping_show == TRUE | input$upgma_tipshape_mapping_show == TRUE) { + if(input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == FALSE) { + geom_tippoint( + aes(color = !!sym(input$upgma_tipcolor_mapping)), + alpha = input$upgma_tippoint_alpha, + shape = input$upgma_tippoint_shape, + size = upgma_tippoint_size() + ) + } else if (input$upgma_tipcolor_mapping_show == FALSE & input$upgma_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$upgma_tipshape_mapping)), + alpha = input$upgma_tippoint_alpha, + color = input$upgma_tippoint_color, + size = upgma_tippoint_size() + ) + } else if (input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$upgma_tipshape_mapping), + color = !!sym(input$upgma_tipcolor_mapping)), + alpha = input$upgma_tippoint_alpha, + size = upgma_tippoint_size() + ) + } else { + geom_tippoint( + alpha = input$upgma_tippoint_alpha, + colour = input$upgma_tippoint_color, + fill = input$upgma_tippoint_color, + shape = input$upgma_tippoint_shape, + size = upgma_tippoint_size() + ) + } + } else {NULL} + }) + + # Nodepoints + upgma_nodepoint <- reactive({ + if(input$upgma_nodepoint_show == TRUE) { + geom_nodepoint( + alpha = input$upgma_nodepoint_alpha, + color = input$upgma_nodepoint_color, + shape = input$upgma_nodepoint_shape, + size = upgma_nodepoint_size() + ) + } else {NULL} + }) + + # Nodepoint size + upgma_nodepoint_size <- reactive({ + if(!is.null(input$upgma_nodepoint_size)) { + input$upgma_nodepoint_size + } else { + Vis$nodepointsize_upgma + } + }) + + # upgma circular or not + upgma_tiplab <- reactive({ + if(input$upgma_tiplab_show == TRUE) { + if(input$upgma_layout == "circular") { + if(input$upgma_mapping_show == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position), + check.overlap = input$upgma_tiplab_overlap + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + color = input$upgma_tiplab_color, + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position), + check.overlap = input$upgma_tiplab_overlap + ) + } + } else if (input$upgma_layout == "inward") { + if(input$upgma_mapping_show == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position_inw), + check.overlap = input$upgma_tiplab_overlap + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + color = input$upgma_tiplab_color, + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position_inw), + check.overlap = input$upgma_tiplab_overlap + ) + } + } else { + if(input$upgma_mapping_show == TRUE) { + if(input$upgma_geom == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap, + label.padding = unit(upgma_tiplab_padding(), "lines"), + label.r = unit(input$upgma_tiplab_labelradius, "lines"), + fill = input$upgma_tiplab_fill + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap + ) + } + } else { + if(input$upgma_geom == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + color = input$upgma_tiplab_color, + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap, + label.padding = unit(upgma_tiplab_padding(), "lines"), + label.r = unit(input$upgma_tiplab_labelradius, "lines"), + fill = input$upgma_tiplab_fill + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + color = input$upgma_tiplab_color, + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap + ) + } + } + } + } else {NULL} + }) + + # Tip panel size + upgma_tiplab_padding <- reactive({ + if(!is.null(input$upgma_tiplab_padding)) { + input$upgma_tiplab_padding + } else { + Vis$tiplab_padding_upgma + } + }) + + # Tiplab size + upgma_tiplab_size <- reactive({ + if(!is.null(input$upgma_tiplab_size)) { + input$upgma_tiplab_size + } else { + Vis$labelsize_upgma + } + }) + + # Tippoint size + upgma_tippoint_size <- reactive({ + if(!is.null(input$upgma_tippoint_size)) { + input$upgma_tippoint_size + } else { + Vis$tippointsize_upgma + } + }) + + # Show Label Panels? + upgma_geom <- reactive({ + if(input$upgma_geom == TRUE) { + "label" + } else {"text"} + }) + + # upgma Tiplab color + upgma_mapping_tiplab <- reactive({ + if(input$upgma_mapping_show == TRUE) { + if(!is.null(input$upgma_tiplab)) { + aes(label = !!sym(input$upgma_tiplab), + color = !!sym(input$upgma_color_mapping)) + } else { + aes(label = !!sym("Assembly Name"), + color = !!sym(input$upgma_color_mapping)) + } + } else { + if(!is.null(input$upgma_tiplab)) { + aes(label = !!sym(input$upgma_tiplab)) + } else { + aes(label = !!sym("Assembly Name")) + } + } + }) + + # upgma Tree Layout + layout_upgma <- reactive({ + if(input$upgma_layout == "inward") { + "circular" + } else {input$upgma_layout} + }) + + # upgma inward circular + upgma_inward <- reactive({ + if (input$upgma_layout == "inward") { + layout_inward_circular(xlim = input$upgma_inward_xlim) + } else { + NULL + } + }) + + ### Save MST Plot ---- + output$save_plot_html <- downloadHandler( + filename = function() { + log_print(paste0("Save MST;", paste0("MST_", Sys.Date(), ".html"))) + paste0("MST_", Sys.Date(), ".html") + }, + content = function(file) { + mst_tree() %>% visSave(file = file, background = mst_background_color()) + } + ) + + ### Save NJ Plot ---- + + # Define download handler to save the plot + + output$download_nj <- downloadHandler( + filename = function() { + log_print(paste0("Save NJ;", paste0("NJ_", Sys.Date(), ".", input$filetype_nj))) + paste0("NJ_", Sys.Date(), ".", input$filetype_nj) + }, + content = function(file) { + if (input$filetype_nj == "png") { + png(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) + print(nj_tree()) + dev.off() + } else if (input$filetype_nj == "jpeg") { + jpeg(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) + print(nj_tree()) + dev.off() + } else if (input$filetype_nj == "svg") { + plot <- print(nj_tree()) + ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio))/96, + height = as.numeric(input$nj_scale)/96)) + } else if (input$filetype_nj == "bmp") { + bmp(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) + print(nj_tree()) + dev.off() + } + } + ) + + ### Save UPGMA Plot ---- + + # Define download handler to save the plot + + output$download_upgma <- downloadHandler( + filename = function() { + log_print(paste0("Save UPGMA;", paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma))) + paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma) + }, + content = function(file) { + if (input$filetype_upgma == "png") { + png(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) + print(upgma_tree()) + dev.off() + } else if (input$filetype_upgma == "jpeg") { + jpeg(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) + print(upgma_tree()) + dev.off() + } else if (input$filetype_upgma == "svg") { + plot <- print(upgma_tree()) + ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio))/96, + height = as.numeric(input$upgma_scale)/96)) + } else if (input$filetype_upgma == "bmp") { + bmp(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) + print(upgma_tree()) + dev.off() + } + } + ) + + ### Reactive Events ---- + + # MST cluster reset button + observeEvent(input$mst_cluster_reset, { + if(!is.null(DB$schemeinfo)) + updateNumericInput(session, "mst_cluster_threshold", value = as.numeric(DB$schemeinfo[7, 2])) + }) + + # Shut off "Align Labels" control for UPGMA trees + shinyjs::disable('upgma_align') + shinyjs::disable('upgma_tiplab_linesize') + shinyjs::disable('upgma_tiplab_linetype') + + # Conditional disabling of control elemenmts + observe({ + + # Tiles for inward layout + if(input$nj_layout == "inward") { + shinyjs::disable('nj_tiles_show') + shinyjs::disable('nj_tiles_show_2') + shinyjs::disable('nj_tiles_show_3') + shinyjs::disable('nj_tiles_show_4') + shinyjs::disable('nj_tiles_show_5') + shinyjs::disable('nj_fruit_variable') + shinyjs::disable('nj_fruit_variable_2') + shinyjs::disable('nj_fruit_variable_3') + shinyjs::disable('nj_fruit_variable_4') + shinyjs::disable('nj_fruit_variable_5') + shinyjs::disable('nj_fruit_width') + shinyjs::disable('nj_fruit_width_2') + shinyjs::disable('nj_fruit_width_3') + shinyjs::disable('nj_fruit_width_4') + shinyjs::disable('nj_fruit_width_5') + shinyjs::disable('nj_fruit_offset') + shinyjs::disable('nj_fruit_offset_2') + shinyjs::disable('nj_fruit_offset_3') + shinyjs::disable('nj_fruit_offset_4') + shinyjs::disable('nj_fruit_offset_5') + } else { + shinyjs::enable('nj_tiles_show') + shinyjs::enable('nj_tiles_show_2') + shinyjs::enable('nj_tiles_show_3') + shinyjs::enable('nj_tiles_show_4') + shinyjs::enable('nj_tiles_show_5') + shinyjs::enable('nj_fruit_variable') + shinyjs::enable('nj_fruit_variable_2') + shinyjs::enable('nj_fruit_variable_3') + shinyjs::enable('nj_fruit_variable_4') + shinyjs::enable('nj_fruit_variable_5') + shinyjs::enable('nj_fruit_width') + shinyjs::enable('nj_fruit_width_2') + shinyjs::enable('nj_fruit_width_3') + shinyjs::enable('nj_fruit_width_4') + shinyjs::enable('nj_fruit_width_5') + shinyjs::enable('nj_fruit_offset') + shinyjs::enable('nj_fruit_offset_2') + shinyjs::enable('nj_fruit_offset_3') + shinyjs::enable('nj_fruit_offset_4') + shinyjs::enable('nj_fruit_offset_5') + } + + if(input$upgma_layout == "inward") { + shinyjs::disable('upgma_tiles_show') + shinyjs::disable('upgma_tiles_show_2') + shinyjs::disable('upgma_tiles_show_3') + shinyjs::disable('upgma_tiles_show_4') + shinyjs::disable('upgma_tiles_show_5') + shinyjs::disable('upgma_fruit_variable') + shinyjs::disable('upgma_fruit_variable_2') + shinyjs::disable('upgma_fruit_variable_3') + shinyjs::disable('upgma_fruit_variable_4') + shinyjs::disable('upgma_fruit_variable_5') + shinyjs::disable('upgma_fruit_width') + shinyjs::disable('upgma_fruit_width_2') + shinyjs::disable('upgma_fruit_width_3') + shinyjs::disable('upgma_fruit_width_4') + shinyjs::disable('upgma_fruit_width_5') + shinyjs::disable('upgma_fruit_offset') + shinyjs::disable('upgma_fruit_offset_2') + shinyjs::disable('upgma_fruit_offset_3') + shinyjs::disable('upgma_fruit_offset_4') + shinyjs::disable('upgma_fruit_offset_5') + } else { + shinyjs::enable('upgma_tiles_show') + shinyjs::enable('upgma_tiles_show_2') + shinyjs::enable('upgma_tiles_show_3') + shinyjs::enable('upgma_tiles_show_4') + shinyjs::enable('upgma_tiles_show_5') + shinyjs::enable('upgma_fruit_variable') + shinyjs::enable('upgma_fruit_variable_2') + shinyjs::enable('upgma_fruit_variable_3') + shinyjs::enable('upgma_fruit_variable_4') + shinyjs::enable('upgma_fruit_variable_5') + shinyjs::enable('upgma_fruit_width') + shinyjs::enable('upgma_fruit_width_2') + shinyjs::enable('upgma_fruit_width_3') + shinyjs::enable('upgma_fruit_width_4') + shinyjs::enable('upgma_fruit_width_5') + shinyjs::enable('upgma_fruit_offset') + shinyjs::enable('upgma_fruit_offset_2') + shinyjs::enable('upgma_fruit_offset_3') + shinyjs::enable('upgma_fruit_offset_4') + shinyjs::enable('upgma_fruit_offset_5') + } + + # Shut off branch labels for NJ and UPGMA plots for circular layout + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + shinyjs::disable('nj_show_branch_label') + } else { + shinyjs::enable('nj_show_branch_label') + } + + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + shinyjs::disable('upgma_show_branch_label') + } else { + shinyjs::enable('upgma_show_branch_label') + } + }) + + #### Generate Plot ---- + + hamming_nj <- reactive({ + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + + allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] + + compute.distMatrix(allelic_profile_noNA_true, hamming.dist) + + } else if(input$na_handling == "ignore_na"){ + compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) + + } else { + compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) + } + + } else {compute.distMatrix(DB$allelic_profile_true, hamming.dist)} + }) + + hamming_mst <- reactive({ + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + + allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] + + dist <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) + + } else if (input$na_handling == "ignore_na") { + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) + } else { + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) + } + } else { + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) + } + + # Find indices of pairs with a distance of 0 + zero_distance_pairs <- as.data.frame(which(as.matrix(dist) == 0, arr.ind = TRUE)) + + zero_distance_pairs <- zero_distance_pairs[zero_distance_pairs$row != zero_distance_pairs$col, ] + + if(nrow(zero_distance_pairs) > 0) { + + # Sort each row so that x <= y + df_sorted <- t(apply(zero_distance_pairs, 1, function(row) sort(row))) + + # Remove duplicate rows + df_unique <- as.data.frame(unique(df_sorted)) + + colnames(df_unique) <- c("col", "row") + + # get metadata in df + vector_col <- character(0) + count <- 1 + for (i in df_unique$col) { + vector_col[count] <- Vis$meta_mst$`Assembly Name`[i] + count <- count + 1 + } + + vector_row <- character(0) + count <- 1 + for (i in df_unique$row) { + vector_row[count] <- Vis$meta_mst$`Assembly Name`[i] + count <- count + 1 + } + + col_id <- character(0) + count <- 1 + for (i in df_unique$col) { + col_id[count] <- Vis$meta_mst$`Assembly ID`[i] + count <- count + 1 + } + + row_id <- character(0) + count <- 1 + for (i in df_unique$row) { + row_id[count] <- Vis$meta_mst$`Assembly ID`[i] + count <- count + 1 + } + + col_index <- character(0) + count <- 1 + for (i in df_unique$col) { + col_index[count] <- Vis$meta_mst$Index[i] + count <- count + 1 + } + + row_index <- character(0) + count <- 1 + for (i in df_unique$row) { + row_index[count] <- Vis$meta_mst$Index[i] + count <- count + 1 + } + + col_date <- character(0) + count <- 1 + for (i in df_unique$col) { + col_date[count] <- Vis$meta_mst$`Isolation Date`[i] + count <- count + 1 + } + + row_date <- character(0) + count <- 1 + for (i in df_unique$row) { + row_date[count] <- Vis$meta_mst$`Isolation Date`[i] + count <- count + 1 + } + + col_host <- character(0) + count <- 1 + for (i in df_unique$col) { + col_host[count] <- Vis$meta_mst$Host[i] + count <- count + 1 + } + + row_host <- character(0) + count <- 1 + for (i in df_unique$row) { + row_host[count] <- Vis$meta_mst$Host[i] + count <- count + 1 + } + + col_country <- character(0) + count <- 1 + for (i in df_unique$col) { + col_country[count] <- Vis$meta_mst$Country[i] + count <- count + 1 + } + + row_country <- character(0) + count <- 1 + for (i in df_unique$row) { + row_country[count] <- Vis$meta_mst$Country[i] + count <- count + 1 + } + + col_city <- character(0) + count <- 1 + for (i in df_unique$col) { + col_city[count] <- Vis$meta_mst$City[i] + count <- count + 1 + } + + row_city <- character(0) + count <- 1 + for (i in df_unique$row) { + row_city[count] <- Vis$meta_mst$City[i] + count <- count + 1 + } + + df_unique <- cbind(df_unique, col_name = vector_col, row_name = vector_row, + col_index = col_index, row_index = row_index, col_id = col_id, + row_id = row_id, col_date = col_date, row_date = row_date, + col_host = col_host, row_host = row_host, col_country = col_country, + row_country = row_country, col_city = col_city, row_city = row_city) + + # Add groups + grouped_df <- df_unique %>% + group_by(col) %>% + mutate(group_id = cur_group_id()) + + # Merge groups + name <- character(0) + index <- character(0) + id <- character(0) + count <- 1 + for (i in grouped_df$group_id) { + name[count] <- paste(unique(append(grouped_df$col_name[which(grouped_df$group_id == i)], + grouped_df$row_name[which(grouped_df$group_id == i)])), + collapse = "\n") + + id[count] <- paste(unique(append(grouped_df$col_id[which(grouped_df$group_id == i)], + grouped_df$row_id[which(grouped_df$group_id == i)])), + collapse = "\n") + + index[count] <- paste(unique(append(grouped_df$col_index[which(grouped_df$group_id == i)], + grouped_df$row_index[which(grouped_df$group_id == i)])), + collapse = "\n") + + count <- count + 1 + } + + merged_names <- cbind(grouped_df, "Index" = index, "Assembly Name" = name, "Assembly ID" = id) + + # remove duplicate groups + + final <- merged_names[!duplicated(merged_names$group_id), ] + + final_cleaned <- final[!(final$col_name %in% final$row_name),] + + final_cleaned <- select(final_cleaned, 3, 17:20) + + # adapt metadata + Date_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + Date <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + Date <- append(Date, Vis$meta_mst$`Isolation Date`[which(Vis$meta_mst$Index == i)]) + } + Date_merged <- append(Date_merged, paste(Date, collapse = "\n")) + } + + Host_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + Host <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + Host <- append(Host, Vis$meta_mst$Host[which(Vis$meta_mst$Index == i)]) + } + Host_merged <- append(Host_merged, paste(Host, collapse = "\n")) + } + + Country_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + Country <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + Country <- append(Country, Vis$meta_mst$Country[which(Vis$meta_mst$Index == i)]) + } + Country_merged <- append(Country_merged, paste(Country, collapse = "\n")) + } + + City_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + City <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + City <- append(City, Vis$meta_mst$City[which(Vis$meta_mst$Index == i)]) + } + City_merged <- append(City_merged, paste(City, collapse = "\n")) + } + + final_meta <- cbind(final_cleaned, "Isolation Date" = Date_merged, + "Host" = Host_merged, "Country" = Country_merged, "City" = City_merged) + + + # Merging with original data frame / allelic profile + + allelic_profile_true <- DB$allelic_profile_true + meta_true <- Vis$meta_mst + + rownames(allelic_profile_true) <- Vis$meta_mst$`Assembly Name` + rownames(meta_true) <- Vis$meta_mst$`Assembly Name` + + omit <- unique(append(df_unique$col_name, df_unique$row_name)) %in% final_cleaned$col_name + + omit_id <- unique(append(df_unique$col_name, df_unique$row_name))[!omit] + + remove <- !(rownames(allelic_profile_true) %in% omit_id) + + allelic_profile_clean <- allelic_profile_true[remove, ] + + meta_clean <- meta_true[remove, ] + + # substitute meta assembly names with group names + + count <- 1 + for(i in which(rownames(meta_clean) %in% final_meta$col_name)) { + meta_clean$Index[i] <- final_meta$Index[count] + meta_clean$`Assembly Name`[i] <- final_meta$`Assembly Name`[count] + meta_clean$`Assembly ID`[i] <- final_meta$`Assembly ID`[count] + meta_clean$`Isolation Date`[i] <- final_meta$`Isolation Date`[count] + meta_clean$Host[i] <- final_meta$Host[count] + meta_clean$Country[i] <- final_meta$Country[count] + meta_clean$City[i] <- final_meta$City[count] + count <- count + 1 + } + + # Metadata completion + # get group size + + size_vector <- numeric(0) + for(i in 1:nrow(meta_clean)) { + if (str_count(meta_clean$`Assembly Name`[i], "\n") == 0) { + size_vector[i] <- 1 + } else { + size_vector[i] <- str_count(meta_clean$`Assembly Name`[i], "\n") +1 + } + } + + meta_clean <- mutate(meta_clean, size = size_vector) + + # get font size dependent on group size + + font_size <- numeric(nrow(meta_clean)) + + for (i in 1:length(font_size)) { + if(meta_clean$size[i] < 3) { + font_size[i] <- 12 + } else { + font_size[i] <- 11 + } + } + + # get v-align dependent on group size + valign <- numeric(nrow(meta_clean)) + + for (i in 1:length(valign)) { + if(meta_clean$size[i] == 1) { + valign[i] <- -30 + } else if(meta_clean$size[i] == 2) { + valign[i] <- -38 + } else if(meta_clean$size[i] == 3) { + valign[i] <- -46 + } else if(meta_clean$size[i] == 4) { + valign[i] <- -54 + } else if(meta_clean$size[i] == 5) { + valign[i] <- -62 + } else if(meta_clean$size[i] > 5) { + valign[i] <- -70 + } + } + + Vis$unique_meta <- meta_clean %>% + cbind(font_size = font_size, valign = valign) + + # final dist calculation + + if(anyNA(DB$allelic_profile)){ + if(input$na_handling == "omit") { + allelic_profile_clean_noNA_names <- allelic_profile_clean[, colSums(is.na(allelic_profile_clean)) == 0] + compute.distMatrix(allelic_profile_clean_noNA_names, hamming.dist) + } else if (input$na_handling == "ignore_na") { + compute.distMatrix(allelic_profile_clean, hamming.distIgnore) + } else { + compute.distMatrix(allelic_profile_clean, hamming.distCategory) + } + } else {compute.distMatrix(allelic_profile_clean, hamming.dist)} + + + } else { + font_size <- rep(12, nrow(Vis$meta_mst)) + valign <- rep(-30, nrow(Vis$meta_mst)) + size <- rep(1, nrow(Vis$meta_mst)) + Vis$unique_meta <- Vis$meta_mst %>% + cbind(size , font_size, valign) + + dist + } + + }) + + observeEvent(input$create_tree, { + log_print("Input create_tree") + + if(is.null(DB$data)) { + log_print("Missing data") + + show_toast( + title = "Missing data", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else if(nrow(DB$allelic_profile_true) < 3) { + log_print("Min. of 3 entries required for visualization") + + show_toast( + title = "Min. of 3 entries required for visualization", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + + if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { + log_print("Duplicated assemblies") + + dup_name <- which(duplicated(DB$meta_true$`Assembly Name`)) + dup_id <- which(duplicated(DB$meta_true$`Assembly ID`)) + + showModal( + modalDialog( + if((length(dup_name) + length(dup_id)) == 1) { + if(length(dup_name) == 1) { + HTML(paste0("Entry #", dup_name, + " contains a duplicated assembly name:", "

", + DB$meta_true$`Assembly Name`[dup_name])) + } else { + HTML(paste0("Entry #", dup_id, + " contains a duplicated assembly ID:", "

", + DB$meta_true$`Assembly ID`[dup_id])) + } + } else { + if(length(dup_name) == 0) { + HTML(c("Entries contain duplicated IDs

", + paste0(unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) + } else if(length(dup_id) == 0) { + HTML(c("Entries contain duplicated names

", + paste0(unique(DB$meta_true$`Assembly Name`[dup_name]), "
"))) + } else { + HTML(c("Entries contain duplicated names and IDs

", + paste0("Name: ", unique(DB$meta_true$`Assembly Name`[dup_name]), "
"), + paste0("ID: ", unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) + } + }, + title = "Duplicate entries", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("change_entries", "Go to Entry Table", class = "btn btn-default") + ) + ) + ) + } else { + + set.seed(1) + + if (input$tree_algo == "Neighbour-Joining") { + + log_print("Rendering NJ tree") + + output$nj_field <- renderUI({ + addSpinner( + plotOutput("tree_nj", width = paste0(as.character(as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), "px"), height = paste0(as.character(input$nj_scale), "px")), + spin = "dots", + color = "#ffffff" + ) + }) + + Vis$meta_nj <- select(DB$meta_true, -2) + + if(length(unique(gsub(" ", "_", colnames(Vis$meta_nj)))) < length(gsub(" ", "_", colnames(Vis$meta_nj)))) { + show_toast( + title = "Conflicting Custom Variable Names", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + # Create phylogenetic tree data + Vis$nj <- ape::nj(hamming_nj()) + + # Create phylogenetic tree meta data + Vis$meta_nj <- mutate(Vis$meta_nj, taxa = Index) %>% + relocate(taxa) + + # Get number of included entries calculate start values for tree + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_nj <- 5.5 + Vis$tippointsize_nj <- 5.5 + Vis$nodepointsize_nj <- 4 + Vis$tiplab_padding_nj <- 0.25 + Vis$branch_size_nj <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_nj <- 5 + Vis$tippointsize_nj <- 5 + Vis$nodepointsize_nj <- 3.5 + Vis$tiplab_padding_nj <- 0.2 + Vis$branch_size_nj <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_nj <- 4.5 + Vis$tippointsize_nj <- 4.5 + Vis$nodepointsize_nj <- 3 + Vis$tiplab_padding_nj <- 0.15 + Vis$branch_size_nj <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_nj <- 4 + Vis$tippointsize_nj <- 4 + Vis$nodepointsize_nj <- 2.5 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_nj <- 3.5 + Vis$tippointsize_nj <- 3.5 + Vis$nodepointsize_nj <- 2 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 2.5 + } else { + Vis$labelsize_nj <- 3 + Vis$tippointsize_nj <- 3 + Vis$nodepointsize_nj <- 1.5 + Vis$tiplab_padding_nj <- 0.05 + Vis$branch_size_nj <- 2 + } + } else { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_nj <- 5 + Vis$tippointsize_nj <- 5 + Vis$nodepointsize_nj <- 4 + Vis$tiplab_padding_nj <- 0.25 + Vis$branch_size_nj <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_nj <- 4.5 + Vis$tippointsize_nj <- 4.5 + Vis$nodepointsize_nj <- 3.5 + Vis$tiplab_padding_nj <- 0.2 + Vis$branch_size_nj <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_nj <- 4 + Vis$tippointsize_nj <- 4 + Vis$nodepointsize_nj <- 3 + Vis$tiplab_padding_nj <- 0.15 + Vis$branch_size_nj <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_nj <- 3.5 + Vis$tippointsize_nj <- 3.5 + Vis$nodepointsize_nj <- 2.5 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_nj <- 3 + Vis$tippointsize_nj <- 3 + Vis$nodepointsize_nj <- 2 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 2.5 + } else { + Vis$labelsize_nj <- 2.5 + Vis$tippointsize_nj <- 2.5 + Vis$nodepointsize_nj <- 1.5 + Vis$tiplab_padding_nj <- 0.05 + Vis$branch_size_nj <- 2 + } + } + } else { + Vis$labelsize_nj <- 4 + Vis$tippointsize_nj <- 4 + Vis$nodepointsize_nj <- 2.5 + Vis$tiplab_padding_nj <- 0.2 + Vis$branch_size_nj <- 3.5 + } + + Vis$nj_tree <- ggtree(Vis$nj) + + # Get upper and lower end of x range + Vis$nj_max_x <- max(Vis$nj_tree$data$x) + Vis$nj_min_x <- min(Vis$nj_tree$data$x) + + # Get parent node numbers + Vis$nj_parentnodes <- Vis$nj_tree$data$parent + + # Update visualization control inputs + if(!is.null(input$nj_tiplab_size)) { + updateNumericInput(session, "nj_tiplab_size", value = Vis$labelsize_nj) + } + if(!is.null(input$nj_tippoint_size)) { + updateSliderInput(session, "nj_tippoint_size", value = Vis$tippointsize_nj) + } + if(!is.null(input$nj_nodepoint_size)) { + updateSliderInput(session, "nj_nodepoint_size", value = Vis$nodepointsize_nj) + } + if(!is.null(input$nj_tiplab_padding)) { + updateSliderInput(session, "nj_tiplab_padding", value = Vis$tiplab_padding_nj) + } + if(!is.null(input$nj_branch_size)) { + updateNumericInput(session, "nj_branch_size", value = Vis$branch_size_nj) + } + if(!is.null(input$nj_treescale_width)) { + updateNumericInput(session, "nj_treescale_width", value = round(ceiling(Vis$nj_max_x) * 0.1, 0)) + } + if(!is.null(input$nj_rootedge_length)) { + updateSliderInput(session, "nj_rootedge_length", value = round(ceiling(Vis$nj_max_x) * 0.05, 0)) + } + + output$tree_nj <- renderPlot({ + nj_tree() + }) + + Vis$nj_true <- TRUE + } + } else if (input$tree_algo == "UPGMA") { + + log_print("Rendering UPGMA tree") + + output$upgma_field <- renderUI({ + addSpinner( + plotOutput("tree_upgma", width = paste0(as.character(as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), "px"), height = paste0(as.character(input$upgma_scale), "px")), + spin = "dots", + color = "#ffffff" + ) + }) + + Vis$meta_upgma <- select(DB$meta_true, -2) + + if(length(unique(gsub(" ", "_", colnames(Vis$meta_upgma)))) < length(gsub(" ", "_", colnames(Vis$meta_upgma)))) { + show_toast( + title = "Conflicting Custom Variable Names", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + # Create phylogenetic tree data + Vis$upgma <- phangorn::upgma(hamming_nj()) + + # Create phylogenetic tree meta data + Vis$meta_upgma <- mutate(Vis$meta_upgma, taxa = Index) %>% + relocate(taxa) + + # Get number of included entries calculate start values for tree + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_upgma <- 5.5 + Vis$tippointsize_upgma <- 5.5 + Vis$nodepointsize_upgma <- 4 + Vis$tiplab_padding_upgma <- 0.25 + Vis$branch_size_upgma <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_upgma <- 5 + Vis$tippointsize_upgma <- 5 + Vis$nodepointsize_upgma <- 3.5 + Vis$tiplab_padding_upgma <- 0.2 + Vis$branch_size_upgma <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_upgma <- 4.5 + Vis$tippointsize_upgma <- 4.5 + Vis$nodepointsize_upgma <- 3 + Vis$tiplab_padding_upgma <- 0.15 + Vis$branch_size_upgma <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_upgma <- 4 + Vis$tippointsize_upgma <- 4 + Vis$nodepointsize_upgma <- 2.5 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_upgma <- 3.5 + Vis$tippointsize_upgma <- 3.5 + Vis$nodepointsize_upgma <- 2 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 2.5 + } else { + Vis$labelsize_upgma <- 3 + Vis$tippointsize_upgma <- 3 + Vis$nodepointsize_upgma <- 1.5 + Vis$tiplab_padding_upgma <- 0.05 + Vis$branch_size_upgma <- 2 + } + } else { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_upgma <- 5 + Vis$tippointsize_upgma <- 5 + Vis$nodepointsize_upgma <- 4 + Vis$tiplab_padding_upgma <- 0.25 + Vis$branch_size_upgma <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_upgma <- 4.5 + Vis$tippointsize_upgma <- 4.5 + Vis$nodepointsize_upgma <- 3.5 + Vis$tiplab_padding_upgma <- 0.2 + Vis$branch_size_upgma <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_upgma <- 4 + Vis$tippointsize_upgma <- 4 + Vis$nodepointsize_upgma <- 3 + Vis$tiplab_padding_upgma <- 0.15 + Vis$branch_size_upgma <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_upgma <- 3.5 + Vis$tippointsize_upgma <- 3.5 + Vis$nodepointsize_upgma <- 2.5 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_upgma <- 3 + Vis$tippointsize_upgma <- 3 + Vis$nodepointsize_upgma <- 2 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 2.5 + } else { + Vis$labelsize_upgma <- 2.5 + Vis$tippointsize_upgma <- 2.5 + Vis$nodepointsize_upgma <- 1.5 + Vis$tiplab_padding_upgma <- 0.05 + Vis$branch_size_upgma <- 2 + } + } + } else { + Vis$labelsize_upgma <- 4 + Vis$tippointsize_upgma <- 4 + Vis$nodepointsize_upgma <- 2.5 + Vis$tiplab_padding_upgma <- 0.2 + Vis$branch_size_upgma <- 3.5 + } + + Vis$upgma_tree <- ggtree(Vis$upgma) + + # Get upper and lower end of x range + Vis$upgma_max_x <- max(Vis$upgma_tree$data$x) + Vis$upgma_min_x <- min(Vis$upgma_tree$data$x) + + # Get parent node numbers + Vis$upgma_parentnodes <- Vis$upgma_tree$data$parent + + # Update visualization control inputs + if(!is.null(input$upgma_tiplab_size)) { + updateNumericInput(session, "upgma_tiplab_size", value = Vis$labelsize_upgma) + } + if(!is.null(input$upgma_tippoint_size)) { + updateSliderInput(session, "upgma_tippoint_size", value = Vis$tippointsize_upgma) + } + if(!is.null(input$upgma_nodepoint_size)) { + updateSliderInput(session, "upgma_nodepoint_size", value = Vis$nodepointsize_upgma) + } + if(!is.null(input$upgma_tiplab_padding)) { + updateSliderInput(session, "upgma_tiplab_padding", value = Vis$tiplab_padding_upgma) + } + if(!is.null(input$upgma_branch_size)) { + updateNumericInput(session, "upgma_branch_size", value = Vis$branch_size_upgma) + } + if(!is.null(input$upgma_treescale_width)) { + updateNumericInput(session, "upgma_treescale_width", value = round(ceiling(Vis$upgma_max_x) * 0.1, 0)) + } + if(!is.null(input$upgma_rootedge_length)) { + updateSliderInput(session, "upgma_rootedge_length", value = round(ceiling(Vis$upgma_max_x) * 0.05, 0)) + } + + output$tree_upgma <- renderPlot({ + upgma_tree() + }) + + Vis$upgma_true <- TRUE + } + } else { + + log_print("Rendering MST graph") + + output$mst_field <- renderUI({ + if(input$mst_background_transparent == TRUE) { + visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")) + } else { + addSpinner( + visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")), + spin = "dots", + color = "#ffffff" + ) + } + }) + + if(nrow(DB$meta_true) > 100) { + + log_print("Over 100 isolates in MST graph") + + show_toast( + title = "Computation might take a while", + type = "warning", + position = "bottom-end", + timer = 10000 + ) + } + + meta_mst <- DB$meta_true + Vis$meta_mst <- meta_mst + + # prepare igraph object + Vis$ggraph_1 <- hamming_mst() |> + as.matrix() |> + graph.adjacency(weighted = TRUE) |> + igraph::mst() + + output$tree_mst <- renderVisNetwork({ + mst_tree() + }) + + Vis$mst_true <- TRUE + } + } + } + }) + + # _______________________ #### + + ## Report ---- + + observe({ + if(!is.null(DB$data)) { + if(!is.null(input$tree_algo)) { + if(input$tree_algo == "Minimum-Spanning") { + shinyjs::disable("rep_plot_report") + updateCheckboxInput(session, "rep_plot_report", value = FALSE) + } else { + shinyjs::enable("rep_plot_report") + } + } + } + }) + + ### Report creation UI ---- + + observeEvent(input$create_rep, { + + if((input$tree_algo == "Minimum-Spanning" & isTRUE(Vis$mst_true)) | + (input$tree_algo == "UPGMA" & isTRUE(Vis$upgma_true)) | + (input$tree_algo == "Neighbour-Joining" & isTRUE(Vis$nj_true))) { + # Get currently selected missing value handling option + if(input$na_handling == "ignore_na") { + na_handling <- "Ignore missing values for pairwise comparison" + } else if(input$na_handling == "omit") { + na_handling <- "Omit loci with missing values for all assemblies" + } else if(input$na_handling == "category") { + na_handling <- "Treat missing values as allele variant" + } + + extra_var <- character() + if(input$tree_algo == "Minimum-Spanning") { + shinyjs::runjs("mstReport();") + if(isTRUE(input$mst_color_var)) { + extra_var <- c(extra_var, input$mst_col_var) + } + } else if(input$tree_algo == "Neighbour-Joining") { + if(isTRUE(input$nj_mapping_show)) { + extra_var <- c(extra_var, input$nj_color_mapping) + } + if(isTRUE(input$nj_tipcolor_mapping_show)) { + extra_var <- c(extra_var, input$nj_tipcolor_mapping) + } + if(isTRUE(input$nj_tipshape_mapping_show)) { + extra_var <- c(extra_var, input$nj_tipshape_mapping) + } + if(isTRUE(input$nj_tiles_show_1)) { + extra_var <- c(extra_var, input$nj_fruit_variable) + } + if(isTRUE(input$nj_tiles_show_2)) { + extra_var <- c(extra_var, input$nj_fruit_variable_2) + } + if(isTRUE(input$nj_tiles_show_3)) { + extra_var <- c(extra_var, input$nj_fruit_variable_3) + } + if(isTRUE(input$nj_tiles_show_4)) { + extra_var <- c(extra_var, input$nj_fruit_variable_4) + } + if(isTRUE(input$nj_tiles_show_5)) { + extra_var <- c(extra_var, input$nj_fruit_variable_5) + } + if(isTRUE(input$nj_heatmap_show)) { + extra_var <- c(extra_var, input$nj_heatmap_select) + } + } else if(input$tree_algo == "UPGMA") { + if(isTRUE(input$UPGMA_mapping_show)) { + extra_var <- c(extra_var, input$UPGMA_color_mapping) + } + if(isTRUE(input$UPGMA_tipcolor_mapping_show)) { + extra_var <- c(extra_var, input$UPGMA_tipcolor_mapping) + } + if(isTRUE(input$UPGMA_tipshape_mapping_show)) { + extra_var <- c(extra_var, input$UPGMA_tipshape_mapping) + } + if(isTRUE(input$UPGMA_tiles_show_1)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable) + } + if(isTRUE(input$UPGMA_tiles_show_2)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_2) + } + if(isTRUE(input$UPGMA_tiles_show_3)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_3) + } + if(isTRUE(input$UPGMA_tiles_show_4)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_4) + } + if(isTRUE(input$UPGMA_tiles_show_5)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_5) + } + if(isTRUE(input$UPGMA_heatmap_show)) { + extra_var <- c(extra_var, input$UPGMA_heatmap_select) + } + } + + showModal( + modalDialog( + fluidRow( + column( + width = 12, + fluidRow( + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color:black; font-size: 15px; font-weight: 900', 'General') + ) + ) + ), + column( + width = 3, + align = "left", + checkboxInput( + "rep_general", + label = "", + value = TRUE + ) + ) + ), + fluidRow( + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + checkboxInput( + "rep_date_general", + label = h5("Date", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 7, + dateInput( + "mst_date_general_select", + "", + max = Sys.Date() + ) + ) + ), + fluidRow( + column( + width = 3, + checkboxInput( + "rep_operator_general", + label = h5("Operator", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + textInput( + "mst_operator_general_select", + "" + ) + ) + ), + fluidRow( + column( + width = 3, + checkboxInput( + "rep_institute_general", + label = h5("Institute", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + textInput( + "mst_institute_general_select", + "" + ) + ) + ), + fluidRow( + column( + width = 3, + checkboxInput( + "rep_comm_general", + label = h5("Comment", style = "color:black;") + ) + ), + column( + width = 8, + textAreaInput( + inputId = "mst_comm_general_select", + label = "", + width = "100%", + height = "60px", + cols = NULL, + rows = NULL, + placeholder = NULL, + resize = "vertical" + ) + ) + ) + ) + ), + hr(), + fluidRow( + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Isolate Table') + ) + ) + ), + column( + width = 3, + align = "left", + checkboxInput( + "rep_entrytable", + label = "", + value = TRUE + ) + ), + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Include Plot') + ) + ) + ), + column( + width = 1, + align = "left", + checkboxInput( + "rep_plot_report", + label = "", + value = TRUE + ) + ) + ), + fluidRow( + column( + width = 6, + align = "left", + div( + class = "rep_tab_sel", + pickerInput("select_rep_tab", + label = "", + choices = names(DB$meta)[-2], + selected = c("Assembly Name", "Scheme", "Isolation Date", + "Host", "Country", "City", extra_var), + options = list( + size = 10, + `actions-box` = TRUE, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE) + ) + ) + ), + hr(), + fluidRow( + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Analysis Parameter') + ) + ) + ), + column( + width = 3, + align = "left", + checkboxInput( + "rep_analysis", + label = "", + value = TRUE + ) + ) + ), + fluidRow( + column( + width = 6, + align = "left", + fluidRow( + column( + width = 4, + checkboxInput( + "rep_cgmlst_analysis", + label = h5("Scheme", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic', DB$scheme) + ) + ) + ) + ), + fluidRow( + column( + width = 4, + checkboxInput( + "rep_tree_analysis", + label = h5("Tree", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic', input$tree_algo) + ) + ) + ) + ) + ), + column( + width = 6, + align = "left", + fluidRow( + column(2), + column( + width = 4, + checkboxInput( + "rep_distance", + label = h5("Distance", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 5, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic', 'Hamming') + ) + ) + ) + ), + fluidRow( + column(2), + column( + width = 4, + checkboxInput( + "rep_version", + label = h5("Version", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 5, + align = "right", + HTML( + paste( + tags$span(style='color:black; position: relative; top: 17px; font-style: italic', phylotraceVersion) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 3, + align = "left", + checkboxInput( + "rep_missval", + label = h5("NA handling", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 7, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic; right: 35px;', na_handling) + ) + ) + ) + ) + ) + ), + title = "cgMLST Report Generation", + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + downloadBttn( + "download_report", + style = "simple", + label = "Save", + size = "sm", + icon = icon("download") + ) + ) + ) + ) + } else { + show_toast( + title = "No tree created", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + + observe({ + if(!is.null(input$rep_general)) { + if(isFALSE(input$rep_general)) { + shinyjs::disable('rep_date_general') + shinyjs::disable('rep_operator_general') + shinyjs::disable('rep_institute_general') + shinyjs::disable('rep_comm_general') + shinyjs::disable('mst_date_general_select') + shinyjs::disable('mst_operator_general_select') + shinyjs::disable('mst_institute_general_select') + shinyjs::disable('mst_comm_general_select') + } else { + shinyjs::enable('rep_date_general') + shinyjs::enable('rep_operator_general') + shinyjs::enable('rep_institute_general') + shinyjs::enable('rep_comm_general') + shinyjs::enable('mst_date_general_select') + shinyjs::enable('mst_operator_general_select') + shinyjs::enable('mst_institute_general_select') + shinyjs::enable('mst_comm_general_select') + } + } + + if(!is.null(input$rep_analysis)) { + if(isFALSE(input$rep_analysis)) { + shinyjs::disable('rep_cgmlst_analysis') + shinyjs::disable('rep_tree_analysis') + shinyjs::disable('rep_distance') + shinyjs::disable('rep_missval') + shinyjs::disable('rep_version') + } else { + shinyjs::enable('rep_cgmlst_analysis') + shinyjs::enable('rep_tree_analysis') + shinyjs::enable('rep_distance') + shinyjs::enable('rep_missval') + shinyjs::enable('rep_version') + } + } + + if(length(input$select_rep_tab) > 0) { + updateCheckboxInput(session, "rep_entrytable", value = TRUE) + } else { + updateCheckboxInput(session, "rep_entrytable", value = FALSE) + } + }) + + ### Save Report ---- + + #### Get Report elements ---- + + observe({ + if(!is.null(DB$data)){ + if(!is.null(input$tree_algo)) { + req(c(input$rep_entrytable, input$rep_general, + input$rep_date_general, input$rep_operator_general, + input$rep_institute_general, input$rep_comm_general, + input$rep_analysis, input$rep_cgmlst_analysis, + input$rep_tree_analysis, input$rep_distance, + input$rep_missval, input$rep_version, + input$rep_plot_report, input$select_rep_tab)) + Report$report_df <- data.frame(Element = c("entry_table", "general_show", + "general_date", "operator", + "institute", "comment", + "analysis_show", "scheme", + "tree", "distance", "na_handling", "version", + "plot"), + Include = c(input$rep_entrytable, input$rep_general, + input$rep_date_general, input$rep_operator_general, + input$rep_institute_general, input$rep_comm_general, + input$rep_analysis, input$rep_cgmlst_analysis, + input$rep_tree_analysis, input$rep_distance, + input$rep_missval, input$rep_version, + input$rep_plot_report)) + } + } + }) + + #### Get Report values ---- + + observeEvent(input$create_tree, { + if(input$tree_algo == "Minimum-Spanning") { + Report$report_list_mst <- list(entry_table = DB$meta_true, + scheme = DB$schemeinfo, + tree = input$tree_algo, + na_handling = if(anyNA(DB$allelic_profile_true)){input$na_handling} else {NULL}, + distance = "Hamming Distances", + version = c(phylotraceVersion, "2.5.1"), + plot = "MST") + } else if(input$tree_algo == "Neighbour-Joining") { + Report$report_list_nj <- list(entry_table = DB$meta_true, + scheme = DB$schemeinfo, + tree = input$tree_algo, + na_handling = input$na_handling, + distance = "Hamming Distances", + version = c(phylotraceVersion, "2.5.1"), + plot = "NJ") + } else { + Report$report_list_upgma <- list(entry_table = DB$meta_true, + scheme = DB$schemeinfo, + tree = input$tree_algo, + na_handling = input$na_handling, + distance = "Hamming Distances", + version = c(phylotraceVersion, "2.5.1"), + plot = "UPGMA") + } + }) + + # Save plot for Report + plot.report <- reactive({ + if(input$tree_algo == "Neighbour-Joining") { + jpeg(paste0(getwd(), "/Report/NJ.jpeg"), width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) + print(nj_tree()) + dev.off() + } else if(input$tree_algo == "UPGMA") { + jpeg(paste0(getwd(), "/Report/UPGMA.jpeg"), width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) + print(upgma_tree()) + dev.off() + } else if (input$tree_algo == "Minimum-Spanning") { + shinyjs::runjs("mstReport();") + decoded_data <- base64enc::base64decode(input$canvas_data) + writeBin(decoded_data, paste0(getwd(), "/Report/MST.jpg")) + } + }) + + #### Event Save Report ---- + output$download_report <- downloadHandler( + filename = function() { + if(input$tree_algo == "Minimum-Spanning") { + paste0("MST_Report_", Sys.Date(), ".html") + } else if(input$tree_algo == "Neighbour-Joining") { + paste0("NJ_Report_", Sys.Date(), ".html") + } else {paste0("UPGMA_Report_", Sys.Date(), ".html")} + }, + content = function(file) { + if(input$tree_algo == "Minimum-Spanning") { + plot.report() + + report <- c(Report$report_list_mst, + "general_date" = as.character(input$mst_date_general_select), + "operator" = input$mst_operator_general_select, + "institute" = input$mst_institute_general_select, + "comment" = input$mst_comm_general_select, + "report_df" = Report$report_df) + + report[["table_columns"]] <- input$select_rep_tab + + # Save data to an RDS file if any elements were selected + if (!is.null(report)) { + + log_print("Creating MST report") + + saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) + + rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) + + file.copy(paste0(getwd(), "/Report/Report.html"), file) + } else { + log_print("Creating MST report failed (report is null)") + } + } else if(input$tree_algo == "Neighbour-Joining") { + plot.report() + report <- c(Report$report_list_nj, + "general_date" = as.character(input$mst_date_general_select), + "operator" = input$mst_operator_general_select, + "institute" = input$mst_institute_general_select, + "comment" = input$mst_comm_general_select, + "report_df" = Report$report_df) + + report[["table_columns"]] <- input$select_rep_tab + + # Save data to an RDS file if any elements were selected + if (!is.null(report)) { + log_print("Creating NJ report") + + saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) + + rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) + + file.copy(paste0(getwd(), "/Report/Report.html"), file) + } else { + log_print("Creating NJ report failed (report is null)") + } + + } else { + plot.report() + report <- c(Report$report_list_upgma, + "general_date" = as.character(input$mst_date_general_select), + "operator" = input$mst_operator_general_select, + "institute" = input$mst_institute_general_select, + "comment" = input$mst_comm_general_select, + "report_df" = Report$report_df) + + report[["table_columns"]] <- input$select_rep_tab + + # Save data to an RDS file if any elements were selected + if (!is.null(report)) { + log_print("Creating UPGMA report") + + saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) + + rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) + + file.copy(paste0(getwd(), "/Report/Report.html"), file) + } else { + log_print("Creating UPGMA report failed (report is null)") + } + + } + removeModal() + } + ) + + + # _______________________ #### + + ## Gene Screening ---- + + ### Render UI Elements ---- + + # Rendering results table + output$gs_results_table <- renderUI({ + req(DB$data) + if(!is.null(Screening$selected_isolate)) { + if(length(Screening$selected_isolate) > 0) { + fluidRow( + div(class = "loci_table", + DT::dataTableOutput("gs_profile_table")), + br(), + HTML( + paste0("", + 'RSL = Reference Sequence Length  |  ', + '%CRS = % Coverage of Reference Sequence  |  ', + '%IRS = % Identity to Reference Sequence  |  ', + 'ACS = Accession of Closest Sequence  |  ', + 'NCS = Name of Closest Sequence') + + ) + ) + } else { + fluidRow( + br(), br(), + p( + HTML( + paste0("", + 'Select entry from the table to display resistance profile') + + ) + ) + ) + } + } else { + fluidRow( + br(), br(), + p( + HTML( + paste0("", + 'Select entry from the table to display resistance profile') + + ) + ) + ) + } + }) + + # Gene screening download button + output$gs_download <- renderUI({ + req(DB$data) + if(!is.null(Screening$selected_isolate)) { + if(length(Screening$selected_isolate) > 0) { + fluidRow( + downloadBttn( + "download_resistance_profile", + style = "simple", + label = "Profile Table", + size = "sm", + icon = icon("download"), + color = "primary" + ), + bsTooltip("download_resistance_profile_bttn", + HTML(paste0("Save resistance profile table for
", + Screening$selected_isolate)), + placement = "bottom", trigger = "hover") + ) + } else {NULL} + } else {NULL} + }) + + # Conditionally render table selectiom interface + output$gs_table_selection <- renderUI({ + req(DB$data, input$gs_view) + if(input$gs_view == "Table") { + fluidRow( + column(1), + column( + width = 10, + div(class = "loci_table", + dataTableOutput("gs_isolate_table")) + ) + ) + } else {NULL} + }) + + # Resistance profile table output display + output$gs_profile_display <- renderUI({ + req(DB$data) + if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { + if(input$gs_view == "Table") { + column( + width = 10, + hr(), + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) + ) + ), + column( + width = 4, + uiOutput("gs_download") + ) + ), + br(), + uiOutput("gs_results_table") + ) + } else { + column( + width = 10, + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) + ) + ), + column( + width = 4, + div( + class = "gs-picker", + pickerInput( + "gs_profile_select", + "", + choices = list( + Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] + } + ), + choicesOpt = list( + disabled = c( + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) + ) + ), + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ) + ) + ) + ), + column( + width = 3, + uiOutput("gs_download") + ) + ), + br(), + uiOutput("gs_results_table") + ) + } + } else {NULL} + }) + + # Screening sidebar + output$screening_sidebar <- renderUI({ + req(DB$data) + if(!is.null(DB$meta_gs)) { + column( + width = 12, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Toggle View') + ) + ) + ), + radioGroupButtons( + inputId = "gs_view", + choices = c("Picker", "Table"), + selected = "Picker", + checkIcon = list( + yes = icon("square-check"), + no = icon("square") + ) + ), + br() + ) + } else {NULL} + }) + + # Resistance profile table + observe({ + req(DB$meta_gs, Screening$selected_isolate, DB$database, DB$scheme, DB$data) + + if(length(Screening$selected_isolate) > 0 & any(Screening$selected_isolate %in% DB$data$`Assembly ID`)) { + iso_select <- Screening$selected_isolate + iso_path <- file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", + iso_select, "resProfile.tsv") + + res_profile <- read.delim(iso_path) + + colnames(res_profile) <- c( + "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", + "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", + "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", + "Alignment Length", "ACS", "Name of Closest Sequence", "HMM ID", "HMM Description") + + Screening$res_profile <- res_profile %>% + relocate(c("Gene Symbol", "Sequence Name", "Element Subtype", "Class", + "Subclass", "Scope", "Contig ID", "Target Length", "Alignment Length", + "Start", "Stop", "Strand")) + + # Generate gene profile table + output$gs_profile_table <- DT::renderDataTable( + Screening$res_profile, + selection = "single", + rownames= FALSE, + options = list(pageLength = 10, scrollX = TRUE, + autoWidth = TRUE, + columnDefs = list(list(width = '400px', targets = c("Sequence Name", + "Name of Closest Sequence"))), + columnDefs = list(list(width = 'auto', targets = "_all")), + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + } else { + output$gs_profile_table <- NULL + } + }) + + #Resistance profile selection table + observe({ + req(DB$meta, DB$data) + output$gs_isolate_table <- renderDataTable( + select(DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ], -c(3, 4, 10, 11, 12)), + selection = "single", + rownames= FALSE, + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + }) + + observe({ + req(input$screening_res_sel, DB$database, DB$scheme, DB$data) + if(!is.null(Screening$status_df) & + !is.null(input$screening_res_sel) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate)) { + if(length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", + input$screening_res_sel, "resProfile.tsv")) + + output$screening_table <- renderDataTable( + select(results, c(6, 7, 8, 9, 11)), + selection = "single", + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ))) + } else {output$screening_table <- NULL} + } + } else { + output$screening_table <- NULL + } + } else { + output$screening_table <- NULL + } + + }) + + # Availablity feedback + output$gene_screening_info <- renderUI({ + req(DB$data) + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } else { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } + }) + + output$gene_resistance_info <- renderUI({ + req(DB$data) + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } else { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } + }) + + # Screening Interface + + output$screening_interface <- renderUI({ + req(DB$data) + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + column( + width = 12, + fluidRow( + column(1), + column( + width = 3, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Isolates for Screening') + ) + ) + ), + if(Screening$picker_status) { + div( + class = "screening_div", + pickerInput( + "screening_select", + "", + choices = list( + Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] + } + ), + choicesOpt = list( + disabled = c( + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) + ) + ), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + } else { + div( + class = "screening_div", + pickerInput( + "screening_select", + "", + choices = Screening$picker_choices, + selected = Screening$picker_selected, + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + }, + br(), br(), + uiOutput("genome_path_gs") + ), + column( + width = 3, + uiOutput("screening_start") + ), + column( + width = 3, + align = "center", + br(), br(), + uiOutput("screening_result_sel") + ), + column(1) + ), + fluidRow( + column(1), + column( + width = 10, + br(), br(), + uiOutput("screening_result"), + br(), br(), br(), br() + ) + ) + ) + } + }) + + ### Screening Events ---- + + observe({ + req(DB$data, input$gs_view) + if(input$gs_view == "Table") { + meta_gs <- DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ] + Screening$selected_isolate <- meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] + } else if(input$gs_view == "Picker") { + Screening$selected_isolate <- input$gs_profile_select + } + }) + + output$download_resistance_profile <- downloadHandler( + filename = function() { + log_print(paste0("Save resistance profile table ", Screening$selected_isolate, "_Profile.csv")) + + paste0(format(Sys.Date()), "_", Screening$selected_isolate, "_Profile.csv") + }, + content = function(file) { + write.table( + Screening$res_profile, + file, + sep = ";", + row.names = FALSE, + quote = FALSE + ) + } + ) + + # Reset screening + observeEvent(input$screening_reset_bttn, { + log_print("Reset gene screening") + + # reset status file + sapply(Screening$status_df$isolate, remove.screening.status) + + # set feedback variables + Screening$status <- "idle" + Screening$status_df <- NULL + Screening$choices <- NULL + Screening$picker_status <- TRUE + Screening$first_result <- NULL + + # change reactive UI + output$screening_table <- NULL + output$screening_result <- NULL + output$screening_fail <- NULL + + updatePickerInput(session, "screening_select", selected = character(0)) + + # disable isolate picker + shinyjs::runjs("$('#screening_select').prop('disabled', false);") + shinyjs::runjs("$('#screening_select').selectpicker('refresh');") + }) + + # Cancel screening + observeEvent(input$screening_cancel, { + showModal( + modalDialog( + paste0( + "Gene screening is still pending. Stopping this process will cancel the screening." + ), + title = "Reset Multi Typing", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_screening_cancel", "Stop", class = "btn btn-danger") + ) + ) + ) + }) + + observeEvent(input$conf_screening_cancel, { + log_print("Cancelled gene screening") + removeModal() + + show_toast( + title = "Gene Screening Terminated", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + + # terminate screening + system(paste("kill $(pgrep -f 'execute/screening.sh')"), wait = FALSE) + system(paste("killall -TERM tblastn"), wait = FALSE) + + # reset status file + sapply(Screening$status_df$isolate, remove.screening.status) + + # set feedback variables + Screening$status <- "idle" + Screening$status_df <- NULL + Screening$choices <- NULL + Screening$picker_status <- TRUE + Screening$first_result <- NULL + + # change reactive UI + output$screening_table <- NULL + output$screening_result <- NULL + + updatePickerInput(session, "screening_select", selected = character(0)) + + # disable isolate picker + shinyjs::runjs("$('#screening_select').prop('disabled', false);") + shinyjs::runjs("$('#screening_select').selectpicker('refresh');") + }) + + # Get selected assembly + observe({ + req(DB$data, Screening$status) + if (length(input$screening_select) < 1) { + output$genome_path_gs <- renderUI(HTML( + paste("", length(input$screening_select), " isolate(s) queried for screening") + )) + + output$screening_start <- NULL + + } else if (length(input$screening_select) > 0) { + + output$screening_start <- renderUI({ + + fluidRow( + column( + width = 12, + br(), br(), + if(length(input$screening_select) < 1) { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Select Isolate(s) for Screening"))) + ) + ) + } else if(Screening$status == "finished") { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Reset to Perform Screening Again"))) + ), + actionButton( + "screening_reset_bttn", + "Reset", + icon = icon("arrows-rotate") + ), + if(!is.null(Screening$status_df)) { + p( + HTML(paste("", + sum(Screening$status_df$status != "unfinished"), "/", + nrow(Screening$status_df), " Isolate(s) screened")) + ) + } + ) + } else if(Screening$status == "idle") { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Screening Ready"))) + ), + actionButton( + inputId = "screening_start_button", + label = "Start", + icon = icon("circle-play") + ) + ) + } else if(Screening$status == "started") { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Running Screening ..."))) + ), + fluidRow( + column(3), + column( + width = 3, + actionButton( + inputId = "screening_cancel", + label = "Terminate", + icon = icon("ban") + ) + ), + column( + width = 3, + HTML(paste('')) + ) + ), + if(!is.null(Screening$status_df)) { + p( + HTML(paste("", + sum(Screening$status_df$status != "unfinished"), "/", + nrow(Screening$status_df), " isolate(s) screened")) + ) + } + ) + } + ) + ) + }) + } else {NULL} + }) + + #### Running Screening ---- + + observeEvent(input$screening_start_button, { + + if(tail(readLogFile(), 1) != "0") { + show_toast( + title = "Pending Multi Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + log_print("Started gene screening") + + Screening$status <- "started" + Screening$picker_choices <- list( + Unscreened = if (sum(DB$data$Screened == "No") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + Screened = if (sum(DB$data$Screened == "Yes") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] + } + ) + Screening$picker_selected <- input$screening_select + Screening$picker_status <- FALSE + + show_toast( + title = "Gene screening started", + type = "success", + position = "bottom-end", + timer = 6000 + ) + + Screening$meta_df <- data.frame(wd = getwd(), + selected = paste( + file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_select, + paste0(input$screening_select, ".zip")), + collapse = " "), + species = gsub(" ", "_", DB$scheme)) + + Screening$status_df <- data.frame(isolate = basename(gsub(".zip", "", str_split_1(Screening$meta_df$selected, " "))), + status = "unfinished") + + # Reset screening status + sapply(Screening$status_df$isolate, remove.screening.status) + + saveRDS(Screening$meta_df, paste0(getwd(), "/execute/screening_meta.rds")) + + # Disable pickerInput + shinyjs::delay(200, shinyjs::runjs("$('#screening_select').prop('disabled', true);")) + shinyjs::delay(200, shinyjs::runjs("$('#screening_select').selectpicker('refresh');")) + + # System execution screening.sh + system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) + } + }) + + observe({ + req(DB$data, Screening$status, input$screening_res_sel, Screening$status_df) + if(!is.null(Screening$status_df) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate) & + !is.null(input$screening_res_sel)) { + if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + dataTableOutput("screening_table") + ) + ) + } else { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + verbatimTextOutput("screening_fail") + ) + ) + } + } + } else { + output$screening_result <- NULL + } + } else { + output$screening_result <- NULL + } + }) + + observe({ + req(DB$data, Screening$status, input$screening_res_sel) + if(!is.null(Screening$status_df) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate) & + !is.null(input$screening_res_sel)) { + if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { + output$screening_fail <- renderPrint({ + cat(paste(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_res_sel, "status.txt")),"\n")) + }) + } + } + } else { + output$screening_fail <- NULL + } + } else { + output$screening_fail <- NULL + } + }) + + observe({ + req(DB$data) + if(!is.null(Screening$status)) { + if(Screening$status != "idle") { + + # start status screening for user feedback + check_screening() + + if(isTRUE(Screening$first_result)) { + output$screening_result_sel <- renderUI( + column( + width = 12, + align = "center", + selectInput( + "screening_res_sel", + label = h5("Select Result", style = "color:white; margin-bottom: 28px; margin-top: -10px;"), + choices = "" + ), + if(!is.null(Screening$status_df)) { + p(HTML(paste("", + if(sum(Screening$status_df$status == "success") == 1) { + "1 success   /  " + } else { + paste0(sum(Screening$status_df$status == "success"), " successes   /  ") + }, + if(sum(Screening$status_df$status == "fail") == 1) { + "1 failure" + } else { + paste0(sum(Screening$status_df$status == "fail"), " failures") + }))) + } + ) + ) + + Screening$first_result <- FALSE + } + } else if(Screening$status == "idle") { + output$screening_result_sel <- NULL + } + } + }) + + check_screening <- reactive({ + invalidateLater(500, session) + + req(Screening$status_df) + + if(Screening$status == "started") { + + Screening$status_df$status <- sapply(Screening$status_df$isolate, check_status) + + if(any("unfinished" != Screening$status_df$status) & + !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status != "unfinished")])) { + + status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] + + Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | + Screening$status_df$status == "fail")] + + if(sum(Screening$status_df$status != "unfinished") > 0) { + if(is.null(Screening$first_result)) { + Screening$first_result <- TRUE + } + } + + if(tail(status_df$status, 1) == "success") { + + # Changing "Screened" metadata variable in database + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + Database[["Typing"]]$Screened[which(Database[["Typing"]]["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + + saveRDS(Database, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + DB$data$Screened[which(DB$data["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + + show_toast( + title = paste("Successful screening of", tail(Screening$choices, 1)), + type = "success", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + + } else if(tail(status_df$status, 1) == "fail") { + + show_toast( + title = paste("Failed screening of", tail(status_df$isolate, 1)), + type = "error", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + } + + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } else { + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } + + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } + }) + + + # _______________________ #### + + ## Typing ---- + + # Render Single/Multi Switch + + readLogFile <- reactive({ + invalidateLater(5000, session) + readLines(paste0(getwd(), "/logs/script_log.txt")) + }) + + # Render sidebar dependent on data presence + # No sidebar + output$typing_sidebar <- renderUI({ + if(!is.null(DB$exist)) { + if(DB$exist) { + NULL + } else { + column( + width = 12, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Typing Mode') + ) + ) + ), + radioGroupButtons( + inputId = "typing_mode", + choices = c("Single", "Multi"), + selected = "Single", + checkIcon = list( + yes = icon("square-check"), + no = icon("square") + ) + ), + br() + ) + } + } + + }) + + # No db typing message + output$typing_no_db <- renderUI({ + if(!is.null(DB$exist)) { + if(DB$exist) { + column( + width = 4, + align = "left", + br(), + br(), + br(), + br(), + p( + HTML( + paste0( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 50px', 'To initiate allelic typing, a cgMLST scheme must be downloaded first.' + ) + ) + ) + ) + ) + } else {NULL} + } else {NULL} + }) + + ### Single Typing ---- + + #### Render UI Elements ---- + + # Render single typing naming issues + output$single_select_issues <- renderUI({ + req(input$assembly_id) + + if(nchar(trimws(input$assembly_id)) < 1) { + ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) + } else { + ass_id <- trimws(input$assembly_id) + } + + if(ass_id %in% unlist(DB$data["Assembly ID"])) { + HTML(paste( + '', + paste("", + "  Assembly ID already present in database."))) + } else if (ass_id == "") { + HTML(paste( + '', + paste("", + "  Empty Assembly ID."))) + } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { + HTML(paste( + '', + paste("", + "  Invalid Assembly ID. Avoid special characters."))) + } else if(grepl(" ", ass_id)) { + HTML(paste( + '', + paste("", + "  Invalid Assembly ID. Avoid empty spaces."))) + } else {HTML(paste( + '', + paste("", + "  Assembly ID compatible with local database.")))} + }) + + # Render Typing Results if finished + observe({ + if(Typing$progress_format_end == 999999) { + if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { + if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { + output$typing_result_table <- renderRHandsontable({ + Typing$typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) + Typing$typing_result_table <- mutate_all(Typing$typing_result_table, as.character) + if(nrow(Typing$typing_result_table) > 0) { + if(nrow(Typing$typing_result_table) > 15) { + rhandsontable(Typing$typing_result_table, rowHeaders = NULL, + stretchH = "all", height = 500, readOnly = TRUE, + contextMenu = FALSE) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + } else { + rhandsontable(Typing$typing_result_table, rowHeaders = NULL, + stretchH = "all", readOnly = TRUE, + contextMenu = FALSE,) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + } + } + }) + + output$single_typing_results <- renderUI({ + result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) + number_events <- nrow(result_table) + + n_new <- length(grep("New Variant", result_table$Event)) + + n_missing <- number_events - n_new + + # Show results table only if successful typing + if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { + if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { + if(number_events > 0) { + column( + width = 12, + HTML(paste("", + length(Typing$scheme_loci_f) - number_events, + "loci were assigned a variant from local scheme.")), + br(), + HTML(paste("", + n_missing, + if(n_missing == 1) " locus not assigned (NA)." else " loci not assigned (NA).")), + br(), + HTML(paste("", + n_new, + if(n_new == 1) " locus with new variant." else " loci with new variants.")), + br(), br(), + rHandsontableOutput("typing_result_table") + ) + } else { + column( + width = 12, + HTML(paste("", + length(Typing$scheme_loci_f), + "successfully assigned from local scheme.")) + ) + } + } + } + }) + + } else { + + output$single_typing_results <- NULL + + } + } else { + output$single_typing_results <- NULL + } + } + + }) + + # Render Initiate Typing UI + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + # Render Declare Metadata UI + + observe({ + if (nrow(Typing$single_path) < 1) { + output$genome_path <- renderUI(HTML( + paste("", "No file selected.") + )) + + # dont show subsequent metadata declaration and typing start UI + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + } else if (nrow(Typing$single_path) > 0) { + + if (str_detect(str_sub(Typing$single_path$name, start = -6), ".fasta") | + str_detect(str_sub(Typing$single_path$name, start = -6), ".fna") | + str_detect(str_sub(Typing$single_path$name, start = -6), ".fa")) { + + # Render selected assembly path + output$genome_path <- renderUI({ + HTML( + paste( + "", + as.character(Typing$single_path$name) + ) + ) + }) + + # Render metadata declaration box + output$metadata_single_box <- renderUI({ + + # Render placeholder + updateTextInput(session, "assembly_id", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) + updateTextInput(session, "assembly_name", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) + + column( + width = 3, + align = "center", + br(), br(), + h3(p("Declare Metadata"), style = "color:white; margin-left:-40px"), + br(), br(), + div( + class = "multi_meta_box", + box( + solidHeader = TRUE, + status = "primary", + width = "90%", + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("assembly_id", + value = "", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 12, + uiOutput("single_select_issues") + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("assembly_name", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + dateInput("append_isodate", + label = "", + width = "80%", + max = Sys.Date()) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_host", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table_country", + pickerInput( + "append_country", + label = "", + choices = list("Common" = sel_countries, + "All Countries" = country_names), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "90%" + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput( + "append_city", + label = "", + width = "80%" + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + actionButton( + inputId = "conf_meta_single", + label = "Confirm" + ), + br() + ) + ), + br() + ) + ) + ) + }) + } else { + show_toast( + title = "Wrong file type (only fasta/fna/fa)", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } + }) + + # Get genome datapath + + observe({ + # Get selected Genome in Single Mode + shinyFileChoose(input, + "genome_file", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + Typing$single_path <- parseFilePaths(roots = c(Home = path_home(), Root = "/"), input$genome_file) + + }) + + #### Run blat ---- + + observeEvent(input$typing_start, { + + log_print("Input typing_start") + + if(tail(readLogFile(), 1) != "0") { + show_toast( + title = "Pending Multi Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if (Screening$status == "started") { + show_toast( + title = "Pending Gene Screening", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + if(!is.null(DB$data)) { + if(sum(apply(DB$data, 1, anyNA)) >= 1) { + DB$no_na_switch <- TRUE + } else { + DB$no_na_switch <- FALSE + } + } + + # Activate entry detection + DB$check_new_entries <- TRUE + + Typing$single_end <- FALSE + + Typing$progress_format_start <- 0 + Typing$progress_format_end <- 0 + + # Remove Initiate Typing UI + output$initiate_typing_ui <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + # status feedback + Typing$status <- "Processing" + + # Locate folder containing cgMLST scheme + search_string <- paste0(gsub(" ", "_", DB$scheme), "_alleles") + + scheme_folders <- dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme))) + + if (any(grepl(search_string, scheme_folders))) { + + # reset results file + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + } + + # blat initiate index + scheme_select <- as.character(scheme_folders[which(grepl(search_string, scheme_folders))]) + + show_toast( + title = "Typing Initiated", + type = "success", + position = "bottom-end", + timer = 6000 + ) + + log_print("Initiated single typing") + + ### Run blat Typing + + single_typing_df <- data.frame( + db_path = DB$database, + wd = getwd(), + save = input$save_assembly_st, + scheme = paste0(gsub(" ", "_", DB$scheme)), + genome = Typing$single_path$datapath, + alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", search_string) + ) + + saveRDS(single_typing_df, "execute/single_typing_df.rds") + + # Execute single typing script + system(paste("bash", paste0(getwd(), "/execute/single_typing.sh")), + wait = FALSE) + + scheme_loci <- list.files(path = scheme_select, full.names = TRUE) + + # Filter the files that have FASTA extensions + Typing$scheme_loci_f <- + scheme_loci[grep("\\.(fasta|fa|fna)$", scheme_loci, ignore.case = TRUE)] + + output$single_typing_progress <- renderUI({ + fluidRow( + br(), br(), + column(width = 1), + column( + width = 3, + h3(p("Pending Single Typing ..."), style = "color:white") + ), + br(), br(), br(), + fluidRow( + column(width = 1), + column( + width = 4, + br(), br(), br(), + fluidRow( + column( + width = 12, + uiOutput("reset_single_typing"), + HTML( + paste( + "", + as.character(Typing$single_path$name) + ) + ), + br(), br(), + progressBar( + "progress_bar", + value = 0, + display_pct = TRUE, + title = "" + ) + ) + ), + fluidRow( + column( + width = 12, + uiOutput("typing_formatting"), + uiOutput("typing_fin") + ) + ) + ), + column(1), + column( + width = 5, + br(), br(), br(), + uiOutput("single_typing_results") + ) + ) + ) + }) + } else { + log_print("Folder containing cgMLST alleles not in working directory") + + show_alert( + title = "Error", + text = paste0( + "Folder containing cgMLST alleles not in working directory.", + "\n", + "Download cgMLST Scheme for selected Organism first." + ), + type = "error" + ) + } + } + }) + + # Function to update Progress Bar + update <- reactive({ + invalidateLater(3000, session) + + # write progress in process tracker + cat( + c(length(list.files(paste0(getwd(), "/execute/blat_single/results"))), + readLines(paste0(getwd(), "/logs/progress.txt"))[-1]), + file = paste0(getwd(), "/logs/progress.txt"), + sep = "\n" + ) + + progress <- readLines(paste0(getwd(), "/logs/progress.txt")) + + # if typing with blat is finished -> "attaching" phase started + if(!is.na(progress[1])) { + if(!is.na(progress[2])) { + if(progress[2] == "888888") { + Typing$progress_format_start <- progress[2] + Typing$pending_format <- progress[2] + Typing$status <- "Attaching" + } + } + # "attaching" phase completed + if(!is.na(progress[3])) { + if(progress[3] == "999999") { + Typing$progress_format_end <- progress[3] + Typing$entry_added <- progress[3] + Typing$status <- "Finalized" + } + } + Typing$progress <- as.numeric(progress[1]) + floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) + } else { + floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) + } + }) + + # Observe Typing Progress + observe({ + + if(readLogFile()[1] == "0") { + # Update Progress Bar + updateProgressBar( + session = session, + id = "progress_bar", + value = update(), + total = 100, + title = paste0(as.character(Typing$progress), "/", length(Typing$scheme_loci_f), " loci screened") + ) + } + + if (Typing$progress_format_start == 888888) { + output$typing_formatting <- renderUI({ + column( + width = 12, + align = "center", + br(), + fluidRow( + column( + width = 6, + HTML(paste("", "Transforming data ...")) + ), + column( + width = 3, + align = "left", + HTML(paste('')) + ) + ) + ) + }) + } else { + output$typing_formatting <- NULL + } + + # Render when finalized + if (Typing$progress_format_end == 999999) { + + output$typing_formatting <- NULL + + output$typing_fin <- renderUI({ + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { + if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { + req(Typing$scheme_loci_f, Typing$typing_result_table) + if(sum(Typing$typing_result_table$Event != "New Variant") > (0.5 * length(Typing$scheme_loci_f))){ + HTML( + paste("", + sub(".*Successful", "Finished", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + paste("", "Warning: Isolate contains large number of failed allele assignments."), + paste("", "Reset to start another typing process."), + sep = '
\n')) + } else { + HTML(paste("", + sub(".*Successful", "Successful", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + "Reset to start another typing process.", sep = '
')) + } + } else { + HTML(paste("", + sub(".*typing", "Typing", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + "Reset to start another typing process.", sep = '
')) + } + }, + br(), br(), + actionButton( + "reset_single_typing", + "Reset", + icon = icon("arrows-rotate") + ) + ) + ) + }) + } else { + output$typing_fin <- NULL + output$single_typing_results <- NULL + } + + }) + + #### Declare Metadata ---- + + observeEvent(input$conf_meta_single, { + + if(nchar(trimws(input$assembly_id)) < 1) { + ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) + } else { + ass_id <- trimws(input$assembly_id) + } + + if(nchar(trimws(input$assembly_name)) < 1) { + ass_name <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) + } else { + ass_name <- trimws(input$assembly_name) + } + + if(ass_id %in% unlist(DB$data["Assembly ID"])) { + show_toast( + title = "Assembly ID already present", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (isFALSE(Typing$reload)) { + show_toast( + title = "Reload Database first", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if (ass_id == "") { + show_toast( + title = "Empty Assembly ID", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { + show_toast( + title = "Invalid Assembly ID. No special characters allowed: ()/\\:*?\"<>|", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if(grepl(" ", ass_id)) { + show_toast( + title = "Empty spaces in Assembly ID not allowed", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + log_print("Single typing metadata confirmed") + + meta_info <- data.frame(assembly_id = ass_id, + assembly_name = ass_name, + cgmlst_typing = DB$scheme, + append_isodate = input$append_isodate, + append_host = trimws(input$append_host), + append_country = trimws(input$append_country), + append_city = trimws(input$append_city), + append_analysisdate = Sys.Date(), + db_directory = getwd()) + + saveRDS(meta_info, paste0( + getwd(), + "/execute/meta_info_single.rds" + )) + + show_toast( + title = "Metadata declared", + type = "success", + position = "bottom-end", + timer = 3000 + ) + + # Render Start Typing UI + output$start_typing_ui <- renderUI({ + div( + class = "multi_start_col", + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Start Typing"), style = "color:white"), + br(), + br(), + HTML( + paste( + "", + "Typing by ", + DB$scheme, + " scheme." + ) + ), + br(), br(), br(), br(), + div( + class = "save-assembly", + materialSwitch( + "save_assembly_st", + h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), + value = TRUE, + right = TRUE) + ), + HTML( + paste( + "", + "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." + ) + ), + br(), br(), br(), br(), + actionButton( + inputId = "typing_start", + label = "Start", + icon = icon("circle-play") + ) + ) + ) + }) + } + }) + + #### Events Single Typing ---- + + observeEvent(input$reset_single_typing, { + log_print("Reset single typing") + + Typing$status <- "Inactive" + + Typing$progress <- 0 + + Typing$progress_format <- 900000 + + output$single_typing_progress <- NULL + + output$typing_fin <- NULL + + output$single_typing_results <- NULL + + output$typing_formatting <- NULL + + Typing$single_path <- data.frame() + + # reset results file + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + # Resetting single typing progress logfile bar + con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") + + cat("0\n", file = con) + + close(con) + } + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + }) + + # Notification for finalized Single typing + Typing$single_end <- TRUE + Typing$progress_format_end <- 0 + + observe({ + if(Typing$single_end == FALSE) { + if (Typing$progress_format_end == 999999) { + show_toast( + title = "Single Typing finalized", + type = "success", + position = "bottom-end", + timer = 8000 + ) + Typing$single_end <- TRUE + } + } + }) + + ### Multi Typing ---- + + #### Render Multi Typing UI Elements ---- + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + # Render selection info + output$multi_select_info <- renderUI({ + + if(!is.null(Typing$multi_path)) { + if(length(Typing$multi_path) < 1) { + HTML(paste("", + "No files selected.")) + } else { + HTML(paste("", + sum(hot_to_r(input$multi_select_table)$Include == TRUE), + " files selected.")) + } + } + }) + + # Render multi selection table issues + output$multi_select_issues <- renderUI({ + req(Typing$multi_sel_table, input$multi_select_table) + if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & + any(duplicated(hot_to_r(input$multi_select_table)$Files))){ + HTML( + paste( + paste("", + "Some name(s) are already present in local database.
"), + paste("", + "Duplicated name(s).
") + ) + ) + } else if (any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & + !any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + HTML( + paste("", + "Some name(s) are already present in local database.
") + ) + } else if (!any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & + any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + HTML( + paste("", + "Duplicated name(s).
") + ) + } + }) + + output$multi_select_issue_info <- renderUI({ + req(Typing$multi_sel_table, input$multi_select_table) + + multi_select_table <- hot_to_r(input$multi_select_table) + + if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | + any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)])) | + any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + + if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + + if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | + any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + HTML(paste( + paste( + '', + paste("", + " Rename highlighted isolates or deselect them.
")), + paste( + '', + paste("", + " Filename(s) contain(s) empty spaces.")) + )) + } else { + HTML(paste( + '', + paste("", + " Filename(s) contain(s) empty spaces."))) + } + } else { + HTML(paste( + '', + paste("", + " Rename highlighted isolates or deselect them."))) + } + } else { + HTML(paste( + '', + paste("", + " Files ready for allelic typing."))) + } + }) + + # Render Metadata Select Box after Folder selection + observe({ + if(!is.null(Typing$multi_sel_table)) { + if (nrow(Typing$multi_sel_table) > 0) { + + output$multi_select_tab_ctrls <- renderUI( + fluidRow( + column(1), + column( + width = 2, + align = "left", + actionButton( + "sel_all_mt", + "All", + icon = icon("check") + ) + ), + column( + width = 2, + align = "left", + actionButton( + "desel_all_mt", + "None", + icon = icon("xmark") + ) + ), + column(2), + column( + width = 5, + align = "right", + br(), + uiOutput("multi_select_issues") + ) + ) + ) + + output$metadata_multi_box <- renderUI({ + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Declare Metadata"), style = "color:white;margin-left:-40px"), + br(), br(), + div( + class = "multi_meta_box", + box( + solidHeader = TRUE, + status = "primary", + width = "90%", + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + dateInput("append_isodate_multi", + label = "", + width = "80%", + max = Sys.Date()) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_host_multi", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table_country", + pickerInput( + "append_country_multi", + label = "", + choices = list("Common" = sel_countries, + "All Countries" = country_names), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "90%" + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_city_multi", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + actionButton( + inputId = "conf_meta_multi", + label = "Confirm" + ), + br(), br(), + uiOutput("multi_select_issue_info") + ) + ) + ) + ) + ) + }) + } else { + output$metadata_multi_box <- NULL + } + } + }) + + # Check if ongoing Multi Typing - Render accordingly + observe({ + # Get selected Genome in Multi Mode + shinyDirChoose(input, + "genome_file_multi", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + + Typing$multi_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi) + + files_selected <- list.files(as.character(Typing$multi_path)) + Typing$files_filtered <- files_selected[which(!endsWith(files_selected, ".gz") & + grepl("\\.fasta|\\.fna|\\.fa", files_selected))] + + Typing$multi_sel_table <- data.frame( + Include = rep(TRUE, length(Typing$files_filtered)), + Files = gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", + Typing$files_filtered), + Type = sub(".*(\\.fasta|\\.fasta\\.gz|\\.fna|\\.fna\\.gz|\\.fa|\\.fa\\.gz)$", + "\\1", Typing$files_filtered, perl = F)) + + if(nrow(Typing$multi_sel_table) > 0) { + output$multi_select_tab_ctrls <- renderUI( + fluidRow( + column(1), + column( + width = 2, + align = "left", + actionButton( + "sel_all_mt", + "All", + icon = icon("check") + ) + ), + column( + width = 2, + align = "left", + actionButton( + "desel_all_mt", + "None", + icon = icon("xmark") + ) + ), + column(2), + column( + width = 5, + align = "right", + br(), + uiOutput("multi_select_issues") + ) + ) + ) + } else { + output$multi_select_tab_ctrls <- NULL + } + + if(between(nrow(Typing$multi_sel_table), 1, 15)) { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", contextMenu = FALSE + ) %>% + hot_cols(columnSorting = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()))) + }) + + } else if(nrow(Typing$multi_sel_table) > 15) { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", height = 500, + contextMenu = FALSE + ) %>% + hot_cols(columnSorting = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, + readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()))) + + }) + + } else { + output$multi_select_table <- NULL + } + }) + + observeEvent(input$conf_meta_multi, { + + multi_select_table <- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] + + if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", multi_select_table$Files)) %in% unlist(DB$data["Assembly ID"]))) { + show_toast( + title = "Assembly ID(s) already present", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (any(duplicated(multi_select_table$Files))) { + show_toast( + title = "Duplicated filename(s)", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (any(multi_select_table$Files == "")) { + show_toast( + title = "Empty filename(s)", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (any(grepl("[()/\\:*?\"<>|]", multi_select_table$Files))) { + show_toast( + title = "Invalid filename(s). No special characters allowed: ()/\\:*?\"<>|", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (!any(multi_select_table$Include == TRUE)) { + show_toast( + title = "No files selected", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + show_toast( + title = "Empty spaces in filename(s) not allowed", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (isFALSE(Typing$reload)) { + show_toast( + title = "Reload Database first", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + log_print("Multi typing metadata confirmed") + + meta_info <- data.frame(cgmlst_typing = DB$scheme, + append_isodate = trimws(input$append_isodate_multi), + append_host = trimws(input$append_host_multi), + append_country = trimws(input$append_country_multi), + append_city = trimws(input$append_city_multi), + append_analysisdate = Sys.Date(), + db_directory = getwd()) + + saveRDS(meta_info, paste0(getwd(), "/execute/meta_info.rds")) + + show_toast( + title = "Metadata declared", + type = "success", + position = "bottom-end", + timer = 3000 + ) + + output$start_multi_typing_ui <- renderUI({ + div( + class = "multi_start_col", + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Start Typing"), style = "color:white"), + br(), + br(), + HTML( + paste( + "", + "Typing by ", + DB$scheme, + " scheme." + ) + ), + br(), br(), br(), br(), + div( + class = "save-assembly", + materialSwitch( + "save_assembly_mt", + h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), + value = TRUE, + right = TRUE) + ), + HTML( + paste( + "", + "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." + ) + ), + br(), br(), br(), br(), + actionButton( + "start_typ_multi", + "Start", + icon = icon("circle-play") + ) + ) + ) + }) + } + }) + + #### Events Multi Typing ---- + + observeEvent(input$sel_all_mt, { + session$sendCustomMessage(type = "setColumnValue", message = list(value = TRUE)) + }) + + observeEvent(input$desel_all_mt, { + session$sendCustomMessage(type = "setColumnValue", message = list(value = FALSE)) + }) + + # Print Log + output$print_log <- downloadHandler( + filename = function() { + log_print(paste0("Save multi typing log ", paste("Multi_Typing_", Sys.Date(), ".txt", sep = ""))) + paste("Multi_Typing_", Sys.Date(), ".txt", sep = "") + }, + content = function(file) { + writeLines(readLines(paste0(getwd(), "/logs/script_log.txt")), file) + } + ) + + # Reset Multi Typing + observeEvent(input$reset_multi, { + if(!grepl("Multi Typing", tail(readLines(paste0(getwd(),"/logs/script_log.txt")), n = 1))) { + showModal( + modalDialog( + paste0( + "A Multi Typing process is still pending. Stopping this process will cancel the processing." + ), + title = "Reset Multi Typing", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_multi_kill", "Stop", class = "btn btn-danger") + ) + ) + ) + } else { + + log_print("Reset multi typing") + + # Reset multi typing result list + saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) + multi_help <- FALSE + Typing$result_list <- NULL + + # Null logfile + writeLines("0", paste0(getwd(), "/logs/script_log.txt")) + + # Reset User Feedback variable + Typing$pending_format <- 0 + Typing$multi_started <- FALSE + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + output$pending_typing <- NULL + output$multi_typing_results <- NULL + } + }) + + # Confirm Reset after + observeEvent(input$conf_multi_kill, { + removeModal() + + log_print("Kill multi typing") + + # Kill multi typing and reset logfile + system(paste("bash", paste0(getwd(), "/execute/kill_multi.sh")), + wait = TRUE) + + show_toast( + title = "Execution cancelled", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + + # Kill multi typing and reset logfile + writeLines("0", paste0(getwd(), "/logs/script_log.txt")) + + #Reset multi typing result list + saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) + multi_help <- FALSE + Typing$result_list <- NULL + + # Reset User Feedback variable + Typing$pending_format <- 0 + output$pending_typing <- NULL + output$multi_typing_results <- NULL + Typing$failures <- 0 + Typing$successes <- 0 + Typing$multi_started <- FALSE + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + }) + + observeEvent(input$start_typ_multi, { + log_print("Initiate multi typing") + + if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if (Screening$status == "started") { + show_toast( + title = "Pending Gene Screening", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + removeModal() + + show_toast( + title = "Multi Typing started", + type = "success", + position = "bottom-end", + timer = 10000 + ) + + Typing$new_table <- NULL + + # Remove Allelic Typing Controls + output$initiate_multi_typing_ui <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + + # Activate entry detection + DB$check_new_entries <- TRUE + + # Initiate Feedback variables + Typing$multi_started <- TRUE + Typing$pending <- TRUE + Typing$failures <- 0 + Typing$successes <- 0 + + # get selected file table + multi_select_table <- hot_to_r(input$multi_select_table) + + filenames <- paste(multi_select_table$Files[which(multi_select_table$Include == TRUE)], collapse = " ") + + files <- Typing$multi_sel_table$Files[which(multi_select_table$Include == TRUE)] + type <- Typing$multi_sel_table$Type[which(multi_select_table$Include == TRUE)] + genome_names <- paste(paste0(gsub(" ", "~", files), type), collapse = " ") + + # Start Multi Typing Script + multi_typing_df <- data.frame( + db_path = DB$database, + wd = getwd(), + save = input$save_assembly_mt, + scheme = paste0(gsub(" ", "_", DB$scheme)), + genome_folder = as.character(parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi)), + filenames = paste0(filenames, collapse= " "), + genome_names = genome_names, + alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles") + ) + + saveRDS(multi_typing_df, "execute/multi_typing_df.rds") + + # Execute multi blat script + system(paste("bash", paste0(getwd(), "/execute/multi_typing.sh")), wait = FALSE) + } + }) + + + #### User Feedback ---- + + observe({ + if(file.exists(paste0(getwd(), "/logs/script_log.txt"))) { + if(Typing$multi_started == TRUE) { + check_multi_status() + } else { + Typing$status <- "Inactive" + } + } + }) + + check_multi_status <- reactive({ + + invalidateLater(3000, session) + + log <- readLines(paste0(getwd(), "/logs/script_log.txt")) + + # Determine if Single or Multi Typing + if(str_detect(log[1], "Multi")) { + Typing$pending_mode <- "Multi" + } else { + Typing$pending_mode <- "Single" + } + + # Check typing status + if(str_detect(tail(log, 1), "Attaching")) { + Typing$status <- "Attaching" + } else if(str_detect(tail(log, 1), "Successful")) { + Typing$multi_help <- TRUE + Typing$status <- "Successful" + show_toast( + title = paste0("Successful", sub(".*Successful", "", tail(log, 1))), + type = "success", + position = "bottom-end", + timer = 8000 + ) + } else if(str_detect(tail(log, 1), "failed")) { + Typing$status <- "Failed" + show_toast( + title = sub(".* - ", "", tail(log, 1)), + type = "error", + position = "bottom-end", + timer = 8000 + ) + } else if(str_detect(tail(log, 1), "Processing")) { + Typing$status <- "Processing" + + if(any(str_detect(tail(log, 2), "Successful"))) { + + if(!identical(Typing$last_success, tail(log, 2)[1])) { + Typing$multi_help <- TRUE + show_toast( + title = paste0("Successful", sub(".*Successful", "", tail(log, 2)[1])), + type = "success", + position = "bottom-end", + timer = 8000 + ) + + Typing$last_success <- tail(log, 2)[1] + } + } else if(any(str_detect(tail(log, 2), "failed"))) { + + if(!identical(Typing$last_failure, tail(log, 2)[1])) { + + show_toast( + title = sub(".* - ", "", tail(log, 2)[1]), + type = "error", + position = "bottom-end", + timer = 8000 + ) + + Typing$last_failure <- tail(log, 2)[1] + } + } + } else if(str_detect(tail(log, 1), "finalized")) { + Typing$multi_help <- TRUE + Typing$status <- "Finalized" + + if(Typing$pending == TRUE) { + show_toast( + title = "Typing finalized", + type = "success", + position = "bottom-end", + timer = 8000 + ) + + Typing$pending <- FALSE + } + } + }) + + ##### Render Multi Typing UI Feedback ---- + + observe({ + if(!is.null(input$multi_results_picker)) { + Typing$multi_table_length <- nrow(Typing$result_list[[input$multi_results_picker]]) + } else { + Typing$multi_table_length <- NULL + } + }) + + observe({ + if(!is.null(Typing$result_list)) { + if(length(Typing$result_list) > 0) { + if(is.null(Typing$multi_table_length)) { + output$multi_typing_result_table <- renderRHandsontable({ + rhandsontable(Typing$result_list[[input$multi_results_picker]], + rowHeaders = NULL, stretchH = "all", + readOnly = TRUE, contextMenu = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + + } else { + if(Typing$multi_table_length > 15) { + output$multi_typing_result_table <- renderRHandsontable({ + rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, + stretchH = "all", height = 500, + readOnly = TRUE, contextMenu = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } else { + output$multi_typing_result_table <- renderRHandsontable({ + rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, + stretchH = "all", readOnly = TRUE, + contextMenu = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } + } + } else { + output$multi_typing_result_table <- NULL + } + } else { + output$multi_typing_result_table <- NULL + } + }) + + observe({ + if(!is.null(Typing$multi_result_status)) { + if(Typing$multi_result_status == "start" | Typing$multi_result_status == "finalized"){ + + if(Typing$multi_help == TRUE) { + Typing$result_list <- readRDS(paste0(getwd(), "/execute/event_list.rds")) + Typing$multi_help <- FALSE + } + } + } + }) + + + observe({ + #Render multi typing result feedback table + + if(!is.null(Typing$result_list)) { + if(length(Typing$result_list) > 0) { + output$multi_typing_results <- renderUI({ + column( + width = 12, + fluidRow( + column(1), + column( + width = 9, + br(), br(), + br(), br(), + br(), + div( + class = "mult_res_sel", + selectInput( + "multi_results_picker", + label = h5("Select Typing Results", style = "color:white"), + choices = names(Typing$result_list), + selected = names(Typing$result_list)[length(names(Typing$result_list))], + ) + ), + br(), br() + ) + ), + rHandsontableOutput("multi_typing_result_table") + ) + }) + } + } + }) + + observe({ + + # Render log content + output$logText <- renderPrint({ + cat(rev(paste0(tail(readLogFile(), 50), "\n"))) + }) + + output$logTextFull <- renderPrint({ + cat(rev(paste0(readLines(paste0(getwd(), "/logs/script_log.txt")), "\n"))) + }) + + # Render Pending UI + if(!grepl("Multi Typing", tail(readLogFile(), n = 1)) & grepl("Start Multi Typing", head(readLogFile(), n = 1))) { + + Typing$multi_result_status <- "start" + + output$initiate_multi_typing_ui <- NULL + + output$pending_typing <- renderUI({ + fluidRow( + fluidRow( + br(), br(), + column(width = 2), + column( + width = 4, + h3(p("Pending Typing ..."), style = "color:white"), + br(), br(), + fluidRow( + column( + width = 5, + HTML(paste('')) + ), + column( + width = 6, + align = "left", + actionButton( + "reset_multi", + "Terminate", + icon = icon("ban") + ) + ) + ), + ) + ), + br(), br(), + fluidRow( + column(width = 2), + column( + width = 10, + verbatimTextOutput("logText") + ) + ) + ) + }) + } else if(grepl("Multi Typing finalized", tail(readLogFile(), n = 1))) { + + Typing$multi_result_status <- "finalized" + + Typing$last_scheme <- NULL + + output$initiate_multi_typing_ui <- NULL + + output$pending_typing <- renderUI({ + + fluidRow( + fluidRow( + br(), br(), + column(width = 2), + column( + width = 4, + h3(p("Pending Multi Typing ..."), style = "color:white"), + br(), br(), + HTML(paste("", + paste("Typing of", sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Processing")), "assemblies finalized."), + paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Successful")), "successes."), + paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "failed")), "failures."), + "Reset to start another typing process.", + sep = '
')), + br(), br(), + fluidRow( + column( + width = 5, + actionButton( + "reset_multi", + "Reset", + icon = icon("arrows-rotate") + ) + ), + column( + width = 5, + downloadButton( + "print_log", + "Logfile", + icon = icon("floppy-disk") + ) + ) + ) + ) + ), + br(), br(), + fluidRow( + column(width = 2), + column( + width = 10, + verbatimTextOutput("logTextFull"), + ) + ) + ) + }) + } else if (!grepl("Start Multi Typing", head(readLogFile(), n = 1))){ + output$pending_typing <- NULL + Typing$multi_result_status <- "idle" + } + }) + + observe({ + # Get selected Genome in Multi Mode + shinyDirChoose(input, + "hash_dir", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + }) + + observeEvent(input$hash_start, { + dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) + if (!is_empty(list.files(dir_path)) && all(endsWith(list.files(dir_path), ".fasta"))) { + log_print("Hashing directory using utilities") + shinyjs::hide("hash_start") + shinyjs::show("hash_loading") + show_toast( + title = "Hashing started!", + type = "success", + position = "bottom-end", + timer = 6000 + ) + hash_database(dir_path) + shinyjs::hide("hash_loading") + shinyjs::show("hash_start") + show_toast( + title = "Hashing completed!", + type = "success", + position = "bottom-end", + timer = 6000 + ) + } else { + show_toast( + title = "Incorrect folder selected!", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + +} # end server + +# _______________________ #### + +# Shiny ---- + +shinyApp(ui = ui, server = server) From f32892da156f5605e789efb39ff68b060dde760e Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 15:48:41 +0200 Subject: [PATCH 68/75] Added link to NCBI/AMRFinder --- App.R | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/App.R b/App.R index 9f57ace..f19c5a1 100644 --- a/App.R +++ b/App.R @@ -23139,8 +23139,10 @@ server <- function(input, output, session) { HTML( paste( '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + '', + DB$scheme, 'available for gene screening with ', + 'NCBI/AMRFinder.', + '' ) ) ) @@ -23148,9 +23150,11 @@ server <- function(input, output, session) { p( HTML( paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + '', + '', + DB$scheme, 'not available for gene screening with ', + 'NCBI/AMRFinder.', + '' ) ) ) @@ -23163,8 +23167,10 @@ server <- function(input, output, session) { HTML( paste( '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + '', + DB$scheme, 'available for gene screening with ', + 'NCBI/AMRFinder.', + '' ) ) ) @@ -23172,9 +23178,11 @@ server <- function(input, output, session) { p( HTML( paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + '', + '', + DB$scheme, 'not available for gene screening with ', + 'NCBI/AMRFinder.', + '' ) ) ) From 4ac6f0df74f4c7c8cf237f4b57081d426c509f3b Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 17:38:06 +0200 Subject: [PATCH 69/75] Minor changes --- App.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/App.R b/App.R index f19c5a1..2b69951 100644 --- a/App.R +++ b/App.R @@ -11184,11 +11184,11 @@ server <- function(input, output, session) { paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv") }, content = function(file) { - download_matrix <<- hot_to_r(input$db_entries) + download_matrix <- hot_to_r(input$db_entries) - if(input$download_table_hashes == TRUE) { - included_loci <<- colnames(select(download_matrix, -(1:(13 + nrow(DB$cust_var))))) - full_hashes <<- DB$allelic_profile[included_loci] + if(input$download_table_hashes == FALSE) { + included_loci <- colnames(select(download_matrix, -(1:(13 + nrow(DB$cust_var))))) + full_hashes <- DB$allelic_profile[included_loci] download_matrix[included_loci] <- full_hashes } From 65d72b834d66627255b6b941b854c07d1f34ab5a Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 17:43:01 +0200 Subject: [PATCH 70/75] Temporary removal of utilities tab allele database hashing feature --- App.R | 86 ----------------------------------------------------------- 1 file changed, 86 deletions(-) diff --git a/App.R b/App.R index 2b69951..dd5f675 100644 --- a/App.R +++ b/App.R @@ -5267,50 +5267,6 @@ ui <- dashboardPage( ) ), - ## Tab Utilities ------------------------------------------------------- - - tabItem( - tabName = "utilities", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Utilities"), style = "color:white") - ) - ), - br(), - hr(), - column( - width = 5, - align = "left", - shinyDirButton( - "hash_dir", - "Choose folder with .fasta files", - title = "Locate folder with loci", - buttonType = "default", - style = "border-color: white; margin: 10px; min-width: 200px; text-align: center" - ), - actionButton("hash_start", "Start Hashing", icon = icon("circle-play")), - shinyjs::hidden( - div(id = "hash_loading", - HTML('')) - ) - ) - # br(), - # actionButton( - # "backup_database", - # "Create backup", - # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - # ), - # br(), - # actionButton( - # "import_db_backup", - # "Restore backup", - # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - # ) - ), - - ## Tab Screening ------------------------------------------------------- tabItem( @@ -26036,48 +25992,6 @@ server <- function(input, output, session) { Typing$multi_result_status <- "idle" } }) - - observe({ - # Get selected Genome in Multi Mode - shinyDirChoose(input, - "hash_dir", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - }) - - observeEvent(input$hash_start, { - dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) - if (!is_empty(list.files(dir_path)) && all(endsWith(list.files(dir_path), ".fasta"))) { - log_print("Hashing directory using utilities") - shinyjs::hide("hash_start") - shinyjs::show("hash_loading") - show_toast( - title = "Hashing started!", - type = "success", - position = "bottom-end", - timer = 6000 - ) - hash_database(dir_path) - shinyjs::hide("hash_loading") - shinyjs::show("hash_start") - show_toast( - title = "Hashing completed!", - type = "success", - position = "bottom-end", - timer = 6000 - ) - } else { - show_toast( - title = "Incorrect folder selected!", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - } # end server # _______________________ #### From a711c43406bc2c8a60ba6ed101741f3629f619d4 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 17:53:43 +0200 Subject: [PATCH 71/75] Removed Utilities tab UI --- App.R | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/App.R b/App.R index dd5f675..d5f3753 100644 --- a/App.R +++ b/App.R @@ -6462,11 +6462,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -6642,11 +6637,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -6732,11 +6722,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -6824,11 +6809,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -6945,11 +6925,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -7165,11 +7140,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -7232,11 +7202,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -9341,11 +9306,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -9882,11 +9842,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) @@ -9945,11 +9900,6 @@ server <- function(input, output, session) { text = "Visualization", tabName = "visualization", icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") ) ) ) From 71ebf59aa4acd804c05545ed277f016ba2b49276 Mon Sep 17 00:00:00 2001 From: Marian Freisleben Date: Tue, 20 Aug 2024 18:16:54 +0200 Subject: [PATCH 72/75] Added skeleton cluster width UI --- App.R | 51813 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 25917 insertions(+), 25896 deletions(-) diff --git a/App.R b/App.R index 0cd1d6b..5a25259 100644 --- a/App.R +++ b/App.R @@ -1,25896 +1,25917 @@ -######## PhyloTrace ######### - -# _______________________ #### -# CRAN Packages -library(shiny) -library(R.utils) -library(igraph) -library(shinyWidgets) -library(shinydashboard) -library(dashboardthemes) -library(ggplot2) -library(ggnewscale) -library(ggplotify) -library(ape) -library(tidyverse) -library(rlang) -library(tidytree) -library(shinyFiles) -library(dplyr) -library(downloader) -library(rvest) -library(rmarkdown) -library(knitr) -library(kableExtra) -library(fs) -library(data.table) -library(zoo) -library(ggnetwork) -library(rhandsontable) -library(visNetwork) -library(proxy) -library(phangorn) -library(cowplot) -library(viridis) -library(RColorBrewer) -library(bslib) -library(bsicons) -library(DT) -library(shinyBS) -library(openssl) -library(logr) -# Bioconductor Packages -library(treeio) -library(ggtree) -library(ggtreeExtra) - -source(paste0(getwd(), "/www/resources.R")) - -options(ignore.negative.edge=TRUE) - -# User Interface ---- - -ui <- dashboardPage( - - title = "PhyloTrace 1.5.0", - - # Title - dashboardHeader( - - title = span( - div( - class = "img_logo", - img( - src = "PhyloTrace.jpg", width = 190 - ) - ) - ), - uiOutput("loaded_scheme"), - uiOutput("databasetext"), - uiOutput("statustext"), - tags$li(class = "dropdown", - tags$span(id = "currentTime", style = "color:white; font-weight:bold;")), - disable = FALSE - ), - - ## Sidebar ---- - dashboardSidebar( - tags$head(includeCSS("www/head.css")), - tags$style(includeCSS("www/body.css")), - tags$style(HTML( - "@keyframes pulsate { - 0% { transform: scale(1); } - 50% { transform: scale(1.1); } - 100% { transform: scale(1); } - } - .pulsating-button { - animation: pulsate 1s ease infinite; - } - .pulsating-button:hover { - animation: none; - }")), - br(), br(), - sidebarMenu( - id = "tabs", - sidebarMenuOutput("menu"), - uiOutput("menu_sep2"), - conditionalPanel( - "input.tabs==='db_browse_entries'", - uiOutput("entrytable_sidebar") - ), - conditionalPanel( - "input.tabs==='db_distmatrix'", - uiOutput("distmatrix_sidebar") - ), - conditionalPanel( - "input.tabs==='db_missing_values'", - uiOutput("missing_values_sidebar") - ), - conditionalPanel( - "input.tabs==='typing'", - uiOutput("typing_sidebar") - ), - conditionalPanel( - "input.tabs==='visualization'", - uiOutput("visualization_sidebar") - ), - conditionalPanel( - "input.tabs==='gs_profile'", - uiOutput("screening_sidebar") - ) - ) - ), - - dashboardBody( - tags$head(tags$link(rel = "shortcut icon", href = "favicon.ico")), - shinyjs::useShinyjs(), - - shinyDashboardThemeDIY( - ### general - appFontFamily = "Liberation Sans", - appFontColor = "#000000", - primaryFontColor = "#ffffff", - infoFontColor = "rgb(0,0,0)", - successFontColor = "rgb(0,0,0)", - warningFontColor = "rgb(0,0,0)", - dangerFontColor = "rgb(0,0,0)", - bodyBackColor = cssGradientThreeColors( - direction = "down", - colorStart = "#282f38", - colorMiddle = "#384454", - colorEnd = "#495d78", - colorStartPos = 0, - colorMiddlePos = 50, - colorEndPos = 100 - ), - - ### header - logoBackColor = "#282f38", - headerButtonBackColor = "#282f38", - headerButtonIconColor = "#18ece1", - headerButtonBackColorHover = "#282f38", - headerButtonIconColorHover = "#ffffff", - headerBackColor = "#282f38", - headerBoxShadowColor = "#aaaaaa", - headerBoxShadowSize = "0px 0px 0px", - - ### sidebar - sidebarBackColor = cssGradientThreeColors( - direction = "down", - colorStart = "#282f38", - colorMiddle = "#384454", - colorEnd = "#495d78", - colorStartPos = 0, - colorMiddlePos = 50, - colorEndPos = 100), - - sidebarPadding = 0, - sidebarMenuBackColor = "transparent", - sidebarMenuPadding = 0, - sidebarMenuBorderRadius = 0, - sidebarShadowRadius = "5px 5px 5px", - sidebarShadowColor = "#282f38", - sidebarUserTextColor = "#ffffff", - sidebarSearchBackColor = "rgb(55,72,80)", - sidebarSearchIconColor = "rgb(153,153,153)", - sidebarSearchBorderColor = "rgb(55,72,80)", - sidebarTabTextColor = "rgb(255,255,255)", - sidebarTabTextSize = 15, - sidebarTabBorderStyle = "none none solid none", - sidebarTabBorderColor = "rgb(35,106,135)", - sidebarTabBorderWidth = 0, - sidebarTabBackColorSelected = cssGradientThreeColors( - direction = "right", - colorStart = "rgba(44,222,235,1)", - colorMiddle = "rgba(44,222,235,1)", - colorEnd = "rgba(0,255,213,1)", - colorStartPos = 0, - colorMiddlePos = 30, - colorEndPos = 100 - ), - sidebarTabTextColorSelected = "rgb(0,0,0)", - sidebarTabRadiusSelected = "0px 0px 0px 0px", - sidebarTabBackColorHover = cssGradientThreeColors( - direction = "right", - colorStart = "rgba(44,222,235,1)", - colorMiddle = "rgba(44,222,235,1)", - colorEnd = "rgba(0,255,213,1)", - colorStartPos = 0, - colorMiddlePos = 30, - colorEndPos = 100 - ), - sidebarTabTextColorHover = "rgb(50,50,50)", - sidebarTabBorderStyleHover = "none none solid none", - sidebarTabBorderColorHover = "rgb(75,126,151)", - sidebarTabBorderWidthHover = 0, - sidebarTabRadiusHover = "0px 0px 0px 0px", - - ### boxes - boxBackColor = "#ffffff", - boxBorderRadius = 7, - boxShadowSize = "0px 0px 0px", - boxShadowColor = "#ffffff", - boxTitleSize = 20, - boxDefaultColor = "#00a65a", - boxPrimaryColor = "#ffffff", - boxInfoColor = "#00a65a", - boxSuccessColor = "#00a65a", - boxWarningColor = "#ffffff", - boxDangerColor = "#ffffff", - tabBoxTabColor = "#ffffff", - tabBoxTabTextSize = 14, - tabBoxTabTextColor = "rgb(0,0,0)", - tabBoxTabTextColorSelected = "rgb(0,0,0)", - tabBoxBackColor = "#ffffff", - tabBoxHighlightColor = "#ffffff", - tabBoxBorderRadius = 5, - - ### inputs - buttonBackColor = "#282F38", - buttonTextColor = "#ffffff", - buttonBorderColor = "#282F38", - buttonBorderRadius = 5, - buttonBackColorHover = cssGradientThreeColors( - direction = "right", - colorStart = "rgba(44,222,235,1)", - colorMiddle = "rgba(44,222,235,1)", - colorEnd = "rgba(0,255,213,1)", - colorStartPos = 0, - colorMiddlePos = 30, - colorEndPos = 100 - ), - buttonTextColorHover = "#000000", - buttonBorderColorHover = "transparent", - textboxBackColor = "#ffffff", - textboxBorderColor = "#ffffff", - textboxBorderRadius = 5, - textboxBackColorSelect = "#ffffff", - textboxBorderColorSelect = "#000000", - - ### tables - tableBackColor = "rgb(255,255,255)", - tableBorderColor = "rgb(240,240,240)", - tableBorderTopSize = 1, - tableBorderRowSize = 1 - ), - - uiOutput("start_message"), - - tabItems( - - ## Tab Database ---- - - ### Tab Browse Entries ---- - - tabItem( - tabName = "db_browse_entries", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Browse Local Database"), style = "color:white") - ) - ), - hr(), br(), - br(), - br(), - uiOutput("no_scheme_entries"), - uiOutput("db_no_entries"), - uiOutput("entry_table_controls"), - br(), br(), - fluidRow( - column(1), - column( - width = 8, - uiOutput("db_entries_table") - ), - column( - width = 3, - align = "left", - uiOutput("delete_box"), - uiOutput("compare_allele_box"), - uiOutput("download_entries"), - br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br() - ) - ), - br() - ), - - ### Tab Scheme Info ---- - - tabItem( - tabName = "db_schemeinfo", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Scheme Info"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - uiOutput("no_scheme_info"), - fluidRow( - column(2), - column( - width = 7, - align = "center", - fluidRow( - column( - width = 7, - align = "right", - uiOutput("scheme_header") - ), - column( - width = 2, - align = "left", - uiOutput("download_scheme_info") - ) - ), - br(), - br(), - uiOutput("scheme_info") - ) - ) - ), - - ### Tab Loci Info ---- - - tabItem( - tabName = "db_loci_info", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Loci Info"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - fluidRow( - column(1), - column( - width = 10, - align = "center", - fluidRow( - column( - width = 6, - align = "right", - uiOutput("loci_header") - ), - column( - width = 2, - align = "left", - uiOutput("download_loci") - ) - ), - br(), - div(class = "loci_table", - dataTableOutput("db_loci")) - ) - ), - br(), br(), - fluidRow( - column(1), - uiOutput("sequence_selector"), - column(1), - column( - width = 7, - br(), - uiOutput("loci_sequences") - ) - ) - ), - - ### Tab Distance Matrix ---- - - tabItem( - tabName = "db_distmatrix", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Distance Matrix"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - uiOutput("no_scheme_distancematrix"), - uiOutput("distancematrix_no_entries"), - fluidRow( - column(1), - uiOutput("distmatrix_show") - ), - br(), br() - ), - - ### Tab Missing Values ---- - - tabItem( - tabName = "db_missing_values", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Missing Values"), style = "color:white") - ) - ), - hr(), br(), br(), br(), - fluidRow( - column( - width = 3, - uiOutput("missing_values"), - fluidRow( - column( - width = 2, - div( - class = "rectangle-red-space" - ) - ), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 75px; position: relative; bottom: -12px", " = ≥ 5% of loci missing") - ) - ) - ) - ) - ) - ), - column( - width = 8, - rHandsontableOutput("table_missing_values") - ) - ) - ), - - ## Tab Manage Schemes ---- - - tabItem( - tabName = "init", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Select cgMLST Scheme"), style = "color:white") - ) - ), - hr(), - fluidRow( - column(1), - column( - width = 3, - br(), - br(), - br(), - pickerInput( - inputId = "select_cgmlst", - label = NULL, - choices = list( - "Acinetobacter baumanii", - "Bacillus anthracis", - "Bordetella pertussis", - "Brucella melitensis", - "Brucella spp.", - "Burkholderia mallei (FLI)", - "Burkholderia mallei (RKI)", - "Burkholderia pseudomallei", - "Campylobacter jejuni/coli", - "Clostridioides difficile", - "Clostridium perfringens", - "Corynebacterium diphtheriae", - "Cronobacter sakazakii/malonaticus", - "Enterococcus faecalis", - "Enterococcus faecium", - "Escherichia coli", - "Francisella tularensis", - "Klebsiella oxytoca sensu lato", - "Klebsiella pneumoniae sensu lato", - "Legionella pneumophila", - "Listeria monocytogenes", - "Mycobacterium tuberculosis complex", - "Mycobacteroides abscessus", - "Mycoplasma gallisepticum", - "Paenibacillus larvae", - "Pseudomonas aeruginosa", - "Salmonella enterica", - "Serratia marcescens", - "Staphylococcus aureus", - "Staphylococcus capitis", - "Streptococcus pyogenes" - ), - width = "300px", - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = FALSE - ) - ), - column( - width = 2, - br(), - br(), - br(), - h5(textOutput("scheme_update_info"), style = "color: white") - ), - column( - width = 2, - br(), - br(), - br(), - actionButton( - "download_cgMLST", - label = "Download", - icon = icon("download") - ), - shinyjs::hidden( - div(id = "loading", - HTML('')) - ) - ) - ), - fluidRow( - column(1), - column( - width = 6, - align = "center", - br(), - br(), - br(), - addSpinner( - tableOutput("cgmlst_scheme"), - spin = "dots", - color = "#ffffff" - ) - ) - ) - ), - - - - ## Tab Allelic Typing ---------------------------------------------- - - - tabItem( - tabName = "typing", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Generate Allelic Profile"), style = "color:white") - ) - ), - hr(), - uiOutput("typing_no_db"), - conditionalPanel( - "input.typing_mode == 'Single'", - fluidRow( - uiOutput("initiate_typing_ui"), - uiOutput("single_typing_progress"), - column(1), - uiOutput("metadata_single_box"), - column(1), - uiOutput("start_typing_ui") - ) - ), - conditionalPanel( - "input.typing_mode == 'Multi'", - fluidRow( - uiOutput("initiate_multi_typing_ui"), - uiOutput("multi_stop"), - column(1), - uiOutput("metadata_multi_box"), - column(1), - uiOutput("start_multi_typing_ui") - ), - fluidRow( - column( - width = 6, - uiOutput("pending_typing") - ), - column( - width = 6, - uiOutput("multi_typing_results") - ) - ) - ) - ), - - - ## Tab Visualization ------------------------------------------------------- - - - tabItem( - tabName = "visualization", - fluidRow( - tags$script(src = "javascript_functions.js"), - column( - width = 12, - align = "center", - br(), - conditionalPanel( - "input.tree_algo=='Minimum-Spanning'", - uiOutput("mst_field") - ), - conditionalPanel( - "input.tree_algo=='Neighbour-Joining'", - uiOutput("nj_field") - ), - conditionalPanel( - "input.tree_algo=='UPGMA'", - uiOutput("upgma_field") - ) - ) - ), - br(), - hr(), - - ### Control panels MST ---- - conditionalPanel( - "input.tree_algo=='Minimum-Spanning'", - fluidRow( - column( - width = 4, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - height = "500px", - h3(p("Layout"), style = "color:white; position:relative; right:-15px"), - hr(), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Title"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "mst_title", - label = "", - width = "100%", - placeholder = "Plot Title" - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_title_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_title_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - numericInput( - "mst_title_size", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 40, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Subtitle"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "mst_subtitle", - label = "", - width = "100%", - placeholder = "Plot Subtitle" - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_subtitle_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_subtitle_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - numericInput( - "mst_subtitle_size", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 20, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ) - ) - ) - ), - hr(), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Legend"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_legend_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_legend_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 11, - sliderInput( - "mst_font_size", - label = h5("Font Size", style = "color:white; margin-bottom: 0px;"), - value = 18, - min = 15, - max = 30, - step = 1, - ticks = FALSE, - width = "180px" - ) - ), - column(1) - ), - br(), - fluidRow( - column( - width = 11, - sliderInput( - "mst_symbol_size", - label = h5("Key Size", style = "color:white; margin-bottom: 0px;"), - value = 20, - min = 10, - max = 30, - step = 1, - ticks = FALSE, - width = "180px" - ) - ), - column(1) - ) - ) - ) - ), - fluidRow( - column( - width = 7, - selectInput( - "mst_legend_ori", - label = "", - width = "100%", - choices = c("Left" = "left", "Right" = "right") - ) - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Background"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 12, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "mst_background_transparent", - h5(p("Transparent"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_background_color", - width = "100%", - selected = "#ffffff", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 4, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - height = "500px", - h3(p("Nodes"), style = "color:white; position:relative; right:-15px"), - hr(), - fluidRow( - column( - width = 6, - column( - width = 12, - align = "left", - h4(p("Label"), style = "color:white;") - ), - column( - width = 12, - align = "center", - div( - class = "label_sel", - uiOutput("mst_node_label") - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "node_font_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - numericInput( - "node_label_fontsize", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 14, - min = 8, - max = 30, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 10, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "mst_color_var", - h5(p("Add Variable"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 2, - bslib::tooltip( - bsicons::bs_icon("info-circle", title = "Only categorical variables can \nbe mapped to the node color", color = "white", - height = "12px", width = "12px", position = "relative", top = "27px", right = "56px"), - "Text shown in the tooltip.", - show = FALSE, - id = "mst_node_col_info" - ) - ) - ), - uiOutput("mst_color_mapping") - ) - ) - ), br() - ) - ), - hr(), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Size"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 12, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "scale_nodes", - h5(p("Scale by Duplicates"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ) - ) - ) - ) - ), - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - align = "left", - conditionalPanel( - "input.scale_nodes==true", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Range') - ) - ) - ), - conditionalPanel( - "input.scale_nodes==false", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Size') - ) - ) - ) - ), - column( - width = 9, - align = "center", - conditionalPanel( - "input.scale_nodes==true", - div( - class = "mst_scale_slider", - sliderInput( - "mst_node_scale", - label = "", - min = 1, - max = 80, - value = c(20, 40), - ticks = FALSE - ) - ) - ), - conditionalPanel( - "input.scale_nodes==false", - div( - class = "mst_scale_slider", - sliderInput( - inputId = "mst_node_size", - label = "", - min = 1, - max = 100, - value = 30, - ticks = FALSE - ) - ) - ) - ) - ), - br() - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Other Elements"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 12, - align = "left", - div( - class = "mat-switch-mst-nodes", - materialSwitch( - "mst_shadow", - h5(p("Show Shadow"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - fluidRow( - column( - width = 3, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Shape') - ) - ) - ), - column( - width = 9, - align = "center", - div( - class = "mst_shape_sel", - selectInput( - "mst_node_shape", - "", - choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), - `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), - selected = c("Dot" = "dot"), - width = "85%" - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 4, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - height = "500px", - h3(p("Edges"), style = "color:white; position:relative; right:-15px"), - hr(), - fluidRow( - column( - width = 6, - column( - width = 12, - align = "left", - h4(p("Label"), style = "color:white;") - ), - column( - width = 12, - align = "center", - div( - class = "label_sel", - selectInput( - "mst_edge_label", - label = "", - choices = c( - `Allelic Distance` = "weight", - Index = "index", - `Assembly ID` = "assembly_id", - `Assembly Name` = "assembly_name", - `Isolation Date` = "isolation_date", - Host = "host", - Country = "country", - City = "city" - ), - selected = c(`Allelic Distance` = "weight"), - width = "100%" - ) - ), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "mst_edge_font_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_edgelabel_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - numericInput( - "mst_edge_font_size", - label = h5("Size", style = "color:white; margin-bottom: 0px;"), - value = 18, - step = 1, - min = 8, - max = 30, - width = "80px" - ) - ) - ) - ), - br() - ) - ), - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - div( - class = "node_color", - colorPickr( - inputId = "mst_color_edge", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_edgecolor_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - sliderInput( - "mst_edge_opacity", - label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), - value = 0.7, - step = 0.1, - min = 0, - max = 1, - ticks = FALSE, - width = "150px" - ) - ) - ) - ) - ) - ) - ) - ) - ), - hr(style = "margin-top: 3px !important"), - fluidRow( - column( - width = 6, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Length multiplier"), style = "color:white; position: relative; right: -15px; margin-bottom: -5px") - ) - ), - column( - width = 12, - align = "left", - br(), - div( - class = "switch-mst-edges", - materialSwitch( - "mst_scale_edges", - h5(p("Scale Allelic Distance"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - fluidRow( - column( - width = 3, - align = "left", - conditionalPanel( - "input.mst_scale_edges==true", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Multiplier') - ) - ) - ), - conditionalPanel( - "input.mst_scale_edges==false", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Length') - ) - ) - ) - ), - column( - width = 9, - align = "center", - conditionalPanel( - "input.mst_scale_edges==true", - div( - class = "slider_edge", - sliderInput( - inputId = "mst_edge_length_scale", - label = NULL, - min = 1, - max = 40, - value = 15, - ticks = FALSE - ) - ) - ), - conditionalPanel( - "input.mst_scale_edges==false", - div( - class = "slider_edge", - sliderTextInput( - inputId = "mst_edge_length", - label = NULL, - choices = append(seq(0.1, 1, 0.1), 2:100), - selected = 35, - hide_min_max = FALSE - ) - ) - ) - ) - ) - ) - ), - column( - width = 6, - fluidRow( - column( - width = 6, - align = "left", - h4(p("Clustering"), style = "color:white; text-align: left; position: relative; right: -15px") - ), - column( - width = 2, - bslib::tooltip( - bsicons::bs_icon("info-circle", - title = "Cluster threshold according to species-specific\nComplex Type Distance (cgMLST.org)", - color = "white", height = "14px", width = "14px", - position = "relative", top = "9px", right = "28px"), - "Text shown in the tooltip.", - show = FALSE, - id = "mst_cluster_info" - ) - ) - ), - br(), - fluidRow( - column( - width = 9, - div( - class = "mst-cluster-switch", - materialSwitch( - "mst_show_clusters", - h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "mst_cluster_col_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - selectInput( - "mst_cluster_col_scale", - label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), - choices = c("Viridis", "Rainbow"), - width = "150px" - ), - selectInput( - "mst_cluster_type", - label = h5("Cluster Type", style = "color:white; margin-bottom: 0px;"), - choices = c("Type 1", "Type 2"), - width = "150px" - ) - ) - ) - ), - br(), - fluidRow( - column( - width = 4, - HTML( - paste( - tags$span(style='color: white; text-align: left; font-size: 14px; margin-left: 15px', 'Threshold') - ) - ) - ), - column( - width = 4, - uiOutput("mst_cluster") - ), - column( - width = 4, - actionButton( - "mst_cluster_reset", - label = "", - icon = icon("rotate") - ), - bsTooltip("mst_cluster_reset", - HTML("Reset to default Complex Type Distance"), - placement = "top", trigger = "hover") - ) - ) - ), - br(), - ) - ), br(), br(), br(), br(), br(), br() - ) - ) - ), - - ### Control Panels NJ ---- - - conditionalPanel( - "input.tree_algo=='Neighbour-Joining'", - fluidRow( - column( - width = 1, - radioGroupButtons( - inputId = "nj_controls", - label = "", - choices = c("Layout", "Label", "Elements", "Variables"), - direction = "vertical" - ) - ), - conditionalPanel( - "input.nj_controls=='Layout'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Theme"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - align = "center", - selectInput( - inputId = "nj_layout", - label = "", - choices = list( - Linear = list( - "Rectangular" = "rectangular", - "Roundrect" = "roundrect", - "Slanted" = "slanted", - "Ellipse" = "ellipse" - ), - Circular = list("Circular" = "circular", - "Inward" = "inward") - ), - selected = "rectangular", - width = "90%" - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "nj_rootedge_show", - h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_rootedge_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_rootedge_length"), - br(), - selectInput( - "nj_rootedge_line", - label = h5("Rootedge Line", style = "color:white"), - choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), - selected = c(Dotted = "solid"), - width = "100px" - ), - br(), - conditionalPanel( - "input.nj_layout=='circular'", - sliderInput( - "nj_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = -50, - max = 0, - value = -10, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_layout=='inward'", - sliderInput( - "nj_inward_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = 30, - max = 120, - value = 50, - ticks = FALSE, - width = "150px", - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-re", - materialSwitch( - "nj_ladder", - h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - colorPickr( - inputId = "nj_color", - width = "90%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - br(), - fluidRow( - column( - width = 5, - h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") - ), - column( - width = 7, - colorPickr( - inputId = "nj_bg", - width = "90%", - selected = "#ffffff", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - br() - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Title"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "nj_title", - label = "", - width = "100%", - placeholder = "Plot Title" - ), - textInput( - "nj_subtitle", - label = "", - width = "100%", - placeholder = "Plot Subtitle" - ), - br(), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "nj_title_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "nj_title_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "nj_title_size", - label = h5("Title Size", style = "color:white; margin-bottom: 0px"), - value = 30, - min = 15, - max = 40, - step = 1, - width = "80px" - ), - br(), - numericInput( - "nj_subtitle_size", - label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), - value = 20, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ), - br() - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - br(), - fluidRow( - column( - width = 3, - h5("Ratio", style = "color: white; font-size: 14px;") - ), - column( - width = 6, - align = "left", - div( - class = "ratio-sel", - selectInput( - "nj_ratio", - "", - choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "nj_size_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - sliderInput( - "nj_v", - label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "nj_h", - label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - sliderInput( - "nj_scale", - "", - min = 500, - max = 1200, - value = 800, - step = 5, - width = "95%", - ticks = FALSE - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - div( - class = "zoom-slider", - sliderInput( - "nj_zoom", - label = NULL, - min = 0.5, - max = 1.5, - step = 0.05, - value = 0.95, - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "nj_treescale_show", - h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - br() - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_treescale_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_treescale_width"), - br(), - uiOutput("nj_treescale_x"), - br(), - uiOutput("nj_treescale_y") - ) - ) - ) - ) - ) - ) - ), - column( - width = 12, - align = "left", - h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - align = "left", - prettyRadioButtons( - "nj_legend_orientation", - "", - choices = c(Horizontal = "horizontal", - Vertical = "vertical"), - selected = c(Vertical = "vertical"), - inline = FALSE - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "nj_legend_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "nj_legend_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - value = 10, - min = 5, - max = 25, - step = 1, - width = "80px" - ), - br(), - sliderInput( - "nj_legend_x", - label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), - value = 0.9, - min = -0.9, - max = 1.9, - step = 0.2, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "nj_legend_y", - label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), - value = 0.2, - min = -1.5, - max = 1.5, - step = 0.1, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_controls=='Label'", - column( - width = 4, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Tips"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 4, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "nj_tiplab_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "center", - uiOutput("nj_tiplab") - ), - column( - width = 3, - div( - class = "mat-switch-align", - materialSwitch( - "nj_align", - h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 1, - align = "right", - dropMenu( - actionBttn( - "nj_labeltext_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "nj_tiplab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - width = "150px", - ticks = FALSE - ), - br(), - conditionalPanel( - "!(input.nj_layout=='inward'|input.nj_layout=='circular')", - sliderInput( - inputId = "nj_tiplab_nudge_x", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 0, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_layout=='circular'", - sliderInput( - inputId = "nj_tiplab_position", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = -0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_layout=='inward'", - sliderInput( - inputId = "nj_tiplab_position_inw", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 1.1, - width = "150px", - ticks = FALSE - ) - ), - br(), - sliderInput( - inputId = "nj_tiplab_angle", - label = h5("Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - ticks = FALSE, - width = "150px", - ) - ), - column( - width = 6, - align = "center", - uiOutput("nj_tiplab_size"), - br(), - selectInput( - "nj_tiplab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") - ), - column( - width = 4, - align = "center", - colorPickr( - inputId = "nj_tiplab_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - br(), - div( - class = "mat-switch-geom", - materialSwitch( - "nj_geom", - h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - colorPickr( - inputId = "nj_tiplab_fill", - width = "100%", - selected = "#84D9A0", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 3, - align = "left", - dropMenu( - actionBttn( - "nj_labelformat_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_tiplab_padding"), - br(), - sliderInput( - inputId = "nj_tiplab_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.2, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Branches"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "nj_show_branch_label", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 5, - align = "center", - uiOutput("nj_branch_label") - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "nj_branch_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "nj_branchlab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 0.65, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "nj_branch_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "nj_branch_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ) - ), - column( - width = 6, - align = "center", - uiOutput("nj_branch_size"), - selectInput( - "nj_branchlab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ), - br(), - sliderInput( - "nj_branch_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.5, - width = "250px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") - ), - column( - width = 5, - colorPickr( - inputId = "nj_branch_label_color", - width = "100%", - selected = "#FFB7B7", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 6, - textInput( - "nj_new_label_name", - "", - placeholder = "New Label" - ) - ), - column( - width = 3, - actionButton( - "nj_add_new_label", - "", - icon = icon("plus") - ) - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "nj_custom_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_custom_labelsize"), - br(), - uiOutput("nj_sliderInput_y"), - br(), - uiOutput("nj_sliderInput_x") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 6, - uiOutput("nj_custom_label_select") - ), - column( - width = 4, - uiOutput("nj_del_label"), - ) - ), - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_cust_label_save") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_controls=='Elements'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "nj_tippoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_tippoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "nj_tippoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 0.5, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("nj_tippoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "nj_tippoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - conditionalPanel( - "input.nj_tipshape_mapping_show==false", - selectInput( - "nj_tippoint_shape", - "", - width = "100%", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ) - ), - conditionalPanel( - "input.nj_tipshape_mapping_show==true", - h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "nj_nodepoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "nj_nodepoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "nj_nodepoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 1, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("nj_nodepoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "nj_nodepoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - selectInput( - "nj_nodepoint_shape", - "", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Tiles"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 5, - div( - class = "sel-tile-number", - selectInput( - "nj_tile_number", - "", - choices = 1:5, - width = "70px" - ) - ) - ), - column( - width = 7, - align = "right", - dropMenu( - actionBttn( - "nj_tile_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - conditionalPanel( - "input.nj_tile_num == 1", - sliderInput( - "nj_fruit_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - sliderInput( - "nj_fruit_alpha_2", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - sliderInput( - "nj_fruit_alpha_3", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - sliderInput( - "nj_fruit_alpha_4", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - sliderInput( - "nj_fruit_alpha_5", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 1", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width2"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_2"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width3"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_3"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width4"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_4"), - br() - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_width5"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("nj_fruit_offset_circ_5"), - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 3, - h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") - ), - column( - width = 6, - align = "center", - textInput( - "nj_heatmap_title", - label = "", - value = "Heatmap", - placeholder = "Heatmap" - ) - ), - column( - width = 3, - align = "right", - dropMenu( - actionBttn( - "nj_heatmap_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("nj_colnames_angle"), - br(), - uiOutput("nj_colnames_y") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") - ), - column( - width = 7, - uiOutput("nj_heatmap_width") - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") - ), - column( - width = 7, - uiOutput("nj_heatmap_offset") - ) - ), - br(), br() - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - div( - class = "mat-switch", - materialSwitch( - "nj_nodelabel_show", - h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") - ), - column( - width = 9, - uiOutput("nj_parentnode") - ) - ), - uiOutput("nj_clade_scale"), - fluidRow( - column( - width = 5, - h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - div( - class = "sel-clade", - selectInput( - "nj_clade_type", - "", - choices = c("Rect" = "rect", - "Round" = "roundrect"), - selected = c("Round" = "roundrect") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.nj_controls=='Variables'", - column( - width = 7, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - align = "center", - h4(p("Element"), style = "color:white; margin-bottom: 20px") - ), - column( - width = 3, - align = "center", - h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") - ), - column( - width = 6, - align = "center", - h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") - ) - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_mapping_show", - h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_color_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("nj_tiplab_scale") - ), - uiOutput("nj_tiplab_mapping_info"), - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_tipcolor_mapping_show", - h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_tipcolor_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("nj_tippoint_scale") - ), - uiOutput("nj_tipcolor_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_tipshape_mapping_show", - h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_tipshape_mapping") - ), - column( - width = 3, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') - ) - ) - ), - uiOutput("nj_tipshape_mapping_info") - ), - fluidRow( - column( - width = 3, - fluidRow( - column( - width = 8, - conditionalPanel( - "input.nj_tile_num == 1", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_1", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_2", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_3", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_4", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - div( - class = "mat-switch-v", - materialSwitch( - "nj_tiles_show_5", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - column( - width = 4, - align = "left", - div( - class = "tile-sel", - selectInput( - "nj_tile_num", - "", - choices = 1:5, - width = "50px" - ) - ) - ) - ) - ), - column( - width = 3, - align = "center", - conditionalPanel( - "input.nj_tile_num == 1", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable") - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable2") - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable3") - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable4") - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - div( - class = "heatmap-scale", - uiOutput("nj_fruit_variable5") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 1", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_1") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 2", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_2") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 3", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_3") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 4", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_4") - ) - ) - ), - conditionalPanel( - "input.nj_tile_num == 5", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_tiles_scale_5") - ) - ) - ), - uiOutput("nj_fruit_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "nj_heatmap_show", - h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("nj_heatmap_sel") - ), - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("nj_heatmap_scale") - ) - ), - uiOutput("nj_heatmap_mapping_info") - ) - ) - ) - ) - ) - ), - br(), br(), br(), br(), br(), br() - ), - - ### Control Panels UPGMA ---- - - conditionalPanel( - "input.tree_algo=='UPGMA'", - fluidRow( - column( - width = 1, - radioGroupButtons( - inputId = "upgma_controls", - label = "", - choices = c("Layout", "Label", "Elements", "Variables"), - direction = "vertical" - ) - ), - conditionalPanel( - "input.upgma_controls=='Layout'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Theme"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - align = "center", - selectInput( - inputId = "upgma_layout", - label = "", - choices = list( - Linear = list( - "Rectangular" = "rectangular", - "Roundrect" = "roundrect", - "Slanted" = "slanted", - "Ellipse" = "ellipse" - ), - Circular = list("Circular" = "circular", - "Inward" = "inward") - ), - selected = "rectangular", - width = "90%" - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "upgma_rootedge_show", - h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_rootedge_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_rootedge_length"), - br(), - selectInput( - "upgma_rootedge_line", - label = h5("Rootedge Line", style = "color:white"), - choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), - selected = c(Dotted = "solid"), - width = "100px" - ), - br(), - conditionalPanel( - "input.upgma_layout=='circular'", - sliderInput( - "upgma_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = -50, - max = 0, - value = -10, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_layout=='inward'", - sliderInput( - "upgma_inward_xlim", - label = h5("Adjust Circular", style = "color:white"), - min = 30, - max = 120, - value = 50, - ticks = FALSE, - width = "150px", - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-re", - materialSwitch( - "upgma_ladder", - h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Color"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - colorPickr( - inputId = "upgma_color", - width = "90%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - br(), - fluidRow( - column( - width = 5, - h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") - ), - column( - width = 7, - colorPickr( - inputId = "upgma_bg", - width = "90%", - selected = "#ffffff", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Title"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - textInput( - "upgma_title", - label = "", - width = "100%", - placeholder = "Plot Title" - ), - textInput( - "upgma_subtitle", - label = "", - width = "100%", - placeholder = "Plot Subtitle" - ), - br(), - fluidRow( - column( - width = 7, - colorPickr( - inputId = "upgma_title_color", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "upgma_title_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "upgma_title_size", - label = h5("Title Size", style = "color:white; margin-bottom: 0px"), - value = 30, - min = 15, - max = 40, - step = 1, - width = "80px" - ), - br(), - numericInput( - "upgma_subtitle_size", - label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), - value = 20, - min = 15, - max = 40, - step = 1, - width = "80px" - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - align = "center", - br(), - fluidRow( - column( - width = 3, - h5("Ratio", style = "color: white; font-size: 14px;") - ), - column( - width = 6, - align = "left", - div( - class = "ratio-sel", - selectInput( - "upgma_ratio", - "", - choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "upgma_size_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - sliderInput( - "upgma_v", - label = "Vertical Position", - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "upgma_h", - label = "Horizontal Position", - min = -0.5, - max = 0.5, - step = 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - sliderInput( - "upgma_scale", - "", - min = 500, - max = 1200, - value = 800, - step = 5, - width = "95%", - ticks = FALSE - ) - ) - ), - fluidRow( - column( - width = 3, - h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") - ), - column( - width = 9, - div( - class = "zoom-slider", - sliderInput( - "upgma_zoom", - label = NULL, - min = 0.5, - max = 1.5, - step = 0.05, - value = 0.95, - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "250px", - column( - width = 12, - align = "left", - h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), - column( - width = 12, - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch-layout", - materialSwitch( - "upgma_treescale_show", - h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - br() - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_treescale_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_treescale_width"), - br(), - uiOutput("upgma_treescale_x"), - br(), - uiOutput("upgma_treescale_y") - ) - ) - ) - ) - ) - ) - ), - column( - width = 12, - align = "left", - h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), - column( - width = 12, - align = "center", - fluidRow( - column( - width = 7, - align = "left", - prettyRadioButtons( - "upgma_legend_orientation", - "", - choices = c(Horizontal = "horizontal", - Vertical = "vertical"), - selected = c(Vertical = "vertical"), - inline = FALSE - ) - ), - column( - width = 5, - align = "right", - dropMenu( - actionBttn( - "upgma_legend_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - numericInput( - "upgma_legend_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - value = 10, - min = 5, - max = 25, - step = 1, - width = "80px" - ), - br(), - sliderInput( - "upgma_legend_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - value = 0.9, - min = -0.9, - max = 1.9, - step = 0.2, - width = "150px", - ticks = FALSE - ), - br(), - sliderInput( - "upgma_legend_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - value = 0.2, - min = -1.5, - max = 1.5, - step = 0.1, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_controls=='Label'", - column( - width = 4, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Tips"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 4, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "upgma_tiplab_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "center", - uiOutput("upgma_tiplab") - ), - column( - width = 3, - div( - class = "mat-switch-align", - materialSwitch( - "upgma_align", - h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 1, - align = "right", - dropMenu( - actionBttn( - "upgma_labeltext_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "upgma_tiplab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - width = "150px", - ticks = FALSE - ), - br(), - conditionalPanel( - "!(input.upgma_layout=='inward'|input.upgma_layout=='circular')", - sliderInput( - inputId = "upgma_tiplab_nudge_x", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 0, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_layout=='circular'", - sliderInput( - inputId = "upgma_tiplab_position", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = -0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_layout=='inward'", - sliderInput( - inputId = "upgma_tiplab_position_inw", - label = h5("Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - step = 0.05, - value = 1.1, - width = "150px", - ticks = FALSE - ) - ), - br(), - sliderInput( - inputId = "upgma_tiplab_angle", - label = h5("Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - ticks = FALSE, - width = "150px", - ) - ), - column( - width = 6, - align = "center", - uiOutput("upgma_tiplab_size"), - br(), - selectInput( - "upgma_tiplab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") - ), - column( - width = 4, - align = "center", - colorPickr( - inputId = "upgma_tiplab_color", - width = "100%", - selected = "#000000", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 4, - align = "left", - br(), - div( - class = "mat-switch-geom", - materialSwitch( - "upgma_geom", - h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - colorPickr( - inputId = "upgma_tiplab_fill", - width = "100%", - selected = "#84D9A0", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ), - column( - width = 3, - align = "left", - dropMenu( - actionBttn( - "upgma_labelformat_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_tiplab_padding"), - br(), - sliderInput( - inputId = "upgma_tiplab_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.2, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Branches"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 5, - align = "left", - div( - class = "mat-switch-lab", - materialSwitch( - "upgma_show_branch_label", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 5, - align = "center", - uiOutput("upgma_branch_label") - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "upgma_branch_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 6, - align = "center", - sliderInput( - "upgma_branchlab_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 0.65, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "upgma_branch_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ), - br(), - sliderInput( - inputId = "upgma_branch_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = -3, - max = 3, - value = 0, - width = "250px", - ticks = FALSE - ) - ), - column( - width = 6, - align = "center", - uiOutput("upgma_branch_size"), - selectInput( - "upgma_branchlab_fontface", - label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), - width = "250px", - choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") - ), - br(), - sliderInput( - "upgma_branch_labelradius", - label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 0.5, - value = 0.5, - width = "250px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") - ), - column( - width = 5, - colorPickr( - inputId = "upgma_branch_label_color", - width = "100%", - selected = "#FFB7B7", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ), - br(), br() - ) - ) - ) - ) - ), - column( - width = 3, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "280px", - column( - width = 12, - fluidRow( - column( - width = 12, - align = "left", - h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 6, - textInput( - "upgma_new_label_name", - "", - placeholder = "New Label" - ) - ), - column( - width = 3, - actionButton( - "upgma_add_new_label", - "", - icon = icon("plus") - ) - ), - column( - width = 2, - align = "right", - dropMenu( - actionBttn( - "upgma_custom_label_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_custom_labelsize"), - br(), - uiOutput("upgma_sliderInput_y"), - br(), - uiOutput("upgma_sliderInput_x") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 6, - uiOutput("upgma_custom_label_select") - ), - column( - width = 4, - uiOutput("upgma_del_label"), - ) - ), - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_cust_label_save") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_controls=='Elements'", - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "upgma_tippoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_tippoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "upgma_tippoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 0.5, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("upgma_tippoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "upgma_tippoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - conditionalPanel( - "input.upgma_tipshape_mapping_show==false", - selectInput( - "upgma_tippoint_shape", - "", - width = "100%", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ) - ), - conditionalPanel( - "input.upgma_tipshape_mapping_show==true", - h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") - ), - br() - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "mat-switch", - materialSwitch( - "upgma_nodepoint_show", - h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 4, - align = "right", - dropMenu( - actionBttn( - "upgma_nodepoint_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - sliderInput( - "upgma_nodepoint_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - value = 1, - min = 0.1, - max = 1, - width = "150px", - ticks = FALSE - ), - br(), - uiOutput("upgma_nodepoint_size") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "upgma_nodepoint_color", - width = "100%", - selected = "#3A4657", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - fluidRow( - column( - width = 5, - h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") - ), - column( - width = 7, - align = "center", - selectInput( - "upgma_nodepoint_shape", - "", - choices = c( - Circle = "circle", - Square = "square", - Diamond = "diamond", - Triangle = "triangle", - Cross = "cross", - Asterisk = "asterisk" - ) - ), - br() - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Tiles"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 5, - div( - class = "sel-tile-number", - selectInput( - "upgma_tile_number", - "", - choices = 1:5, - width = "70px" - ) - ) - ), - column( - width = 7, - align = "right", - dropMenu( - actionBttn( - "upgma_tile_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - conditionalPanel( - "input.upgma_tile_num == 1", - sliderInput( - "upgma_fruit_alpha", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - sliderInput( - "upgma_fruit_alpha_2", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - sliderInput( - "upgma_fruit_alpha_3", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - sliderInput( - "upgma_fruit_alpha_4", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - sliderInput( - "upgma_fruit_alpha_5", - label = h5("Opacity", style = "color:white; margin-bottom: 0px"), - min = 0.1, - max = 1, - value = 1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 1", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width2"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_2"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width3"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_3"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width4"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_4"), - br() - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - fluidRow( - column( - width = 5, - h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_width5"), - br() - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") - ), - column( - width = 7, - align = "center", - uiOutput("upgma_fruit_offset_circ_5"), - br() - ) - ) - ) - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 6, - h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") - ) - ), - fluidRow( - column( - width = 3, - h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") - ), - column( - width = 6, - align = "center", - textInput( - "upgma_heatmap_title", - label = "", - value = "Heatmap", - placeholder = "Heatmap" - ) - ), - column( - width = 3, - align = "right", - dropMenu( - actionBttn( - "upgma_heatmap_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-end", - theme = "translucent", - fluidRow( - column( - width = 12, - align = "center", - uiOutput("upgma_colnames_angle"), - br(), - uiOutput("upgma_colnames_y") - ) - ) - ) - ) - ), - fluidRow( - column( - width = 5, - h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") - ), - column( - width = 7, - uiOutput("upgma_heatmap_width") - ) - ), - fluidRow( - column( - width = 5, - h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") - ), - column( - width = 7, - uiOutput("upgma_heatmap_offset") - ) - ), - br(), br() - ) - ) - ), - column( - width = 2, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - height = "295px", - column( - width = 12, - align = "left", - h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), - fluidRow( - column( - width = 12, - div( - class = "mat-switch", - materialSwitch( - "upgma_nodelabel_show", - h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - fluidRow( - column( - width = 3, - h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") - ), - column( - width = 9, - uiOutput("upgma_parentnode") - ) - ), - uiOutput("upgma_clade_scale"), - fluidRow( - column( - width = 5, - h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - div( - class = "sel-clade", - selectInput( - "upgma_clade_type", - "", - choices = c("Rect" = "rect", - "Round" = "roundrect"), - selected = c("Round" = "roundrect") - ) - ) - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.upgma_controls=='Variables'", - column( - width = 7, - box( - solidHeader = TRUE, - status = "info", - width = "100%", - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - align = "center", - h4(p("Element"), style = "color:white; margin-bottom: 20px") - ), - column( - width = 3, - align = "center", - h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") - ), - column( - width = 6, - align = "center", - h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") - ) - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_mapping_show", - h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_color_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tiplab_scale") - ), - uiOutput("upgma_tiplab_mapping_info"), - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tipcolor_mapping_show", - h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tipcolor_mapping") - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tippoint_scale") - ), - uiOutput("upgma_tipcolor_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tipshape_mapping_show", - h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_tipshape_mapping") - ), - column( - width = 3, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') - ) - ) - ), - uiOutput("upgma_tipshape_mapping_info") - ), - fluidRow( - column( - width = 3, - fluidRow( - column( - width = 8, - conditionalPanel( - "input.upgma_tile_num == 1", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_1", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_2", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_3", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_4", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - div( - class = "mat-switch-v", - materialSwitch( - "upgma_tiles_show_5", - h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ) - ), - column( - width = 4, - align = "left", - div( - class = "tile-sel", - selectInput( - "upgma_tile_num", - "", - choices = 1:5, - width = "50px" - ) - ) - ) - ) - ), - column( - width = 3, - align = "center", - conditionalPanel( - "input.upgma_tile_num == 1", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable2") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable3") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable4") - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - div( - class = "heatmap-scale", - uiOutput("upgma_fruit_variable5") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 1", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_1") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 2", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_2") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 3", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_3") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 4", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_4") - ) - ) - ), - conditionalPanel( - "input.upgma_tile_num == 5", - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_tiles_scale_5") - ) - ) - ), - uiOutput("upgma_fruit_mapping_info") - ), - fluidRow( - column( - width = 3, - div( - class = "mat-switch-v", - materialSwitch( - "upgma_heatmap_show", - h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - ), - column( - width = 3, - align = "center", - uiOutput("upgma_heatmap_sel") - ), - column( - width = 3, - align = "center", - div( - class = "heatmap-scale", - uiOutput("upgma_heatmap_scale") - ) - ), - uiOutput("upgma_heatmap_mapping_info") - ) - ) - ) - ) - ) - ), - br(), br(), br(), br(), br(), br() - ) - ), - - ## Tab Utilities ------------------------------------------------------- - - tabItem( - tabName = "utilities", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Utilities"), style = "color:white") - ) - ), - br(), - hr(), - column( - width = 5, - align = "left", - shinyDirButton( - "hash_dir", - "Choose folder with .fasta files", - title = "Locate folder with loci", - buttonType = "default", - style = "border-color: white; margin: 10px; min-width: 200px; text-align: center" - ), - actionButton("hash_start", "Start Hashing", icon = icon("circle-play")), - shinyjs::hidden( - div(id = "hash_loading", - HTML('')) - ) - ) - # br(), - # actionButton( - # "backup_database", - # "Create backup", - # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - # ), - # br(), - # actionButton( - # "import_db_backup", - # "Restore backup", - # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" - # ) - ), - - - ## Tab Screening ------------------------------------------------------- - - tabItem( - tabName = "gs_screening", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Screening"), style = "color:white; margin-bottom: -20px;") - ), - column( - width = 7, - align = "left", - uiOutput("gene_screening_info") - ) - ), - br(), - hr(), - fluidRow( - uiOutput("screening_interface") - ) - ), - - ## Tab Resistance Profile ------------------------------------------------------- - - tabItem( - tabName = "gs_profile", - fluidRow( - column( - width = 3, - align = "center", - h2(p("Browse Entries"), style = "color:white; margin-bottom: -20px") - ), - column( - width = 7, - align = "left", - uiOutput("gene_resistance_info") - ) - ), - br(), - hr(), - br(), br(), - uiOutput("gs_table_selection"), - fluidRow( - column(1), - uiOutput("gs_profile_display") - ) - ) - ) # End tabItems - ) # End dashboardPage -) # end UI - -# _______________________ #### - -# Server ---- - -server <- function(input, output, session) { - - phylotraceVersion <- paste("1.5.0") - - #TODO Enable this, or leave disabled - # Kill server on session end - session$onSessionEnded( function() { - stopApp() - }) - - # Disable various user inputs (visualization control) - shinyjs::disable('mst_edge_label') - - ## Functions ---- - - # Function to read and format FASTA sequences - format_fasta <- function(filepath) { - fasta <- readLines(filepath) - formatted_fasta <- list() - current_sequence <- "" - - for (line in fasta) { - if (startsWith(line, ">")) { - if (current_sequence != "") { - formatted_fasta <- append(formatted_fasta, list(current_sequence)) - current_sequence <- "" - } - formatted_fasta <- append(formatted_fasta, list(line)) - } else { - current_sequence <- paste0(current_sequence, line) - } - } - if (current_sequence != "") { - formatted_fasta <- append(formatted_fasta, list(current_sequence)) - } - - formatted_fasta - } - - # Function to color-code the bases in a sequence - color_sequence <- function(sequence) { - sequence <- gsub("A", "A", sequence) - sequence <- gsub("T", "T", sequence) - sequence <- gsub("G", "G", sequence) - sequence <- gsub("C", "C", sequence) - sequence - } - - # Function to log messages to logfile - log_message <- function(log_file, message, append = TRUE) { - cat(format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "-", message, "\n", file = log_file, append = append) - } - - # Modified gheatmap function - gheatmap.mod <- function(p, data, offset=0, width=1, low="green", high="red", color="white", - colnames=TRUE, colnames_position="bottom", colnames_angle=0, colnames_level=NULL, - colnames_offset_x = 0, colnames_offset_y = 0, font.size=4, family="", hjust=0.5, legend_title = "value", - colnames_color = "black") { - - colnames_position %<>% match.arg(c("bottom", "top")) - variable <- value <- lab <- y <- NULL - - ## if (is.null(width)) { - ## width <- (p$data$x %>% range %>% diff)/30 - ## } - - ## convert width to width of each cell - width <- width * (p$data$x %>% range(na.rm=TRUE) %>% diff) / ncol(data) - - isTip <- x <- y <- variable <- value <- from <- to <- NULL - - ## handle the display of heatmap on collapsed nodes - ## https://github.com/GuangchuangYu/ggtree/issues/242 - ## extract data on leaves (& on collapsed internal nodes) - ## (the latter is extracted only when the input data has data on collapsed - ## internal nodes) - df <- p$data - nodeCo <- intersect(df %>% filter(is.na(x)) %>% - select(.data$parent, .data$node) %>% unlist(), - df %>% filter(!is.na(x)) %>% - select(.data$parent, .data$node) %>% unlist()) - labCo <- df %>% filter(.data$node %in% nodeCo) %>% - select(.data$label) %>% unlist() - selCo <- intersect(labCo, rownames(data)) - isSel <- df$label %in% selCo - - df <- df[df$isTip | isSel, ] - start <- max(df$x, na.rm=TRUE) + offset - - dd <- as.data.frame(data) - ## dd$lab <- rownames(dd) - i <- order(df$y) - - ## handle collapsed tree - ## https://github.com/GuangchuangYu/ggtree/issues/137 - i <- i[!is.na(df$y[i])] - - lab <- df$label[i] - ## dd <- dd[lab, , drop=FALSE] - ## https://github.com/GuangchuangYu/ggtree/issues/182 - dd <- dd[match(lab, rownames(dd)), , drop = FALSE] - - - dd$y <- sort(df$y) - dd$lab <- lab - ## dd <- melt(dd, id=c("lab", "y")) - dd <- gather(dd, variable, value, -c(lab, y)) - - i <- which(dd$value == "") - if (length(i) > 0) { - dd$value[i] <- NA - } - if (is.null(colnames_level)) { - dd$variable <- factor(dd$variable, levels=colnames(data)) - } else { - dd$variable <- factor(dd$variable, levels=colnames_level) - } - V2 <- start + as.numeric(dd$variable) * width - mapping <- data.frame(from=dd$variable, to=V2) - mapping <- unique(mapping) - - dd$x <- V2 - dd$width <- width - dd[[".panel"]] <- factor("Tree") - if (is.null(color)) { - p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, inherit.aes=FALSE) - } else { - p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, color=color, inherit.aes=FALSE) - } - if (is(dd$value,"numeric")) { - p2 <- p2 + scale_fill_gradient(low=low, high=high, na.value=NA, name = legend_title) # "white") - } else { - p2 <- p2 + scale_fill_discrete(na.value=NA, name = legend_title) #"white") - } - - if (colnames) { - if (colnames_position == "bottom") { - y <- 0 - } else { - y <- max(p$data$y) + 1 - } - mapping$y <- y - mapping[[".panel"]] <- factor("Tree") - p2 <- p2 + geom_text(data=mapping, aes(x=to, y = y, label=from), color = colnames_color, size=font.size, family=family, inherit.aes = FALSE, - angle=colnames_angle, nudge_x=colnames_offset_x, nudge_y = colnames_offset_y, hjust=hjust) - } - - p2 <- p2 + theme(legend.position="right") - ## p2 <- p2 + guides(fill = guide_legend(override.aes = list(colour = NULL))) - - if (!colnames) { - ## https://github.com/GuangchuangYu/ggtree/issues/204 - p2 <- p2 + scale_y_continuous(expand = c(0,0)) - } - - attr(p2, "mapping") <- mapping - return(p2) - } - - # Get rhandsontable - get.entry.table.meta <- reactive({ - if(!is.null(hot_to_r(input$db_entries))){ - table <- hot_to_r(input$db_entries) - select(select(table, -13), 1:(12 + nrow(DB$cust_var))) - } - }) - - # Function to find columns with varying values - var_alleles <- function(dataframe) { - - varying_columns <- c() - - for (col in 1:ncol(dataframe)) { - unique_values <- unique(dataframe[, col]) - - if (length(unique_values) > 1) { - varying_columns <- c(varying_columns, col) - } - } - - return(varying_columns) - } - - # Functions to compute hamming distances dependent on missing value handling - hamming.dist <- function(x, y) { - sum(x != y) - } - - hamming.distIgnore <- function(x, y) { - sum( (x != y) & !is.na(x) & !is.na(y) ) - } - - hamming.distCategory <- function(x, y) { - sum((x != y | xor(is.na(x), is.na(y))) & !(is.na(x) & is.na(y))) - } - - compute.distMatrix <- function(profile, hamming.method) { - mat <- as.matrix(profile) - n <- nrow(mat) - dist_mat <- matrix(0, n, n) - for (i in 1:(n-1)) { - for (j in (i+1):n) { - dist_mat[i, j] <- hamming.method(x = mat[i, ], y = mat[j, ]) - dist_mat[j, i] <- dist_mat[i, j] - } - } - return(dist_mat) - } - - # Function to determine entry table height - table_height <- reactive({ - if (input$table_height == TRUE) { - NULL - } else {900} - }) - - # Function to determine distance matrix height - distancematrix_height <- reactive({ - if(DB$distancematrix_nrow > 33) { - 800 - } else {NULL} - }) - - # Function to missing value table height - miss.val.height <- reactive({ - if(input$miss_val_height == TRUE) { - NULL - } else {800} - }) - - #Function to check custom variable classes - column_classes <- function(df) { - sapply(df, function(x) { - if (class(x) == "numeric") { - return("cont") - } else if (class(x) == "character") { - return("categ") - } else { - return(class(x)) - } - }) - } - - # Function to hash database - hash_database <- function(folder) { - loci_files <- list.files(folder) - loci_names <- sapply(strsplit(loci_files, "[.]"), function(x) x[1]) - loci_paths <- file.path(folder, loci_files) - - hashes <- sapply(loci_paths, hash_locus) - names(hashes) <- loci_names - hashes - } - - # Function to hash a locus - hash_locus <- function(locus_path) { - locus_file <- readLines(locus_path) - seq_list <- locus_file[seq(2, length(locus_file), 3)] - seq_hash <- sha256(seq_list) - seq_idx <- paste0(">", seq_hash) - - locus_file[seq(1, length(locus_file), 3)] <- seq_idx - writeLines(locus_file, locus_path) - - seq_hash - } - - # Get locus hashes - get_locus_hashes <- function(locus_path) { - locus_file <- readLines(locus_path) - hash_list <- locus_file[seq(1, length(locus_file), 3)] - hash_list <- sapply(strsplit(hash_list, "[>]"), function(x) x[2]) - } - - extract_seq <- function(locus_path, hashes) { - locus_file <- readLines(locus_path) - hash_list <- sapply(strsplit(locus_file[seq(1, length(locus_file), 3)], "[>]"), function(x) x[2]) - seq_list <- locus_file[seq(2, length(locus_file), 3)] - seq_idx <- hash_list %in% hashes - - list( - idx = hash_list[seq_idx], - seq = seq_list[seq_idx] - ) - } - - add_new_sequences <- function(locus_path, sequences) { - locus_file <- file(locus_path, open = "a+") - for (i in seq_along(sequences$idx)) { - writeLines(c("", paste0(">", sequences$idx[i]), sequences$seq[i]), locus_file) - } - close(locus_file) - } - - # Compute clusters to use in visNetwork - compute_clusters <- function(nodes, edges, threshold) { - groups <- rep(0, length(nodes$id)) - edges_groups <- rep(0, length(edges$from)) - - edges_table <- data.frame( - from = edges$from, - to = edges$to, - weight = edges$weight - ) - - count <- 0 - while (any(groups == 0)) { - group_na <- groups == 0 - labels <- nodes$id[group_na] - - cluster <- nodes$id[group_na][1] # Initialize with 1 label - while (!is_empty(labels)) { - sub_tb <- edges_table[(edges_table$from %in% cluster | edges_table$to %in% cluster) & edges_table$weight <= threshold,] - - if (nrow(sub_tb) == 0 | length(unique(c(sub_tb$from, sub_tb$to))) == length(cluster)) { - count <- count + 1 - groups[nodes$id %in% cluster] <- paste("Group", count) - edges_groups[edges$from %in% cluster & edges$to %in% cluster] <- paste("Group", count) - break - } else { - cluster <- unique(c(sub_tb$from, sub_tb$to)) - } - } - } - list(groups = groups, - edges = edges_groups) - } - - # Check gene screening status - check_status <- function(isolate) { - iso_name <- gsub(".zip", "", basename(isolate)) - if(file.exists(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", iso_name, "status.txt"))) { - if(str_detect(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", iso_name, "status.txt"))[1], - "successfully")) { - return("success") - } else { - return("fail") - } - } else {return("unfinished")} - } - - # Reset gene screening status - remove.screening.status <- function(isolate) { - if(file.exists(file.path(DB$database, - gsub(" ", "_", DB$scheme), - "Isolates", - isolate, - "status.txt"))) { - file.remove( - file.path(DB$database, - gsub(" ", "_", DB$scheme), - "Isolates", - isolate, - "status.txt") - ) - } - } - - # Truncate hashes - truncHash <- function(hash) { - if(!is.na(hash)) { - paste0(str_sub(hash, 1, 4), "...", str_sub(hash, nchar(hash) - 3, nchar(hash))) - } else {NA} - } - - # Function to check for duplicate isolate IDs for multi typing start - dupl_mult_id <- reactive({ - req(Typing$multi_sel_table) - if(!is.null(DB$data)) { - selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] - selection$Files - } else {""} - }) - - # Function to check single typing log file - check_new_entry <- reactive({ - - invalidateLater(5000, session) - - if(!is.null(DB$database)) { - if(file_exists(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds"))) { - - Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) - - if(is.null(DB$data)) { - if(nrow(Database[["Typing"]]) >= 1) { - TRUE - } else {FALSE} - } else { - if(nrow(DB$data) < nrow(Database[["Typing"]])) { - TRUE - } else { - FALSE - } - } - } else {FALSE} - } - }) - - # Render Entry Table Highlights - - diff_allele <- reactive({ - if (!is.null(DB$data) & !is.null(input$compare_select) & !is.null(DB$cust_var)) { - var_alleles(select(DB$data, input$compare_select)) + (13 + nrow(DB$cust_var)) - } - }) - - err_thresh <- reactive({ - if (!is.null(DB$data) & !is.null(DB$number_loci)) { - which(as.numeric(DB$data[["Errors"]]) >= (DB$number_loci * 0.05)) - } - }) - - err_thresh_na <- reactive({ - if (!is.null(DB$na_table) & !is.null(DB$number_loci)) { - which(as.numeric(DB$na_table[["Errors"]]) >= (DB$number_loci * 0.05)) - } - }) - - true_rows <- reactive({ - if (!is.null(DB$data)) { - which(DB$data$Include == TRUE) - } - }) - - duplicated_names <- reactive({ - if (!is.null(DB$meta)) { - which(duplicated(DB$meta$`Assembly Name`) | duplicated(DB$meta$`Assembly Name`, fromLast = TRUE)) - } - }) - - duplicated_ids <- reactive({ - if (!is.null(DB$meta)) { - which(duplicated(DB$meta$`Assembly ID`) | duplicated(DB$meta$`Assembly ID`, fromLast = TRUE)) - } - }) - - # _______________________ #### - - ## Startup ---- - shinyjs::addClass(selector = "body", class = "sidebar-collapse") - shinyjs::removeClass(selector = "body", class = "sidebar-toggle") - - output$messageMenu <- renderText({ - HTML(format(Sys.time(), "%Y-%m-%d %H:%M:%S %Z")) - }) - - # Initiate logging - if(!dir_exists(paste0(getwd(), "/logs"))) { - dir_create(paste0(getwd(), "/logs")) - } - - logfile <- file.path(paste0(getwd(), "/logs/phylotrace.log")) - - log <- log_open(logfile, logdir = FALSE) - - log_print("Session started") - - # Clear screening file - if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { - file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) - } - - if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { - file.remove(paste0(getwd(), "/execute/screening/error.txt")) - } - - # Declare reactive variables - Startup <- reactiveValues(sidebar = TRUE, - header = TRUE) # reactive variables related to startup process - - DB <- reactiveValues(data = NULL, - block_db = FALSE, - load_selected = TRUE, - no_na_switch = FALSE, - first_look = FALSE) # reactive variables related to local database - - Typing <- reactiveValues(table = data.frame(), - single_path = data.frame(), - progress = 0, - progress_format_start = 0, - progress_format_end = 0, - result_list = NULL, - status = "") # reactive variables related to typing process - - Screening <- reactiveValues(status = "idle", - picker_status = TRUE, - first_result = NULL) # reactive variables related to gene screening - - Vis <- reactiveValues(cluster = NULL, - metadata = list(), - custom_label_nj = data.frame(), - nj_label_pos_y = list(), - nj_label_pos_x = list(), - nj_label_size = list(), - custom_label_upgma = data.frame(), - upgma_label_pos_y = list(), - upgma_label_pos_x = list(), - upgma_label_size = list()) # reactive variables related to visualization - - Report <- reactiveValues() # reactive variables related to report functions - - Scheme <- reactiveValues() # reactive variables related to scheme functions - - # Load last used database if possible - if(paste0(getwd(), "/execute/last_db.rds") %in% dir_ls(paste0(getwd(), "/execute"))) { - DB$last_db <- TRUE - } - - # Locate local Database - observe({ - shinyDirChoose(input, - "db_location", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session) - - if(!is.null(DB$select_new)) { - if(DB$select_new == FALSE) { - if(DB$block_db == FALSE) { - DB$database <- as.character( - parseDirPath( - roots = c(Home = path_home(), Root = "/"), - input$db_location - ) - ) - - DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present - - DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available - } - - } else if (DB$select_new == TRUE) { - DB$database <- paste0(DB$new_database, "/Database") - - } - } else { - if(!is.null(DB$last_db) & file.exists(paste0(getwd(), "/execute/last_db.rds"))) { - - DB$database <- readRDS(paste0(getwd(), "/execute/last_db.rds")) - - if(dir_exists(DB$database)) { - DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present - - DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available - } - } - } - }) - - ### Set up typing environment ---- - - # Null typing progress trackers - writeLines("0", paste0(getwd(), "/logs/script_log.txt")) - writeLines("0\n", paste0(getwd(), "/logs/progress.txt")) - - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - } - - # Reset typing feedback values - Typing$pending <- FALSE - Typing$multi_started <- FALSE - Typing$multi_help <- FALSE - saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) - Typing$last_success <- "0" # Null last multi typing success name - Typing$last_failure <- "0" # Null last multi typing failure name - - ### Landing page UI ---- - observe({ - if (Startup$sidebar == FALSE) { - shinyjs::removeClass(selector = "body", class = "sidebar-collapse") - shinyjs::addClass(selector = "body", class = "sidebar-toggle") - } - }) - - output$start_message <- renderUI({ - column( - width = 12, - align = "center", - br(), br(), br(), br(), br(), br(), - div( - class = "image", - imageOutput("imageOutput") - ), - br(), br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 16px;', 'Proceed by loading a compatible local database or create a new one.') - ) - ) - ), - br(), - fluidRow( - column( - width = 6, - align = "right", - shinyDirButton( - "db_location", - "Browse", - icon = icon("folder-open"), - title = "Locate the database folder", - buttonType = "default", - root = path_home() - ) - ), - column( - width = 6, - align = "left", - shinyDirButton( - "create_new_db", - "Create New", - icon = icon("plus"), - title = "Choose location for new PhyloTrace database", - buttonType = "default", - root = path_home() - ) - ) - ), - br(), br(), - fluidRow( - column( - width = 12, - align = "center", - uiOutput("load_db"), - br(), br(), br(), br(), br(), br(), br() - ) - ) - ) - }) - - # User selection new db or load db - observeEvent(input$create_new_db, { - log_print("Input create_new_db") - DB$select_new <- TRUE - }) - - observeEvent(input$db_location, { - log_print("Input db_location") - DB$select_new <- FALSE - }) - - # Load db & scheme selection UI - output$load_db <- renderUI({ - if(!is.null(DB$select_new)) { - if(length(DB$new_database) > 0 & DB$select_new) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px;', - HTML( - paste( - 'New database will be created in', - DB$new_database - ) - ) - ) - ), - br(), - actionButton( - "load", - "Create", - class = "load-start" - ) - ) - } else if(length(DB$available) > 0 & !(DB$select_new)) { - if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Selected:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), - p( - HTML( - paste( - tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', - 'Warning: Folder contains invalid elements.') - ) - ) - ), - br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } else { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Selected:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } - } - } else if((!is.null(DB$last_db)) & (!is.null(DB$available))) { - if (DB$last_db == TRUE & (length(DB$available) > 0)) { - if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Last used:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), - p( - HTML( - paste( - tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', - 'Warning: Folder contains invalid elements.') - ) - ) - ), - br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } else { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Last used:', DB$database) - ) - ) - ), - uiOutput("scheme_db"), - br(), br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } - } else if (DB$last_db == TRUE & (length(DB$available) == 0)) { - column( - width = 12, - p( - tags$span( - style='color: white; font-size: 15px; font-style: italic;', - HTML( - paste('Last used:', DB$database) - ) - ) - ), - br(), - actionButton( - "load", - "Load", - class = "load-start" - ) - ) - } - } - }) - - output$imageOutput <- renderImage({ - # Path to your PNG image with a transparent background - image_path <- paste0(getwd(), "/www/PhyloTrace.png") - - # Use HTML to display the image with the tag - list(src = image_path, - height = 180) - }, deleteFile = FALSE) - - ### Load app event ---- - - observeEvent(input$load, { - - # Reset reactive screening variables - output$screening_start <- NULL - output$screening_result_sel <- NULL - output$screening_result <- NULL - output$screening_fail <- NULL - Screening$status_df <- NULL - Screening$choices <- NULL - Screening$picker_status <- TRUE - Screening$status <- "idle" - Screening$first_result <- NULL - if(!is.null(input$screening_select)) { - if(!is.null(DB$data)) { - updatePickerInput(session, "screening_select", selected = character(0)) - } - } - - log_print("Input load") - - # set typing start control variable - Typing$reload <- TRUE - - # reset typing status on start( - if(Typing$status == "Finalized") {Typing$status <- "Inactive"} - if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} - - #### Render status bar ---- - observe({ - req(DB$scheme) - - if(is.null(input$scheme_position)) { - output$loaded_scheme <- renderUI({ - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Selected scheme:   ", - DB$scheme, - "")), - style = "color:white;") - ) - ) - }) - } - - if(!is.null(input$scheme_position)) { - output$loaded_scheme <- renderUI({ - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Selected scheme:   ", - DB$scheme, - "")), - style = "color:white;"), - div( - class = "reload-bttn", - style = paste0("margin-left:", 30 + input$scheme_position, "px; position: relative; top: -24px;"), - actionButton( - "reload_db", - label = "", - icon = icon("rotate") - ) - ) - ) - ) - }) - } - }) - - observe({ - if(!is.null(DB$database)){ - if(nchar(DB$database) > 60) { - database <- paste0(substring(DB$database, first = 1, last = 60), "...") - } else { - database <- DB$database - } - output$databasetext <- renderUI({ - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Database:   ", - database, - "")), - style = "color:white;") - ), - if(nchar(database) > 60) {bsTooltip("databasetext", - HTML(DB$database), - placement = "bottom", - trigger = "hover")} - ) - }) - } - }) - - observe({ - if(!is.null(DB$database)) { - if(Typing$status == "Finalized"){ - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    typing finalized")), - style = "color:white;") - ) - ) - ) - } else if(Typing$status == "Attaching"){ - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    evaluating typing results")), - style = "color:white;") - ) - ) - ) - } else if(Typing$status == "Processing") { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    pending typing")), - style = "color:white;") - ) - ) - ) - } else if(Screening$status == "started") { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    pending gene screening")), - style = "color:white;") - ) - ) - ) - } else if(Screening$status == "finished") { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    gene screening finalized")), - style = "color:white;") - ) - ) - ) - } else { - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    ready")), - style = "color:white;") - ) - ) - ) - } - } - }) - - # Null single typing status - if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - Typing$progress <- 0 - - Typing$progress_format <- 900000 - - output$single_typing_progress <- NULL - - output$typing_fin <- NULL - - output$single_typing_results <- NULL - - output$typing_formatting <- NULL - - Typing$single_path <- data.frame() - - # reset results file - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - # Resetting single typing progress logfile bar - con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") - - cat("0\n", file = con) - - close(con) - } - } - - shinyjs::runjs( - 'if(document.querySelector("#loaded_scheme > div > li > span") !== null) { - // Select the span element - let spanElement = document.querySelector("#loaded_scheme > div > li > span"); - - // Get the bounding rectangle of the span element - let rect = spanElement.getBoundingClientRect(); - - // Extract the width - let width = rect.width; - - Shiny.setInputValue("scheme_position", width); - }' - ) - - # Load app elements based on database availability and missing value presence - if(!is.null(DB$select_new)) { - if(DB$select_new & (paste0(DB$new_database, "/Database") %in% dir_ls(DB$new_database))) { - - log_print("Directory already contains a database") - - show_toast( - title = "Directory already contains a database", - type = "error", - position = "bottom-end", - timer = 6000 - ) - DB$load_selected <- FALSE - - } else if(DB$select_new | (DB$select_new == FALSE & is.null(input$scheme_db))) { - - log_print(paste0("New database created in ", DB$new_database)) - - DB$check_new_entries <- TRUE - DB$data <- NULL - DB$meta_gs <- NULL - DB$meta <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_trunc <- NULL - DB$allelic_profile_true <- NULL - - # null Distance matrix, entry table and plots - output$db_distancematrix <- NULL - output$db_entries_table <- NULL - output$tree_mst <- NULL - output$tree_nj <- NULL - output$tree_upgma <- NULL - - # null report values - Report$report_list_mst <- list() - Report$report_list_nj <- list() - Report$report_list_upgma <- list() - - # null plots - Vis$nj <- NULL - Vis$upgma <- NULL - Vis$ggraph_1 <- NULL - - removeModal() - - #### Render Menu Items ---- - - Startup$sidebar <- FALSE - Startup$header <- FALSE - - output$menu_sep2 <- renderUI(hr()) - - # Hide start message - output$start_message <- NULL - - DB$load_selected <- FALSE - - # Declare database path - DB$database <- file.path(DB$new_database, "Database") - - # Set database availability screening variables to present database - DB$block_db <- TRUE - DB$select_new <- FALSE - - # Render menu with Manage Schemes as start tab and no Missing values tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - # Dont render these elements - output$db_no_entries <- NULL - output$distancematrix_no_entries <- NULL - output$db_entries <- NULL - output$edit_index <- NULL - output$edit_scheme_d <- NULL - output$edit_entries <- NULL - output$compare_select <- NULL - output$delete_select <- NULL - output$del_bttn <- NULL - output$compare_allele_box <- NULL - output$download_entries <- NULL - output$missing_values <- NULL - output$delete_box <- NULL - output$missing_values_sidebar <- NULL - output$distmatrix_sidebar <- NULL - output$download_scheme_info <- NULL - output$download_loci <- NULL - output$entry_table_controls <- NULL - output$multi_stop <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - output$pending_typing <- NULL - output$multi_typing_results <- NULL - output$single_typing_progress <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - } - } else { - log_print(paste0("Loading existing ", input$scheme_db, " database from ", DB$database)) - } - - if(DB$load_selected == TRUE) { - - if(gsub(" ", "_", input$scheme_db) %in% schemes) { #Check if selected scheme valid - - # Save database path for next start - saveRDS(DB$database, paste0(getwd(), "/execute/last_db.rds")) - - DB$check_new_entries <- TRUE - DB$data <- NULL - DB$meta_gs <- NULL - DB$meta <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_trunc <- NULL - DB$allelic_profile_true <- NULL - DB$scheme <- input$scheme_db - - # null Distance matrix, entry table and plots - output$db_distancematrix <- NULL - output$db_entries_table <- NULL - output$tree_mst <- NULL - output$tree_nj <- NULL - output$tree_upgma <- NULL - - # null typing initiation UI - output$multi_stop <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - output$pending_typing <- NULL - output$multi_typing_results <- NULL - output$single_typing_progress <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - # null report values - Report$report_list_mst <- list() - Report$report_list_nj <- list() - Report$report_list_upgma <- list() - - # null plots - Vis$nj <- NULL - Vis$upgma <- NULL - Vis$ggraph_1 <- NULL - - removeModal() - - #### Render Menu Items ---- - - Startup$sidebar <- FALSE - Startup$header <- FALSE - - output$menu_sep2 <- renderUI(hr()) - - # Hide start message - output$start_message <- NULL - - if(any(grepl(gsub(" ", "_", DB$scheme), dir_ls(DB$database)))) { - - if(!any(grepl("alleles", dir_ls(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme)))))) { - - log_print("Missing loci files") - - # Show message that loci files are missing - showModal( - modalDialog( - paste0("Whoops! No loci files are present in the local ", - DB$scheme, - " folder. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } else if (!any(grepl("scheme_info.html", dir_ls(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme)))))) { - - output$download_scheme_info <- NULL - - log_print("Scheme info file missing") - - # Show message that scheme info is missing - showModal( - modalDialog( - paste0("Whoops! Scheme info of the local ", - DB$scheme, - " database is missing. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - } else if (!any(grepl("targets.csv", dir_ls(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme)))))) { - - # Dont render target download button - output$download_loci <- NULL - - log_print("Missing loci info (targets.csv)") - - # Show message that scheme info is missing - showModal( - modalDialog( - paste0("Whoops! Loci info of the local ", - DB$scheme, - " database is missing. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - } else { - # Produce Scheme Info Table - schemeinfo <- - read_html(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/scheme_info.html" - )) %>% - html_table(header = FALSE) %>% - as.data.frame(stringsAsFactors = FALSE) - names(schemeinfo) <- NULL - DB$schemeinfo <- schemeinfo - number_loci <- as.vector(DB$schemeinfo[6, 2]) - DB$number_loci <- as.numeric(gsub(",", "", number_loci)) - - # Produce Loci Info table - DB$loci_info <- read.csv( - file.path(DB$database, gsub(" ", "_", DB$scheme), "targets.csv"), - header = TRUE, - sep = "\t", - row.names = NULL, - colClasses = c( - "NULL", - "character", - "character", - "integer", - "integer", - "character", - "integer", - "NULL" - ) - ) - - # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme - if(DB$number_loci > length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { - - log_print(paste0("Loci files are missing in the local ", DB$scheme, " folder")) - - # Show message that loci files are missing - showModal( - modalDialog( - paste0("Whoops! Some loci files are missing in the local ", - DB$scheme, - " folder. Download the scheme again (no influence on already typed assemblies)."), - title = "Local Database Error", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Okay") - ) - ) - ) - - # Render menu with Manage Schemes as start tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group"), - selected = TRUE - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - } else { - ###### Alle checks bestanden -> Laden der DTB - # If typed entries present - if (any(grepl("Typing.rds", dir_ls(paste0( - DB$database, "/", gsub(" ", "_", DB$scheme) - ))))) { - - # Load database from files - Database <- readRDS(file.path(DB$database, - gsub(" ", "_", DB$scheme), - "Typing.rds")) - - DB$data <- Database[["Typing"]] - - if(!is.null(DB$data)){ - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - } else { - DB$cust_var <- data.frame() - } - } - - DB$change <- FALSE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - - # Null pipe - con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") - - cat("0\n", file = con) - - # Close the file connection - close(con) - - # Reset other reactive typing variables - Typing$progress_format_end <- 0 - Typing$progress_format_start <- 0 - Typing$pending_format <- 0 - Typing$entry_added <- 0 - Typing$progress <- 0 - Typing$progress_format <- 900000 - output$single_typing_progress <- NULL - output$typing_fin <- NULL - output$single_typing_results <- NULL - output$typing_formatting <- NULL - Typing$single_path <- data.frame() - - # Null multi typing feedback variable - Typing$reset <- TRUE - - # Check need for new missing vlaue display - if(DB$first_look == TRUE) { - if(sum(apply(DB$data, 1, anyNA)) >= 1) { - DB$no_na_switch <- TRUE - } else { - DB$no_na_switch <- FALSE - } - } - - DB$first_look <- TRUE - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - if(!anyNA(DB$allelic_profile)) { - - # no NA's -> dont render missing values sidebar elements - output$missing_values_sidebar <- NULL - - # Render menu if no NA's present - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } else { - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries", - selected = TRUE - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } - - # Render custom variable display - output$show_cust_var <- renderTable( - width = "100%", - { - if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { - if(nrow(DB$cust_var) > 5) { - low <- -4 - high <- 0 - for (i in 1:input$cust_var_select) { - low <- low + 5 - if((nrow(DB$cust_var) %% 5) != 0) { - if(i == ceiling(nrow(DB$cust_var) / 5 )) { - high <- high + nrow(DB$cust_var) %% 5 - } else { - high <- high + 5 - } - } else { - high <- high + 5 - } - } - DB$cust_var[low:high,] - } else { - DB$cust_var - } - } else if (!is.null(DB$cust_var)) { - DB$cust_var - } - }) - - # render visualization sidebar elements - observe({ - Vis$tree_algo <- input$tree_algo - }) - - output$visualization_sidebar <- renderUI({ - if(!is.null(DB$data)) { - column( - width = 12, - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - prettyRadioButtons( - "tree_algo", - choices = c("Minimum-Spanning", "Neighbour-Joining", "UPGMA"), - label = "", - selected = if(!is.null(Vis$tree_algo)){Vis$tree_algo} else {"Minimum-Spanning"} - ), - ) - ), - br(), - fluidRow( - column( - width = 12, - align = "center", - tags$div( - id = "button-wrapper", - actionButton( - "create_tree", - h5("Create Tree", style = "position: relative; left: 15px; color: white; font-size: 15px;"), - width = "100%" - ), - tags$img( - src = "phylo.png", - alt = "icon", - class = "icon" - ) - ) - ) - ), - br(), - hr(), - conditionalPanel( - "input.tree_algo=='Minimum-Spanning'", - fluidRow( - column( - width = 12, - align = "left", - br(), - HTML( - paste( - tags$span(style='color: white; font-size: 16px; margin-left: 15px', "Sizing") - ) - ) - ) - ), - fluidRow( - column( - width = 12, - radioGroupButtons( - "mst_ratio", - "", - choiceNames = c("16:10", "16:9", "4:3"), - choiceValues = c((16/10), (16/9), (4/3)), - width = "100%" - ), - br(), - sliderInput( - "mst_scale", - "", - min = 500, - max = 1200, - step = 5, - value = 800, - width = "95%", - ticks = FALSE - ) - ) - ), - br(), - hr(), - fluidRow( - column( - width = 12, - column( - width = 5, - align = "left", - conditionalPanel( - "input.mst_plot_format=='jpeg'", - actionBttn( - "save_plot_jpeg", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - conditionalPanel( - "input.mst_plot_format=='png'", - actionBttn( - "save_plot_png", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - conditionalPanel( - "input.mst_plot_format=='bmp'", - actionBttn( - "save_plot_bmp", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - conditionalPanel( - "input.mst_plot_format=='html'", - downloadBttn( - "save_plot_html", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ) - ), - column( - width = 7, - div( - style = "max-width: 150px", - class = "format", - selectInput( - inputId = "mst_plot_format", - label = "", - choices = c("html", "jpeg", "png", "bmp") - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.tree_algo=='Neighbour-Joining'", - fluidRow( - column( - width = 12, - column( - width = 5, - align = "left", - downloadBttn( - "download_nj", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - column( - width = 7, - div( - style = "max-width: 150px", - class = "format", - selectInput( - inputId = "filetype_nj", - label = "", - choices = c("png", "jpeg", "bmp", "svg") - ) - ) - ) - ) - ) - ), - conditionalPanel( - "input.tree_algo=='UPGMA'", - fluidRow( - column( - width = 12, - column( - width = 5, - align = "left", - downloadBttn( - "download_upgma", - style = "simple", - label = "Save Plot", - size = "sm", - icon = NULL, - color = "primary" - ) - ), - column( - width = 7, - div( - style = "max-width: 150px", - class = "format", - selectInput( - inputId = "filetype_upgma", - label = "", - choices = c("png", "jpeg", "bmp", "svg") - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 6, - align = "left", - br(), - actionButton( - "create_rep", - "Print Report" - ) - ) - ) - ) - } - }) - - # Render entry table sidebar elements - output$entrytable_sidebar <- renderUI({ - if(!is.null(DB$data)) { - column( - width = 12, - align = "center", - br(), - fluidRow( - column(1), - column( - width = 10, - align = "left", - if(nrow(DB$data) > 40) { - div( - class = "mat-switch-db-tab", - materialSwitch( - "table_height", - h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - } - ) - ), - br(), br(), - fluidRow( - column( - width = 12, - HTML( - paste( - tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Custom Variables') - ) - ) - ) - ), - fluidRow( - column( - width = 8, - textInput( - "new_var_name", - label = "", - placeholder = "New Variable" - ) - ), - column( - width = 2, - actionButton( - "add_new_variable", - "", - icon = icon("plus") - ) - ) - ), - fluidRow( - column( - width = 8, - align = "left", - div( - class = "textinput_var", - selectInput( - "del_which_var", - "", - DB$cust_var$Variable - ) - ) - ), - column( - width = 2, - align = "left", - actionButton( - "delete_new_variable", - "", - icon = icon("minus") - ) - ) - ), - br(), - fluidRow( - column(1), - column( - width = 4, - uiOutput("cust_var_info") - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - tableOutput("show_cust_var") - ) - ), - fluidRow( - column(4), - column( - width = 7, - align = "center", - uiOutput("cust_var_select") - ) - ) - ) - } - }) - - # Render missing values sidebar elements - output$missing_values_sidebar <- renderUI({ - column( - width = 12, - fluidRow( - column( - width = 12, - br(), - materialSwitch( - "miss_val_height", - h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - br() - ), - fluidRow( - column( - width = 6, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: -23px; right: -15px', - 'Download CSV') - ) - ) - ), - column( - width = 4, - downloadBttn( - "download_na_matrix", - style = "simple", - label = "", - size = "sm", - icon = icon("download") - ) - ) - ) - ) - }) - - # Render scheme info download button - output$download_loci <- renderUI({ - column( - 12, - downloadBttn( - "download_loci_info", - style = "simple", - label = "", - size = "sm", - icon = icon("download"), - color = "primary" - ), - bsTooltip("download_loci_info_bttn", HTML("Save loci information
(without sequence)"), placement = "top", trigger = "hover") - ) - }) - - # Render scheme info download button - output$download_scheme_info <- renderUI({ - downloadBttn( - "download_schemeinfo", - style = "simple", - label = "", - size = "sm", - icon = icon("download"), - color = "primary" - ) - }) - - # Render distance matrix sidebar - output$distmatrix_sidebar <- renderUI({ - column( - width = 12, - align = "left", - fluidRow( - column( - width = 12, - align = "center", - selectInput( - "distmatrix_label", - label = "", - choices = c("Index", "Assembly Name", "Assembly ID"), - selected = c("Assembly Name"), - width = "100%" - ), - br() - ) - ), - div( - class = "mat-switch-dmatrix", - materialSwitch( - "distmatrix_true", - h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - div( - class = "mat-switch-dmatrix", - materialSwitch( - "distmatrix_triangle", - h5(p("Show Upper Triangle"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - div( - class = "mat-switch-dmatrix-last", - materialSwitch( - "distmatrix_diag", - h5(p("Show Diagonal"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = TRUE, - right = TRUE - ) - ), - fluidRow( - column( - width = 6, - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: relative; bottom: 37px; right: -15px', - 'Download CSV') - ) - ) - ), - column( - width = 4, - downloadBttn( - "download_distmatrix", - style = "simple", - label = "", - size = "sm", - icon = icon("download") - ) - ) - ) - ) - }) - - # Render select input to choose displayed loci - output$compare_select <- renderUI({ - - if(nrow(DB$data) == 1) { - HTML( - paste( - tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to compare") - ) - ) - } else { - if(!is.null(input$compare_difference)) { - if (input$compare_difference == FALSE) { - pickerInput( - inputId = "compare_select", - label = "", - width = "85%", - choices = names(DB$allelic_profile), - selected = names(DB$allelic_profile)[1:20], - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - } else { - pickerInput( - inputId = "compare_select", - label = "", - width = "85%", - choices = names(DB$allelic_profile), - selected = names(DB$allelic_profile)[var_alleles(DB$allelic_profile)], - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - } - } - } - }) - - #### Render Entry Data Table ---- - output$db_entries_table <- renderUI({ - if(!is.null(DB$data)) { - if(between(nrow(DB$data), 1, 30)) { - rHandsontableOutput("db_entries") - } else { - addSpinner( - rHandsontableOutput("db_entries"), - spin = "dots", - color = "#ffffff" - ) - } - } - }) - - if (!is.null(DB$data)) { - - observe({ - - if (!is.null(DB$data)) { - if (nrow(DB$data) == 1) { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else if (between(nrow(DB$data), 2, 40)) { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - highlightCol = TRUE, - highlightRow = TRUE, - contextMenu = FALSE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - valign = "htMiddle", - halign = "htCenter", - readOnly = TRUE) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - strict = TRUE, - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }" - ) %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names()- 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } else { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - rowHeaders = NULL, - height = table_height(), - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - readOnly = TRUE, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - height = table_height(), - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", halign = "htCenter") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } - } - - # Dynamic save button when rhandsontable changes or new entries - output$edit_entry_table <- renderUI({ - if(check_new_entry() & DB$check_new_entries) { - Typing$reload <- FALSE - fluidRow( - column( - width = 8, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', - 'New entries - reload database') - ) - ) - ), - column( - width = 4, - actionButton( - "load", - "", - icon = icon("rotate"), - class = "pulsating-button" - ) - ) - ) - } else if(Typing$status == "Attaching") { - fluidRow( - column( - width = 11, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', 'No database changes possible - pending entry addition') - ) - ) - ), - column( - width = 1, - HTML(paste('')) - ) - ) - } else if((DB$change == TRUE) | !identical(get.entry.table.meta(), select(DB$meta, -13))) { - - if(!is.null(input$db_entries)) { - fluidRow( - column( - width = 5, - HTML( - paste( - tags$span(style='color: white; font-size: 16px; position: absolute; bottom: -30px; right: -5px', 'Confirm changes') - ) - ) - ), - column( - width = 3, - actionButton( - "edit_button", - "", - icon = icon("bookmark"), - class = "pulsating-button" - ) - ), - column( - width = 4, - actionButton( - "undo_changes", - "Undo", - icon = icon("repeat") - ) - ) - ) - } - } else {NULL} - }) - - }) - - # Hide no entry message - output$db_no_entries <- NULL - output$distancematrix_no_entries <- NULL - - } else { - - # If database loading not successful dont show entry table - output$db_entries_table <- NULL - output$entry_table_controls <- NULL - } - - # Render Entry table controls - output$entry_table_controls <- renderUI({ - fluidRow( - column(1), - column( - width = 3, - align = "center", - fluidRow( - column( - width = 4, - align = "center", - actionButton( - "sel_all_entries", - "Select All", - icon = icon("check") - ) - ), - column( - width = 4, - align = "left", - actionButton( - "desel_all_entries", - "Deselect All", - icon = icon("xmark") - ) - ) - ) - ), - column( - width = 3, - uiOutput("edit_entry_table") - ) - ) - }) - - #### Render Distance Matrix ---- - observe({ - if(!is.null(DB$data)) { - - if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { - output$db_distancematrix <- NULL - - if( (sum(duplicated(DB$meta$`Assembly Name`)) > 0) & (sum(duplicated(DB$meta$`Assembly ID`)) == 0) ) { - duplicated_txt <- paste0( - paste( - paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), - DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] - ), - "
" - ) - } else if ( (sum(duplicated(DB$meta$`Assembly ID`)) > 0) & (sum(duplicated(DB$meta$`Assembly Name`)) == 0) ){ - duplicated_txt <- paste0( - paste( - paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), - DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] - ), - "
" - ) - } else { - duplicated_txt <- c( - paste0( - paste( - paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), - DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] - ), - "
" - ), - paste0( - paste( - paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), - DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] - ), - "
" - ) - ) - } - - output$distancematrix_duplicated <- renderUI({ - column( - width = 12, - tags$span(style = "font-size: 15; color: white", - "Change duplicated entry names to display distance matrix."), - br(), br(), br(), - actionButton("change_entries", "Go to Entry Table", class = "btn btn-default"), - br(), br(), br(), - tags$span( - style = "font-size: 15; color: white", - HTML( - append( - "Duplicated:", - append( - "
", - duplicated_txt - ) - ) - ) - ) - ) - }) - } else { - output$distancematrix_duplicated <- NULL - if(!is.null(DB$data) & !is.null(DB$allelic_profile) & !is.null(DB$allelic_profile_true) & !is.null(DB$cust_var) & !is.null(input$distmatrix_label) & !is.null(input$distmatrix_diag) & !is.null(input$distmatrix_triangle)) { - output$db_distancematrix <- renderRHandsontable({ - rhandsontable(hamming_df(), - digits = 1, - readOnly = TRUE, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE, - height = distancematrix_height(), rowHeaders = NULL) %>% - hot_heatmap(renderer = paste0(" - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - heatmapScale = chroma.scale(['#17F556', '#ED6D47']); - - if (instance.heatmap[col]) { - mn = ", DB$matrix_min, "; - mx = ", DB$matrix_max, "; - - pt = (parseInt(value, 10) - mn) / (mx - mn); - - td.style.backgroundColor = heatmapScale(pt).hex(); - } - }")) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1:(dim(DB$ham_matrix)[1]+1), - halign = "htCenter", - valign = "htMiddle") %>% - hot_col(1, renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - td.style.background = '#F0F0F0' - }" - ) - }) - } - } - - # Render Distance Matrix UI - - output$distmatrix_show <- renderUI({ - if(!is.null(DB$data)) { - if(nrow(DB$data) > 1) { - column( - width = 10, - uiOutput("distancematrix_duplicated"), - div( - class = "distmatrix", - rHandsontableOutput("db_distancematrix") - ) - ) - } else { - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to display a distance matrix.") - ) - ) - ), - br(), - br() - ) - } - } - }) - - } - }) - - - # Render delete entry box UI - output$delete_box <- renderUI({ - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - column( - width = 12, - align = "center", - h3(p("Delete Entries"), style = "color:white") - ) - ), - hr(), - fluidRow( - column( - width = 2, - offset = 1, - align = "right", - br(), - h5("Index", style = "color:white; margin-bottom: 0px;") - ), - column( - width = 6, - align = "center", - uiOutput("delete_select") - ), - column( - width = 2, - align = "center", - br(), - uiOutput("del_bttn") - ) - ), - br() - ) - }) - - # Render loci comparison box UI - output$compare_allele_box <- renderUI({ - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - column( - width = 12, - align = "center", - h3(p("Compare Loci"), style = "color:white") - ) - ), - hr(), - column( - width = 12, - align = "center", - br(), - uiOutput("compare_select"), - br(), - column(2), - column( - width = 10, - align = "left", - uiOutput("compare_difference_box") - ) - ), - br() - ) - }) - - # Render entry table download box UI - output$download_entries <- renderUI({ - fluidRow( - column( - width = 12, - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - column( - width = 12, - align = "center", - h3(p("Download Table"), style = "color:white") - ) - ), - hr(), - fluidRow( - column(2), - column( - width = 10, - align = "left", - br(), - div( - class = "mat-switch-db", - materialSwitch( - "download_table_include", - h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - div( - class = "mat-switch-db", - materialSwitch( - "download_table_loci", - h5(p("Include Displayed Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ), - br(), - ) - ), - fluidRow( - column( - width = 12, - align = "center", - downloadBttn( - "download_entry_table", - style = "simple", - label = "", - size = "sm", - icon = icon("download"), - color = "primary" - ) - ) - ), - br() - ) - ), - column( - width = 12, - fluidRow( - column( - width = 2, - div( - class = "rectangle-blue" - ), - div( - class = "rectangle-orange" - ), - div( - class = "rectangle-red" - ), - div( - class = "rectangle-green" - ) - ), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -12px", " = included for analyses") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -13px", " = duplicated name/ID") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -14px", " = ≥ 5% of loci missing") - ) - ) - ), - p( - HTML( - paste( - tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -15px", " = locus contains multiple variants") - ) - ) - ), - ) - ) - ) - ) - }) - - # Render entry deletion select input - output$delete_select <- renderUI({ - pickerInput("select_delete", - label = "", - choices = DB$data[, "Index"], - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE) - }) - - # Render delete entry button - output$del_bttn <- renderUI({ - actionBttn( - "del_button", - label = "", - color = "danger", - size = "sm", - style = "material-circle", - icon = icon("xmark") - ) - }) - - #### Missing Values UI ---- - - # Missing values calculations and table - observe({ - - if (!is.null(DB$allelic_profile)) { - NA_table <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) != 0] - - NA_table <- NA_table[rowSums(is.na(NA_table)) != 0,] - - NA_table[is.na(NA_table)] <- "NA" - - NA_table <- NA_table %>% - cbind("Assembly Name" = DB$meta[rownames(NA_table),]$`Assembly Name`) %>% - cbind("Errors" = DB$meta[rownames(NA_table),]$Errors) %>% - relocate("Assembly Name", "Errors") - - DB$na_table <- NA_table - - if(!is.null(input$miss_val_height)) { - if(nrow(DB$na_table) < 31) { - output$table_missing_values <- renderRHandsontable({ - rhandsontable( - DB$na_table, - readOnly = TRUE, - rowHeaders = NULL, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE, - error_highlight = err_thresh_na() - 1 - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% - hot_col(2, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } else { - output$table_missing_values <- renderRHandsontable({ - rhandsontable( - DB$na_table, - readOnly = TRUE, - rowHeaders = NULL, - height = miss.val.height(), - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE, - error_highlight = err_thresh() - 1 - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% - hot_col(2, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } - } - } - - }) - - # Render missing value informatiojn box UI - output$missing_values <- renderUI({ - div( - class = "miss_val_box", - box( - solidHeader = TRUE, - status = "primary", - width = "100%", - fluidRow( - div( - class = "white", - column( - width = 12, - align = "left", - br(), - HTML( - paste0("There are ", - strong(as.character(sum(is.na(DB$data)))), - " unsuccessful allele allocations (NA). ", - strong(sum(sapply(DB$allelic_profile, anyNA))), - " out of ", - strong(ncol(DB$allelic_profile)), - " total loci in this scheme contain NA's (", - strong(round((sum(sapply(DB$allelic_profile, anyNA)) / ncol(DB$allelic_profile) * 100), 1)), - " %). ", - "Decide how these missing values should be treated:") - - ), - br() - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "left", - br(), - prettyRadioButtons( - "na_handling", - "", - choiceNames = c("Ignore missing values for pairwise comparison", - "Omit loci with missing values for all assemblies", - "Treat missing values as allele variant"), - choiceValues = c("ignore_na", "omit", "category"), - shape = "curve", - selected = c("ignore_na") - ), - br() - ) - ) - ) - ) - }) - - } else { - #if no typed assemblies present - - # null underlying database - - DB$data <- NULL - DB$meta <- NULL - DB$meta_gs <- NULL - DB$meta_true <- NULL - DB$allelic_profile <- NULL - DB$allelic_profile_trunc <- NULL - DB$allelic_profile_true <- NULL - - # Render menu without missing values tab - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - selected = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - - observe({ - if(is.null(DB$data)) { - if(check_new_entry()) { - output$db_no_entries <- renderUI( - column( - width = 12, - fluidRow( - column(1), - column( - width = 3, - align = "left", - HTML( - paste( - tags$span(style='color: white; font-size: 15px; position: absolute; bottom: -30px; right: -5px', 'New entries - reload database') - ) - ) - ), - column( - width = 4, - actionButton( - "load", - "", - icon = icon("rotate"), - class = "pulsating-button" - ) - ) - ) - ) - ) - } else { - output$db_no_entries <- renderUI( - column( - width = 12, - fluidRow( - column(1), - column( - width = 11, - align = "left", - HTML( - paste( - "", - "No Entries for this scheme available.\n", - "Type a genome in the section Allelic Typing and add the result to the local database.", - sep = '
' - ) - ) - ) - ) - ) - ) - } - } - }) - - output$distancematrix_no_entries <- renderUI( - fluidRow( - column(1), - column( - width = 11, - align = "left", - HTML(paste( - "", - "No Entries for this scheme available.", - "Type a genome in the section Allelic Typing and add the result to the local database.", - sep = '
' - )) - ) - ) - ) - - output$db_entries <- NULL - output$edit_index <- NULL - output$edit_scheme_d <- NULL - output$edit_entries <- NULL - output$compare_select <- NULL - output$delete_select <- NULL - output$del_bttn <- NULL - output$compare_allele_box <- NULL - output$download_entries <- NULL - output$missing_values <- NULL - output$delete_box <- NULL - output$entry_table_controls <- NULL - output$multi_stop <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - output$pending_typing <- NULL - output$multi_typing_results <- NULL - output$single_typing_progress <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - } - } - } - } - } else { - - log_print("Invalid scheme folder") - show_toast( - title = "Invalid scheme folder", - type = "warning", - position = "bottom-end", - timer = 4000 - ) - } - } - - }) - - # _______________________ #### - - ## Database ---- - - ### Conditional UI Elements rendering ---- - - # Contro custom variables table - output$cust_var_select <- renderUI({ - if(nrow(DB$cust_var) > 5) { - selectInput( - "cust_var_select", - "", - choices = 1:ceiling(nrow(DB$cust_var) / 5 ) - ) - } - }) - - output$cust_var_info <- renderUI({ - if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { - if(nrow(DB$cust_var) > 5) { - low <- -4 - high <- 0 - for (i in 1:input$cust_var_select) { - low <- low + 5 - if((nrow(DB$cust_var) %% 5) != 0) { - if(i == ceiling(nrow(DB$cust_var) / 5 )) { - high <- high + nrow(DB$cust_var) %% 5 - } else { - high <- high + 5 - } - } else { - high <- high + 5 - } - } - h5(paste0("Showing ", low, " to ", high," of ", nrow(DB$cust_var), " variables"), style = "color: white; font-size: 10px;") - } - } - }) - - # Message on Database tabs if no scheme available yet - observe({ - if(!is.null(DB$exist)) { - if(DB$exist){ - - # Message for tab Browse Entries - output$no_scheme_entries <- renderUI({ - fluidRow( - column(1), - column( - width = 4, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'No scheme available.') - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'Download a scheme first and type assemblies in the section Allelic Typing.') - ) - ) - ) - ) - ) - }) - - # Message for Tab Scheme Info - output$no_scheme_info <- renderUI({ - fluidRow( - column(1), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'No scheme available.') - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'Download a scheme first and type assemblies in the section Allelic Typing.') - ) - ) - ) - ) - ) - }) - - # Message for Tab Distance Matrix - output$no_scheme_distancematrix <- renderUI({ - fluidRow( - column(1), - column( - width = 10, - align = "left", - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'No scheme available.') - ) - ) - ), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; ', - 'Download a scheme first and type assemblies in the section Allelic Typing.') - ) - ) - ) - ) - ) - }) - - } else { - output$no_scheme_entries <- NULL - output$no_scheme_info <- NULL - output$no_scheme_distancematrix <- NULL - } - } - - }) - - observe({ - # Conditional Missing Values Tab - if(!is.null(DB$allelic_profile)) { - if(anyNA(DB$allelic_profile)) { - if(DB$no_na_switch == FALSE) { - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ), - menuSubItem( - text = "Missing Values", - tabName = "db_missing_values", - selected = TRUE, - icon = icon("triangle-exclamation") - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } - - } else { - output$menu <- renderMenu( - sidebarMenu( - menuItem( - text = "Database Browser", - tabName = "database", - icon = icon("hard-drive"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "db_browse_entries" - ), - menuSubItem( - text = "Scheme Info", - tabName = "db_schemeinfo" - ), - menuSubItem( - text = "Loci Info", - tabName = "db_loci_info" - ), - menuSubItem( - text = "Distance Matrix", - tabName = "db_distmatrix" - ) - ), - menuItem( - text = "Manage Schemes", - tabName = "init", - icon = icon("layer-group") - ), - menuItem( - text = "Allelic Typing", - tabName = "typing", - icon = icon("gears") - ), - menuItem( - text = "Resistance Profile", - tabName = "gene_screening", - icon = icon("dna"), - startExpanded = TRUE, - menuSubItem( - text = "Browse Entries", - tabName = "gs_profile" - ), - menuSubItem( - text = "Screening", - tabName = "gs_screening" - ) - ), - menuItem( - text = "Visualization", - tabName = "visualization", - icon = icon("circle-nodes") - ), - menuItem( - text = "Utilities", - tabName = "utilities", - icon = icon("screwdriver-wrench") - ) - ) - ) - } - } - - }) - - observe({ - - if (!is.null(DB$available)) { - output$scheme_db <- renderUI({ - if (length(DB$available) > 5) { - selectInput( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} - ) - } else { - prettyRadioButtons( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} - ) - } - }) - - if (!is.null(DB$schemeinfo)) { - - output$scheme_info <- renderTable({ - DB$schemeinfo - }) - - output$scheme_header <- renderUI(h3(p("cgMLST Scheme"), style = "color:white")) - - } else { - - output$scheme_info <- NULL - output$scheme_header <- NULL - - } - - if (!is.null(DB$loci_info)) { - loci_info <- DB$loci_info - names(loci_info)[6] <- "Allele Count" - - output$db_loci <- renderDataTable( - loci_info, - selection = "single", - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - )) - ) - - output$loci_header <- renderUI(h3(p("Loci"), style = "color:white")) - - } else { - output$db_loci <- NULL - output$loci_header <- NULL - } - } - }) - - # If only one entry available disable varying loci checkbox - - output$compare_difference_box <- renderUI({ - if(!is.null(DB$data)) { - if(nrow(DB$data) > 1) { - div( - class = "mat-switch-db", - materialSwitch( - "compare_difference", - h5(p("Only Varying Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), - value = FALSE, - right = TRUE - ) - ) - } - } - }) - - ### Database Events ---- - - # Invalid entries table input - observe({ - req(DB$data, input$db_entries) - if (isTRUE(input$invalid_date)) { - show_toast( - title = "Invalid date", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - DB$inhibit_change <- TRUE - } else if (isTRUE(input$empty_name)) { - show_toast( - title = "Empty name", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - DB$inhibit_change <- TRUE - } else if (isTRUE(input$empty_id)) { - show_toast( - title = "Empty ID", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - DB$inhibit_change <- TRUE - } else { - DB$inhibit_change <- FALSE - } - }) - - # Change scheme - observeEvent(input$reload_db, { - log_print("Input reload_db") - - if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { - show_toast( - title = "Pending Multi Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(Screening$status == "started") { - show_toast( - title = "Pending Screening", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - showModal( - modalDialog( - selectInput( - "scheme_db", - label = "", - choices = DB$available, - selected = DB$scheme), - title = "Select a local database to load.", - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("load", "Load", class = "btn btn-default") - ) - ) - ) - } - }) - - # Create new database - observe({ - shinyDirChoose(input, - "create_new_db", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session) - - if(!is.null(input$create_new_db)) { - DB$new_database <- as.character( - parseDirPath( - roots = c(Home = path_home(), Root = "/"), - input$create_new_db - ) - ) - } - }) - - # Undo db changes - observeEvent(input$undo_changes, { - log_print("Input undo_changes") - - DB$inhibit_change <- FALSE - - Data <- readRDS(paste0( - DB$database, "/", - gsub(" ", "_", DB$scheme), - "/Typing.rds" - )) - - DB$data <- Data[["Typing"]] - - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - } else { - DB$cust_var <- data.frame() - } - - DB$change <- FALSE - DB$count <- 0 - DB$no_na_switch <- TRUE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - DB$deleted_entries <- character(0) - - observe({ - if (!is.null(DB$data)) { - if (nrow(DB$data) == 1) { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else if (between(nrow(DB$data), 1, 40)) { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - rowHeaders = NULL, - highlightCol = TRUE, - highlightRow = TRUE, - contextMenu = FALSE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - valign = "htMiddle", - halign = "htCenter", - readOnly = TRUE) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - strict = TRUE, - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }" - ) %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names()- 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } else { - if (length(input$compare_select) > 0) { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { - output$db_entries <- renderRHandsontable({ - - entry_data <- DB$data %>% - select(1:(13 + nrow(DB$cust_var))) %>% - add_column(select(DB$allelic_profile_trunc, input$compare_select)) - - rhandsontable( - entry_data, - col_highlight = diff_allele() - 1, - rowHeaders = NULL, - height = table_height(), - row_highlight = true_rows() - 1, - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), - readOnly = TRUE, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", - halign = "htCenter", - allowInvalid = FALSE, - copyable = TRUE) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(diff_allele(), - renderer = " - function(instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.NumericRenderer.apply(this, arguments); - - if (instance.params) { - hcols = instance.params.col_highlight; - hcols = hcols instanceof Array ? hcols : [hcols]; - } - - if (instance.params && hcols.includes(col)) { - td.style.background = 'rgb(116, 188, 139)'; - } - }") - }) - } - } else { - if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { - output$db_entries <- renderRHandsontable({ - rhandsontable( - select(DB$data, 1:(13 + nrow(DB$cust_var))), - rowHeaders = NULL, - height = table_height(), - dup_names_high = duplicated_names() - 1, - dup_ids_high = duplicated_ids() - 1, - row_highlight = true_rows() - 1, - error_highlight = err_thresh() - 1, - contextMenu = FALSE, - highlightCol = TRUE, - highlightRow = TRUE - ) %>% - hot_cols(fixedColumnsLeft = 1) %>% - hot_col(1, - valign = "htMiddle", - halign = "htCenter") %>% - hot_col(c(1, 5, 10, 11, 12, 13), - readOnly = TRUE) %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(3, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(4, validator = " - function(value, callback) { - try { - if (value === null || value.trim() === '') { - callback(false); // Cell is empty - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } else { - callback(true); // Cell is not empty - Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty - } - } catch (err) { - console.log(err); - callback(false); // In case of error, consider it as invalid - Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell - } - } - ") %>% - hot_col(8, type = "dropdown", source = country_names) %>% - hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, - validator = " - function (value, callback) { - var today_date = new Date(); - today_date.setHours(0, 0, 0, 0); - - var new_date = new Date(value); - new_date.setHours(0, 0, 0, 0); - - try { - if (new_date <= today_date) { - callback(true); - Shiny.setInputValue('invalid_date', false); - } else { - callback(false); - Shiny.setInputValue('invalid_date', true); - } - } catch (err) { - console.log(err); - callback(false); - Shiny.setInputValue('invalid_date', true); - } - }") %>% - hot_col(3:(13 + nrow(DB$cust_var)), - valign = "htMiddle", - halign = "htLeft") %>% - hot_rows(fixedRowsTop = 0) %>% - hot_col(1, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.row_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' - } - } - }") %>% - hot_col(2, type = "checkbox", width = "auto", - valign = "htTop", halign = "htCenter") %>% - hot_col(4, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_names_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(3, renderer = " - function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - - if (instance.params) { - hrows = instance.params.dup_ids_high - hrows = hrows instanceof Array ? hrows : [hrows] - - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgb(224, 179, 0)' - } - } - }") %>% - hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { - Handsontable.renderers.TextRenderer.apply(this, arguments); - if (instance.params) { - hrows = instance.params.error_highlight - hrows = hrows instanceof Array ? hrows : [hrows] - if (hrows.includes(row)) { - td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' - } - } - }") - }) - } - } - } - } - }) - }) - - observe({ - if(!is.null(DB$data)){ - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - - } else { - DB$cust_var <- data.frame() - } - } - }) - - DB$count <- 0 - - observeEvent(input$add_new_variable, { - log_print("Input add_new_variable") - - if(nchar(input$new_var_name) > 12) { - log_print("Add variable; max. 10 character") - show_toast( - title = "Max. 10 characters", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - if (input$new_var_name == "") { - log_print("Add variable; min. 1 character") - show_toast( - title = "Min. 1 character", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - if(trimws(input$new_var_name) %in% names(DB$meta)) { - log_print("Add variable; name already existing") - show_toast( - title = "Variable name already existing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - showModal( - modalDialog( - selectInput( - "new_var_type", - label = "", - choices = c("Categorical (character)", - "Continous (numeric)")), - title = paste0("Select Data Type"), - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_new_var", "Confirm", class = "btn btn-default") - ) - ) - ) - } - } - } - }) - - observeEvent(input$conf_new_var, { - log_print("Input conf_new_var") - - # User feedback variables - removeModal() - DB$count <- DB$count + 1 - DB$change <- TRUE - - # Format variable name - name <- trimws(input$new_var_name) - - if(input$new_var_type == "Categorical (character)") { - DB$data <- DB$data %>% - mutate("{name}" := character(nrow(DB$data)), .after = 13) - - DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "categ")) - } else { - DB$data <- DB$data %>% - mutate("{name}" := numeric(nrow(DB$data)), .after = 13) - - DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "cont")) - } - - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - - log_print(paste0("New custom variable added: ", input$new_var_name)) - - show_toast( - title = paste0("Variable ", trimws(input$new_var_name), " added"), - type = "success", - position = "bottom-end", - timer = 6000 - ) - - }) - - observeEvent(input$delete_new_variable, { - log_print("Input delete_new_variable") - - if (input$del_which_var == "") { - log_print("Delete custom variables; no custom variable") - show_toast( - title = "No custom variables", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - showModal( - modalDialog( - paste0( - "Confirmation will lead to irreversible deletion of the custom ", - input$del_which_var, - " variable. Continue?" - ), - title = "Delete custom variables", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_var_del", "Delete", class = "btn btn-danger") - ) - ) - ) - } - }) - - observeEvent(input$conf_var_del, { - log_print("Input conf_var_del") - - DB$change <- TRUE - - removeModal() - - if(DB$count >= 1) { - DB$count <- DB$count - 1 - } - - show_toast( - title = paste0("Variable ", input$del_which_var, " removed"), - type = "warning", - position = "bottom-end", - timer = 6000 - ) - - log_print(paste0("Variable ", input$del_which_var, " removed")) - - DB$cust_var <- DB$cust_var[-which(DB$cust_var$Variable == input$del_which_var),] - DB$data <- select(DB$data, -(input$del_which_var)) - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - }) - - # Select all button - - observeEvent(input$sel_all_entries, { - log_print("Input sel_all_entries") - - DB$data$Include <- TRUE - }) - - observeEvent(input$desel_all_entries, { - log_print("Input desel_all_entries") - - DB$data$Include <- FALSE - }) - - # Switch to entry table - - observeEvent(input$change_entries, { - log_print("Input change_entries") - - removeModal() - updateTabItems(session, "tabs", selected = "db_browse_entries") - }) - - #### Save Missing Value as CSV ---- - - output$download_na_matrix <- downloadHandler( - filename = function() { - log_print(paste0("Save missing values table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv"))) - paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv") - }, - content = function(file) { - download_matrix <- hot_to_r(input$table_missing_values) - write.csv(download_matrix, file, sep = ",", row.names=FALSE, quote=FALSE) - } - ) - - #### Save scheme info table as CSV ---- - - output$download_schemeinfo <- downloadHandler( - filename = function() { - log_print(paste0("Save scheme info table ", paste0(gsub(" ", "_", DB$scheme), "_scheme.csv"))) - - paste0(gsub(" ", "_", DB$scheme), "_scheme.csv") - }, - content = function(file) { - pub_index <- which(DB$schemeinfo[,1] == "Publications") - write.table( - DB$schemeinfo[1:(pub_index-1),], - file, - sep = ";", - row.names = FALSE, - quote = FALSE - ) - } - ) - - #### Save Loci info table as CSV ---- - - output$download_loci_info <- downloadHandler( - filename = function() { - log_print(paste0("Save loci info table ", paste0(gsub(" ", "_", DB$scheme), "_Loci.csv"))) - - paste0(gsub(" ", "_", DB$scheme), "_Loci.csv") - }, - content = function(file) { - write.table( - DB$loci_info, - file, - sep = ";", - row.names = FALSE, - quote = FALSE - ) - } - ) - - #### Save entry table as CSV ---- - - output$download_entry_table <- downloadHandler( - filename = function() { - log_print(paste0("Save entry table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv"))) - - paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv") - }, - content = function(file) { - download_matrix <- hot_to_r(input$db_entries) - - if (input$download_table_include == TRUE) { - download_matrix <- download_matrix[which(download_matrix$Include == TRUE),] - } - - if (input$download_table_loci == FALSE) { - download_matrix <- select(download_matrix, 1:(13 + nrow(DB$cust_var))) - } - - write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) - } - ) - - # Save Edits Button - - observeEvent(input$edit_button, { - if(nrow(hot_to_r(input$db_entries)) > nrow(DB$data)) { - show_toast( - title = "Invalid rows entered. Saving not possible.", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - if(!isTRUE(DB$inhibit_change)) { - log_print("Input edit_button") - - showModal( - modalDialog( - if(length(DB$deleted_entries > 0)) { - paste0( - "Overwriting previous metadata of local ", - DB$scheme, - " database. Deleted entries will be irreversibly removed. Continue?" - ) - } else { - paste0( - "Overwriting previous metadata of local ", - DB$scheme, - " database. Continue?" - ) - }, - title = "Save Database", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_db_save", "Save", class = "btn btn-default") - ) - ) - ) - } else { - log_print("Input edit_button, invalid values.") - show_toast( - title = "Invalid values entered. Saving not possible.", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } - }) - - observeEvent(input$Cancel, { - log_print("Input Cancel") - removeModal() - }) - - observeEvent(input$conf_db_save, { - log_print("Input conf_db_save") - - # Remove isolate assembly file if present - if(!is.null(DB$remove_iso)) { - if(length(DB$remove_iso) > 0) { - lapply(DB$remove_iso, unlink, recursive = TRUE, force = FALSE, expand = TRUE) - } - } - DB$remove_iso <- NULL - - Data <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) - - if ((ncol(Data[["Typing"]]) - 13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_vars_pre <- select(Data[["Typing"]], - 14:(ncol(Data[["Typing"]]) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - cust_vars_pre <- names(cust_vars_pre) - } else { - cust_vars_pre <- character() - } - - Data[["Typing"]] <- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) - - meta_hot <- hot_to_r(input$db_entries) - - if(length(DB$deleted_entries > 0)) { - - meta_hot <- mutate(meta_hot, Index = as.character(1:nrow(DB$data))) - - Data[["Typing"]] <- mutate(Data[["Typing"]][-as.numeric(DB$deleted_entries), ], - meta_hot, .before = 1) - rownames(Data[["Typing"]]) <- Data[["Typing"]]$Index - } else { - Data[["Typing"]] <- mutate(Data[["Typing"]], meta_hot, .before = 1) - } - - # Ensure correct logical data type - Data[["Typing"]][["Include"]] <- as.logical(Data[["Typing"]][["Include"]]) - saveRDS(Data, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - # Load database from files - Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - DB$data <- Database[["Typing"]] - - if(!is.null(DB$data)){ - if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { - cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) - DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) - } else { - DB$cust_var <- data.frame() - } - } - - DB$change <- FALSE - DB$count <- 0 - DB$no_na_switch <- TRUE - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - DB$deleted_entries <- character(0) - - removeModal() - - show_toast( - title = "Database successfully saved", - type = "success", - position = "bottom-end", - timer = 4000 - ) - }) - - observeEvent(input$del_button, { - log_print("Input del_button") - - if (length(input$select_delete) < 1) { - log_print("Delete entries; no entry selected") - show_toast( - title = "No entry selected", - type = "warning", - position = "bottom-end", - timer = 4000 - ) - } else if((readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") | - (tail(readLogFile(), 1) != "0")) { - log_print("Delete entries; pending typing") - - show_toast( - title = "Pending Typing", - type = "warning", - position = "bottom-end", - timer = 4000 - ) - } else { - if( (length(input$select_delete) - nrow(DB$data) ) == 0) { - showModal( - modalDialog( - paste0("Deleting will lead to removal of all entries and assemblies from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?"), - easyClose = TRUE, - title = "Deleting Entries", - footer = tagList( - modalButton("Cancel"), - actionButton("conf_delete_all", "Delete", class = "btn btn-danger") - ) - ) - ) - } else { - showModal( - modalDialog( - paste0( - "Confirmation will lead to irreversible removal of selected entries and the respectively saved assembly. Continue?" - ), - title = "Deleting Entries", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton( - "conf_delete", - "Delete", - class = "btn btn-danger") - ) - ) - ) - } - } - }) - - observeEvent(input$conf_delete_all, { - log_print("Input conf_delete_all") - - # remove file with typing data - file.remove(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - unlink(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates"), recursive = TRUE, force = FALSE, expand =TRUE) - - showModal( - modalDialog( - selectInput( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}}), - title = "All entries have been removed. Select a local database to load.", - footer = tagList( - actionButton("load", "Load", class = "btn btn-default") - ) - ) - ) - - }) - - DB$deleted_entries <- character(0) - - observeEvent(input$conf_delete, { - - log_print("Input conf_delete") - - # Get isolates selected for deletion - DB$deleted_entries <- append(DB$deleted_entries, DB$data$Index[as.numeric(input$select_delete)]) - - # Set reactive status variables - DB$no_na_switch <- TRUE - DB$change <- TRUE - DB$check_new_entries <- FALSE - - # Set isolate directory deletion variables - isopath <- dir_ls(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates")) - DB$remove_iso <- isopath[which(basename(isopath) == DB$data$`Assembly ID`[as.numeric(input$select_delete)])] - - # Reload updated database reactive variables - DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) - DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) - DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] - - # User feedback - removeModal() - - if(length(input$select_delete) > 1) { - show_toast( - title = "Entries deleted", - type = "success", - position = "bottom-end", - timer = 4000 - ) - } else { - show_toast( - title = "Entry deleted", - type = "success", - position = "bottom-end", - timer = 4000 - ) - } - }) - - - ### Distance Matrix ---- - - hamming_df <- reactive({ - if(input$distmatrix_true == TRUE) { - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - - allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - - hamming_mat <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) - - } else if(input$na_handling == "ignore_na"){ - hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) - - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) - - } - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) - } - } else { - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - hamming_mat <- compute.distMatrix(allelic_profile_noNA, hamming.dist) - } else if(input$na_handling == "ignore_na"){ - hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distIgnore) - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distCategory) - } - } else { - hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.dist) - } - } - - # Extreme values for distance matrix heatmap display - DB$matrix_min <- min(hamming_mat, na.rm = TRUE) - DB$matrix_max <- max(hamming_mat, na.rm = TRUE) - - if(input$distmatrix_triangle == FALSE) { - hamming_mat[upper.tri(hamming_mat, diag = !input$distmatrix_diag)] <- NA - } - - # Row- and colnames change - if(input$distmatrix_true == TRUE) { - rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label][which(DB$data$Include == TRUE),]) - } else { - rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label]) - } - colnames(hamming_mat) <- rownames(hamming_mat) - - mode(hamming_mat) <- "integer" - - DB$ham_matrix <- hamming_mat %>% - as.data.frame() %>% - mutate(Index = colnames(hamming_mat)) %>% - relocate(Index) - DB$distancematrix_nrow <- nrow(DB$ham_matrix) - - DB$ham_matrix - }) - - output$download_distmatrix <- downloadHandler( - filename = function() { - paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Distance_Matrix.csv") - }, - content = function(file) { - download_matrix <- hot_to_r(input$db_distancematrix) - download_matrix[is.na(download_matrix)] <- "" - write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) - } - ) - - # _______________________ #### - - ## Locus sequences ---- - - observe({ - if(!is.null(DB$database) & !is.null(DB$scheme)) { - DB$loci <- list.files( - path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), - pattern = "\\.(fasta|fa|fna)$", - full.names = TRUE - ) - } - }) - - output$loci_sequences <- renderUI({ - req(input$db_loci_rows_selected, DB$database, DB$scheme, input$seq_sel) - - DB$loci <- list.files( - path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), - pattern = "\\.(fasta|fa|fna)$", - full.names = TRUE - ) - - fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) - - seq <- fasta[[which(fasta == paste0(">", gsub("Allele ", "", sub(" -.*", "", input$seq_sel)))) + 1]] - - DB$seq <- seq - - column( - width = 12, - HTML( - paste( - tags$span(style='color: white; font-size: 15px; position: relative; top: -15px; left: -50px', - sub(" -.*", "", input$seq_sel)) - ) - ), - tags$pre(HTML(color_sequence(seq)), class = "sequence") - ) - }) - - output$sequence_selector <- renderUI({ - if(!is.null(input$db_loci_rows_selected)) { - - req(input$db_loci_rows_selected, DB$database, DB$scheme) - - DB$loci <- list.files( - path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), - pattern = "\\.(fasta|fa|fna)$", - full.names = TRUE - ) - - fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) - - seq_names <- c() - for (i in seq_along(fasta)) { - if (startsWith(fasta[[i]], ">")) { - name <- sub(">", "", fasta[[i]]) - seq_names <- c(seq_names, name) - } - } - - var_count <- table(DB$allelic_profile[gsub(".fasta", "", (basename(DB$loci[input$db_loci_rows_selected])))]) - - vec <- prop.table(var_count) - - perc <- sapply(unname(vec), scales::percent, accuracy = 0.1) - - names(perc) <- names(vec) - - choices <- seq_names - - present <- which(choices %in% names(vec)) - absent <- which(!(choices %in% names(vec))) - - choices[present] <- paste0("Allele ", choices[present], " - ", unname(var_count), " times in DB (", unname(perc), ")") - - choices[absent] <- paste0("Allele ", choices[absent], " - not present") - - choices <- c(choices[present], choices[absent]) - - names(choices) <- sapply(choices, function(x) { - x <- strsplit(x, " ")[[1]] - x[2] <- paste0(substr(x[2], 1, 4), "...", substr(x[2], nchar(x[2])-3, nchar(x[2]))) - paste(x, collapse = " ") - }) - - column( - width = 3, - selectInput( - "seq_sel", - h5("Select Variant", style = "color:white;"), - choices = choices, - width = "80%" - ), - br(), - fluidRow( - column( - width = 8, - align = "left", - actionButton("copy_seq", "Copy Sequence", - icon = icon("copy")), - bsTooltip("copy_seq", "Copy the variant sequence
to clipboard", placement = "top", trigger = "hover") - ) - ), - br(), - fluidRow( - column( - width = 8, - align = "left", - downloadBttn( - "get_locus", - style = "simple", - label = "Save .fasta", - size = "sm", - icon = icon("download") - ), - bsTooltip("get_locus_bttn", "Save locus file with all variants", placement = "top", trigger = "hover") - ) - ), - br(), br(), br(), br(), br(), br(), br() - ) - } - }) - - observeEvent(input$copy_seq, { - if(!is.null(DB$seq)) { - session$sendCustomMessage("txt", DB$seq) - } - show_toast( - title = "Copied sequence", - type = "success", - position = "bottom-end", - timer = 3000 - ) - }) - - output$get_locus <- downloadHandler( - filename = function() { - fname <- basename(DB$loci[input$db_loci_rows_selected]) - log_print(paste0("Get locus fasta ", fname)) - fname - }, - content = function(file) { - cont <- readLines(DB$loci[input$db_loci_rows_selected]) - writeLines(cont, file) - } - ) - - # _______________________ #### - - ## Download cgMLST ---- - - observe({ - if (input$select_cgmlst == "Acinetobacter baumanii") { - species <- "Abaumannii1907" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- Scheme$folder_name <- "Acinetobacter_baumanii" - } else if (input$select_cgmlst == "Bacillus anthracis") { - species <- "Banthracis1917" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Bacillus_anthracis" - } else if (input$select_cgmlst == "Bordetella pertussis") { - species <- "Bpertussis1917" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Bordetella_pertussis" - } else if (input$select_cgmlst == "Brucella melitensis") { - species <- "Bmelitensis1912" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Brucella_melitensis" - } else if (input$select_cgmlst == "Brucella spp.") { - species <- "Brucella1914" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Brucella_spp" - } else if (input$select_cgmlst == "Burkholderia mallei (FLI)") { - species <- "Bmallei_fli1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Burkholderia_mallei_FLI" - } else if (input$select_cgmlst == "Burkholderia mallei (RKI)") { - species <- "Bmallei_rki1909" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Burkholderia_mallei_RKI" - } else if (input$select_cgmlst == "Burkholderia pseudomallei") { - species <- "Bpseudomallei1906" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Burkholderia_pseudomallei" - } else if (input$select_cgmlst == "Campylobacter jejuni/coli") { - species <- "Cjejuni1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Campylobacter_jejuni_coli" - } else if (input$select_cgmlst == "Clostridioides difficile") { - species <- "Cdifficile1905" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Clostridioides_difficile" - } else if (input$select_cgmlst == "Clostridium perfringens") { - species <- "Cperfringens1907" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Clostridium_perfringens" - } else if (input$select_cgmlst == "Corynebacterium diphtheriae") { - species <- "Cdiphtheriae1907" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Corynebacterium_diphtheriae" - } else if (input$select_cgmlst == "Cronobacter sakazakii/malonaticus") { - species <- "Csakazakii1910" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Cronobacter_sakazakii_malonaticus" - } else if (input$select_cgmlst == "Enterococcus faecalis") { - species <- "Efaecalis1912" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Enterococcus_faecalis" - } else if (input$select_cgmlst == "Enterococcus faecium") { - species <- "Efaecium1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Enterococcus_faecium" - } else if (input$select_cgmlst == "Escherichia coli") { - species <- "Ecoli1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Escherichia_coli" - } else if (input$select_cgmlst == "Francisella tularensis") { - species <- "Ftularensis1913" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Francisella_tularensis" - } else if (input$select_cgmlst == "Klebsiella oxytoca sensu lato") { - species <- "Koxytoca717" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Klebsiella_oxytoca_sensu_lato" - } else if (input$select_cgmlst == "Klebsiella pneumoniae sensu lato") { - species <- "Kpneumoniae1909" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Klebsiella_pneumoniae_sensu_lato" - } else if (input$select_cgmlst == "Legionella pneumophila") { - species <- "Lpneumophila1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Legionella_pneumophila" - } else if (input$select_cgmlst == "Listeria monocytogenes") { - species <- "Lmonocytogenes1910" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Listeria_monocytogenes" - } else if (input$select_cgmlst == "Mycobacterium tuberculosis complex") { - species <- "Mtuberculosis1909" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Mycobacterium_tuberculosis_complex" - } else if (input$select_cgmlst == "Mycobacteroides abscessus") { - species <- "Mabscessus1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Mycobacteroides_abscessus" - } else if (input$select_cgmlst == "Mycoplasma gallisepticum") { - species <- "Mgallisepticum1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Mycoplasma_gallisepticum" - } else if (input$select_cgmlst == "Paenibacillus larvae") { - species <- "Plarvae1902" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Paenibacillus_larvae" - } else if (input$select_cgmlst == "Pseudomonas aeruginosa") { - species <- "Paeruginosa1911" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Pseudomonas_aeruginosa" - } else if (input$select_cgmlst == "Salmonella enterica") { - species <- "Senterica1913" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Salmonella_enterica" - } else if (input$select_cgmlst == "Serratia marcescens") { - species <- "Smarcescens1912" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Serratia_marcescens" - } else if (input$select_cgmlst == "Staphylococcus aureus") { - species <- "Saureus1908" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Staphylococcus_aureus" - } else if (input$select_cgmlst == "Staphylococcus capitis") { - species <- "Scapitis1905" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Staphylococcus_capitis" - } else if (input$select_cgmlst == "Streptococcus pyogenes") { - species <- "Spyogenes1904" - Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") - Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") - Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") - Scheme$folder_name <- "Streptococcus_pyogenes" - } - }) - - observeEvent(input$download_cgMLST, { - log_print(paste0("Started download of scheme for ", Scheme$folder_name)) - - shinyjs::hide("download_cgMLST") - shinyjs::show("loading") - - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    Downloading scheme...")), - style = "color:white;") - ) - ) - ) - - show_toast( - title = "Download started", - type = "success", - position = "bottom-end", - timer = 5000 - ) - - if(length(DB$available) == 0) { - saveRDS(DB$new_database, paste0(getwd(), "/execute/new_db.rds")) - dir.create(file.path(readRDS(paste0(getwd(), "/execute/new_db.rds")), "Database"), recursive = TRUE) - } - - DB$load_selected <- TRUE - - # Check if .downloaded_schemes folder exists and if not create it - if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { - dir.create(file.path(DB$database, ".downloaded_schemes"), recursive = TRUE) - } - - # Check if remains of old temporary folder exists and remove them - if (dir.exists(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")))) { - unlink(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")), recursive = TRUE) - } - - # Download Loci Fasta Files - options(timeout = 600) - - tryCatch({ - download.file(Scheme$link_cgmlst, - file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip"))) - "Download successful!" - }, error = function(e) { - paste("Error: ", e$message) - }) - - # Unzip the scheme in temporary folder - unzip( - zipfile = file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")), - exdir = file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp") - ) - ) - - log_print("Hashing downloaded database") - # Hash temporary folder - hash_database(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"))) - - # Get list from local database - local_db_filelist <- list.files(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"))) - if (!is_empty(local_db_filelist)) { - # Get list from temporary database - tmp_db_filelist <- list.files(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"))) - - # Find the difference (extra files in local database) - local_db_extra <- setdiff(local_db_filelist, tmp_db_filelist) - - # Copy extra files to temporary folder - file.copy(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), local_db_extra), - file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"))) - - # Check differences in file pairs - local_db_hashes <- tools::md5sum(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), - local_db_filelist)) - tmp_db_hashes <- tools::md5sum(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"), - local_db_filelist)) - - diff_files <- local_db_hashes %in% tmp_db_hashes - diff_loci <- names(local_db_hashes)[diff_files == FALSE] - diff_loci <- sapply(strsplit(diff_loci, "/"), function(x) x[length(x)]) - - # Check locus hashes - for (locus in diff_loci) { - local_db_hashes <- get_locus_hashes(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), - locus)) - tmp_db_hashes <- get_locus_hashes(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"), - locus)) - diff_hashes <- setdiff(local_db_hashes, tmp_db_hashes) - - sequences <- extract_seq(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"), - locus), diff_hashes) - if (!is_empty(sequences$idx) && !is_empty(sequences$seq) && - length(sequences$idx) == length(sequences$seq)) { - add_new_sequences(file.path(DB$database, - Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp"), - locus), sequences) - } - } - } - - unlink(file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) - - file.rename(file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, ".tmp")), - file.path(DB$database, Scheme$folder_name, - paste0(Scheme$folder_name, "_alleles"))) - - # Download Scheme Info - download( - Scheme$link_scheme, - dest = file.path(DB$database, Scheme$folder_name, "scheme_info.html"), - mode = "wb" - ) - - # Download Loci Info - download( - Scheme$link_targets, - dest = file.path(DB$database, Scheme$folder_name, "targets.csv"), - mode = "wb" - ) - - # Send downloaded scheme to database browser overview - DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) - - Scheme$target_table <- read.csv( - file.path(DB$database, Scheme$folder_name, "targets.csv"), - header = TRUE, - sep = "\t", - row.names = NULL, - colClasses = c( - "NULL", - "character", - "character", - "integer", - "integer", - "character", - "integer", - "NULL" - ) - ) - - DB$exist <- length(dir_ls(DB$database)) == 0 - - shinyjs::show("download_cgMLST") - shinyjs::hide("loading") - - output$statustext <- renderUI( - fluidRow( - tags$li( - class = "dropdown", - tags$span(HTML( - paste('', - "Status:    ready")), - style = "color:white;") - ) - ) - ) - - show_toast( - title = "Download successful", - type = "success", - position = "bottom-end", - timer = 5000 - ) - - log_print("Download successful") - - showModal( - modalDialog( - selectInput( - "scheme_db", - label = "", - choices = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {DB$available}, - selected = if(!is.null(Typing$last_scheme)) { - Typing$last_scheme - } else {if(!is.null(DB$scheme)) {input$select_cgmlst} else {DB$available[1]}}), - title = "Select a local database to load.", - footer = tagList( - actionButton("load", "Load", class = "btn btn-default") - ) - ) - ) - }) - - # Download Target Info (CSV Table) - observe({ - input$download_cgMLST - - scheme_overview <- read_html(Scheme$link_scheme) %>% - html_table(header = FALSE) %>% - as.data.frame(stringsAsFactors = FALSE) - - last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], - format = "%B %d, %Y, %H:%M %p") - names(scheme_overview) <- NULL - - last_file_change <- format( - file.info(file.path(DB$database, - ".downloaded_schemes", - paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") - - output$cgmlst_scheme <- renderTable({scheme_overview}) - output$scheme_update_info <- renderText({ - req(last_file_change) - if (last_file_change < last_scheme_change) { - "(Newer scheme available \u274c)" - } else { - "(Scheme is up-to-date \u2705)" - } - }) - }) - - # _______________________ #### - - ## Visualization ---- - - # Render placeholder image - - output$placeholder <- renderImage({ - # Path to your PNG image with a transparent background - image_path <- paste0(getwd(), "/www/PhyloTrace.png") - - # Use HTML to display the image with the tag - list(src = image_path, - height = 180) - }, deleteFile = FALSE) - - # Render tree plot fields - - output$nj_field <- renderUI( - fluidRow( - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br() - ) - ) - - output$mst_field <- renderUI( - fluidRow( - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br() - ) - ) - - output$upgma_field <- renderUI( - fluidRow( - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), - br(), br(), br(), br(), br(), br(), br(), br(), br(), br() - ) - ) - - ### Render Visualization Controls ---- - - #### NJ and UPGMA controls ---- - - # Control enable/disable of variable mapping inputs - observe({ - shinyjs::toggleState(id = "nj_color_mapping", condition = isTRUE(input$nj_mapping_show)) - shinyjs::toggleState(id = "nj_tiplab_scale", condition = isTRUE(input$nj_mapping_show)) - shinyjs::toggleState(id = "upgma_color_mapping", condition = isTRUE(input$upgma_mapping_show)) - shinyjs::toggleState(id = "upgma_tiplab_scale", condition = isTRUE(input$upgma_mapping_show)) - - shinyjs::toggleState(id = "nj_tipcolor_mapping", condition = isTRUE(input$nj_tipcolor_mapping_show)) - shinyjs::toggleState(id = "nj_tippoint_scale", condition = isTRUE(input$nj_tipcolor_mapping_show)) - shinyjs::toggleState(id = "upgma_tipcolor_mapping", condition = isTRUE(input$upgma_tipcolor_mapping_show)) - shinyjs::toggleState(id = "upgma_tippoint_scale", condition = isTRUE(input$upgma_tipcolor_mapping_show)) - - shinyjs::toggleState(id = "nj_tipshape_mapping", condition = isTRUE(input$nj_tipshape_mapping_show)) - shinyjs::toggleState(id = "upgma_tipshape_mapping", condition = isTRUE(input$upgma_tipshape_mapping_show)) - - shinyjs::toggleState(id = "nj_fruit_variable", condition = isTRUE(input$nj_tiles_show_1)) - shinyjs::toggleState(id = "upgma_fruit_variable", condition = isTRUE(input$upgma_tiles_show_1)) - shinyjs::toggleState(id = "nj_fruit_variable_2", condition = isTRUE(input$nj_tiles_show_2)) - shinyjs::toggleState(id = "upgma_fruit_variable_2", condition = isTRUE(input$upgma_tiles_show_2)) - shinyjs::toggleState(id = "nj_fruit_variable_3", condition = isTRUE(input$nj_tiles_show_3)) - shinyjs::toggleState(id = "upgma_fruit_variable_3", condition = isTRUE(input$upgma_tiles_show_3)) - shinyjs::toggleState(id = "nj_fruit_variable_4", condition = isTRUE(input$nj_tiles_show_4)) - shinyjs::toggleState(id = "upgma_fruit_variable_4", condition = isTRUE(input$upgma_tiles_show_4)) - shinyjs::toggleState(id = "nj_fruit_variable_5", condition = isTRUE(input$nj_tiles_show_5)) - shinyjs::toggleState(id = "upgma_fruit_variable_5", condition = isTRUE(input$upgma_tiles_show_5)) - shinyjs::toggleState(id = "nj_tiles_scale_1", condition = isTRUE(input$nj_tiles_show_1)) - shinyjs::toggleState(id = "upgma_tiles_scale_1", condition = isTRUE(input$upgma_tiles_show_1)) - shinyjs::toggleState(id = "nj_tiles_scale_2", condition = isTRUE(input$nj_tiles_show_2)) - shinyjs::toggleState(id = "upgma_tiles_scale_2", condition = isTRUE(input$upgma_tiles_show_2)) - shinyjs::toggleState(id = "nj_tiles_scale_3", condition = isTRUE(input$nj_tiles_show_3)) - shinyjs::toggleState(id = "upgma_tiles_scale_3", condition = isTRUE(input$upgma_tiles_show_3)) - shinyjs::toggleState(id = "nj_tiles_scale_4", condition = isTRUE(input$nj_tiles_show_4)) - shinyjs::toggleState(id = "upgma_tiles_scale_4", condition = isTRUE(input$upgma_tiles_show_4)) - shinyjs::toggleState(id = "nj_tiles_scale_5", condition = isTRUE(input$nj_tiles_show_5)) - shinyjs::toggleState(id = "upgma_tiles_scale_5", condition = isTRUE(input$upgma_tiles_show_5)) - - shinyjs::toggleState(id = "nj_heatmap_sel", condition = isTRUE(input$nj_heatmap_show)) - shinyjs::toggleState(id = "nj_heatmap_scale", condition = isTRUE(input$nj_heatmap_show)) - shinyjs::toggleState(id = "upgma_heatmap_sel", condition = isTRUE(input$upgma_heatmap_show)) - shinyjs::toggleState(id = "upgma_heatmap_scale", condition = isTRUE(input$upgma_heatmap_show)) - }) - - # Size scaling NJ - observe({ - req(input$nj_ratio) - if(input$nj_ratio == "1.6") { - updateSliderInput(session, "nj_scale", - step = 5, value = 800, min = 500, max = 1200) - } else if(input$nj_ratio == "1.77777777777778") { - updateSliderInput(session, "nj_scale", - step = 9, value = 801, min = 504, max = 1197) - } else if(input$nj_ratio == "1.33333333333333"){ - updateSliderInput(session, "nj_scale", - step = 3, value = 801, min = 501, max = 1200) - } - }) - - # Size scaling UPGMA - observe({ - req(input$upgma_ratio) - if(input$upgma_ratio == "1.6") { - updateSliderInput(session, "upgma_scale", - step = 5, value = 800, min = 500, max = 1200) - } else if(input$upgma_ratio == "1.77777777777778") { - updateSliderInput(session, "upgma_scale", - step = 9, value = 801, min = 504, max = 1197) - } else if(input$upgma_ratio == "1.33333333333333"){ - updateSliderInput(session, "upgma_scale", - step = 3, value = 801, min = 501, max = 1200) - } - }) - - # Size scaling MST - observe({ - req(input$mst_ratio) - if(input$mst_ratio == "1.6") { - updateSliderInput(session, "mst_scale", - step = 5, value = 800, min = 500, max = 1200) - } else if(input$mst_ratio == "1.77777777777778") { - updateSliderInput(session, "mst_scale", - step = 9, value = 801, min = 504, max = 1197) - } else if(input$mst_ratio == "1.33333333333333"){ - updateSliderInput(session, "mst_scale", - step = 3, value = 801, min = 501, max = 1200) - } - }) - - # Custom Labels - - # Add custom label - observeEvent(input$nj_add_new_label, { - - if(nchar(input$nj_new_label_name) > 0) { - if(!(input$nj_new_label_name %in% Vis$custom_label_nj)) { - Vis$custom_label_nj <- rbind(Vis$custom_label_nj, input$nj_new_label_name) - if(!(nrow(Vis$custom_label_nj) == 1)) { - updateSelectInput(session, "nj_custom_label_sel", selected = input$nj_new_label_name) - } - } else { - show_toast( - title = "Label already exists", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } else { - show_toast( - title = "Min. 1 character", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - - observeEvent(input$upgma_add_new_label, { - - if(nchar(input$upgma_new_label_name) > 0) { - if(!(input$upgma_new_label_name %in% Vis$custom_label_upgma)) { - Vis$custom_label_upgma <- rbind(Vis$custom_label_upgma, input$upgma_new_label_name) - if(!(nrow(Vis$custom_label_upgma) == 1)) { - updateSelectInput(session, "upgma_custom_label_sel", selected = input$upgma_new_label_name) - } - } else { - show_toast( - title = "Label already exists", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } else { - show_toast( - title = "Min. 1 character", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - - # Delete custom label - observeEvent(input$nj_del_label, { - - if(nrow(Vis$custom_label_nj) > 1) { - Vis$custom_label_nj <- Vis$custom_label_nj[-which(Vis$custom_label_nj[,1] == input$nj_custom_label_sel), , drop = FALSE] - } else if (nrow(Vis$custom_label_nj) == 1) { - Vis$nj_label_pos_x <- list() - Vis$nj_label_pos_y <- list() - Vis$nj_label_size <- list() - Vis$custom_label_nj <- data.frame() - } - }) - - observeEvent(input$upgma_del_label, { - - if(nrow(Vis$custom_label_upgma) > 1) { - Vis$custom_label_upgma <- Vis$custom_label_upgma[-which(Vis$custom_label_upgma[,1] == input$upgma_custom_label_sel), , drop = FALSE] - } else if (nrow(Vis$custom_label_upgma) == 1) { - Vis$upgma_label_pos_x <- list() - Vis$upgma_label_pos_y <- list() - Vis$upgma_label_size <- list() - Vis$custom_label_upgma <- data.frame() - } - }) - - # Select custom labels - output$nj_custom_label_select <- renderUI({ - if(nrow(Vis$custom_label_nj) > 0) { - selectInput( - "nj_custom_label_sel", - "", - choices = Vis$custom_label_nj[,1] - ) - } - }) - - output$upgma_custom_label_select <- renderUI({ - if(nrow(Vis$custom_label_upgma) > 0) { - selectInput( - "upgma_custom_label_sel", - "", - choices = Vis$custom_label_upgma[,1] - ) - } - }) - - # Select custom labels - output$nj_cust_label_save <- renderUI({ - if(nrow(Vis$custom_label_nj) > 0) { - actionButton( - "nj_cust_label_save", - "Apply" - ) - } else { - column( - width = 12, - br(), br(), br(), br(), br(), br(), - h5("test", style = "color: transparent; margin-bottom: 3px") - ) - } - }) - - output$upgma_cust_label_save <- renderUI({ - if(nrow(Vis$custom_label_upgma) > 0) { - actionButton( - "upgma_cust_label_save", - "Apply" - ) - } else { - column( - width = 12, - br(), br(), br(), br(), br(), br(), - h5("test", style = "color: transparent; margin-bottom: 3px") - ) - } - }) - - # Custom Label Size - output$nj_custom_labelsize <- renderUI({ - if(length(Vis$custom_label_nj) > 0) { - if(!is.null(Vis$nj_label_size[[input$nj_custom_label_sel]])) { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, - value = Vis$nj_label_size[[input$nj_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, value = 5, - width = "150px") - } - } - }) - - output$upgma_custom_labelsize <- renderUI({ - if(length(Vis$custom_label_upgma) > 0) { - if(!is.null(Vis$upgma_label_size[[input$upgma_custom_label_sel]])) { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, - value = Vis$upgma_label_size[[input$upgma_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), - label = h5("Size", style = "color: white; margin-bottom: 0px;"), - min = 0, max = 10, step = 0.5, ticks = F, value = 5, - width = "150px") - } - } - }) - - # Render slider input based on selected label - output$nj_sliderInput_y <- renderUI({ - if(length(Vis$custom_label_nj) > 0) { - if(!is.null(Vis$nj_label_pos_y[[input$nj_custom_label_sel]])) { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$nj_label_pos_y[[input$nj_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = sum(DB$data$Include), step = 1, ticks = F, - value = sum(DB$data$Include) / 2, - width = "150px") - } - } - }) - - output$upgma_sliderInput_y <- renderUI({ - if(length(Vis$custom_label_upgma) > 0) { - if(!is.null(Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]])) { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), - label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), - min = 0, max = sum(DB$data$Include), step = 1, ticks = F, - value = sum(DB$data$Include) / 2, - width = "150px") - } - } - }) - - output$nj_sliderInput_x <- renderUI({ - if(length(Vis$custom_label_nj) > 0) { - if(!is.null(Vis$nj_label_pos_x[[input$nj_custom_label_sel]])) { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$nj_label_pos_x[[input$nj_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = round(Vis$nj_max_x, 0), step = 1, ticks = F, - value = round(Vis$nj_max_x / 2, 0), - width = "150px") - } - } - }) - - output$upgma_sliderInput_x <- renderUI({ - if(length(Vis$custom_label_upgma) > 0) { - if(!is.null(Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]])) { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = 50, step = 1, ticks = F, - value = Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]], - width = "150px") - } else { - sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), - label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), - min = 0, max = round(Vis$upgma_max_x, 0), step = 1, ticks = F, - value = round(Vis$upgma_max_x / 2, 0), - width = "150px") - } - } - }) - - # Apply custom label changes - observeEvent(input$nj_cust_label_save, { - - if(!is.null(Vis$nj_label_pos_y) & - !is.null(Vis$nj_label_pos_x) & - !is.null(Vis$nj_label_size) & - !is.null(input$nj_custom_label_sel)) { - Vis$nj_label_pos_y[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_y")]] - Vis$nj_label_pos_x[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_x")]] - Vis$nj_label_size[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_size")]] - } - }) - - observeEvent(input$upgma_cust_label_save, { - - if(!is.null(Vis$upgma_label_pos_y) & - !is.null(Vis$upgma_label_pos_x) & - !is.null(Vis$upgma_label_size) & - !is.null(input$upgma_custom_label_sel)) { - Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_y")]] - Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_x")]] - Vis$upgma_label_size[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_size")]] - } - }) - - # Show delete custom label button if custam label added - output$nj_del_label <- renderUI({ - if(nrow(Vis$custom_label_nj) > 0) { - actionButton( - "nj_del_label", - "", - icon = icon("minus") - ) - } else {NULL} - }) - - output$upgma_del_label <- renderUI({ - if(nrow(Vis$custom_label_upgma) > 0) { - actionButton( - "upgma_del_label", - "", - icon = icon("minus") - ) - } else {NULL} - }) - - # Mapping value number information - output$nj_tiplab_mapping_info <- renderUI({ - if(!is.null(input$nj_color_mapping) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_color_mapping]))) { - if(input$nj_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_color_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$upgma_tiplab_mapping_info <- renderUI({ - if(!is.null(input$upgma_color_mapping) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) { - if(input$upgma_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_color_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$nj_tipcolor_mapping_info <- renderUI({ - if(!is.null(input$nj_tipcolor_mapping) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) { - if(input$nj_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tipcolor_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$upgma_tipcolor_mapping_info <- renderUI({ - if(!is.null(input$upgma_tipcolor_mapping) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) { - if(input$upgma_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tipcolor_mapping_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$nj_tipshape_mapping_info <- renderUI({ - if(!is.null(input$nj_tipshape_mapping) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) { - column( - width = 3, - h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) > 6) { - column( - width = 3, - h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$upgma_tipshape_mapping_info <- renderUI({ - if(!is.null(input$upgma_tipshape_mapping) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) { - column( - width = 3, - h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) > 6) { - column( - width = 3, - h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - }) - - output$nj_fruit_mapping_info <- renderUI({ - if(input$nj_tile_num == 1) { - if(!is.null(input$nj_fruit_variable) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable]))) { - if(input$nj_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_1", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 2) { - if(!is.null(input$nj_fruit_variable_2) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) { - if(input$nj_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_2", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 3) { - if(!is.null(input$nj_fruit_variable_3) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) { - if(input$nj_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_3", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 4) { - if(!is.null(input$nj_fruit_variable_4) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) { - if(input$nj_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_4", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$nj_tile_num == 5) { - if(!is.null(input$nj_fruit_variable_5) & (!is.null(Vis$meta_nj))) { - if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) { - if(input$nj_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_tiles_mapping_div_mid_5", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } - }) - - output$upgma_fruit_mapping_info <- renderUI({ - if(input$upgma_tile_num == 1) { - if(!is.null(input$upgma_fruit_variable) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) { - if(input$upgma_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_1", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 2) { - if(!is.null(input$upgma_fruit_variable_2) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) { - if(input$upgma_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_2", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 3) { - if(!is.null(input$upgma_fruit_variable_3) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) { - if(input$upgma_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_3", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 4) { - if(!is.null(input$upgma_fruit_variable_4) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) { - if(input$upgma_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_4", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } else if (input$upgma_tile_num == 5) { - if(!is.null(input$upgma_fruit_variable_5) & (!is.null(Vis$meta_upgma))) { - if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) { - if(input$upgma_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_tiles_mapping_div_mid_5", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { - column( - width = 3, - h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } else {NULL} - } - }) - - output$nj_heatmap_mapping_info <- renderUI({ - if(!is.null(input$nj_heatmap_select) & (!is.null(Vis$meta_nj))) { - if (any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { - column( - width = 3, - h5("Heatmap with categorical and continous values not possible", - style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") - ) - } else { - if(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { - if(input$nj_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "nj_heatmap_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { - column( - width = 3, - h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } - } else {NULL} - }) - - output$upgma_heatmap_mapping_info <- renderUI({ - if(!is.null(input$upgma_heatmap_select) & (!is.null(Vis$meta_upgma))) { - if (any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { - column( - width = 3, - h5("Heatmap with categorical and continous values not possible", - style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") - ) - } else { - if(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { - if(input$upgma_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { - column( - width = 3, - fluidRow( - column( - width = 4, - h5("Midpoint", style = "color: white; margin-top: 22px;") - ), - column( - width = 8, - div( - class = "divmid-sel1", - selectInput( - "upgma_heatmap_div_mid", - label = "", - choices = c("Zero", "Mean", "Median"), - selected = "Mean" - ) - ) - ) - ) - ) - } else { - column( - width = 3, - h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") - ) - } - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { - column( - width = 3, - h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") - ) - } else { - column( - width = 3, - h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") - ) - } - } - } - } else {NULL} - }) - - # Tiles offset - output$nj_fruit_offset_circ <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ", - label = "", - min = min, - max = max, - step= step, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.1 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.05 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ", - label = "", - min = min, - max = max, - step= step, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ", - label = "", - min = -0.2, - max = 0.2, - step= 0.05, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_2 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_2", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_2", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_2 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_2", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_2", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_3 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_3", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_3", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_3 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_3", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_3", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_4 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_4", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_4", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_4 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_4", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_4", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_fruit_offset_circ_5 <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "nj_fruit_offset_circ_5", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_offset_circ_5", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_fruit_offset_circ_5 <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } else { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } - - sliderInput( - "upgma_fruit_offset_circ_5", - label = "", - min = min, - max = max, - step= step, - value = offset, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_offset_circ_5", - label = "", - min = -0.2, - max = 0.2, - step= 0.01, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - # For Layout change update tiles offset position - observeEvent(input$nj_layout, { - - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } else { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } - - updateSliderInput(session, "nj_fruit_offset_circ", min = min, step = step, max = max) - updateSliderInput(session, "nj_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "nj_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "nj_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "nj_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) - }) - - observeEvent(input$upgma_layout, { - - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - offset <- 0.05 - step <- 0.01 - min <- -0.2 - max <- 0.2 - } else { - offset <- 0.15 - step <- 0.03 - min <- -0.6 - max <- 0.6 - } - - updateSliderInput(session, "upgma_fruit_offset_circ", min = min, step = step, max = max) - updateSliderInput(session, "upgma_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "upgma_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "upgma_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) - updateSliderInput(session, "upgma_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) - }) - - # Heatmap width - output$nj_heatmap_width <- renderUI({ - if(!is.null(input$nj_heatmap_select)) { - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - - sliderInput( - "nj_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = width, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = 0.1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_heatmap_width <- renderUI({ - if(!is.null(input$upgma_heatmap_select)) { - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - - sliderInput( - "upgma_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = width, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_heatmap_width", - label = "", - min = 0.05, - max = 1.5, - value = 0.1, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - }) - - # Update value if new variables added - observeEvent(input$nj_heatmap_select, { - - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "nj_heatmap_width", value = width) - }) - - observeEvent(input$upgma_heatmap_select, { - - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "upgma_heatmap_width", value = width) - }) - - # Update value if layout changed - observeEvent(input$nj_layout, { - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "nj_heatmap_width", value = width) - }) - - observeEvent(input$upgma_layout, { - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - width <- 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 1.5 - } - } - } else { - if(length_input < 3) { - width <- 0.3 - } else if (length_input >= 3 && length_input <= 27) { - width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - width <- 3 - } - } - updateSliderInput(session, "upgma_heatmap_width", value = width) - }) - - # Heatmap column titles position - observeEvent(input$nj_layout, { - if(!(input$nj_layout == "inward" | input$nj_layout == "circular")) { - updateSliderInput(session, "nj_colnames_y", value = -1) - } else { - updateSliderInput(session, "nj_colnames_y", value = 0) - } - }) - - observeEvent(input$upgma_layout, { - if(!(input$upgma_layout == "inward" | input$upgma_layout == "circular")) { - updateSliderInput(session, "upgma_colnames_y", value = -1) - } else { - updateSliderInput(session, "upgma_colnames_y", value = 0) - } - }) - - output$nj_colnames_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - if(input$nj_layout == "inward" | input$nj_layout == "circular") { - min <- 0 - val <- 0 - } else { - val <- -1 - if((sum(DB$data$Include) * -0.1) > -2) { - min <- -2 - } else { - min <- round(sum(DB$data$Include) * -0.1, 0) - } - } - sliderInput( - "nj_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = min, - max = sum(DB$data$Include), - value = val, - step = 1, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = -10, - max = 10, - value = 0, - step = 1, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_colnames_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { - min <- 0 - val <- 0 - } else { - val <- -1 - if((sum(DB$data$Include) * -0.1) > -2) { - min <- -2 - } else { - min <- round(sum(DB$data$Include) * -0.1, 0) - } - } - sliderInput( - "upgma_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = min, - max = sum(DB$data$Include), - value = val, - step = 1, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_colnames_y", - label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), - min = -10, - max = 10, - value = 0, - step = 1, - width = "150px", - ticks = FALSE - ) - } - }) - - # Heatmap column titles angle - output$nj_colnames_angle <- renderUI({ - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - angle <- 90 - } else {angle <- -90} - sliderInput( - "nj_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = angle, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_colnames_angle <- renderUI({ - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - angle <- 90 - } else {angle <- -90} - sliderInput( - "upgma_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = angle, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_colnames_angle", - label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), - min = -90, - max = 90, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - # Change heatmap column titles angle and label align when switching layout - observeEvent(input$nj_layout, { - if(input$nj_layout == "circular" | input$nj_layout == "inward"){ - angle <- 90 - val <- TRUE - } else { - angle <- -90 - val <- FALSE - } - updateSwitchInput(session, "nj_align", value = val) - updateSliderInput(session, "nj_colnames_angle", value = angle) - }) - - observeEvent(input$upgma_layout, { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward"){ - angle <- 90 - val <- TRUE - } else { - angle <- -90 - val <- FALSE - } - updateSwitchInput(session, "upgma_align", value = val) - updateSliderInput(session, "upgma_colnames_angle", value = angle) - }) - - # Tile number selector update each other - observeEvent(input$nj_tile_num, { - updateSelectInput(session, "nj_tile_number", selected = input$nj_tile_num) - }) - - observeEvent(input$nj_tile_number, { - updateSelectInput(session, "nj_tile_num", selected = input$nj_tile_number) - }) - - observeEvent(input$upgma_tile_num, { - updateSelectInput(session, "upgma_tile_number", selected = input$upgma_tile_num) - }) - - observeEvent(input$upgma_tile_number, { - updateSelectInput(session, "upgma_tile_num", selected = input$upgma_tile_number) - }) - - # Clade coloring - output$nj_clade_scale <- renderUI({ - if(length(input$nj_parentnode) <= 1) { - fluidRow( - column( - width = 5, - h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "nj_clade_scale", - selected = "#D0F221", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ) - ) - } else { - fluidRow( - column( - width = 5, - h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - div( - class = "sel-clade-scale", - selectInput( - "nj_clade_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - ) - ) - } - }) - - output$upgma_clade_scale <- renderUI({ - if(length(input$upgma_parentnode) <= 1) { - fluidRow( - column( - width = 5, - h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - colorPickr( - inputId = "upgma_clade_scale", - selected = "#D0F221", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start", - width = "100%" - ) - ) - ) - } else { - fluidRow( - column( - width = 5, - h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") - ), - column( - width = 7, - align = "center", - div( - class = "sel-clade-scale", - selectInput( - "upgma_clade_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - ) - ) - } - }) - - # Heatmap variable color scale - output$nj_heatmap_scale <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_heatmap_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_heatmap_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_heatmap_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Paired" - ) - ) - } - } - }) - - output$upgma_heatmap_scale <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_heatmap_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_heatmap_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_heatmap_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Paired" - ) - ) - } - } - }) - - # Tiles variable color scale - output$nj_tiles_scale_1 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_1", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_1", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_1", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_1 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_1", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_1", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_1", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_2 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_2", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_2", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_2", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_2 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_2", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_2", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_2", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_3 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_3", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_3", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_3", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_3 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_3", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_3", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_3", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_4 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_4])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_4", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { - shinyjs::disabled(selectInput( - "nj_tiles_scale_4", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - )) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_4", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_4 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_4", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_4", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_4", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$nj_tiles_scale_5 <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_5", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_5", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiles_scale_5", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - output$upgma_tiles_scale_5 <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_5", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_5", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiles_scale_5", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Accent" - ) - ) - } - } - }) - - # Tip Labels Variable Color Scale - output$nj_tiplab_scale <- renderUI({ - if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tiplab_scale", - "", - selectize = FALSE, - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tiplab_scale", - "", - selectize = FALSE, - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tiplab_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - } - } - }) - - output$upgma_tiplab_scale <- renderUI({ - if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tiplab_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tiplab_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tiplab_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ) - ) - ) - } - } - }) - - # Tippoint Scale - output$nj_tippoint_scale <- renderUI({ - if(!is.null(Vis$meta_nj)) { - if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ) - ) - ) - } else { - if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - } - } else { - shinyjs::disabled( - selectInput( - "nj_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - }) - - output$upgma_tippoint_scale <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Continous = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ), - Diverging = list( - "Spectral", - "RdYlGn", - "RdYlBu", - "RdGy", - "RdBu", - "PuOr", - "PRGn", - "PiYG", - "BrBG" - ) - ), - selected = c("Viridis" = "viridis") - ) - ) - } else { - if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Gradient = list( - "Magma" = "magma", - "Inferno" = "inferno", - "Plasma" = "plasma", - "Viridis" = "viridis", - "Cividis" = "cividis", - "Rocket" = "rocket", - "Mako" = "mako", - "Turbo" = "turbo" - ) - ), - selected = "turbo" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - } - } else { - shinyjs::disabled( - selectInput( - "upgma_tippoint_scale", - "", - choices = list( - Qualitative = list( - "Set1", - "Set2", - "Set3", - "Pastel1", - "Pastel2", - "Paired", - "Dark2", - "Accent" - ), - Sequential = list( - "YlOrRd", - "YlOrBr", - "YlGnBu", - "YlGn", - "Reds", - "RdPu", - "Purples", - "PuRd", - "PuBuGn", - "PuBu", - "OrRd", - "Oranges", - "Greys", - "Greens", - "GnBu", - "BuPu", - "BuGn", - "Blues" - ) - ), - selected = "Set2" - ) - ) - } - }) - - # Clade Highlights - output$nj_parentnode <- renderUI({ - if(!is.null(Vis$nj_parentnodes)) { - pickerInput( - "nj_parentnode", - label = "", - choices = sort(unique(as.numeric(Vis$nj_parentnodes))), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } else { - pickerInput( - "nj_parentnode", - label = "", - choices = c(), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } - }) - - output$upgma_parentnode <- renderUI({ - if(!is.null(Vis$upgma_parentnodes)) { - pickerInput( - "upgma_parentnode", - label = "", - choices = sort(unique(as.numeric(Vis$upgma_parentnodes))), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } else { - pickerInput( - "upgma_parentnode", - label = "", - choices = c(), - multiple = TRUE, - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "99%" - ) - } - }) - - # Branch label size - output$nj_branch_size <- renderUI( - numericInput( - "nj_branch_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 2, - max = 10, - step = 0.5, - value = Vis$branch_size_nj, - width = "80px" - ) - ) - - output$upgma_branch_size <- renderUI( - numericInput( - "upgma_branch_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 2, - max = 10, - step = 0.5, - value = Vis$branch_size_upgma, - width = "80px" - ) - ) - - # Tippanel size - output$nj_tiplab_padding <- renderUI( - if(!is.null(Vis$tiplab_padding_nj)) { - sliderInput( - inputId = "nj_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = Vis$tiplab_padding_nj, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "nj_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = 0.2, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - ) - - output$upgma_tiplab_padding <- renderUI( - if(!is.null(Vis$tiplab_padding_upgma)) { - sliderInput( - inputId = "upgma_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = Vis$tiplab_padding_upgma, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "upgma_tiplab_padding", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 0.05, - max = 1, - value = 0.2, - step = 0.05, - width = "150px", - ticks = FALSE - ) - } - ) - - # Nodepoint size - output$nj_nodepoint_size <- renderUI( - if(!is.null(Vis$nodepointsize_nj)) { - sliderInput( - inputId = "nj_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = Vis$nodepointsize_nj, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "nj_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = 2.5, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } - ) - - output$upgma_nodepoint_size <- renderUI( - if(!is.null(Vis$nodepointsize_upgma)) { - sliderInput( - inputId = "upgma_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = Vis$nodepointsize_upgma, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "upgma_nodepoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - value = 2.5, - step = 0.5, - width = "150px", - ticks = FALSE - ) - } - ) - - # Tippoint size - output$nj_tippoint_size <- renderUI( - if(!is.null(Vis$tippointsize_nj)) { - sliderInput( - inputId = "nj_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = Vis$tippointsize_nj, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "nj_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = 4, - width = "150px", - ticks = FALSE - ) - } - ) - - output$upgma_tippoint_size <- renderUI( - if(!is.null(Vis$tippointsize_upgma)) { - sliderInput( - inputId = "upgma_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = Vis$tippointsize_upgma, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - inputId = "upgma_tippoint_size", - label = h5("Size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 20, - step = 0.5, - value = 4, - width = "150px", - ticks = FALSE - ) - } - ) - - # Tiplabel size - output$nj_tiplab_size <- renderUI( - if(!is.null(Vis$labelsize_nj)) { - numericInput( - "nj_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = Vis$labelsize_nj, - width = "80px" - ) - } else { - numericInput( - "nj_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = 4, - width = "80px" - ) - } - ) - - output$upgma_tiplab_size <- renderUI( - if(!is.null(Vis$labelsize_upgma)) { - numericInput( - "upgma_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = Vis$labelsize_upgma, - width = "80px" - ) - } else { - numericInput( - "upgma_tiplab_size", - label = h5("Label size", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - step = 0.5, - value = 4, - width = "80px" - ) - } - ) - - # Rootedge length - output$nj_rootedge_length <- renderUI({ - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.02, 0) < 1) { - min <- 1 - } else { - min <- round(ceiling(Vis$nj_max_x) * 0.02, 0) - } - max <- round(ceiling(Vis$nj_max_x) * 0.2, 0) - sliderInput( - "nj_rootedge_length", - label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), - min = min, - max = max, - value = round(ceiling(Vis$nj_max_x) * 0.05, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_rootedge_length", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_rootedge_length <- renderUI({ - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.02, 0) < 1) { - min <- 1 - } else { - min <- round(ceiling(Vis$upgma_max_x) * 0.02, 0) - } - max <- round(ceiling(Vis$upgma_max_x) * 0.2, 0) - sliderInput( - "upgma_rootedge_length", - label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), - min = min, - max = max, - value = round(ceiling(Vis$upgma_max_x) * 0.05, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_rootedge_length", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - # Treescale - output$nj_treescale_width <- renderUI({ - if(!is.null(Vis$nj_max_x)) { - numericInput( - "nj_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = round(ceiling(Vis$nj_max_x) * 0.1, 0), - min = 1, - max = round(floor(Vis$nj_max_x) * 0.5, 0), - step = 1, - width = "80px" - ) - } else { - numericInput( - "nj_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = 2, - min = 1, - max = 10, - step = 1, - width = "80px" - ) - } - }) - - output$upgma_treescale_width <- renderUI({ - if(!is.null(Vis$upgma_max_x)) { - numericInput( - "upgma_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = round(ceiling(Vis$upgma_max_x) * 0.1, 0), - min = 1, - max = round(floor(Vis$upgma_max_x) * 0.5, 0), - step = 1, - width = "80px" - ) - } else { - numericInput( - "upgma_treescale_width", - label = h5("Length", style = "color:white; margin-bottom: 0px"), - value = 2, - min = 1, - max = 10, - step = 1, - width = "80px" - ) - } - }) - - output$nj_treescale_x <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(ceiling(Vis$nj_min_x) < 1) { - floor <- 1 - } else { - floor <- ceiling(Vis$nj_min_x) - } - sliderInput( - "nj_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = floor, - max = round(floor(Vis$nj_max_x)), - value = round(ceiling(Vis$nj_max_x) * 0.2, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_treescale_x <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(ceiling(Vis$upgma_min_x) < 1) { - floor <- 1 - } else { - floor <- ceiling(Vis$upgma_min_x) - } - sliderInput( - "upgma_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = floor, - max = round(floor(Vis$upgma_max_x)), - value = round(ceiling(Vis$upgma_max_x) * 0.2, 0), - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_treescale_x", - label = h5("X Position", style = "color:white; margin-bottom: 0px"), - min = 1, - max = 10, - value = 2, - width = "150px", - ticks = FALSE - ) - } - }) - - output$nj_treescale_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - sliderInput( - "nj_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = sum(DB$data$Include), - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 10, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_treescale_y <- renderUI({ - if(!is.null(sum(DB$data$Include))) { - sliderInput( - "upgma_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = sum(DB$data$Include), - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_treescale_y", - label = h5("Y Position", style = "color:white; margin-bottom: 0px"), - min = 0, - max = 10, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - ### Heatmap - # Heatmap picker - output$nj_heatmap_sel <- renderUI({ - if(!is.null(Vis$meta_nj)) { - meta <- select(Vis$meta_nj, -c(taxa, Index, `Assembly ID`, `Assembly Name`, - Scheme, `Typing Date`, Successes, Errors)) - - # Identify numeric columns - numeric_columns <- sapply(meta, is.numeric) - - numeric_column_names <- names(meta[numeric_columns]) - - non_numeric_column_names <- names(meta)[!numeric_columns] - - choices <- list() - - # Add Continuous list only if there are numeric columns - if (length(numeric_column_names) > 0) { - choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) - } - - # Add Diverging list - choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) - - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "nj_heatmap_select", - label = "", - width = "100%", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else {choices}, - options = list( - `dropdown-align-center` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - ) - } else { - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "nj_heatmap_select", - label = "", - width = "100%", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - multiple = TRUE - ) - ) - ) - } - }) - - output$upgma_heatmap_sel <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - meta <- select(Vis$meta_upgma, -c(taxa, Index, `Assembly ID`, `Assembly Name`, - Scheme, `Typing Date`, Successes, Errors)) - - # Identify numeric columns - numeric_columns <- sapply(meta, is.numeric) - - numeric_column_names <- names(meta[numeric_columns]) - - non_numeric_column_names <- names(meta)[!numeric_columns] - - choices <- list() - - # Add Continuous list only if there are numeric columns - if (length(numeric_column_names) > 0) { - choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) - } - - # Add Diverging list - choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) - - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "upgma_heatmap_select", - label = "", - width = "100%", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else {choices}, - options = list( - `dropdown-align-center` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - ) - } else { - div( - class = "heatmap-picker", - shinyjs::disabled( - pickerInput( - inputId = "upgma_heatmap_select", - label = "", - width = "100%", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - multiple = TRUE - ) - ) - ) - } - }) - - # Heatmap offset - output$nj_heatmap_offset <- renderUI({ - if(!is.null(Vis$nj_max_x)) { - sliderInput( - "nj_heatmap_offset", - label = "", - min = 0, - max = round(ceiling(Vis$nj_max_x)*1.5, 0), - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_heatmap_offset", - label = "", - min = 0, - max = 10, - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - output$upgma_heatmap_offset <- renderUI({ - if(!is.null(Vis$upgma_max_x)) { - sliderInput( - "upgma_heatmap_offset", - label = "", - min = 0, - max = round(ceiling(Vis$upgma_max_x)*1.5, 0), - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_heatmap_offset", - label = "", - min = 0, - max = 10, - step = 1, - value = 0, - width = "150px", - ticks = FALSE - ) - } - }) - - ### Tiling - # Geom Fruit select Variable - output$nj_fruit_variable <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable2 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_2", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_2", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable3 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_3", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_3", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable4 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_4", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_4", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$nj_fruit_variable5 <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_5", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_fruit_variable_5", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable2 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_2", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_2", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable3 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled(selectInput( - "upgma_fruit_variable_3", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - )) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_3", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable4 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_4", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_4", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - output$upgma_fruit_variable5 <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_5", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Isolation Date` = "Isolation Date"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_fruit_variable_5", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - ) - ) - } - }) - - # Geom Fruit Width - output$nj_fruit_width <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width2 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_2", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width3 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_3", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width4 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_4", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$nj_fruit_width5 <- renderUI({ - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "nj_fruit_width_circ_5", - label = "", - min = 1, - max = round(ceiling(Vis$nj_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - sliderInput( - "nj_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "nj_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width2 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_2", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_2", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width3 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_3", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_3", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width4 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_4", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_4", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - output$upgma_fruit_width5 <- renderUI({ - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - if(width_calc < 1) {width <- 1} - } else { - width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - if(width_calc < 1) {width <- 1} - } - } - sliderInput( - "upgma_fruit_width_circ_5", - label = "", - min = 1, - max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), - value = width, - width = "150px", - ticks = FALSE - ) - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - sliderInput( - "upgma_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 3, - width = "150px", - ticks = FALSE - ) - } else { - sliderInput( - "upgma_fruit_width_circ_5", - label = "", - min = 1, - max = 10, - value = 1, - width = "150px", - ticks = FALSE - ) - } - } - }) - - # For Layout change update tiles - observeEvent(input$nj_layout, { - if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } - - updateSliderInput(session, "nj_fruit_width_circ", value = width) - updateSliderInput(session, "nj_fruit_width_circ_2", value = width) - updateSliderInput(session, "nj_fruit_width_circ_3", value = width) - updateSliderInput(session, "nj_fruit_width_circ_4", value = width) - updateSliderInput(session, "nj_fruit_width_circ_5", value = width) - } - }) - - observeEvent(input$upgma_layout, { - if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- 3 - } else { - width <- 1 - } - } else { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } - - updateSliderInput(session, "upgma_fruit_width_circ", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_2", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_3", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_4", value = width) - updateSliderInput(session, "upgma_fruit_width_circ_5", value = width) - } - }) - - # Tip color mapping - output$nj_tipcolor_mapping <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_tipcolor_mapping", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(City = "City"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tipcolor_mapping", - "", - choices = c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(City = "City") - ) - ) - } - }) - - output$upgma_tipcolor_mapping <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_tipcolor_mapping", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(City = "City"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tipcolor_mapping", - "", - choices = c( - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(City = "City") - ) - ) - } - }) - - # Tip shape Mapping - output$nj_tipshape_mapping <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_tipshape_mapping", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_tipshape_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } - }) - - output$upgma_tipshape_mapping <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_tipshape_mapping", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_tipshape_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - ) - } - }) - - # Branch label - output$nj_branch_label <- renderUI({ - if(!is.null(Vis$meta_nj)) { - selectInput( - "nj_branch_label", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - } else { - selectInput( - "nj_branch_label", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - } - }) - - output$upgma_branch_label <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - selectInput( - "upgma_branch_label", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c("Host" = "Host"), - width = "100%" - ) - } else { - selectInput( - "upgma_branch_label", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c("Host" = "Host"), - width = "100%" - ) - } - }) - - # Color mapping - output$nj_color_mapping <- renderUI({ - if(!is.null(Vis$meta_nj)) { - shinyjs::disabled( - selectInput( - "nj_color_mapping", - "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(Country = "Country"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "nj_color_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(Country = "Country"), - width = "100%" - ) - ) - } - }) - - output$upgma_color_mapping <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - shinyjs::disabled( - selectInput( - "upgma_color_mapping", - "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(Country = "Country"), - width = "100%" - ) - ) - } else { - shinyjs::disabled( - selectInput( - "upgma_color_mapping", - "", - choices = c( - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(Country = "Country"), - width = "100%" - ) - ) - } - }) - - # Tip labels - output$nj_tiplab <- renderUI({ - if(!is.null(Vis$meta_nj)) { - selectInput( - "nj_tiplab", - label = "", - choices = if(ncol(Vis$meta_nj) == 11) { - c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) - }, - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } else { - selectInput( - "nj_tiplab", - label = "", - choices = c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } - }) - - output$upgma_tiplab <- renderUI({ - if(!is.null(Vis$meta_upgma)) { - selectInput( - "upgma_tiplab", - label = "", - choices = if(ncol(Vis$meta_upgma) == 11) { - c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ) - } else { - append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), - names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) - }, - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } else { - selectInput( - "upgma_tiplab", - label = "", - choices = c( - Index = "Index", - `Assembly ID` = "Assembly ID", - `Assembly Name` = "Assembly Name", - `Isolation Date` = "Isolation Date", - Host = "Host", - Country = "Country", - City = "City" - ), - selected = c(`Assembly Name` = "Assembly Name"), - width = "100%" - ) - } - }) - - #### MST controls ---- - - # Clustering UI - output$mst_cluster <- renderUI({ - req(DB$schemeinfo) - numericInput( - inputId = "mst_cluster_threshold", - label = NULL, - value = as.numeric(DB$schemeinfo[7, 2]), - min = 1, - max = 99 - ) - }) - - # MST color mapping - output$mst_color_mapping <- renderUI({ - if(input$mst_color_var == FALSE) { - fluidRow( - column( - width = 7, - div( - class = "node_color", - colorPickr( - inputId = "mst_color_node", - width = "100%", - selected = "#B2FACA", - label = "", - update = "changestop", - interaction = list(clear = FALSE, - save = FALSE), - position = "right-start" - ) - ) - ), - column( - width = 5, - dropMenu( - actionBttn( - "mst_node_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - numericInput( - "node_opacity", - label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), - value = 1, - step = 0.1, - min = 0, - max = 1, - width = "80px" - ) - ) - ) - ) - } else { - fluidRow( - column( - width = 9, - div( - class = "mst_col_sel", - selectInput( - "mst_col_var", - label = "", - choices = if(any(DB$cust_var[DB$cust_var$Variable[which(DB$cust_var$Variable %in% c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]))],]$Type != "categ")) { - selection <- c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]) - cust_vars <- DB$cust_var$Variable[which(DB$cust_var$Variable %in% selection)] - selection[-which(selection == cust_vars[DB$cust_var[cust_vars,]$Type != "categ"])] - } else {c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)])}, - width = "100%" - ) - ) - ), - column( - width = 3, - dropMenu( - actionBttn( - "mst_col_menu", - label = "", - color = "default", - size = "sm", - style = "material-flat", - icon = icon("sliders") - ), - placement = "top-start", - theme = "translucent", - width = 5, - selectInput( - "mst_col_scale", - label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), - choices = c("Viridis", "Rainbow"), - width = "150px" - ), - br(), br(), br(), br() - ) - ) - ) - } - }) - - observeEvent(input$mst_color_var, { - - if(input$mst_color_var == TRUE) { - updateSelectizeInput(session, inputId = "mst_node_shape", choices = c("Pie Nodes" = "custom")) - updateSelectizeInput(session, inputId = "mst_node_label", choices = c("Assembly Name")) - } else { - updateSelectizeInput(session, inputId = "mst_node_shape", - choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), - `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), - selected = c("Dot" = "dot")) - updateSelectizeInput(session, inputId = "mst_node_label", - choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], - selected = "Assembly Name") - } - }) - - # MST node labels - output$mst_node_label <- renderUI({ - selectInput( - "mst_node_label", - label = "", - choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], - selected = "Assembly Name", - width = "100%" - ) - }) - - ### Plot Reactives ---- - - #### MST ---- - - mst_tree <- reactive({ - data <- toVisNetworkData(Vis$ggraph_1) - data$nodes <- mutate(data$nodes, - label = label_mst(), - value = mst_node_scaling(), - opacity = node_opacity()) - - ctxRendererJS <- htmlwidgets::JS("({ctx, id, x, y, state: { selected, hover }, style, font, label, metadata}) => { - var pieData = JSON.parse(metadata); - var radius = style.size; - var centerX = x; - var centerY = y; - var total = pieData.reduce((sum, slice) => sum + slice.value, 0) - var startAngle = 0; - - const drawNode = () => { - // Set shadow properties - if (style.shadow) { - var shadowSize = style.shadowSize; - ctx.shadowColor = style.shadowColor; - ctx.shadowBlur = style.shadowSize; - ctx.shadowOffsetX = style.shadowX; - ctx.shadowOffsetY = style.shadowY; - - ctx.beginPath(); - ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); - ctx.fill(); - - ctx.shadowColor = 'transparent'; - ctx.shadowBlur = 0; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - } - - pieData.forEach(slice => { - var sliceAngle = 2 * Math.PI * (slice.value / total); - ctx.beginPath(); - ctx.moveTo(centerX, centerY); - ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle); - ctx.closePath(); - ctx.fillStyle = slice.color; - ctx.fill(); - if (pieData.length > 1) { - ctx.strokeStyle = 'black'; - ctx.lineWidth = 1; - ctx.stroke(); - } - startAngle += sliceAngle; - }); - - // Draw a border - ctx.beginPath(); - ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); - ctx.strokeStyle = 'black'; - ctx.lineWidth = 1; - ctx.stroke(); - }; - drawLabel = () => { - //Draw the label - var lines = label.split(`\n`); - var lineHeight = font.size; - ctx.font = `${font.size}px ${font.face}`; - ctx.fillStyle = font.color; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - lines.forEach((line, index) => { - ctx.fillText(line, centerX, - centerY + radius + (index + 1) * lineHeight); - }) - } - - return { - drawNode, - drawExternalLabel: drawLabel, - nodeDimensions: { width: 2 * radius, height: 2 * radius }, - }; - }") - - Vis$var_cols <- NULL - - # Generate pie charts as nodes - if(input$mst_color_var == TRUE & (!is.null(input$mst_col_var))) { - - group <- character(nrow(data$nodes)) - for (i in 1:length(unique(Vis$meta_mst[[input$mst_col_var]]))) { - group[i] <- unique(Vis$meta_mst[[input$mst_col_var]])[i] - } - - data$nodes <- cbind(data$nodes, data.frame(metadata = character(nrow(data$nodes)))) - - if(length(which(data$nodes$group == "")) != 0) { - data$nodes$group[which(data$nodes$group == "")] <- data$nodes$group[1] - } - - if(is.null(input$mst_col_scale)) { - Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), - color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) - } else if (input$mst_col_scale == "Rainbow") { - Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), - color = rainbow(length(unique(Vis$meta_mst[[input$mst_col_var]])))) - } else if (input$mst_col_scale == "Viridis") { - Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), - color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) - } - - for(i in 1:nrow(data$nodes)) { - - iso_subset <- strsplit(data$nodes$label[i], split = "\n")[[1]] - variable <- Vis$meta_mst[[input$mst_col_var]] - values <- variable[which(Vis$meta_mst$`Assembly Name` %in% iso_subset)] - - for(j in 1:length(unique(values))) { - - share <- sum(unique(values)[j] == values) / length(values) * 100 - color <- Vis$var_cols$color[Vis$var_cols$value == unique(values)[j]] - - if(j == 1) { - pie_vec <- paste0('{"value":', share,',"color":"', color,'"}') - } else { - pie_vec <- paste0(pie_vec, ',{"value":', share,',"color":"', color,'"}') - } - } - - data$nodes$metadata[i] <- paste0('[', pie_vec, ']') - } - } - - data$edges <- mutate(data$edges, - length = if(input$mst_scale_edges == FALSE) { - input$mst_edge_length - } else { - data$edges$weight * input$mst_edge_length_scale - }, - label = as.character(data$edges$weight), - opacity = input$mst_edge_opacity) - - if (input$mst_show_clusters) { - clusters <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) - if (input$mst_cluster_type == "Type 1") { - data$nodes$group <- clusters$group - } - } - - visNetwork_graph <- visNetwork(data$nodes, data$edges, - main = mst_title(), - background = mst_background_color(), - submain = mst_subtitle()) %>% - visNodes(size = mst_node_size(), - shape = input$mst_node_shape, - shadow = input$mst_shadow, - color = mst_color_node(), - ctxRenderer = ctxRendererJS, - scaling = list(min = mst_node_size_min(), - max = mst_node_size_max()), - font = list(color = node_font_color(), - size = input$node_label_fontsize)) %>% - visEdges(color = mst_color_edge(), - font = list(color = mst_edge_font_color(), - size = mst_edge_font_size(), - strokeWidth = 4)) %>% - visOptions(collapse = TRUE) %>% - visInteraction(hover = TRUE) %>% - visLayout(randomSeed = 1) %>% - visLegend(useGroups = FALSE, - zoom = TRUE, - width = legend_width(), - position = input$mst_legend_ori, - ncol = legend_col(), - addNodes = mst_legend()) - - if (input$mst_show_clusters) { - if (input$mst_cluster_col_scale == "Viridis") { - color_palette <- viridis(length(unique(data$nodes$group))) - } else { - color_palette <- rainbow(length(unique(data$nodes$group))) - } - - if (input$mst_cluster_type == "Type 1") { - for (i in 1:length(unique(data$nodes$group))) { - visNetwork_graph <- visNetwork_graph %>% - visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) - } - } else { - thin_edges <- data$edges - thin_edges$width <- 1 - thin_edges$color <- "black" - - thick_edges <- data$edges - thick_edges$width <- 24 - - thick_edges$color <- rep("rgba(0, 0, 0, 0)", length(data$edges$from)) - color_palette <- rainbow(length(unique(clusters$edges))) - for (i in 1:length(unique(clusters$edges))) { - print(clusters$edges) - if (unique(clusters$edges)[i] != "0") { - edge_color <- paste(col2rgb(color_palette[i]), collapse=", ") - thick_edges$color[clusters$edges == unique(clusters$edges)[i]] <- paste0("rgba(", edge_color, ", 0.5)") - } - } - merged_edges <- rbind(thick_edges, thin_edges) - data$edges <- merged_edges - visNetwork_graph <- visNetwork(data$nodes, data$edges, - main = mst_title(), - background = mst_background_color(), - submain = mst_subtitle()) %>% - visNodes(size = mst_node_size(), - shape = input$mst_node_shape, - shadow = input$mst_shadow, - color = mst_color_node(), - ctxRenderer = ctxRendererJS, - scaling = list(min = mst_node_size_min(), - max = mst_node_size_max()), - font = list(color = node_font_color(), - size = input$node_label_fontsize)) %>% - visEdges(color = mst_color_edge(), - font = list(color = mst_edge_font_color(), - size = mst_edge_font_size(), - strokeWidth = 4), - smooth = FALSE, - physics = FALSE) %>% - visOptions(collapse = TRUE) %>% - visInteraction(hover = TRUE) %>% - visLayout(randomSeed = 1) %>% - visLegend(useGroups = FALSE, - zoom = TRUE, - width = legend_width(), - position = input$mst_legend_ori, - ncol = legend_col(), - addNodes = mst_legend()) - } - } - visNetwork_graph - }) - - # MST legend - legend_col <- reactive({ - if(!is.null(Vis$var_cols)) { - if(nrow(Vis$var_cols) > 10) { - 3 - } else if(nrow(Vis$var_cols) > 5) { - 2 - } else { - 1 - } - } else {1} - }) - - mst_legend <- reactive({ - if(is.null(Vis$var_cols)) { - NULL - } else { - legend <- Vis$var_cols - names(legend)[1] <- "label" - mutate(legend, shape = "dot", - font.color = input$mst_legend_color, - size = input$mst_symbol_size, - font.size = input$mst_font_size) - } - }) - - # Set MST legend width - legend_width <- reactive({ - 0.2 - }) - - # Set MST node shape - mst_node_shape <- reactive({ - if(input$mst_node_shape == "Pie Nodes"){ - "dot" - } else if(input$mst_node_shape %in% c("circle", "database", "box", "text")) { - shinyjs::disable('scale_nodes') - updateCheckboxInput(session, "scale_nodes", value = FALSE) - shinyjs::disable('mst_node_size') - shinyjs::disable('mst_node_scale') - input$mst_node_shape - } else { - shinyjs::enable('scale_nodes') - shinyjs::enable('mst_node_size') - shinyjs::enable('mst_node_scale') - input$mst_node_shape - } - }) - - # Set MST label - label_mst <- reactive({ - Vis$unique_meta[, colnames(Vis$unique_meta) %in% input$mst_node_label] - }) - - # Set node color - mst_color_node <- reactive({ - input$mst_color_node - }) - - # Node Label Color - node_font_color <- reactive({ - input$node_font_color - }) - - - # Node Size Scaling - mst_node_scaling <- reactive({ - if(input$scale_nodes == TRUE){ - Vis$unique_meta$size - } else {NULL} - }) - - # Node Size Min/May - mst_node_size_min <- reactive({ - input$mst_node_scale[1] - }) - - mst_node_size_max <- reactive({ - input$mst_node_scale[2] - }) - - # Node Size - mst_node_size <- reactive({ - input$mst_node_size - }) - - # Node Alpha/Opacity - node_opacity <- reactive({ - input$node_opacity - }) - - # Set Title - mst_title <- reactive({ - if(!is.null(input$mst_title)) { - if(nchar(input$mst_title) < 1) { - list(text = "title", - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_title_size), "px", - "; color: ", as.character(mst_background_color())) - ) - } else { - list(text = input$mst_title, - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_title_size), "px", - "; color: ", as.character(input$mst_title_color)) - ) - } - } else { - list(text = "title", - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_title_size), "px", - "; color: ", as.character(mst_background_color())) - ) - } - }) - - # Set Subtitle - mst_subtitle <- reactive({ - list(text = input$mst_subtitle, - style = paste0( - "font-family:Georgia, Times New Roman, Times, serif;", - "text-align:center;", - "font-size: ", as.character(input$mst_subtitle_size), "px", - "; color: ", as.character(input$mst_subtitle_color)) - ) - }) - - # Background color - - mst_background_color <- reactive({ - if(input$mst_background_transparent == TRUE) { - 'rgba(0, 0, 0, 0)' - } else{ - input$mst_background_color - } - }) - - # Edge font color - mst_edge_font_color <- reactive({ - input$mst_edge_font_color - }) - - # Edge color - mst_color_edge <- reactive({ - input$mst_color_edge - }) - - # Edge font size - mst_edge_font_size <- reactive({ - input$mst_edge_font_size - }) - - #### NJ ---- - - nj_tree <- reactive({ - - # Convert negative edges - Vis$nj[["edge.length"]] <- abs(Vis$nj[["edge.length"]]) - - if(input$nj_nodelabel_show == TRUE) { - ggtree(Vis$nj, alpha = 0.2, layout = layout_nj()) + - geom_nodelab(aes(label = node), color = "#29303A", size = nj_tiplab_size() + 1, hjust = 0.7) + - nj_limit() + - nj_inward() - } else { - tree <- - ggtree(Vis$nj, - color = input$nj_color, - layout = layout_nj(), - ladderize = input$nj_ladder) %<+% Vis$meta_nj + - nj_clades() + - nj_tiplab() + - nj_tiplab_scale() + - new_scale_color() + - nj_limit() + - nj_inward() + - nj_label_branch() + - nj_treescale() + - nj_nodepoint() + - nj_tippoint() + - nj_tippoint_scale() + - new_scale_color() + - nj_clip_label() + - nj_rootedge() + - ggtitle(label = input$nj_title, - subtitle = input$nj_subtitle) + - theme_tree(bgcolor = input$nj_bg) + - theme(plot.title = element_text(colour = input$nj_title_color, - size = input$nj_title_size), - plot.subtitle = element_text(colour = input$nj_title_color, - size = input$nj_subtitle_size), - legend.background = element_rect(fill = input$nj_bg), - legend.direction = input$nj_legend_orientation, - legend.title = element_text(color = input$nj_color, - size = input$nj_legend_size*1.2), - legend.title.align = 0.5, - legend.position = nj_legend_pos(), - legend.text = element_text(color = input$nj_color, - size = input$nj_legend_size), - legend.key = element_rect(fill = input$nj_bg), - legend.box.spacing = unit(1.5, "cm"), - legend.key.size = unit(0.05*input$nj_legend_size, 'cm'), - plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) + - new_scale_fill() + - nj_fruit() + - nj_gradient() + - new_scale_fill() + - nj_fruit2() + - nj_gradient2() + - new_scale_fill() + - nj_fruit3() + - nj_gradient3() + - new_scale_fill() + - nj_fruit4() + - nj_gradient4() + - new_scale_fill() + - nj_fruit5() + - nj_gradient5() + - new_scale_fill() - - # Add custom labels - if(length(Vis$custom_label_nj) > 0) { - - for(i in Vis$custom_label_nj[,1]) { - - if(!is.null(Vis$nj_label_pos_x[[i]])) { - x_pos <- Vis$nj_label_pos_x[[i]] - } else { - x_pos <- round(Vis$nj_max_x / 2, 0) - } - - if(!is.null(Vis$nj_label_pos_y[[i]])) { - y_pos <- Vis$nj_label_pos_y[[i]] - } else { - y_pos <- sum(DB$data$Include) / 2 - } - - if(!is.null(Vis$nj_label_size[[i]])) { - size <- Vis$nj_label_size[[i]] - } else { - size <- 5 - } - - tree <- tree + annotate("text", - x = x_pos, - y = y_pos, - label = i, - size = size) - } - } - - # Add heatmap - if(input$nj_heatmap_show == TRUE & length(input$nj_heatmap_select) > 0) { - if (!(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)))) { - tree <- gheatmap.mod(tree, - data = select(Vis$meta_nj, input$nj_heatmap_select), - offset = nj_heatmap_offset(), - width = nj_heatmap_width(), - legend_title = input$nj_heatmap_title, - colnames_angle = -nj_colnames_angle(), - colnames_offset_y = nj_colnames_y(), - colnames_color = input$nj_color) + - nj_heatmap_scale() - } - } - - # Sizing control - Vis$nj_plot <- ggplotify::as.ggplot(tree, - scale = input$nj_zoom, - hjust = input$nj_h, - vjust = input$nj_v) - - Vis$nj_true <- TRUE - - # Correct background color if zoomed out - cowplot::ggdraw(Vis$nj_plot) + - theme(plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) - } - }) - - # Heatmap width - nj_heatmap_width <- reactive({ - if(!is.null(input$nj_heatmap_width)) { - input$nj_heatmap_width - } else { - length_input <- length(input$nj_heatmap_select) - if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { - if(length_input < 3) { - 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - 1.5 - } - } - } else { - if(length_input < 3) { - 0.3 - } else if (length_input >= 3 && length_input <= 27) { - min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - 3 - } - } - } - }) - - # Heatmap column titles position - nj_colnames_y <- reactive({ - if(!is.null(input$nj_colnames_y)) { - input$nj_colnames_y - } else { - if(input$nj_layout == "inward" | input$nj_layout == "circular") { - 0 - } else {-1} - } - }) - - # Heatmap column titles angle - nj_colnames_angle <- reactive({ - if(!is.null(input$nj_colnames_angle)) { - input$nj_colnames_angle - } else { - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "inward" | input$nj_layout == "circular") { - 90 - } else {-90} - } else {-90} - } - }) - - # Heatmap scale - nj_heatmap_scale <- reactive({ - if(!is.null(input$nj_heatmap_scale) & !is.null(input$nj_heatmap_div_mid)) { - if(input$nj_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_heatmap_div_mid == "Zero") { - midpoint <- 0 - } else if(input$nj_heatmap_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$nj_heatmap_scale)[1], - mid = brewer.pal(3, input$nj_heatmap_scale)[2], - high = brewer.pal(3, input$nj_heatmap_scale)[3], - midpoint = midpoint, - name = input$nj_heatmap_title) - } else { - if(input$nj_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { - if(input$nj_heatmap_scale == "magma") { - scale_fill_viridis(option = "A", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "inferno") { - scale_fill_viridis(option = "B", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "plasma") { - scale_fill_viridis(option = "C", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "viridis") { - scale_fill_viridis(option = "D", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "cividis") { - scale_fill_viridis(option = "E", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "rocket") { - scale_fill_viridis(option = "F", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "mako") { - scale_fill_viridis(option = "G", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "turbo") { - scale_fill_viridis(option = "H", - name = input$nj_heatmap_title) - } - } else { - if(input$nj_heatmap_scale == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G", - name = input$nj_heatmap_title) - } else if(input$nj_heatmap_scale == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H", - name = input$nj_heatmap_title) - } - } - } else { - scale_fill_brewer(palette = input$nj_heatmap_scale, - name = input$nj_heatmap_title) - } - } - } - }) - - # Tippoint Scale - nj_tippoint_scale <- reactive({ - if(!is.null(input$nj_tippoint_scale) & !is.null(input$nj_tipcolor_mapping_div_mid)) { - if(input$nj_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tipcolor_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$nj_tipcolor_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$nj_tippoint_scale)[1], - mid = brewer.pal(3, input$nj_tippoint_scale)[2], - high = brewer.pal(3, input$nj_tippoint_scale)[3], - midpoint = midpoint) - } else { - if(input$nj_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { - if(input$nj_tippoint_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$nj_tippoint_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$nj_tippoint_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$nj_tippoint_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$nj_tippoint_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$nj_tippoint_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$nj_tippoint_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$nj_tippoint_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$nj_tippoint_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tippoint_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tippoint_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tippoint_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tippoint_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tippoint_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tippoint_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tippoint_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$nj_tippoint_scale) - } - } - } - }) - - # Tiplab Scale - nj_tiplab_scale <- reactive({ - if(!is.null(input$nj_tiplab_scale) & !is.null(input$nj_color_mapping_div_mid)) { - if(input$nj_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_color_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$nj_color_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$nj_tiplab_scale)[1], - mid = brewer.pal(3, input$nj_tiplab_scale)[2], - high = brewer.pal(3, input$nj_tiplab_scale)[3], - midpoint = midpoint) - } else { - if(input$nj_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { - if(input$nj_tiplab_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$nj_tiplab_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$nj_tiplab_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$nj_tiplab_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$nj_tiplab_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$nj_tiplab_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$nj_tiplab_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$nj_tiplab_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$nj_tiplab_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiplab_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiplab_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiplab_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiplab_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiplab_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiplab_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiplab_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$nj_tiplab_scale) - } - } - } - }) - - # Clade Highlight - nj_clades <- reactive({ - if(!is.null(input$nj_parentnode)) { - if(!length(input$nj_parentnode) == 0) { - if(length(input$nj_parentnode) == 1) { - fill <- input$nj_clade_scale - } else if (length(input$nj_parentnode) == 2) { - if(startsWith(input$nj_clade_scale, "#")) { - fill <- brewer.pal(3, "Set1")[1:2] - } else { - fill <- brewer.pal(3, input$nj_clade_scale)[1:2] - } - } else { - fill <- brewer.pal(length(input$nj_parentnode), input$nj_clade_scale) - } - geom_hilight(node = as.numeric(input$nj_parentnode), - fill = fill, - type = input$nj_clade_type, - to.bottom = TRUE - ) - } else {NULL} - } - }) - - # Legend Position - nj_legend_pos <- reactive({ - if(!is.null(input$nj_legend_x) & !is.null(input$nj_legend_y)) { - c(input$nj_legend_x, input$nj_legend_y) - } else { - c(0.1, 1) - } - }) - - # Heatmap offset - nj_heatmap_offset <- reactive({ - if(is.null(input$nj_heatmap_offset)) { - 0 - } else {input$nj_heatmap_offset} - }) - - # Tiles fill color gradient - nj_gradient <- reactive({ - if(!is.null(input$nj_tiles_show_1) & - !is.null(input$nj_fruit_variable) & - !is.null(input$nj_tiles_scale_1) & - !is.null(input$nj_tiles_mapping_div_mid_1)) { - if(input$nj_tiles_show_1 == TRUE) { - if(input$nj_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_1 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_1 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_1)[1], - mid = brewer.pal(3, input$nj_tiles_scale_1)[2], - high = brewer.pal(3, input$nj_tiles_scale_1)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { - if(input$nj_tiles_scale_1 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_1 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_1 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_1 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_1 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_1 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_1 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_1 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_1 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_1 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_1 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_1 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_1 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_1 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_1 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_1 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_1) - } - } - } else {NULL} - } - }) - - nj_gradient2 <- reactive({ - if(!is.null(input$nj_tiles_show_2) & - !is.null(input$nj_fruit_variable_2) & - !is.null(input$nj_tiles_scale_2) & - !is.null(input$nj_tiles_mapping_div_mid_2)) { - if(input$nj_tiles_show_2 == TRUE) { - if(input$nj_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_2 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_2 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_2)[1], - mid = brewer.pal(3, input$nj_tiles_scale_2)[2], - high = brewer.pal(3, input$nj_tiles_scale_2)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { - if(input$nj_tiles_scale_2 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_2 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_2 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_2 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_2 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_2 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_2 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_2 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_2 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_2 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_2 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_2 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_2 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_2 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_2 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_2 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_2) - } - } - } else {NULL} - } - }) - - nj_gradient3 <- reactive({ - if(!is.null(input$nj_tiles_show_3) & - !is.null(input$nj_fruit_variable_3) & - !is.null(input$nj_tiles_scale_3 & - !is.null(input$nj_tiles_mapping_div_mid_3))) { - if(input$nj_tiles_show_3 == TRUE) { - if(input$nj_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_3 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_3 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) - } - scale_fill_gradient3(low = brewer.pal(3, input$nj_tiles_scale_3)[1], - mid = brewer.pal(3, input$nj_tiles_scale_3)[2], - high = brewer.pal(3, input$nj_tiles_scale_3)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { - if(input$nj_tiles_scale_3 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_3 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_3 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_3 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_3 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_3 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_3 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_3 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_3 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_3 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_3 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_3 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_3 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_3 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_3 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_3 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_3) - } - } - } else {NULL} - } - }) - - nj_gradient4 <- reactive({ - if(!is.null(input$nj_tiles_show_4) & - !is.null(input$nj_fruit_variable_4) & - !is.null(input$nj_tiles_scale_4) & - !is.null(input$nj_tiles_mapping_div_mid_4)) { - if(input$nj_tiles_show_4 == TRUE) { - if(input$nj_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_4 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_4 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) - } - scale_fill_gradient4(low = brewer.pal(3, input$nj_tiles_scale_4)[1], - mid = brewer.pal(3, input$nj_tiles_scale_4)[2], - high = brewer.pal(3, input$nj_tiles_scale_4)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { - if(input$nj_tiles_scale_4 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_4 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_4 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_4 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_4 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_4 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_4 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_4 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_4 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_4 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_4 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_4 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_4 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_4 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_4 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_4 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_4) - } - } - } else {NULL} - } - }) - - nj_gradient5 <- reactive({ - if(!is.null(input$nj_tiles_show_5) & - !is.null(input$nj_fruit_variable_5) & - !is.null(input$nj_tiles_scale_5) & - !is.null(input$nj_tiles_mapping_div_mid_5)) { - if(input$nj_tiles_show_5 == TRUE) { - if(input$nj_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$nj_tiles_mapping_div_mid_5 == "Zero") { - midpoint <- 0 - } else if(input$nj_tiles_mapping_div_mid_5 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) - } - scale_fill_gradient5(low = brewer.pal(3, input$nj_tiles_scale_5)[1], - mid = brewer.pal(3, input$nj_tiles_scale_5)[2], - high = brewer.pal(3, input$nj_tiles_scale_5)[3], - midpoint = midpoint) - } else { - if(input$nj_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { - if(input$nj_tiles_scale_5 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$nj_tiles_scale_5 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$nj_tiles_scale_5 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$nj_tiles_scale_5 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$nj_tiles_scale_5 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$nj_tiles_scale_5 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$nj_tiles_scale_5 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$nj_tiles_scale_5 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$nj_tiles_scale_5 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$nj_tiles_scale_5 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$nj_tiles_scale_5 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$nj_tiles_scale_5 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$nj_tiles_scale_5 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$nj_tiles_scale_5 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$nj_tiles_scale_5 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$nj_tiles_scale_5 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$nj_tiles_scale_5) - } - } - } else {NULL} - } - }) - - # No label clip off for linear NJ tree - nj_clip_label <- reactive({ - if(!(input$nj_layout == "circular" | input$nj_layout == "inward")) { - coord_cartesian(clip = "off") - } else {NULL} - }) - - # Geom Fruit - nj_fruit <- reactive({ - if((!is.null(input$nj_tiles_show_1)) & - (!is.null(input$nj_fruit_variable)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ)) & - (!is.null(input$nj_fruit_width_circ)) & - (!is.null(input$nj_fruit_alpha))) { - if(input$nj_tiles_show_1 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = input$nj_fruit_offset_circ, - width = input$nj_fruit_width_circ, - alpha = input$nj_fruit_alpha - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = input$nj_fruit_offset_circ, - width = input$nj_fruit_width_circ, - alpha = input$nj_fruit_alpha - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_1 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = 0, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable)), - offset = 0, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Geom Fruit - nj_fruit2 <- reactive({ - if((!is.null(input$nj_tiles_show_2)) & - (!is.null(input$nj_fruit_variable_2)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_2)) & - (!is.null(input$nj_fruit_width_circ_2)) & - (!is.null(input$nj_fruit_alpha_2))) { - if(input$nj_tiles_show_2 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), - offset = input$nj_fruit_offset_circ_2, - width = input$nj_fruit_width_circ_2, - alpha = input$nj_fruit_alpha_2 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), - offset = input$nj_fruit_offset_circ_2, - width = input$nj_fruit_width_circ_2, - alpha = input$nj_fruit_alpha_2 - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_2 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - nj_fruit3 <- reactive({ - if((!is.null(input$nj_tiles_show_3)) & - (!is.null(input$nj_fruit_variable_3)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_3)) & - (!is.null(input$nj_fruit_width_circ_3)) & - (!is.null(input$nj_fruit_alpha_3))) { - if(input$nj_tiles_show_3 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), - offset = input$nj_fruit_offset_circ_3, - width = input$nj_fruit_width_circ_3, - alpha = input$nj_fruit_alpha_3 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), - offset = input$nj_fruit_offset_circ_3, - width = input$nj_fruit_width_circ_3, - alpha = input$nj_fruit_alpha_3 - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_3 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - nj_fruit4 <- reactive({ - if((!is.null(input$nj_tiles_show_4)) & - (!is.null(input$nj_fruit_variable_4)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_4)) & - (!is.null(input$nj_fruit_width_circ_4)) & - (!is.null(input$nj_fruit_alpha_4))) { - if(input$nj_tiles_show_4 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), - offset = input$nj_fruit_offset_circ_4, - width = input$nj_fruit_width_circ_4, - alpha = input$nj_fruit_alpha_4 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), - offset = input$nj_fruit_offset_circ_4, - width = input$nj_fruit_width_circ_4, - alpha = input$nj_fruit_alpha_4 - ) - } - } else { - if(input$nj_tiles_show_4 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - } - }) - - nj_fruit5 <- reactive({ - if((!is.null(input$nj_tiles_show_5)) & - (!is.null(input$nj_fruit_variable_5)) & - (!is.null(input$nj_layout)) & - (!is.null(input$nj_fruit_offset_circ_5)) & - (!is.null(input$nj_fruit_width_circ_5)) & - (!is.null(input$nj_fruit_alpha_5))) { - if(input$nj_tiles_show_5 == TRUE) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), - offset = input$nj_fruit_offset_circ_5, - width = input$nj_fruit_width_circ_5, - alpha = input$nj_fruit_alpha_5 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), - offset = input$nj_fruit_offset_circ_5, - width = input$nj_fruit_width_circ_5, - alpha = input$nj_fruit_alpha_5 - ) - } - } else {NULL} - } else { - if(input$nj_tiles_show_5 == TRUE) { - if(!is.null(Vis$nj_max_x)) { - if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Xlim - nj_limit <- reactive({ - if(input$nj_layout == "circular") { - xlim(input$nj_xlim, NA) - } else {NULL} - }) - - # Treescale - nj_treescale <- reactive({ - if(!input$nj_layout == "circular") { - if(input$nj_treescale_show == TRUE) { - geom_treescale(x = nj_treescale_x(), - y = nj_treescale_y(), - width = nj_treescale_width(), - color = input$nj_color, - fontsize = 4) - } else {NULL} - } else {NULL} - }) - - # Treescale Y Position - nj_treescale_y <- reactive({ - if(is.null(input$nj_treescale_y)) { - 0 - } else {input$nj_treescale_y} - }) - - # Treescale X Position - nj_treescale_x <- reactive({ - if(is.null(input$nj_treescale_x)) { - round(ceiling(Vis$nj_max_x) * 0.2, 0) - } else {input$nj_treescale_x} - }) - - # Treescale width - nj_treescale_width <- reactive({ - if(!is.null(input$nj_treescale_width)) { - input$nj_treescale_width - } else { - round(ceiling(Vis$nj_max_x) * 0.1, 0) - } - }) - - # Label branches - nj_label_branch <- reactive({ - if(!input$nj_layout == "circular" | !input$nj_layout == "inward") { - if(input$nj_show_branch_label == TRUE) { - geom_label( - aes( - x=!!sym("branch"), - label= !!sym(input$nj_branch_label)), - fill = input$nj_branch_label_color, - size = nj_branch_size(), - label.r = unit(input$nj_branch_labelradius, "lines"), - nudge_x = input$nj_branch_x, - nudge_y = input$nj_branch_y, - fontface = input$nj_branchlab_fontface, - alpha = input$nj_branchlab_alpha - ) - } else {NULL} - } else {NULL} - }) - - # Branch label size - nj_branch_size <- reactive({ - if(!is.null(input$nj_branch_size)) { - input$nj_branch_size - } else { - Vis$branch_size_nj - } - }) - - # Rootedge - nj_rootedge <- reactive({ - if(input$nj_rootedge_show == TRUE) { - if(is.null(input$nj_rootedge_length)) { - geom_rootedge(rootedge = round(ceiling(Vis$nj_max_x) * 0.05, 0), - linetype = input$nj_rootedge_line) - } else { - geom_rootedge(rootedge = input$nj_rootedge_length, - linetype = input$nj_rootedge_line) - } - } else {NULL} - }) - - # Tippoints - nj_tippoint <- reactive({ - if(input$nj_tippoint_show == TRUE | input$nj_tipcolor_mapping_show == TRUE | input$nj_tipshape_mapping_show == TRUE) { - if(input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == FALSE) { - geom_tippoint( - aes(color = !!sym(input$nj_tipcolor_mapping)), - alpha = input$nj_tippoint_alpha, - shape = input$nj_tippoint_shape, - size = nj_tippoint_size() - ) - } else if (input$nj_tipcolor_mapping_show == FALSE & input$nj_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$nj_tipshape_mapping)), - alpha = input$nj_tippoint_alpha, - color = input$nj_tippoint_color, - size = nj_tippoint_size() - ) - } else if (input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$nj_tipshape_mapping), - color = !!sym(input$nj_tipcolor_mapping)), - alpha = input$nj_tippoint_alpha, - size = nj_tippoint_size() - ) - } else { - geom_tippoint( - alpha = input$nj_tippoint_alpha, - colour = input$nj_tippoint_color, - fill = input$nj_tippoint_color, - shape = input$nj_tippoint_shape, - size = nj_tippoint_size() - ) - } - } else {NULL} - }) - - # Nodepoints - nj_nodepoint <- reactive({ - if(input$nj_nodepoint_show == TRUE) { - geom_nodepoint( - alpha = input$nj_nodepoint_alpha, - color = input$nj_nodepoint_color, - shape = input$nj_nodepoint_shape, - size = nj_nodepoint_size() - ) - } else {NULL} - }) - - # Nodepoint size - nj_nodepoint_size <- reactive({ - if(!is.null(input$nj_nodepoint_size)) { - input$nj_nodepoint_size - } else { - Vis$nodepointsize_nj - } - }) - - # NJ circular or not - nj_tiplab <- reactive({ - if(input$nj_tiplab_show == TRUE) { - if(input$nj_layout == "circular") { - if(input$nj_mapping_show == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position), - check.overlap = input$nj_tiplab_overlap - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - color = input$nj_tiplab_color, - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position), - check.overlap = input$nj_tiplab_overlap - ) - } - } else if (input$nj_layout == "inward") { - if(input$nj_mapping_show == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position_inw), - check.overlap = input$nj_tiplab_overlap - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - color = input$nj_tiplab_color, - geom = "text", - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - hjust = as.numeric(input$nj_tiplab_position_inw), - check.overlap = input$nj_tiplab_overlap - ) - } - } else { - if(input$nj_mapping_show == TRUE) { - if(input$nj_geom == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap, - label.padding = unit(nj_tiplab_padding(), "lines"), - label.r = unit(input$nj_tiplab_labelradius, "lines"), - fill = input$nj_tiplab_fill - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap - ) - } - } else { - if(input$nj_geom == TRUE) { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - color = input$nj_tiplab_color, - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap, - label.padding = unit(nj_tiplab_padding(), "lines"), - label.r = unit(input$nj_tiplab_labelradius, "lines"), - fill = input$nj_tiplab_fill - ) - } else { - geom_tiplab( - nj_mapping_tiplab(), - geom = nj_geom(), - color = input$nj_tiplab_color, - angle = input$nj_tiplab_angle, - size = nj_tiplab_size(), - alpha = input$nj_tiplab_alpha, - fontface = input$nj_tiplab_fontface, - align = as.logical(input$nj_align), - nudge_x = input$nj_tiplab_nudge_x, - check.overlap = input$nj_tiplab_overlap - ) - } - } - } - } else {NULL} - }) - - # Tip panel size - nj_tiplab_padding <- reactive({ - if(!is.null(input$nj_tiplab_padding)) { - input$nj_tiplab_padding - } else { - Vis$tiplab_padding_nj - } - }) - - # Tiplab size - nj_tiplab_size <- reactive({ - if(!is.null(input$nj_tiplab_size)) { - input$nj_tiplab_size - } else { - Vis$labelsize_nj - } - }) - - # Tippoint size - nj_tippoint_size <- reactive({ - if(!is.null(input$nj_tippoint_size)) { - input$nj_tippoint_size - } else { - Vis$tippointsize_nj - } - }) - - # Show Label Panels? - nj_geom <- reactive({ - if(input$nj_geom == TRUE) { - "label" - } else {"text"} - }) - - # NJ Tiplab color - nj_mapping_tiplab <- reactive({ - if(input$nj_mapping_show == TRUE) { - if(!is.null(input$nj_tiplab)) { - aes(label = !!sym(input$nj_tiplab), - color = !!sym(input$nj_color_mapping)) - } else { - aes(label = !!sym("Assembly Name"), - color = !!sym(input$nj_color_mapping)) - } - } else { - if(!is.null(input$nj_tiplab)) { - aes(label = !!sym(input$nj_tiplab)) - } else { - aes(label = !!sym("Assembly Name")) - } - } - }) - - # NJ Tree Layout - layout_nj <- reactive({ - if(input$nj_layout == "inward") { - "circular" - } else {input$nj_layout} - }) - - # NJ inward circular - nj_inward <- reactive({ - if (input$nj_layout == "inward") { - layout_inward_circular(xlim = input$nj_inward_xlim) - } else { - NULL - } - }) - - #### UPGMA ---- - - upgma_tree <- reactive({ - if(input$upgma_nodelabel_show == TRUE) { - ggtree(Vis$upgma, alpha = 0.2, layout = layout_upgma()) + - geom_nodelab(aes(label = node), color = "#29303A", size = upgma_tiplab_size() + 1, hjust = 0.7) + - upgma_limit() + - upgma_inward() - } else { - tree <- - ggtree(Vis$upgma, - color = input$upgma_color, - layout = layout_upgma(), - ladderize = input$upgma_ladder) %<+% Vis$meta_upgma + - upgma_tiplab() + - upgma_tiplab_scale() + - new_scale_color() + - upgma_limit() + - upgma_inward() + - upgma_label_branch() + - upgma_treescale() + - upgma_nodepoint() + - upgma_tippoint() + - upgma_tippoint_scale() + - new_scale_color() + - upgma_clip_label() + - upgma_rootedge() + - upgma_clades() + - ggtitle(label = input$upgma_title, - subtitle = input$upgma_subtitle) + - theme_tree(bgcolor = input$upgma_bg) + - theme(plot.title = element_text(colour = input$upgma_title_color, - size = input$upgma_title_size), - plot.subtitle = element_text(colour = input$upgma_title_color, - size = input$upgma_subtitle_size), - legend.background = element_rect(fill = input$upgma_bg), - legend.direction = input$upgma_legend_orientation, - legend.title = element_text(color = input$upgma_color, - size = input$upgma_legend_size*1.2), - legend.title.align = 0.5, - legend.position = upgma_legend_pos(), - legend.text = element_text(color = input$upgma_color, - size = input$upgma_legend_size), - legend.key = element_rect(fill = input$upgma_bg), - legend.box.spacing = unit(1.5, "cm"), - legend.key.size = unit(0.05*input$upgma_legend_size, 'cm'), - plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) + - new_scale_fill() + - upgma_fruit() + - upgma_gradient() + - new_scale_fill() + - upgma_fruit2() + - upgma_gradient2() + - new_scale_fill() + - upgma_fruit3() + - upgma_gradient3() + - new_scale_fill() + - upgma_fruit4() + - upgma_gradient4() + - new_scale_fill() + - upgma_fruit5() + - upgma_gradient5() + - new_scale_fill() - - # Add custom labels - if(length(Vis$custom_label_upgma) > 0) { - - for(i in Vis$custom_label_upgma[,1]) { - - if(!is.null(Vis$upgma_label_pos_x[[i]])) { - x_pos <- Vis$upgma_label_pos_x[[i]] - } else { - x_pos <- round(Vis$upgma_max_x / 2, 0) - } - - if(!is.null(Vis$upgma_label_pos_y[[i]])) { - y_pos <- Vis$upgma_label_pos_y[[i]] - } else { - y_pos <- sum(DB$data$Include) / 2 - } - - if(!is.null(Vis$upgma_label_size[[i]])) { - size <- Vis$upgma_label_size[[i]] - } else { - size <- 5 - } - - tree <- tree + annotate("text", - x = x_pos, - y = y_pos, - label = i, - size = size) - } - } - - # Add heatmap - if(input$upgma_heatmap_show == TRUE & length(input$upgma_heatmap_select) > 0) { - if (!(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & - any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)))) { - tree <- gheatmap.mod(tree, - data = select(Vis$meta_upgma, input$upgma_heatmap_select), - offset = upgma_heatmap_offset(), - width = upgma_heatmap_width(), - legend_title = input$upgma_heatmap_title, - colnames_angle = -upgma_colnames_angle(), - colnames_offset_y = upgma_colnames_y(), - colnames_color = input$upgma_color) + - upgma_heatmap_scale() - } - } - - # Sizing control - Vis$upgma_plot <- ggplotify::as.ggplot(tree, - scale = input$upgma_zoom, - hjust = input$upgma_h, - vjust = input$upgma_v) - - # Correct background color if zoomed out - cowplot::ggdraw(Vis$upgma_plot) + - theme(plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) - } - }) - - # Heatmap width - upgma_heatmap_width <- reactive({ - if(!is.null(input$upgma_heatmap_width)) { - input$upgma_heatmap_width - } else { - length_input <- length(input$upgma_heatmap_select) - if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { - if(length_input < 3) { - 0.1 - } else { - if (length_input >= 3 && length_input <= 50) { - min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) - } else { - 1.5 - } - } - } else { - if(length_input < 3) { - 0.3 - } else if (length_input >= 3 && length_input <= 27) { - min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) - } else { - 3 - } - } - } - }) - - # Heatmap column titles position - upgma_colnames_y <- reactive({ - if(!is.null(input$upgma_colnames_y)) { - input$upgma_colnames_y - } else { - if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { - 0 - } else {-1} - } - }) - - # Heatmap column titles angle - upgma_colnames_angle <- reactive({ - if(!is.null(input$upgma_colnames_angle)) { - input$upgma_colnames_angle - } else { - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { - 90 - } else {-90} - } else {-90} - } - }) - - # Heatmap scale - upgma_heatmap_scale <- reactive({ - if(!is.null(input$upgma_heatmap_scale) & !is.null(input$upgma_heatmap_div_mid)) { - if(input$upgma_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_heatmap_div_mid == "Zero") { - midpoint <- 0 - } else if(input$upgma_heatmap_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$upgma_heatmap_scale)[1], - mid = brewer.pal(3, input$upgma_heatmap_scale)[2], - high = brewer.pal(3, input$upgma_heatmap_scale)[3], - midpoint = midpoint, - name = input$upgma_heatmap_title) - } else { - if(input$upgma_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { - if(input$upgma_heatmap_scale == "magma") { - scale_fill_viridis(option = "A", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "inferno") { - scale_fill_viridis(option = "B", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "plasma") { - scale_fill_viridis(option = "C", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "viridis") { - scale_fill_viridis(option = "D", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "cividis") { - scale_fill_viridis(option = "E", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "rocket") { - scale_fill_viridis(option = "F", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "mako") { - scale_fill_viridis(option = "G", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "turbo") { - scale_fill_viridis(option = "H", - name = input$upgma_heatmap_title) - } - } else { - if(input$upgma_heatmap_scale == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G", - name = input$upgma_heatmap_title) - } else if(input$upgma_heatmap_scale == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H", - name = input$upgma_heatmap_title) - } - } - } else { - scale_fill_brewer(palette = input$upgma_heatmap_scale, - name = input$upgma_heatmap_title) - } - } - } - }) - - # Tippoint Scale - upgma_tippoint_scale <- reactive({ - if(!is.null(input$upgma_tippoint_scale) & !is.null(input$upgma_tipcolor_mapping_div_mid)) { - if(input$upgma_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tipcolor_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$upgma_tipcolor_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$upgma_tippoint_scale)[1], - mid = brewer.pal(3, input$upgma_tippoint_scale)[2], - high = brewer.pal(3, input$upgma_tippoint_scale)[3], - midpoint = midpoint) - } else { - if(input$upgma_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { - if(input$upgma_tippoint_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$upgma_tippoint_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$upgma_tippoint_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$upgma_tippoint_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$upgma_tippoint_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$upgma_tippoint_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$upgma_tippoint_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$upgma_tippoint_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$upgma_tippoint_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tippoint_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tippoint_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tippoint_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tippoint_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tippoint_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tippoint_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tippoint_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$upgma_tippoint_scale) - } - } - } - }) - - # Tiplab Scale - upgma_tiplab_scale <- reactive({ - if(!is.null(input$upgma_tiplab_scale) & !is.null(input$upgma_color_mapping_div_mid)) { - if(input$upgma_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_color_mapping_div_mid == "Zero") { - midpoint <- 0 - } else if(input$upgma_color_mapping_div_mid == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) - } - scale_color_gradient2(low = brewer.pal(3, input$upgma_tiplab_scale)[1], - mid = brewer.pal(3, input$upgma_tiplab_scale)[2], - high = brewer.pal(3, input$upgma_tiplab_scale)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { - if(input$upgma_tiplab_scale == "magma") { - scale_color_viridis(option = "A") - } else if(input$upgma_tiplab_scale == "inferno") { - scale_color_viridis(option = "B") - } else if(input$upgma_tiplab_scale == "plasma") { - scale_color_viridis(option = "C") - } else if(input$upgma_tiplab_scale == "viridis") { - scale_color_viridis(option = "D") - } else if(input$upgma_tiplab_scale == "cividis") { - scale_color_viridis(option = "E") - } else if(input$upgma_tiplab_scale == "rocket") { - scale_color_viridis(option = "F") - } else if(input$upgma_tiplab_scale == "mako") { - scale_color_viridis(option = "G") - } else if(input$upgma_tiplab_scale == "turbo") { - scale_color_viridis(option = "H") - } - } else { - if(input$upgma_tiplab_scale == "magma") { - scale_color_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiplab_scale == "inferno") { - scale_color_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiplab_scale == "plasma") { - scale_color_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiplab_scale == "viridis") { - scale_color_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiplab_scale == "cividis") { - scale_color_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiplab_scale == "rocket") { - scale_color_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiplab_scale == "mako") { - scale_color_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiplab_scale == "turbo") { - scale_color_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_color_brewer(palette = input$upgma_tiplab_scale) - } - } - } - }) - - # Clade Highlight - upgma_clades <- reactive({ - if(!is.null(input$upgma_parentnode)) { - if(!length(input$upgma_parentnode) == 0) { - if(length(input$upgma_parentnode) == 1) { - fill <- input$upgma_clade_scale - } else if (length(input$upgma_parentnode) == 2) { - if(startsWith(input$upgma_clade_scale, "#")) { - fill <- brewer.pal(3, "Set1")[1:2] - } else { - fill <- brewer.pal(3, input$upgma_clade_scale)[1:2] - } - } else { - fill <- brewer.pal(length(input$upgma_parentnode), input$upgma_clade_scale) - } - geom_hilight(node = as.numeric(input$upgma_parentnode), - fill = fill, - type = input$upgma_clade_type, - to.bottom = TRUE) - } else {NULL} - } - }) - - # Legend Position - upgma_legend_pos <- reactive({ - if(!is.null(input$upgma_legend_x) & !is.null(input$upgma_legend_y)) { - c(input$upgma_legend_x, input$upgma_legend_y) - } else { - c(0.1, 1) - } - }) - - # Heatmap offset - upgma_heatmap_offset <- reactive({ - if(is.null(input$upgma_heatmap_offset)) { - 0 - } else {input$upgma_heatmap_offset} - }) - - # Tiles fill color gradient - upgma_gradient <- reactive({ - if(!is.null(input$upgma_tiles_show_1) & - !is.null(input$upgma_fruit_variable) & - !is.null(input$upgma_tiles_scale_1) & - !is.null(input$upgma_tiles_mapping_div_mid_1)) { - if(input$upgma_tiles_show_1 == TRUE) { - if(input$upgma_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_1 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_1 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_1)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_1)[2], - high = brewer.pal(3, input$upgma_tiles_scale_1)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { - if(input$upgma_tiles_scale_1 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_1 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_1 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_1 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_1 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_1 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_1 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_1 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_1 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_1 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_1 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_1 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_1 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_1 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_1 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_1 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_1) - } - } - } else {NULL} - } - }) - - upgma_gradient2 <- reactive({ - if(!is.null(input$upgma_tiles_show_2) & - !is.null(input$upgma_fruit_variable_2) & - !is.null(input$upgma_tiles_scale_2) & - !is.null(input$upgma_tiles_mapping_div_mid_2)) { - if(input$upgma_tiles_show_2 == TRUE) { - if(input$upgma_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_2 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_2 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) - } - scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_2)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_2)[2], - high = brewer.pal(3, input$upgma_tiles_scale_2)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { - if(input$upgma_tiles_scale_2 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_2 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_2 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_2 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_2 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_2 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_2 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_2 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_2 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_2 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_2 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_2 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_2 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_2 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_2 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_2 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_2) - } - } - } else {NULL} - } - }) - - upgma_gradient3 <- reactive({ - if(!is.null(input$upgma_tiles_show_3) & - !is.null(input$upgma_fruit_variable_3) & - !is.null(input$upgma_tiles_scale_3) & - !is.null(input$upgma_tiles_mapping_div_mid_3)) { - if(input$upgma_tiles_show_3 == TRUE) { - if(input$upgma_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_3 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_3 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) - } - scale_fill_gradient3(low = brewer.pal(3, input$upgma_tiles_scale_3)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_3)[2], - high = brewer.pal(3, input$upgma_tiles_scale_3)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { - if(input$upgma_tiles_scale_3 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_3 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_3 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_3 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_3 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_3 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_3 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_3 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_3 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_3 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_3 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_3 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_3 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_3 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_3 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_3 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_3) - } - } - } else {NULL} - } - }) - - upgma_gradient4 <- reactive({ - if(!is.null(input$upgma_tiles_show_4) & - !is.null(input$upgma_fruit_variable_4) & - !is.null(input$upgma_tiles_scale_4) & - !is.null(input$upgma_tiles_mapping_div_mid_4)) { - if(input$upgma_tiles_show_4 == TRUE) { - if(input$upgma_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_4 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_4 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) - } - scale_fill_gradient4(low = brewer.pal(3, input$upgma_tiles_scale_4)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_4)[2], - high = brewer.pal(3, input$upgma_tiles_scale_4)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { - if(input$upgma_tiles_scale_4 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_4 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_4 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_4 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_4 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_4 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_4 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_4 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_4 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_4 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_4 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_4 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_4 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_4 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_4 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_4 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_4) - } - } - } else {NULL} - } - }) - - upgma_gradient5 <- reactive({ - if(!is.null(input$upgma_tiles_show_5) & - !is.null(input$upgma_fruit_variable_5) & - !is.null(input$upgma_tiles_scale_5) & - !is.null(input$upgma_tiles_mapping_div_mid_5)) { - if(input$upgma_tiles_show_5 == TRUE) { - if(input$upgma_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { - if(input$upgma_tiles_mapping_div_mid_5 == "Zero") { - midpoint <- 0 - } else if(input$upgma_tiles_mapping_div_mid_5 == "Mean") { - midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) - } else { - midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) - } - scale_fill_gradient5(low = brewer.pal(3, input$upgma_tiles_scale_5)[1], - mid = brewer.pal(3, input$upgma_tiles_scale_5)[2], - high = brewer.pal(3, input$upgma_tiles_scale_5)[3], - midpoint = midpoint) - } else { - if(input$upgma_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { - if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { - if(input$upgma_tiles_scale_5 == "magma") { - scale_fill_viridis(option = "A") - } else if(input$upgma_tiles_scale_5 == "inferno") { - scale_fill_viridis(option = "B") - } else if(input$upgma_tiles_scale_5 == "plasma") { - scale_fill_viridis(option = "C") - } else if(input$upgma_tiles_scale_5 == "viridis") { - scale_fill_viridis(option = "D") - } else if(input$upgma_tiles_scale_5 == "cividis") { - scale_fill_viridis(option = "E") - } else if(input$upgma_tiles_scale_5 == "rocket") { - scale_fill_viridis(option = "F") - } else if(input$upgma_tiles_scale_5 == "mako") { - scale_fill_viridis(option = "G") - } else if(input$upgma_tiles_scale_5 == "turbo") { - scale_fill_viridis(option = "H") - } - } else { - if(input$upgma_tiles_scale_5 == "magma") { - scale_fill_viridis(discrete = TRUE, option = "A") - } else if(input$upgma_tiles_scale_5 == "inferno") { - scale_fill_viridis(discrete = TRUE, option = "B") - } else if(input$upgma_tiles_scale_5 == "plasma") { - scale_fill_viridis(discrete = TRUE, option = "C") - } else if(input$upgma_tiles_scale_5 == "viridis") { - scale_fill_viridis(discrete = TRUE, option = "D") - } else if(input$upgma_tiles_scale_5 == "cividis") { - scale_fill_viridis(discrete = TRUE, option = "E") - } else if(input$upgma_tiles_scale_5 == "rocket") { - scale_fill_viridis(discrete = TRUE, option = "F") - } else if(input$upgma_tiles_scale_5 == "mako") { - scale_fill_viridis(discrete = TRUE, option = "G") - } else if(input$upgma_tiles_scale_5 == "turbo") { - scale_fill_viridis(discrete = TRUE, option = "H") - } - } - } else { - scale_fill_brewer(palette = input$upgma_tiles_scale_5) - } - } - } else {NULL} - } - }) - - # No label clip off for linear upgma tree - upgma_clip_label <- reactive({ - if(!(input$upgma_layout == "circular" | input$upgma_layout == "inward")) { - coord_cartesian(clip = "off") - } else {NULL} - }) - - # Geom Fruit - upgma_fruit <- reactive({ - if((!is.null(input$upgma_tiles_show_1)) & - (!is.null(input$upgma_fruit_variable)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ)) & - (!is.null(input$upgma_fruit_width_circ)) & - (!is.null(input$upgma_fruit_alpha))) { - if(input$upgma_tiles_show_1 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = input$upgma_fruit_offset_circ, - width = input$upgma_fruit_width_circ, - alpha = input$upgma_fruit_alpha - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = input$upgma_fruit_offset_circ, - width = input$upgma_fruit_width_circ, - alpha = input$upgma_fruit_alpha - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_1 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = 0, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable)), - offset = 0, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Geom Fruit - upgma_fruit2 <- reactive({ - if((!is.null(input$upgma_tiles_show_2)) & - (!is.null(input$upgma_fruit_variable_2)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_2)) & - (!is.null(input$upgma_fruit_width_circ_2)) & - (!is.null(input$upgma_fruit_alpha_2))) { - if(input$upgma_tiles_show_2 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), - offset = input$upgma_fruit_offset_circ_2, - width = input$upgma_fruit_width_circ_2, - alpha = input$upgma_fruit_alpha_2 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), - offset = input$upgma_fruit_offset_circ_2, - width = input$upgma_fruit_width_circ_2, - alpha = input$upgma_fruit_alpha_2 - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_2 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - upgma_fruit3 <- reactive({ - if((!is.null(input$upgma_tiles_show_3)) & - (!is.null(input$upgma_fruit_variable_3)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_3)) & - (!is.null(input$upgma_fruit_width_circ_3)) & - (!is.null(input$upgma_fruit_alpha_3))) { - if(input$upgma_tiles_show_3 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), - offset = input$upgma_fruit_offset_circ_3, - width = input$upgma_fruit_width_circ_3, - alpha = input$upgma_fruit_alpha_3 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), - offset = input$upgma_fruit_offset_circ_3, - width = input$upgma_fruit_width_circ_3, - alpha = input$upgma_fruit_alpha_3 - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_3 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - upgma_fruit4 <- reactive({ - if((!is.null(input$upgma_tiles_show_4)) & - (!is.null(input$upgma_fruit_variable_4)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_4)) & - (!is.null(input$upgma_fruit_width_circ_4)) & - (!is.null(input$upgma_fruit_alpha_4))) { - if(input$upgma_tiles_show_4 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), - offset = input$upgma_fruit_offset_circ_4, - width = input$upgma_fruit_width_circ_4, - alpha = input$upgma_fruit_alpha_4 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), - offset = input$upgma_fruit_offset_circ_4, - width = input$upgma_fruit_width_circ_4, - alpha = input$upgma_fruit_alpha_4 - ) - } - } else { - if(input$upgma_tiles_show_4 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - } - }) - - upgma_fruit5 <- reactive({ - if((!is.null(input$upgma_tiles_show_5)) & - (!is.null(input$upgma_fruit_variable_5)) & - (!is.null(input$upgma_layout)) & - (!is.null(input$upgma_fruit_offset_circ_5)) & - (!is.null(input$upgma_fruit_width_circ_5)) & - (!is.null(input$upgma_fruit_alpha_5))) { - if(input$upgma_tiles_show_5 == TRUE) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), - offset = input$upgma_fruit_offset_circ_5, - width = input$upgma_fruit_width_circ_5, - alpha = input$upgma_fruit_alpha_5 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), - offset = input$upgma_fruit_offset_circ_5, - width = input$upgma_fruit_width_circ_5, - alpha = input$upgma_fruit_alpha_5 - ) - } - } else {NULL} - } else { - if(input$upgma_tiles_show_5 == TRUE) { - if(!is.null(Vis$upgma_max_x)) { - if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { - width <- 1 - } else { - width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) - } - } else { - width <- 2 - } - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), - offset = 0.15, - width = width * 3, - alpha = 1 - ) - } else { - geom_fruit( - geom = geom_tile, - mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), - offset = 0.05, - width = width, - alpha = 1 - ) - } - } else {NULL} - } - }) - - # Xlim - upgma_limit <- reactive({ - if(input$upgma_layout == "circular") { - xlim(input$upgma_xlim, NA) - } else {NULL} - }) - - # Treescale - upgma_treescale <- reactive({ - if(!input$upgma_layout == "circular") { - if(input$upgma_treescale_show == TRUE) { - geom_treescale(x = upgma_treescale_x(), - y = upgma_treescale_y(), - width = upgma_treescale_width(), - color = input$upgma_color, - fontsize = 4) - } else {NULL} - } else {NULL} - }) - - # Treescale Y Position - upgma_treescale_y <- reactive({ - if(is.null(input$upgma_treescale_y)) { - 0 - } else {input$upgma_treescale_y} - }) - - # Treescale X Position - upgma_treescale_x <- reactive({ - if(is.null(input$upgma_treescale_x)) { - round(ceiling(Vis$upgma_max_x) * 0.2, 0) - } else {input$upgma_treescale_x} - }) - - # Treescale width - upgma_treescale_width <- reactive({ - if(!is.null(input$upgma_treescale_width)) { - input$upgma_treescale_width - } else { - round(ceiling(Vis$upgma_max_x) * 0.1, 0) - } - }) - - # Label branches - upgma_label_branch <- reactive({ - if(!input$upgma_layout == "circular" | !input$upgma_layout == "inward") { - if(input$upgma_show_branch_label == TRUE) { - geom_label( - aes( - x=!!sym("branch"), - label= !!sym(input$upgma_branch_label)), - fill = input$upgma_branch_label_color, - size = upgma_branch_size(), - label.r = unit(input$upgma_branch_labelradius, "lines"), - nudge_x = input$upgma_branch_x, - nudge_y = input$upgma_branch_y, - fontface = input$upgma_branchlab_fontface, - alpha = input$upgma_branchlab_alpha - ) - } else {NULL} - } else {NULL} - }) - - # Branch label size - upgma_branch_size <- reactive({ - if(!is.null(input$upgma_branch_size)) { - input$upgma_branch_size - } else { - Vis$branch_size_upgma - } - }) - - # Rootedge - upgma_rootedge <- reactive({ - if(input$upgma_rootedge_show == TRUE) { - if(is.null(input$upgma_rootedge_length)) { - geom_rootedge(rootedge = round(ceiling(Vis$upgma_max_x) * 0.05, 0), - linetype = input$upgma_rootedge_line) - } else { - geom_rootedge(rootedge = input$upgma_rootedge_length, - linetype = input$upgma_rootedge_line) - } - } else {NULL} - }) - - # Tippoints - upgma_tippoint <- reactive({ - if(input$upgma_tippoint_show == TRUE | input$upgma_tipcolor_mapping_show == TRUE | input$upgma_tipshape_mapping_show == TRUE) { - if(input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == FALSE) { - geom_tippoint( - aes(color = !!sym(input$upgma_tipcolor_mapping)), - alpha = input$upgma_tippoint_alpha, - shape = input$upgma_tippoint_shape, - size = upgma_tippoint_size() - ) - } else if (input$upgma_tipcolor_mapping_show == FALSE & input$upgma_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$upgma_tipshape_mapping)), - alpha = input$upgma_tippoint_alpha, - color = input$upgma_tippoint_color, - size = upgma_tippoint_size() - ) - } else if (input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == TRUE) { - geom_tippoint( - aes(shape = !!sym(input$upgma_tipshape_mapping), - color = !!sym(input$upgma_tipcolor_mapping)), - alpha = input$upgma_tippoint_alpha, - size = upgma_tippoint_size() - ) - } else { - geom_tippoint( - alpha = input$upgma_tippoint_alpha, - colour = input$upgma_tippoint_color, - fill = input$upgma_tippoint_color, - shape = input$upgma_tippoint_shape, - size = upgma_tippoint_size() - ) - } - } else {NULL} - }) - - # Nodepoints - upgma_nodepoint <- reactive({ - if(input$upgma_nodepoint_show == TRUE) { - geom_nodepoint( - alpha = input$upgma_nodepoint_alpha, - color = input$upgma_nodepoint_color, - shape = input$upgma_nodepoint_shape, - size = upgma_nodepoint_size() - ) - } else {NULL} - }) - - # Nodepoint size - upgma_nodepoint_size <- reactive({ - if(!is.null(input$upgma_nodepoint_size)) { - input$upgma_nodepoint_size - } else { - Vis$nodepointsize_upgma - } - }) - - # upgma circular or not - upgma_tiplab <- reactive({ - if(input$upgma_tiplab_show == TRUE) { - if(input$upgma_layout == "circular") { - if(input$upgma_mapping_show == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position), - check.overlap = input$upgma_tiplab_overlap - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - color = input$upgma_tiplab_color, - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position), - check.overlap = input$upgma_tiplab_overlap - ) - } - } else if (input$upgma_layout == "inward") { - if(input$upgma_mapping_show == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position_inw), - check.overlap = input$upgma_tiplab_overlap - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - color = input$upgma_tiplab_color, - geom = "text", - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - hjust = as.numeric(input$upgma_tiplab_position_inw), - check.overlap = input$upgma_tiplab_overlap - ) - } - } else { - if(input$upgma_mapping_show == TRUE) { - if(input$upgma_geom == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap, - label.padding = unit(upgma_tiplab_padding(), "lines"), - label.r = unit(input$upgma_tiplab_labelradius, "lines"), - fill = input$upgma_tiplab_fill - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap - ) - } - } else { - if(input$upgma_geom == TRUE) { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - color = input$upgma_tiplab_color, - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap, - label.padding = unit(upgma_tiplab_padding(), "lines"), - label.r = unit(input$upgma_tiplab_labelradius, "lines"), - fill = input$upgma_tiplab_fill - ) - } else { - geom_tiplab( - upgma_mapping_tiplab(), - geom = upgma_geom(), - color = input$upgma_tiplab_color, - angle = input$upgma_tiplab_angle, - size = upgma_tiplab_size(), - alpha = input$upgma_tiplab_alpha, - fontface = input$upgma_tiplab_fontface, - align = as.logical(input$upgma_align), - nudge_x = input$upgma_tiplab_nudge_x, - check.overlap = input$upgma_tiplab_overlap - ) - } - } - } - } else {NULL} - }) - - # Tip panel size - upgma_tiplab_padding <- reactive({ - if(!is.null(input$upgma_tiplab_padding)) { - input$upgma_tiplab_padding - } else { - Vis$tiplab_padding_upgma - } - }) - - # Tiplab size - upgma_tiplab_size <- reactive({ - if(!is.null(input$upgma_tiplab_size)) { - input$upgma_tiplab_size - } else { - Vis$labelsize_upgma - } - }) - - # Tippoint size - upgma_tippoint_size <- reactive({ - if(!is.null(input$upgma_tippoint_size)) { - input$upgma_tippoint_size - } else { - Vis$tippointsize_upgma - } - }) - - # Show Label Panels? - upgma_geom <- reactive({ - if(input$upgma_geom == TRUE) { - "label" - } else {"text"} - }) - - # upgma Tiplab color - upgma_mapping_tiplab <- reactive({ - if(input$upgma_mapping_show == TRUE) { - if(!is.null(input$upgma_tiplab)) { - aes(label = !!sym(input$upgma_tiplab), - color = !!sym(input$upgma_color_mapping)) - } else { - aes(label = !!sym("Assembly Name"), - color = !!sym(input$upgma_color_mapping)) - } - } else { - if(!is.null(input$upgma_tiplab)) { - aes(label = !!sym(input$upgma_tiplab)) - } else { - aes(label = !!sym("Assembly Name")) - } - } - }) - - # upgma Tree Layout - layout_upgma <- reactive({ - if(input$upgma_layout == "inward") { - "circular" - } else {input$upgma_layout} - }) - - # upgma inward circular - upgma_inward <- reactive({ - if (input$upgma_layout == "inward") { - layout_inward_circular(xlim = input$upgma_inward_xlim) - } else { - NULL - } - }) - - ### Save MST Plot ---- - output$save_plot_html <- downloadHandler( - filename = function() { - log_print(paste0("Save MST;", paste0("MST_", Sys.Date(), ".html"))) - paste0("MST_", Sys.Date(), ".html") - }, - content = function(file) { - mst_tree() %>% visSave(file = file, background = mst_background_color()) - } - ) - - ### Save NJ Plot ---- - - # Define download handler to save the plot - - output$download_nj <- downloadHandler( - filename = function() { - log_print(paste0("Save NJ;", paste0("NJ_", Sys.Date(), ".", input$filetype_nj))) - paste0("NJ_", Sys.Date(), ".", input$filetype_nj) - }, - content = function(file) { - if (input$filetype_nj == "png") { - png(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) - print(nj_tree()) - dev.off() - } else if (input$filetype_nj == "jpeg") { - jpeg(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) - print(nj_tree()) - dev.off() - } else if (input$filetype_nj == "svg") { - plot <- print(nj_tree()) - ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio))/96, - height = as.numeric(input$nj_scale)/96)) - } else if (input$filetype_nj == "bmp") { - bmp(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) - print(nj_tree()) - dev.off() - } - } - ) - - ### Save UPGMA Plot ---- - - # Define download handler to save the plot - - output$download_upgma <- downloadHandler( - filename = function() { - log_print(paste0("Save UPGMA;", paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma))) - paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma) - }, - content = function(file) { - if (input$filetype_upgma == "png") { - png(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) - print(upgma_tree()) - dev.off() - } else if (input$filetype_upgma == "jpeg") { - jpeg(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) - print(upgma_tree()) - dev.off() - } else if (input$filetype_upgma == "svg") { - plot <- print(upgma_tree()) - ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio))/96, - height = as.numeric(input$upgma_scale)/96)) - } else if (input$filetype_upgma == "bmp") { - bmp(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) - print(upgma_tree()) - dev.off() - } - } - ) - - ### Reactive Events ---- - - # MST cluster reset button - observeEvent(input$mst_cluster_reset, { - if(!is.null(DB$schemeinfo)) - updateNumericInput(session, "mst_cluster_threshold", value = as.numeric(DB$schemeinfo[7, 2])) - }) - - # Shut off "Align Labels" control for UPGMA trees - shinyjs::disable('upgma_align') - shinyjs::disable('upgma_tiplab_linesize') - shinyjs::disable('upgma_tiplab_linetype') - - # Conditional disabling of control elemenmts - observe({ - - # Tiles for inward layout - if(input$nj_layout == "inward") { - shinyjs::disable('nj_tiles_show') - shinyjs::disable('nj_tiles_show_2') - shinyjs::disable('nj_tiles_show_3') - shinyjs::disable('nj_tiles_show_4') - shinyjs::disable('nj_tiles_show_5') - shinyjs::disable('nj_fruit_variable') - shinyjs::disable('nj_fruit_variable_2') - shinyjs::disable('nj_fruit_variable_3') - shinyjs::disable('nj_fruit_variable_4') - shinyjs::disable('nj_fruit_variable_5') - shinyjs::disable('nj_fruit_width') - shinyjs::disable('nj_fruit_width_2') - shinyjs::disable('nj_fruit_width_3') - shinyjs::disable('nj_fruit_width_4') - shinyjs::disable('nj_fruit_width_5') - shinyjs::disable('nj_fruit_offset') - shinyjs::disable('nj_fruit_offset_2') - shinyjs::disable('nj_fruit_offset_3') - shinyjs::disable('nj_fruit_offset_4') - shinyjs::disable('nj_fruit_offset_5') - } else { - shinyjs::enable('nj_tiles_show') - shinyjs::enable('nj_tiles_show_2') - shinyjs::enable('nj_tiles_show_3') - shinyjs::enable('nj_tiles_show_4') - shinyjs::enable('nj_tiles_show_5') - shinyjs::enable('nj_fruit_variable') - shinyjs::enable('nj_fruit_variable_2') - shinyjs::enable('nj_fruit_variable_3') - shinyjs::enable('nj_fruit_variable_4') - shinyjs::enable('nj_fruit_variable_5') - shinyjs::enable('nj_fruit_width') - shinyjs::enable('nj_fruit_width_2') - shinyjs::enable('nj_fruit_width_3') - shinyjs::enable('nj_fruit_width_4') - shinyjs::enable('nj_fruit_width_5') - shinyjs::enable('nj_fruit_offset') - shinyjs::enable('nj_fruit_offset_2') - shinyjs::enable('nj_fruit_offset_3') - shinyjs::enable('nj_fruit_offset_4') - shinyjs::enable('nj_fruit_offset_5') - } - - if(input$upgma_layout == "inward") { - shinyjs::disable('upgma_tiles_show') - shinyjs::disable('upgma_tiles_show_2') - shinyjs::disable('upgma_tiles_show_3') - shinyjs::disable('upgma_tiles_show_4') - shinyjs::disable('upgma_tiles_show_5') - shinyjs::disable('upgma_fruit_variable') - shinyjs::disable('upgma_fruit_variable_2') - shinyjs::disable('upgma_fruit_variable_3') - shinyjs::disable('upgma_fruit_variable_4') - shinyjs::disable('upgma_fruit_variable_5') - shinyjs::disable('upgma_fruit_width') - shinyjs::disable('upgma_fruit_width_2') - shinyjs::disable('upgma_fruit_width_3') - shinyjs::disable('upgma_fruit_width_4') - shinyjs::disable('upgma_fruit_width_5') - shinyjs::disable('upgma_fruit_offset') - shinyjs::disable('upgma_fruit_offset_2') - shinyjs::disable('upgma_fruit_offset_3') - shinyjs::disable('upgma_fruit_offset_4') - shinyjs::disable('upgma_fruit_offset_5') - } else { - shinyjs::enable('upgma_tiles_show') - shinyjs::enable('upgma_tiles_show_2') - shinyjs::enable('upgma_tiles_show_3') - shinyjs::enable('upgma_tiles_show_4') - shinyjs::enable('upgma_tiles_show_5') - shinyjs::enable('upgma_fruit_variable') - shinyjs::enable('upgma_fruit_variable_2') - shinyjs::enable('upgma_fruit_variable_3') - shinyjs::enable('upgma_fruit_variable_4') - shinyjs::enable('upgma_fruit_variable_5') - shinyjs::enable('upgma_fruit_width') - shinyjs::enable('upgma_fruit_width_2') - shinyjs::enable('upgma_fruit_width_3') - shinyjs::enable('upgma_fruit_width_4') - shinyjs::enable('upgma_fruit_width_5') - shinyjs::enable('upgma_fruit_offset') - shinyjs::enable('upgma_fruit_offset_2') - shinyjs::enable('upgma_fruit_offset_3') - shinyjs::enable('upgma_fruit_offset_4') - shinyjs::enable('upgma_fruit_offset_5') - } - - # Shut off branch labels for NJ and UPGMA plots for circular layout - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - shinyjs::disable('nj_show_branch_label') - } else { - shinyjs::enable('nj_show_branch_label') - } - - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - shinyjs::disable('upgma_show_branch_label') - } else { - shinyjs::enable('upgma_show_branch_label') - } - }) - - #### Generate Plot ---- - - hamming_nj <- reactive({ - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - - allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - - compute.distMatrix(allelic_profile_noNA_true, hamming.dist) - - } else if(input$na_handling == "ignore_na"){ - compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) - - } else { - compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) - } - - } else {compute.distMatrix(DB$allelic_profile_true, hamming.dist)} - }) - - hamming_mst <- reactive({ - if(anyNA(DB$allelic_profile)) { - if(input$na_handling == "omit") { - allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] - - allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] - - dist <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) - - } else if (input$na_handling == "ignore_na") { - dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) - } else { - dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) - } - } else { - dist <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) - } - - # Find indices of pairs with a distance of 0 - zero_distance_pairs <- as.data.frame(which(as.matrix(dist) == 0, arr.ind = TRUE)) - - zero_distance_pairs <- zero_distance_pairs[zero_distance_pairs$row != zero_distance_pairs$col, ] - - if(nrow(zero_distance_pairs) > 0) { - - # Sort each row so that x <= y - df_sorted <- t(apply(zero_distance_pairs, 1, function(row) sort(row))) - - # Remove duplicate rows - df_unique <- as.data.frame(unique(df_sorted)) - - colnames(df_unique) <- c("col", "row") - - # get metadata in df - vector_col <- character(0) - count <- 1 - for (i in df_unique$col) { - vector_col[count] <- Vis$meta_mst$`Assembly Name`[i] - count <- count + 1 - } - - vector_row <- character(0) - count <- 1 - for (i in df_unique$row) { - vector_row[count] <- Vis$meta_mst$`Assembly Name`[i] - count <- count + 1 - } - - col_id <- character(0) - count <- 1 - for (i in df_unique$col) { - col_id[count] <- Vis$meta_mst$`Assembly ID`[i] - count <- count + 1 - } - - row_id <- character(0) - count <- 1 - for (i in df_unique$row) { - row_id[count] <- Vis$meta_mst$`Assembly ID`[i] - count <- count + 1 - } - - col_index <- character(0) - count <- 1 - for (i in df_unique$col) { - col_index[count] <- Vis$meta_mst$Index[i] - count <- count + 1 - } - - row_index <- character(0) - count <- 1 - for (i in df_unique$row) { - row_index[count] <- Vis$meta_mst$Index[i] - count <- count + 1 - } - - col_date <- character(0) - count <- 1 - for (i in df_unique$col) { - col_date[count] <- Vis$meta_mst$`Isolation Date`[i] - count <- count + 1 - } - - row_date <- character(0) - count <- 1 - for (i in df_unique$row) { - row_date[count] <- Vis$meta_mst$`Isolation Date`[i] - count <- count + 1 - } - - col_host <- character(0) - count <- 1 - for (i in df_unique$col) { - col_host[count] <- Vis$meta_mst$Host[i] - count <- count + 1 - } - - row_host <- character(0) - count <- 1 - for (i in df_unique$row) { - row_host[count] <- Vis$meta_mst$Host[i] - count <- count + 1 - } - - col_country <- character(0) - count <- 1 - for (i in df_unique$col) { - col_country[count] <- Vis$meta_mst$Country[i] - count <- count + 1 - } - - row_country <- character(0) - count <- 1 - for (i in df_unique$row) { - row_country[count] <- Vis$meta_mst$Country[i] - count <- count + 1 - } - - col_city <- character(0) - count <- 1 - for (i in df_unique$col) { - col_city[count] <- Vis$meta_mst$City[i] - count <- count + 1 - } - - row_city <- character(0) - count <- 1 - for (i in df_unique$row) { - row_city[count] <- Vis$meta_mst$City[i] - count <- count + 1 - } - - df_unique <- cbind(df_unique, col_name = vector_col, row_name = vector_row, - col_index = col_index, row_index = row_index, col_id = col_id, - row_id = row_id, col_date = col_date, row_date = row_date, - col_host = col_host, row_host = row_host, col_country = col_country, - row_country = row_country, col_city = col_city, row_city = row_city) - - # Add groups - grouped_df <- df_unique %>% - group_by(col) %>% - mutate(group_id = cur_group_id()) - - # Merge groups - name <- character(0) - index <- character(0) - id <- character(0) - count <- 1 - for (i in grouped_df$group_id) { - name[count] <- paste(unique(append(grouped_df$col_name[which(grouped_df$group_id == i)], - grouped_df$row_name[which(grouped_df$group_id == i)])), - collapse = "\n") - - id[count] <- paste(unique(append(grouped_df$col_id[which(grouped_df$group_id == i)], - grouped_df$row_id[which(grouped_df$group_id == i)])), - collapse = "\n") - - index[count] <- paste(unique(append(grouped_df$col_index[which(grouped_df$group_id == i)], - grouped_df$row_index[which(grouped_df$group_id == i)])), - collapse = "\n") - - count <- count + 1 - } - - merged_names <- cbind(grouped_df, "Index" = index, "Assembly Name" = name, "Assembly ID" = id) - - # remove duplicate groups - - final <- merged_names[!duplicated(merged_names$group_id), ] - - final_cleaned <- final[!(final$col_name %in% final$row_name),] - - final_cleaned <- select(final_cleaned, 3, 17:20) - - # adapt metadata - Date_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - Date <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - Date <- append(Date, Vis$meta_mst$`Isolation Date`[which(Vis$meta_mst$Index == i)]) - } - Date_merged <- append(Date_merged, paste(Date, collapse = "\n")) - } - - Host_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - Host <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - Host <- append(Host, Vis$meta_mst$Host[which(Vis$meta_mst$Index == i)]) - } - Host_merged <- append(Host_merged, paste(Host, collapse = "\n")) - } - - Country_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - Country <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - Country <- append(Country, Vis$meta_mst$Country[which(Vis$meta_mst$Index == i)]) - } - Country_merged <- append(Country_merged, paste(Country, collapse = "\n")) - } - - City_merged <- character(0) - for(j in 1:length(final_cleaned$Index)) { - City <- character(0) - for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { - City <- append(City, Vis$meta_mst$City[which(Vis$meta_mst$Index == i)]) - } - City_merged <- append(City_merged, paste(City, collapse = "\n")) - } - - final_meta <- cbind(final_cleaned, "Isolation Date" = Date_merged, - "Host" = Host_merged, "Country" = Country_merged, "City" = City_merged) - - - # Merging with original data frame / allelic profile - - allelic_profile_true <- DB$allelic_profile_true - meta_true <- Vis$meta_mst - - rownames(allelic_profile_true) <- Vis$meta_mst$`Assembly Name` - rownames(meta_true) <- Vis$meta_mst$`Assembly Name` - - omit <- unique(append(df_unique$col_name, df_unique$row_name)) %in% final_cleaned$col_name - - omit_id <- unique(append(df_unique$col_name, df_unique$row_name))[!omit] - - remove <- !(rownames(allelic_profile_true) %in% omit_id) - - allelic_profile_clean <- allelic_profile_true[remove, ] - - meta_clean <- meta_true[remove, ] - - # substitute meta assembly names with group names - - count <- 1 - for(i in which(rownames(meta_clean) %in% final_meta$col_name)) { - meta_clean$Index[i] <- final_meta$Index[count] - meta_clean$`Assembly Name`[i] <- final_meta$`Assembly Name`[count] - meta_clean$`Assembly ID`[i] <- final_meta$`Assembly ID`[count] - meta_clean$`Isolation Date`[i] <- final_meta$`Isolation Date`[count] - meta_clean$Host[i] <- final_meta$Host[count] - meta_clean$Country[i] <- final_meta$Country[count] - meta_clean$City[i] <- final_meta$City[count] - count <- count + 1 - } - - # Metadata completion - # get group size - - size_vector <- numeric(0) - for(i in 1:nrow(meta_clean)) { - if (str_count(meta_clean$`Assembly Name`[i], "\n") == 0) { - size_vector[i] <- 1 - } else { - size_vector[i] <- str_count(meta_clean$`Assembly Name`[i], "\n") +1 - } - } - - meta_clean <- mutate(meta_clean, size = size_vector) - - # get font size dependent on group size - - font_size <- numeric(nrow(meta_clean)) - - for (i in 1:length(font_size)) { - if(meta_clean$size[i] < 3) { - font_size[i] <- 12 - } else { - font_size[i] <- 11 - } - } - - # get v-align dependent on group size - valign <- numeric(nrow(meta_clean)) - - for (i in 1:length(valign)) { - if(meta_clean$size[i] == 1) { - valign[i] <- -30 - } else if(meta_clean$size[i] == 2) { - valign[i] <- -38 - } else if(meta_clean$size[i] == 3) { - valign[i] <- -46 - } else if(meta_clean$size[i] == 4) { - valign[i] <- -54 - } else if(meta_clean$size[i] == 5) { - valign[i] <- -62 - } else if(meta_clean$size[i] > 5) { - valign[i] <- -70 - } - } - - Vis$unique_meta <- meta_clean %>% - cbind(font_size = font_size, valign = valign) - - # final dist calculation - - if(anyNA(DB$allelic_profile)){ - if(input$na_handling == "omit") { - allelic_profile_clean_noNA_names <- allelic_profile_clean[, colSums(is.na(allelic_profile_clean)) == 0] - compute.distMatrix(allelic_profile_clean_noNA_names, hamming.dist) - } else if (input$na_handling == "ignore_na") { - compute.distMatrix(allelic_profile_clean, hamming.distIgnore) - } else { - compute.distMatrix(allelic_profile_clean, hamming.distCategory) - } - } else {compute.distMatrix(allelic_profile_clean, hamming.dist)} - - - } else { - font_size <- rep(12, nrow(Vis$meta_mst)) - valign <- rep(-30, nrow(Vis$meta_mst)) - size <- rep(1, nrow(Vis$meta_mst)) - Vis$unique_meta <- Vis$meta_mst %>% - cbind(size , font_size, valign) - - dist - } - - }) - - observeEvent(input$create_tree, { - log_print("Input create_tree") - - if(is.null(DB$data)) { - log_print("Missing data") - - show_toast( - title = "Missing data", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else if(nrow(DB$allelic_profile_true) < 3) { - log_print("Min. of 3 entries required for visualization") - - show_toast( - title = "Min. of 3 entries required for visualization", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } else { - - if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { - log_print("Duplicated assemblies") - - dup_name <- which(duplicated(DB$meta_true$`Assembly Name`)) - dup_id <- which(duplicated(DB$meta_true$`Assembly ID`)) - - showModal( - modalDialog( - if((length(dup_name) + length(dup_id)) == 1) { - if(length(dup_name) == 1) { - HTML(paste0("Entry #", dup_name, - " contains a duplicated assembly name:", "

", - DB$meta_true$`Assembly Name`[dup_name])) - } else { - HTML(paste0("Entry #", dup_id, - " contains a duplicated assembly ID:", "

", - DB$meta_true$`Assembly ID`[dup_id])) - } - } else { - if(length(dup_name) == 0) { - HTML(c("Entries contain duplicated IDs

", - paste0(unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) - } else if(length(dup_id) == 0) { - HTML(c("Entries contain duplicated names

", - paste0(unique(DB$meta_true$`Assembly Name`[dup_name]), "
"))) - } else { - HTML(c("Entries contain duplicated names and IDs

", - paste0("Name: ", unique(DB$meta_true$`Assembly Name`[dup_name]), "
"), - paste0("ID: ", unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) - } - }, - title = "Duplicate entries", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("change_entries", "Go to Entry Table", class = "btn btn-default") - ) - ) - ) - } else { - - set.seed(1) - - if (input$tree_algo == "Neighbour-Joining") { - - log_print("Rendering NJ tree") - - output$nj_field <- renderUI({ - addSpinner( - plotOutput("tree_nj", width = paste0(as.character(as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), "px"), height = paste0(as.character(input$nj_scale), "px")), - spin = "dots", - color = "#ffffff" - ) - }) - - Vis$meta_nj <- select(DB$meta_true, -2) - - if(length(unique(gsub(" ", "_", colnames(Vis$meta_nj)))) < length(gsub(" ", "_", colnames(Vis$meta_nj)))) { - show_toast( - title = "Conflicting Custom Variable Names", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - # Create phylogenetic tree data - Vis$nj <- ape::nj(hamming_nj()) - - # Create phylogenetic tree meta data - Vis$meta_nj <- mutate(Vis$meta_nj, taxa = Index) %>% - relocate(taxa) - - # Get number of included entries calculate start values for tree - if(!is.null(input$nj_layout)) { - if(input$nj_layout == "circular" | input$nj_layout == "inward") { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_nj <- 5.5 - Vis$tippointsize_nj <- 5.5 - Vis$nodepointsize_nj <- 4 - Vis$tiplab_padding_nj <- 0.25 - Vis$branch_size_nj <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_nj <- 5 - Vis$tippointsize_nj <- 5 - Vis$nodepointsize_nj <- 3.5 - Vis$tiplab_padding_nj <- 0.2 - Vis$branch_size_nj <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_nj <- 4.5 - Vis$tippointsize_nj <- 4.5 - Vis$nodepointsize_nj <- 3 - Vis$tiplab_padding_nj <- 0.15 - Vis$branch_size_nj <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_nj <- 4 - Vis$tippointsize_nj <- 4 - Vis$nodepointsize_nj <- 2.5 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_nj <- 3.5 - Vis$tippointsize_nj <- 3.5 - Vis$nodepointsize_nj <- 2 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 2.5 - } else { - Vis$labelsize_nj <- 3 - Vis$tippointsize_nj <- 3 - Vis$nodepointsize_nj <- 1.5 - Vis$tiplab_padding_nj <- 0.05 - Vis$branch_size_nj <- 2 - } - } else { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_nj <- 5 - Vis$tippointsize_nj <- 5 - Vis$nodepointsize_nj <- 4 - Vis$tiplab_padding_nj <- 0.25 - Vis$branch_size_nj <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_nj <- 4.5 - Vis$tippointsize_nj <- 4.5 - Vis$nodepointsize_nj <- 3.5 - Vis$tiplab_padding_nj <- 0.2 - Vis$branch_size_nj <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_nj <- 4 - Vis$tippointsize_nj <- 4 - Vis$nodepointsize_nj <- 3 - Vis$tiplab_padding_nj <- 0.15 - Vis$branch_size_nj <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_nj <- 3.5 - Vis$tippointsize_nj <- 3.5 - Vis$nodepointsize_nj <- 2.5 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_nj <- 3 - Vis$tippointsize_nj <- 3 - Vis$nodepointsize_nj <- 2 - Vis$tiplab_padding_nj <- 0.1 - Vis$branch_size_nj <- 2.5 - } else { - Vis$labelsize_nj <- 2.5 - Vis$tippointsize_nj <- 2.5 - Vis$nodepointsize_nj <- 1.5 - Vis$tiplab_padding_nj <- 0.05 - Vis$branch_size_nj <- 2 - } - } - } else { - Vis$labelsize_nj <- 4 - Vis$tippointsize_nj <- 4 - Vis$nodepointsize_nj <- 2.5 - Vis$tiplab_padding_nj <- 0.2 - Vis$branch_size_nj <- 3.5 - } - - Vis$nj_tree <- ggtree(Vis$nj) - - # Get upper and lower end of x range - Vis$nj_max_x <- max(Vis$nj_tree$data$x) - Vis$nj_min_x <- min(Vis$nj_tree$data$x) - - # Get parent node numbers - Vis$nj_parentnodes <- Vis$nj_tree$data$parent - - # Update visualization control inputs - if(!is.null(input$nj_tiplab_size)) { - updateNumericInput(session, "nj_tiplab_size", value = Vis$labelsize_nj) - } - if(!is.null(input$nj_tippoint_size)) { - updateSliderInput(session, "nj_tippoint_size", value = Vis$tippointsize_nj) - } - if(!is.null(input$nj_nodepoint_size)) { - updateSliderInput(session, "nj_nodepoint_size", value = Vis$nodepointsize_nj) - } - if(!is.null(input$nj_tiplab_padding)) { - updateSliderInput(session, "nj_tiplab_padding", value = Vis$tiplab_padding_nj) - } - if(!is.null(input$nj_branch_size)) { - updateNumericInput(session, "nj_branch_size", value = Vis$branch_size_nj) - } - if(!is.null(input$nj_treescale_width)) { - updateNumericInput(session, "nj_treescale_width", value = round(ceiling(Vis$nj_max_x) * 0.1, 0)) - } - if(!is.null(input$nj_rootedge_length)) { - updateSliderInput(session, "nj_rootedge_length", value = round(ceiling(Vis$nj_max_x) * 0.05, 0)) - } - - output$tree_nj <- renderPlot({ - nj_tree() - }) - - Vis$nj_true <- TRUE - } - } else if (input$tree_algo == "UPGMA") { - - log_print("Rendering UPGMA tree") - - output$upgma_field <- renderUI({ - addSpinner( - plotOutput("tree_upgma", width = paste0(as.character(as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), "px"), height = paste0(as.character(input$upgma_scale), "px")), - spin = "dots", - color = "#ffffff" - ) - }) - - Vis$meta_upgma <- select(DB$meta_true, -2) - - if(length(unique(gsub(" ", "_", colnames(Vis$meta_upgma)))) < length(gsub(" ", "_", colnames(Vis$meta_upgma)))) { - show_toast( - title = "Conflicting Custom Variable Names", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - # Create phylogenetic tree data - Vis$upgma <- phangorn::upgma(hamming_nj()) - - # Create phylogenetic tree meta data - Vis$meta_upgma <- mutate(Vis$meta_upgma, taxa = Index) %>% - relocate(taxa) - - # Get number of included entries calculate start values for tree - if(!is.null(input$upgma_layout)) { - if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_upgma <- 5.5 - Vis$tippointsize_upgma <- 5.5 - Vis$nodepointsize_upgma <- 4 - Vis$tiplab_padding_upgma <- 0.25 - Vis$branch_size_upgma <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_upgma <- 5 - Vis$tippointsize_upgma <- 5 - Vis$nodepointsize_upgma <- 3.5 - Vis$tiplab_padding_upgma <- 0.2 - Vis$branch_size_upgma <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_upgma <- 4.5 - Vis$tippointsize_upgma <- 4.5 - Vis$nodepointsize_upgma <- 3 - Vis$tiplab_padding_upgma <- 0.15 - Vis$branch_size_upgma <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_upgma <- 4 - Vis$tippointsize_upgma <- 4 - Vis$nodepointsize_upgma <- 2.5 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_upgma <- 3.5 - Vis$tippointsize_upgma <- 3.5 - Vis$nodepointsize_upgma <- 2 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 2.5 - } else { - Vis$labelsize_upgma <- 3 - Vis$tippointsize_upgma <- 3 - Vis$nodepointsize_upgma <- 1.5 - Vis$tiplab_padding_upgma <- 0.05 - Vis$branch_size_upgma <- 2 - } - } else { - if(sum(DB$data$Include) < 21) { - Vis$labelsize_upgma <- 5 - Vis$tippointsize_upgma <- 5 - Vis$nodepointsize_upgma <- 4 - Vis$tiplab_padding_upgma <- 0.25 - Vis$branch_size_upgma <- 4.5 - } else if (between(sum(DB$data$Include), 21, 40)) { - Vis$labelsize_upgma <- 4.5 - Vis$tippointsize_upgma <- 4.5 - Vis$nodepointsize_upgma <- 3.5 - Vis$tiplab_padding_upgma <- 0.2 - Vis$branch_size_upgma <- 4 - } else if (between(sum(DB$data$Include), 41, 60)) { - Vis$labelsize_upgma <- 4 - Vis$tippointsize_upgma <- 4 - Vis$nodepointsize_upgma <- 3 - Vis$tiplab_padding_upgma <- 0.15 - Vis$branch_size_upgma <- 3.5 - } else if (between(sum(DB$data$Include), 61, 80)) { - Vis$labelsize_upgma <- 3.5 - Vis$tippointsize_upgma <- 3.5 - Vis$nodepointsize_upgma <- 2.5 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 3 - } else if (between(sum(DB$data$Include), 81, 100)) { - Vis$labelsize_upgma <- 3 - Vis$tippointsize_upgma <- 3 - Vis$nodepointsize_upgma <- 2 - Vis$tiplab_padding_upgma <- 0.1 - Vis$branch_size_upgma <- 2.5 - } else { - Vis$labelsize_upgma <- 2.5 - Vis$tippointsize_upgma <- 2.5 - Vis$nodepointsize_upgma <- 1.5 - Vis$tiplab_padding_upgma <- 0.05 - Vis$branch_size_upgma <- 2 - } - } - } else { - Vis$labelsize_upgma <- 4 - Vis$tippointsize_upgma <- 4 - Vis$nodepointsize_upgma <- 2.5 - Vis$tiplab_padding_upgma <- 0.2 - Vis$branch_size_upgma <- 3.5 - } - - Vis$upgma_tree <- ggtree(Vis$upgma) - - # Get upper and lower end of x range - Vis$upgma_max_x <- max(Vis$upgma_tree$data$x) - Vis$upgma_min_x <- min(Vis$upgma_tree$data$x) - - # Get parent node numbers - Vis$upgma_parentnodes <- Vis$upgma_tree$data$parent - - # Update visualization control inputs - if(!is.null(input$upgma_tiplab_size)) { - updateNumericInput(session, "upgma_tiplab_size", value = Vis$labelsize_upgma) - } - if(!is.null(input$upgma_tippoint_size)) { - updateSliderInput(session, "upgma_tippoint_size", value = Vis$tippointsize_upgma) - } - if(!is.null(input$upgma_nodepoint_size)) { - updateSliderInput(session, "upgma_nodepoint_size", value = Vis$nodepointsize_upgma) - } - if(!is.null(input$upgma_tiplab_padding)) { - updateSliderInput(session, "upgma_tiplab_padding", value = Vis$tiplab_padding_upgma) - } - if(!is.null(input$upgma_branch_size)) { - updateNumericInput(session, "upgma_branch_size", value = Vis$branch_size_upgma) - } - if(!is.null(input$upgma_treescale_width)) { - updateNumericInput(session, "upgma_treescale_width", value = round(ceiling(Vis$upgma_max_x) * 0.1, 0)) - } - if(!is.null(input$upgma_rootedge_length)) { - updateSliderInput(session, "upgma_rootedge_length", value = round(ceiling(Vis$upgma_max_x) * 0.05, 0)) - } - - output$tree_upgma <- renderPlot({ - upgma_tree() - }) - - Vis$upgma_true <- TRUE - } - } else { - - log_print("Rendering MST graph") - - output$mst_field <- renderUI({ - if(input$mst_background_transparent == TRUE) { - visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")) - } else { - addSpinner( - visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")), - spin = "dots", - color = "#ffffff" - ) - } - }) - - if(nrow(DB$meta_true) > 100) { - - log_print("Over 100 isolates in MST graph") - - show_toast( - title = "Computation might take a while", - type = "warning", - position = "bottom-end", - timer = 10000 - ) - } - - meta_mst <- DB$meta_true - Vis$meta_mst <- meta_mst - - # prepare igraph object - Vis$ggraph_1 <- hamming_mst() |> - as.matrix() |> - graph.adjacency(weighted = TRUE) |> - igraph::mst() - - output$tree_mst <- renderVisNetwork({ - mst_tree() - }) - - Vis$mst_true <- TRUE - } - } - } - }) - - # _______________________ #### - - ## Report ---- - - observe({ - if(!is.null(DB$data)) { - if(!is.null(input$tree_algo)) { - if(input$tree_algo == "Minimum-Spanning") { - shinyjs::disable("rep_plot_report") - updateCheckboxInput(session, "rep_plot_report", value = FALSE) - } else { - shinyjs::enable("rep_plot_report") - } - } - } - }) - - ### Report creation UI ---- - - observeEvent(input$create_rep, { - - if((input$tree_algo == "Minimum-Spanning" & isTRUE(Vis$mst_true)) | - (input$tree_algo == "UPGMA" & isTRUE(Vis$upgma_true)) | - (input$tree_algo == "Neighbour-Joining" & isTRUE(Vis$nj_true))) { - # Get currently selected missing value handling option - if(input$na_handling == "ignore_na") { - na_handling <- "Ignore missing values for pairwise comparison" - } else if(input$na_handling == "omit") { - na_handling <- "Omit loci with missing values for all assemblies" - } else if(input$na_handling == "category") { - na_handling <- "Treat missing values as allele variant" - } - - extra_var <- character() - if(input$tree_algo == "Minimum-Spanning") { - shinyjs::runjs("mstReport();") - if(isTRUE(input$mst_color_var)) { - extra_var <- c(extra_var, input$mst_col_var) - } - } else if(input$tree_algo == "Neighbour-Joining") { - if(isTRUE(input$nj_mapping_show)) { - extra_var <- c(extra_var, input$nj_color_mapping) - } - if(isTRUE(input$nj_tipcolor_mapping_show)) { - extra_var <- c(extra_var, input$nj_tipcolor_mapping) - } - if(isTRUE(input$nj_tipshape_mapping_show)) { - extra_var <- c(extra_var, input$nj_tipshape_mapping) - } - if(isTRUE(input$nj_tiles_show_1)) { - extra_var <- c(extra_var, input$nj_fruit_variable) - } - if(isTRUE(input$nj_tiles_show_2)) { - extra_var <- c(extra_var, input$nj_fruit_variable_2) - } - if(isTRUE(input$nj_tiles_show_3)) { - extra_var <- c(extra_var, input$nj_fruit_variable_3) - } - if(isTRUE(input$nj_tiles_show_4)) { - extra_var <- c(extra_var, input$nj_fruit_variable_4) - } - if(isTRUE(input$nj_tiles_show_5)) { - extra_var <- c(extra_var, input$nj_fruit_variable_5) - } - if(isTRUE(input$nj_heatmap_show)) { - extra_var <- c(extra_var, input$nj_heatmap_select) - } - } else if(input$tree_algo == "UPGMA") { - if(isTRUE(input$UPGMA_mapping_show)) { - extra_var <- c(extra_var, input$UPGMA_color_mapping) - } - if(isTRUE(input$UPGMA_tipcolor_mapping_show)) { - extra_var <- c(extra_var, input$UPGMA_tipcolor_mapping) - } - if(isTRUE(input$UPGMA_tipshape_mapping_show)) { - extra_var <- c(extra_var, input$UPGMA_tipshape_mapping) - } - if(isTRUE(input$UPGMA_tiles_show_1)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable) - } - if(isTRUE(input$UPGMA_tiles_show_2)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_2) - } - if(isTRUE(input$UPGMA_tiles_show_3)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_3) - } - if(isTRUE(input$UPGMA_tiles_show_4)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_4) - } - if(isTRUE(input$UPGMA_tiles_show_5)) { - extra_var <- c(extra_var, input$UPGMA_fruit_variable_5) - } - if(isTRUE(input$UPGMA_heatmap_show)) { - extra_var <- c(extra_var, input$UPGMA_heatmap_select) - } - } - - showModal( - modalDialog( - fluidRow( - column( - width = 12, - fluidRow( - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color:black; font-size: 15px; font-weight: 900', 'General') - ) - ) - ), - column( - width = 3, - align = "left", - checkboxInput( - "rep_general", - label = "", - value = TRUE - ) - ) - ), - fluidRow( - column( - width = 12, - align = "left", - fluidRow( - column( - width = 3, - checkboxInput( - "rep_date_general", - label = h5("Date", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 7, - dateInput( - "mst_date_general_select", - "", - max = Sys.Date() - ) - ) - ), - fluidRow( - column( - width = 3, - checkboxInput( - "rep_operator_general", - label = h5("Operator", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - textInput( - "mst_operator_general_select", - "" - ) - ) - ), - fluidRow( - column( - width = 3, - checkboxInput( - "rep_institute_general", - label = h5("Institute", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - textInput( - "mst_institute_general_select", - "" - ) - ) - ), - fluidRow( - column( - width = 3, - checkboxInput( - "rep_comm_general", - label = h5("Comment", style = "color:black;") - ) - ), - column( - width = 8, - textAreaInput( - inputId = "mst_comm_general_select", - label = "", - width = "100%", - height = "60px", - cols = NULL, - rows = NULL, - placeholder = NULL, - resize = "vertical" - ) - ) - ) - ) - ), - hr(), - fluidRow( - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Isolate Table') - ) - ) - ), - column( - width = 3, - align = "left", - checkboxInput( - "rep_entrytable", - label = "", - value = TRUE - ) - ), - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Include Plot') - ) - ) - ), - column( - width = 1, - align = "left", - checkboxInput( - "rep_plot_report", - label = "", - value = TRUE - ) - ) - ), - fluidRow( - column( - width = 6, - align = "left", - div( - class = "rep_tab_sel", - pickerInput("select_rep_tab", - label = "", - choices = names(DB$meta)[-2], - selected = c("Assembly Name", "Scheme", "Isolation Date", - "Host", "Country", "City", extra_var), - options = list( - size = 10, - `actions-box` = TRUE, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE) - ) - ) - ), - hr(), - fluidRow( - column( - width = 4, - align = "left", - HTML( - paste( - tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Analysis Parameter') - ) - ) - ), - column( - width = 3, - align = "left", - checkboxInput( - "rep_analysis", - label = "", - value = TRUE - ) - ) - ), - fluidRow( - column( - width = 6, - align = "left", - fluidRow( - column( - width = 4, - checkboxInput( - "rep_cgmlst_analysis", - label = h5("Scheme", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic', DB$scheme) - ) - ) - ) - ), - fluidRow( - column( - width = 4, - checkboxInput( - "rep_tree_analysis", - label = h5("Tree", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 8, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic', input$tree_algo) - ) - ) - ) - ) - ), - column( - width = 6, - align = "left", - fluidRow( - column(2), - column( - width = 4, - checkboxInput( - "rep_distance", - label = h5("Distance", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 5, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic', 'Hamming') - ) - ) - ) - ), - fluidRow( - column(2), - column( - width = 4, - checkboxInput( - "rep_version", - label = h5("Version", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 5, - align = "right", - HTML( - paste( - tags$span(style='color:black; position: relative; top: 17px; font-style: italic', phylotraceVersion) - ) - ) - ) - ) - ) - ), - fluidRow( - column( - width = 3, - align = "left", - checkboxInput( - "rep_missval", - label = h5("NA handling", style = "color:black;"), - value = TRUE - ) - ), - column( - width = 7, - align = "right", - HTML( - paste( - tags$span(style='color: black; position: relative; top: 17px; font-style: italic; right: 35px;', na_handling) - ) - ) - ) - ) - ) - ), - title = "cgMLST Report Generation", - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - downloadBttn( - "download_report", - style = "simple", - label = "Save", - size = "sm", - icon = icon("download") - ) - ) - ) - ) - } else { - show_toast( - title = "No tree created", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - - observe({ - if(!is.null(input$rep_general)) { - if(isFALSE(input$rep_general)) { - shinyjs::disable('rep_date_general') - shinyjs::disable('rep_operator_general') - shinyjs::disable('rep_institute_general') - shinyjs::disable('rep_comm_general') - shinyjs::disable('mst_date_general_select') - shinyjs::disable('mst_operator_general_select') - shinyjs::disable('mst_institute_general_select') - shinyjs::disable('mst_comm_general_select') - } else { - shinyjs::enable('rep_date_general') - shinyjs::enable('rep_operator_general') - shinyjs::enable('rep_institute_general') - shinyjs::enable('rep_comm_general') - shinyjs::enable('mst_date_general_select') - shinyjs::enable('mst_operator_general_select') - shinyjs::enable('mst_institute_general_select') - shinyjs::enable('mst_comm_general_select') - } - } - - if(!is.null(input$rep_analysis)) { - if(isFALSE(input$rep_analysis)) { - shinyjs::disable('rep_cgmlst_analysis') - shinyjs::disable('rep_tree_analysis') - shinyjs::disable('rep_distance') - shinyjs::disable('rep_missval') - shinyjs::disable('rep_version') - } else { - shinyjs::enable('rep_cgmlst_analysis') - shinyjs::enable('rep_tree_analysis') - shinyjs::enable('rep_distance') - shinyjs::enable('rep_missval') - shinyjs::enable('rep_version') - } - } - - if(length(input$select_rep_tab) > 0) { - updateCheckboxInput(session, "rep_entrytable", value = TRUE) - } else { - updateCheckboxInput(session, "rep_entrytable", value = FALSE) - } - }) - - ### Save Report ---- - - #### Get Report elements ---- - - observe({ - if(!is.null(DB$data)){ - if(!is.null(input$tree_algo)) { - req(c(input$rep_entrytable, input$rep_general, - input$rep_date_general, input$rep_operator_general, - input$rep_institute_general, input$rep_comm_general, - input$rep_analysis, input$rep_cgmlst_analysis, - input$rep_tree_analysis, input$rep_distance, - input$rep_missval, input$rep_version, - input$rep_plot_report, input$select_rep_tab)) - Report$report_df <- data.frame(Element = c("entry_table", "general_show", - "general_date", "operator", - "institute", "comment", - "analysis_show", "scheme", - "tree", "distance", "na_handling", "version", - "plot"), - Include = c(input$rep_entrytable, input$rep_general, - input$rep_date_general, input$rep_operator_general, - input$rep_institute_general, input$rep_comm_general, - input$rep_analysis, input$rep_cgmlst_analysis, - input$rep_tree_analysis, input$rep_distance, - input$rep_missval, input$rep_version, - input$rep_plot_report)) - } - } - }) - - #### Get Report values ---- - - observeEvent(input$create_tree, { - if(input$tree_algo == "Minimum-Spanning") { - Report$report_list_mst <- list(entry_table = DB$meta_true, - scheme = DB$schemeinfo, - tree = input$tree_algo, - na_handling = if(anyNA(DB$allelic_profile_true)){input$na_handling} else {NULL}, - distance = "Hamming Distances", - version = c(phylotraceVersion, "2.5.1"), - plot = "MST") - } else if(input$tree_algo == "Neighbour-Joining") { - Report$report_list_nj <- list(entry_table = DB$meta_true, - scheme = DB$schemeinfo, - tree = input$tree_algo, - na_handling = input$na_handling, - distance = "Hamming Distances", - version = c(phylotraceVersion, "2.5.1"), - plot = "NJ") - } else { - Report$report_list_upgma <- list(entry_table = DB$meta_true, - scheme = DB$schemeinfo, - tree = input$tree_algo, - na_handling = input$na_handling, - distance = "Hamming Distances", - version = c(phylotraceVersion, "2.5.1"), - plot = "UPGMA") - } - }) - - # Save plot for Report - plot.report <- reactive({ - if(input$tree_algo == "Neighbour-Joining") { - jpeg(paste0(getwd(), "/Report/NJ.jpeg"), width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) - print(nj_tree()) - dev.off() - } else if(input$tree_algo == "UPGMA") { - jpeg(paste0(getwd(), "/Report/UPGMA.jpeg"), width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) - print(upgma_tree()) - dev.off() - } else if (input$tree_algo == "Minimum-Spanning") { - shinyjs::runjs("mstReport();") - decoded_data <- base64enc::base64decode(input$canvas_data) - writeBin(decoded_data, paste0(getwd(), "/Report/MST.jpg")) - } - }) - - #### Event Save Report ---- - output$download_report <- downloadHandler( - filename = function() { - if(input$tree_algo == "Minimum-Spanning") { - paste0("MST_Report_", Sys.Date(), ".html") - } else if(input$tree_algo == "Neighbour-Joining") { - paste0("NJ_Report_", Sys.Date(), ".html") - } else {paste0("UPGMA_Report_", Sys.Date(), ".html")} - }, - content = function(file) { - if(input$tree_algo == "Minimum-Spanning") { - plot.report() - - report <- c(Report$report_list_mst, - "general_date" = as.character(input$mst_date_general_select), - "operator" = input$mst_operator_general_select, - "institute" = input$mst_institute_general_select, - "comment" = input$mst_comm_general_select, - "report_df" = Report$report_df) - - report[["table_columns"]] <- input$select_rep_tab - - # Save data to an RDS file if any elements were selected - if (!is.null(report)) { - - log_print("Creating MST report") - - saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) - - rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) - - file.copy(paste0(getwd(), "/Report/Report.html"), file) - } else { - log_print("Creating MST report failed (report is null)") - } - } else if(input$tree_algo == "Neighbour-Joining") { - plot.report() - report <- c(Report$report_list_nj, - "general_date" = as.character(input$mst_date_general_select), - "operator" = input$mst_operator_general_select, - "institute" = input$mst_institute_general_select, - "comment" = input$mst_comm_general_select, - "report_df" = Report$report_df) - - report[["table_columns"]] <- input$select_rep_tab - - # Save data to an RDS file if any elements were selected - if (!is.null(report)) { - log_print("Creating NJ report") - - saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) - - rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) - - file.copy(paste0(getwd(), "/Report/Report.html"), file) - } else { - log_print("Creating NJ report failed (report is null)") - } - - } else { - plot.report() - report <- c(Report$report_list_upgma, - "general_date" = as.character(input$mst_date_general_select), - "operator" = input$mst_operator_general_select, - "institute" = input$mst_institute_general_select, - "comment" = input$mst_comm_general_select, - "report_df" = Report$report_df) - - report[["table_columns"]] <- input$select_rep_tab - - # Save data to an RDS file if any elements were selected - if (!is.null(report)) { - log_print("Creating UPGMA report") - - saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) - - rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) - - file.copy(paste0(getwd(), "/Report/Report.html"), file) - } else { - log_print("Creating UPGMA report failed (report is null)") - } - - } - removeModal() - } - ) - - - # _______________________ #### - - ## Gene Screening ---- - - ### Render UI Elements ---- - - # Rendering results table - output$gs_results_table <- renderUI({ - req(DB$data) - if(!is.null(Screening$selected_isolate)) { - if(length(Screening$selected_isolate) > 0) { - fluidRow( - div(class = "loci_table", - DT::dataTableOutput("gs_profile_table")), - br(), - HTML( - paste0("", - 'RSL = Reference Sequence Length  |  ', - '%CRS = % Coverage of Reference Sequence  |  ', - '%IRS = % Identity to Reference Sequence  |  ', - 'ACS = Accession of Closest Sequence  |  ', - 'NCS = Name of Closest Sequence') - - ) - ) - } else { - fluidRow( - br(), br(), - p( - HTML( - paste0("", - 'Select entry from the table to display resistance profile') - - ) - ) - ) - } - } else { - fluidRow( - br(), br(), - p( - HTML( - paste0("", - 'Select entry from the table to display resistance profile') - - ) - ) - ) - } - }) - - # Gene screening download button - output$gs_download <- renderUI({ - req(DB$data) - if(!is.null(Screening$selected_isolate)) { - if(length(Screening$selected_isolate) > 0) { - fluidRow( - downloadBttn( - "download_resistance_profile", - style = "simple", - label = "Profile Table", - size = "sm", - icon = icon("download"), - color = "primary" - ), - bsTooltip("download_resistance_profile_bttn", - HTML(paste0("Save resistance profile table for
", - Screening$selected_isolate)), - placement = "bottom", trigger = "hover") - ) - } else {NULL} - } else {NULL} - }) - - # Conditionally render table selectiom interface - output$gs_table_selection <- renderUI({ - req(DB$data, input$gs_view) - if(input$gs_view == "Table") { - fluidRow( - column(1), - column( - width = 10, - div(class = "loci_table", - dataTableOutput("gs_isolate_table")) - ) - ) - } else {NULL} - }) - - # Resistance profile table output display - output$gs_profile_display <- renderUI({ - req(DB$data) - if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { - if(input$gs_view == "Table") { - column( - width = 10, - hr(), - fluidRow( - column( - width = 4, - p( - HTML( - paste0("", - "Gene Screening Results
", - "", - "Comprising genes for resistance, virulence, stress, etc.") - ) - ) - ), - column( - width = 4, - uiOutput("gs_download") - ) - ), - br(), - uiOutput("gs_results_table") - ) - } else { - column( - width = 10, - fluidRow( - column( - width = 4, - p( - HTML( - paste0("", - "Gene Screening Results
", - "", - "Comprising genes for resistance, virulence, stress, etc.") - ) - ) - ), - column( - width = 4, - div( - class = "gs-picker", - pickerInput( - "gs_profile_select", - "", - choices = list( - Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] - }, - Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "No")] - }, - `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] - } - ), - choicesOpt = list( - disabled = c( - rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) - ) - ), - options = list( - `live-search` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ) - ) - ) - ), - column( - width = 3, - uiOutput("gs_download") - ) - ), - br(), - uiOutput("gs_results_table") - ) - } - } else {NULL} - }) - - # Screening sidebar - output$screening_sidebar <- renderUI({ - req(DB$data) - if(!is.null(DB$meta_gs)) { - column( - width = 12, - align = "center", - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Toggle View') - ) - ) - ), - radioGroupButtons( - inputId = "gs_view", - choices = c("Picker", "Table"), - selected = "Picker", - checkIcon = list( - yes = icon("square-check"), - no = icon("square") - ) - ), - br() - ) - } else {NULL} - }) - - # Resistance profile table - observe({ - req(DB$meta_gs, Screening$selected_isolate, DB$database, DB$scheme, DB$data) - - if(length(Screening$selected_isolate) > 0 & any(Screening$selected_isolate %in% DB$data$`Assembly ID`)) { - iso_select <- Screening$selected_isolate - iso_path <- file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", - iso_select, "resProfile.tsv") - - res_profile <- read.delim(iso_path) - - colnames(res_profile) <- c( - "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", - "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", - "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", - "Alignment Length", "ACS", "Name of Closest Sequence", "HMM ID", "HMM Description") - - Screening$res_profile <- res_profile %>% - relocate(c("Gene Symbol", "Sequence Name", "Element Subtype", "Class", - "Subclass", "Scope", "Contig ID", "Target Length", "Alignment Length", - "Start", "Stop", "Strand")) - - # Generate gene profile table - output$gs_profile_table <- DT::renderDataTable( - Screening$res_profile, - selection = "single", - rownames= FALSE, - options = list(pageLength = 10, scrollX = TRUE, - autoWidth = TRUE, - columnDefs = list(list(width = '400px', targets = c("Sequence Name", - "Name of Closest Sequence"))), - columnDefs = list(list(width = 'auto', targets = "_all")), - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - )) - ) - } else { - output$gs_profile_table <- NULL - } - }) - - #Resistance profile selection table - observe({ - req(DB$meta, DB$data) - output$gs_isolate_table <- renderDataTable( - select(DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ], -c(3, 4, 10, 11, 12)), - selection = "single", - rownames= FALSE, - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - )) - ) - }) - - observe({ - req(input$screening_res_sel, DB$database, DB$scheme, DB$data) - if(!is.null(Screening$status_df) & - !is.null(input$screening_res_sel) & - !is.null(Screening$status_df$status) & - !is.null(Screening$status_df$isolate)) { - if(length(input$screening_res_sel) > 0) { - if(any(Screening$status_df$isolate == input$screening_res_sel)) { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { - results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", - input$screening_res_sel, "resProfile.tsv")) - - output$screening_table <- renderDataTable( - select(results, c(6, 7, 8, 9, 11)), - selection = "single", - options = list(pageLength = 10, - columnDefs = list(list(searchable = TRUE, - targets = "_all")), - initComplete = DT::JS( - "function(settings, json) {", - "$('th:first-child').css({'border-top-left-radius': '5px'});", - "$('th:last-child').css({'border-top-right-radius': '5px'});", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ), - drawCallback = DT::JS( - "function(settings) {", - "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", - "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", - "}" - ))) - } else {output$screening_table <- NULL} - } - } else { - output$screening_table <- NULL - } - } else { - output$screening_table <- NULL - } - - }) - - # Availablity feedback - output$gene_screening_info <- renderUI({ - req(DB$data) - if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } else { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } - }) - - output$gene_resistance_info <- renderUI({ - req(DB$data) - if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } else { - p( - HTML( - paste( - '', - tags$span(style="color: white; font-size: 15px; position:relative; top:25px", - paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) - ) - ) - ) - } - }) - - # Screening Interface - - output$screening_interface <- renderUI({ - req(DB$data) - if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { - column( - width = 12, - fluidRow( - column(1), - column( - width = 3, - align = "center", - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Isolates for Screening') - ) - ) - ), - if(Screening$picker_status) { - div( - class = "screening_div", - pickerInput( - "screening_select", - "", - choices = list( - Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "No")] - }, - Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] - }, - `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] - } - ), - choicesOpt = list( - disabled = c( - rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), - rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) - ) - ), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - } else { - div( - class = "screening_div", - pickerInput( - "screening_select", - "", - choices = Screening$picker_choices, - selected = Screening$picker_selected, - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - multiple = TRUE - ) - ) - }, - br(), br(), - uiOutput("genome_path_gs") - ), - column( - width = 3, - uiOutput("screening_start") - ), - column( - width = 3, - align = "center", - br(), br(), - uiOutput("screening_result_sel") - ), - column(1) - ), - fluidRow( - column(1), - column( - width = 10, - br(), br(), - uiOutput("screening_result"), - br(), br(), br(), br() - ) - ) - ) - } - }) - - ### Screening Events ---- - - observe({ - req(DB$data, input$gs_view) - if(input$gs_view == "Table") { - meta_gs <- DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ] - Screening$selected_isolate <- meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] - } else if(input$gs_view == "Picker") { - Screening$selected_isolate <- input$gs_profile_select - } - }) - - output$download_resistance_profile <- downloadHandler( - filename = function() { - log_print(paste0("Save resistance profile table ", Screening$selected_isolate, "_Profile.csv")) - - paste0(format(Sys.Date()), "_", Screening$selected_isolate, "_Profile.csv") - }, - content = function(file) { - write.table( - Screening$res_profile, - file, - sep = ";", - row.names = FALSE, - quote = FALSE - ) - } - ) - - # Reset screening - observeEvent(input$screening_reset_bttn, { - log_print("Reset gene screening") - - # reset status file - sapply(Screening$status_df$isolate, remove.screening.status) - - # set feedback variables - Screening$status <- "idle" - Screening$status_df <- NULL - Screening$choices <- NULL - Screening$picker_status <- TRUE - Screening$first_result <- NULL - - # change reactive UI - output$screening_table <- NULL - output$screening_result <- NULL - output$screening_fail <- NULL - - updatePickerInput(session, "screening_select", selected = character(0)) - - # disable isolate picker - shinyjs::runjs("$('#screening_select').prop('disabled', false);") - shinyjs::runjs("$('#screening_select').selectpicker('refresh');") - }) - - # Cancel screening - observeEvent(input$screening_cancel, { - showModal( - modalDialog( - paste0( - "Gene screening is still pending. Stopping this process will cancel the screening." - ), - title = "Reset Multi Typing", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_screening_cancel", "Stop", class = "btn btn-danger") - ) - ) - ) - }) - - observeEvent(input$conf_screening_cancel, { - log_print("Cancelled gene screening") - removeModal() - - show_toast( - title = "Gene Screening Terminated", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - - # terminate screening - system(paste("kill $(pgrep -f 'execute/screening.sh')"), wait = FALSE) - system(paste("killall -TERM tblastn"), wait = FALSE) - - # reset status file - sapply(Screening$status_df$isolate, remove.screening.status) - - # set feedback variables - Screening$status <- "idle" - Screening$status_df <- NULL - Screening$choices <- NULL - Screening$picker_status <- TRUE - Screening$first_result <- NULL - - # change reactive UI - output$screening_table <- NULL - output$screening_result <- NULL - - updatePickerInput(session, "screening_select", selected = character(0)) - - # disable isolate picker - shinyjs::runjs("$('#screening_select').prop('disabled', false);") - shinyjs::runjs("$('#screening_select').selectpicker('refresh');") - }) - - # Get selected assembly - observe({ - req(DB$data, Screening$status) - if (length(input$screening_select) < 1) { - output$genome_path_gs <- renderUI(HTML( - paste("", length(input$screening_select), " isolate(s) queried for screening") - )) - - output$screening_start <- NULL - - } else if (length(input$screening_select) > 0) { - - output$screening_start <- renderUI({ - - fluidRow( - column( - width = 12, - br(), br(), - if(length(input$screening_select) < 1) { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Select Isolate(s) for Screening"))) - ) - ) - } else if(Screening$status == "finished") { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Reset to Perform Screening Again"))) - ), - actionButton( - "screening_reset_bttn", - "Reset", - icon = icon("arrows-rotate") - ), - if(!is.null(Screening$status_df)) { - p( - HTML(paste("", - sum(Screening$status_df$status != "unfinished"), "/", - nrow(Screening$status_df), " Isolate(s) screened")) - ) - } - ) - } else if(Screening$status == "idle") { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Screening Ready"))) - ), - actionButton( - inputId = "screening_start_button", - label = "Start", - icon = icon("circle-play") - ) - ) - } else if(Screening$status == "started") { - column( - width = 12, - align = "center", - p( - HTML(paste( - '', - paste("", - "  Running Screening ..."))) - ), - fluidRow( - column(3), - column( - width = 3, - actionButton( - inputId = "screening_cancel", - label = "Terminate", - icon = icon("ban") - ) - ), - column( - width = 3, - HTML(paste('')) - ) - ), - if(!is.null(Screening$status_df)) { - p( - HTML(paste("", - sum(Screening$status_df$status != "unfinished"), "/", - nrow(Screening$status_df), " isolate(s) screened")) - ) - } - ) - } - ) - ) - }) - } else {NULL} - }) - - #### Running Screening ---- - - observeEvent(input$screening_start_button, { - - if(tail(readLogFile(), 1) != "0") { - show_toast( - title = "Pending Multi Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - log_print("Started gene screening") - - Screening$status <- "started" - Screening$picker_choices <- list( - Unscreened = if (sum(DB$data$Screened == "No") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "No")] - }, - Screened = if (sum(DB$data$Screened == "Yes") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] - }, - `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { - as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) - } else { - DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] - } - ) - Screening$picker_selected <- input$screening_select - Screening$picker_status <- FALSE - - show_toast( - title = "Gene screening started", - type = "success", - position = "bottom-end", - timer = 6000 - ) - - Screening$meta_df <- data.frame(wd = getwd(), - selected = paste( - file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", input$screening_select, - paste0(input$screening_select, ".zip")), - collapse = " "), - species = gsub(" ", "_", DB$scheme)) - - Screening$status_df <- data.frame(isolate = basename(gsub(".zip", "", str_split_1(Screening$meta_df$selected, " "))), - status = "unfinished") - - # Reset screening status - sapply(Screening$status_df$isolate, remove.screening.status) - - saveRDS(Screening$meta_df, paste0(getwd(), "/execute/screening_meta.rds")) - - # Disable pickerInput - shinyjs::delay(200, shinyjs::runjs("$('#screening_select').prop('disabled', true);")) - shinyjs::delay(200, shinyjs::runjs("$('#screening_select').selectpicker('refresh');")) - - # System execution screening.sh - system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) - } - }) - - observe({ - req(DB$data, Screening$status, input$screening_res_sel, Screening$status_df) - if(!is.null(Screening$status_df) & - !is.null(Screening$status_df$status) & - !is.null(Screening$status_df$isolate) & - !is.null(input$screening_res_sel)) { - if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { - if(any(Screening$status_df$isolate == input$screening_res_sel)) { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { - output$screening_result <- renderUI( - column( - width = 12, - hr(), br(), - dataTableOutput("screening_table") - ) - ) - } else { - output$screening_result <- renderUI( - column( - width = 12, - hr(), br(), - verbatimTextOutput("screening_fail") - ) - ) - } - } - } else { - output$screening_result <- NULL - } - } else { - output$screening_result <- NULL - } - }) - - observe({ - req(DB$data, Screening$status, input$screening_res_sel) - if(!is.null(Screening$status_df) & - !is.null(Screening$status_df$status) & - !is.null(Screening$status_df$isolate) & - !is.null(input$screening_res_sel)) { - if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { - if(any(Screening$status_df$isolate == input$screening_res_sel)) { - if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { - output$screening_fail <- renderPrint({ - cat(paste(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), - "Isolates", input$screening_res_sel, "status.txt")),"\n")) - }) - } - } - } else { - output$screening_fail <- NULL - } - } else { - output$screening_fail <- NULL - } - }) - - observe({ - req(DB$data) - if(!is.null(Screening$status)) { - if(Screening$status != "idle") { - - # start status screening for user feedback - check_screening() - - if(isTRUE(Screening$first_result)) { - output$screening_result_sel <- renderUI( - column( - width = 12, - align = "center", - selectInput( - "screening_res_sel", - label = h5("Select Result", style = "color:white; margin-bottom: 28px; margin-top: -10px;"), - choices = "" - ), - if(!is.null(Screening$status_df)) { - p(HTML(paste("", - if(sum(Screening$status_df$status == "success") == 1) { - "1 success   /  " - } else { - paste0(sum(Screening$status_df$status == "success"), " successes   /  ") - }, - if(sum(Screening$status_df$status == "fail") == 1) { - "1 failure" - } else { - paste0(sum(Screening$status_df$status == "fail"), " failures") - }))) - } - ) - ) - - Screening$first_result <- FALSE - } - } else if(Screening$status == "idle") { - output$screening_result_sel <- NULL - } - } - }) - - check_screening <- reactive({ - invalidateLater(500, session) - - req(Screening$status_df) - - if(Screening$status == "started") { - - Screening$status_df$status <- sapply(Screening$status_df$isolate, check_status) - - if(any("unfinished" != Screening$status_df$status) & - !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status != "unfinished")])) { - - status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] - - Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | - Screening$status_df$status == "fail")] - - if(sum(Screening$status_df$status != "unfinished") > 0) { - if(is.null(Screening$first_result)) { - Screening$first_result <- TRUE - } - } - - if(tail(status_df$status, 1) == "success") { - - # Changing "Screened" metadata variable in database - Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - Database[["Typing"]]$Screened[which(Database[["Typing"]]["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" - - saveRDS(Database, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) - - DB$data$Screened[which(DB$data["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" - - DB$meta_gs <- select(DB$data, c(1, 3:13)) - DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) - DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] - - show_toast( - title = paste("Successful screening of", tail(Screening$choices, 1)), - type = "success", - position = "bottom-end", - timer = 6000) - - updateSelectInput(session = session, - inputId = "screening_res_sel", - choices = Screening$choices, - selected = tail(Screening$choices, 1)) - - } else if(tail(status_df$status, 1) == "fail") { - - show_toast( - title = paste("Failed screening of", tail(status_df$isolate, 1)), - type = "error", - position = "bottom-end", - timer = 6000) - - updateSelectInput(session = session, - inputId = "screening_res_sel", - choices = Screening$choices, - selected = tail(Screening$choices, 1)) - } - - if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - Screening$status <- "finished" - } - } else { - if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - Screening$status <- "finished" - } - } - - if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { - Screening$status <- "finished" - } - } - }) - - - # _______________________ #### - - ## Typing ---- - - # Render Single/Multi Switch - - readLogFile <- reactive({ - invalidateLater(5000, session) - readLines(paste0(getwd(), "/logs/script_log.txt")) - }) - - # Render sidebar dependent on data presence - # No sidebar - output$typing_sidebar <- renderUI({ - if(!is.null(DB$exist)) { - if(DB$exist) { - NULL - } else { - column( - width = 12, - align = "center", - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Typing Mode') - ) - ) - ), - radioGroupButtons( - inputId = "typing_mode", - choices = c("Single", "Multi"), - selected = "Single", - checkIcon = list( - yes = icon("square-check"), - no = icon("square") - ) - ), - br() - ) - } - } - - }) - - # No db typing message - output$typing_no_db <- renderUI({ - if(!is.null(DB$exist)) { - if(DB$exist) { - column( - width = 4, - align = "left", - br(), - br(), - br(), - br(), - p( - HTML( - paste0( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 50px', 'To initiate allelic typing, a cgMLST scheme must be downloaded first.' - ) - ) - ) - ) - ) - } else {NULL} - } else {NULL} - }) - - ### Single Typing ---- - - #### Render UI Elements ---- - - # Render single typing naming issues - output$single_select_issues <- renderUI({ - req(input$assembly_id) - - if(nchar(trimws(input$assembly_id)) < 1) { - ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) - } else { - ass_id <- trimws(input$assembly_id) - } - - if(ass_id %in% unlist(DB$data["Assembly ID"])) { - HTML(paste( - '', - paste("", - "  Assembly ID already present in database."))) - } else if (ass_id == "") { - HTML(paste( - '', - paste("", - "  Empty Assembly ID."))) - } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { - HTML(paste( - '', - paste("", - "  Invalid Assembly ID. Avoid special characters."))) - } else if(grepl(" ", ass_id)) { - HTML(paste( - '', - paste("", - "  Invalid Assembly ID. Avoid empty spaces."))) - } else {HTML(paste( - '', - paste("", - "  Assembly ID compatible with local database.")))} - }) - - # Render Typing Results if finished - observe({ - if(Typing$progress_format_end == 999999) { - if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { - if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { - output$typing_result_table <- renderRHandsontable({ - Typing$typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) - Typing$typing_result_table <- mutate_all(Typing$typing_result_table, as.character) - if(nrow(Typing$typing_result_table) > 0) { - if(nrow(Typing$typing_result_table) > 15) { - rhandsontable(Typing$typing_result_table, rowHeaders = NULL, - stretchH = "all", height = 500, readOnly = TRUE, - contextMenu = FALSE) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - } else { - rhandsontable(Typing$typing_result_table, rowHeaders = NULL, - stretchH = "all", readOnly = TRUE, - contextMenu = FALSE,) %>% - hot_cols(columnSorting = TRUE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - } - } - }) - - output$single_typing_results <- renderUI({ - result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) - number_events <- nrow(result_table) - - n_new <- length(grep("New Variant", result_table$Event)) - - n_missing <- number_events - n_new - - # Show results table only if successful typing - if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { - if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { - if(number_events > 0) { - column( - width = 12, - HTML(paste("", - length(Typing$scheme_loci_f) - number_events, - "loci were assigned a variant from local scheme.")), - br(), - HTML(paste("", - n_missing, - if(n_missing == 1) " locus not assigned (NA)." else " loci not assigned (NA).")), - br(), - HTML(paste("", - n_new, - if(n_new == 1) " locus with new variant." else " loci with new variants.")), - br(), br(), - rHandsontableOutput("typing_result_table") - ) - } else { - column( - width = 12, - HTML(paste("", - length(Typing$scheme_loci_f), - "successfully assigned from local scheme.")) - ) - } - } - } - }) - - } else { - - output$single_typing_results <- NULL - - } - } else { - output$single_typing_results <- NULL - } - } - - }) - - # Render Initiate Typing UI - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - - # Render Declare Metadata UI - - observe({ - if (nrow(Typing$single_path) < 1) { - output$genome_path <- renderUI(HTML( - paste("", "No file selected.") - )) - - # dont show subsequent metadata declaration and typing start UI - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - } else if (nrow(Typing$single_path) > 0) { - - if (str_detect(str_sub(Typing$single_path$name, start = -6), ".fasta") | - str_detect(str_sub(Typing$single_path$name, start = -6), ".fna") | - str_detect(str_sub(Typing$single_path$name, start = -6), ".fa")) { - - # Render selected assembly path - output$genome_path <- renderUI({ - HTML( - paste( - "", - as.character(Typing$single_path$name) - ) - ) - }) - - # Render metadata declaration box - output$metadata_single_box <- renderUI({ - - # Render placeholder - updateTextInput(session, "assembly_id", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) - updateTextInput(session, "assembly_name", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) - - column( - width = 3, - align = "center", - br(), br(), - h3(p("Declare Metadata"), style = "color:white; margin-left:-40px"), - br(), br(), - div( - class = "multi_meta_box", - box( - solidHeader = TRUE, - status = "primary", - width = "90%", - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("assembly_id", - value = "", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 12, - uiOutput("single_select_issues") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("assembly_name", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - dateInput("append_isodate", - label = "", - width = "80%", - max = Sys.Date()) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_host", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table_country", - pickerInput( - "append_country", - label = "", - choices = list("Common" = sel_countries, - "All Countries" = country_names), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "90%" - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput( - "append_city", - label = "", - width = "80%" - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - actionButton( - inputId = "conf_meta_single", - label = "Confirm" - ), - br() - ) - ), - br() - ) - ) - ) - }) - } else { - show_toast( - title = "Wrong file type (only fasta/fna/fa)", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - } - }) - - # Get genome datapath - - observe({ - # Get selected Genome in Single Mode - shinyFileChoose(input, - "genome_file", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - Typing$single_path <- parseFilePaths(roots = c(Home = path_home(), Root = "/"), input$genome_file) - - }) - - #### Run blat ---- - - observeEvent(input$typing_start, { - - log_print("Input typing_start") - - if(tail(readLogFile(), 1) != "0") { - show_toast( - title = "Pending Multi Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if (Screening$status == "started") { - show_toast( - title = "Pending Gene Screening", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - if(!is.null(DB$data)) { - if(sum(apply(DB$data, 1, anyNA)) >= 1) { - DB$no_na_switch <- TRUE - } else { - DB$no_na_switch <- FALSE - } - } - - # Activate entry detection - DB$check_new_entries <- TRUE - - Typing$single_end <- FALSE - - Typing$progress_format_start <- 0 - Typing$progress_format_end <- 0 - - # Remove Initiate Typing UI - output$initiate_typing_ui <- NULL - output$metadata_single_box <- NULL - output$start_typing_ui <- NULL - - # status feedback - Typing$status <- "Processing" - - # Locate folder containing cgMLST scheme - search_string <- paste0(gsub(" ", "_", DB$scheme), "_alleles") - - scheme_folders <- dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme))) - - if (any(grepl(search_string, scheme_folders))) { - - # reset results file - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - } - - # blat initiate index - scheme_select <- as.character(scheme_folders[which(grepl(search_string, scheme_folders))]) - - show_toast( - title = "Typing Initiated", - type = "success", - position = "bottom-end", - timer = 6000 - ) - - log_print("Initiated single typing") - - ### Run blat Typing - - single_typing_df <- data.frame( - db_path = DB$database, - wd = getwd(), - save = input$save_assembly_st, - scheme = paste0(gsub(" ", "_", DB$scheme)), - genome = Typing$single_path$datapath, - alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", search_string) - ) - - saveRDS(single_typing_df, "execute/single_typing_df.rds") - - # Execute single typing script - system(paste("bash", paste0(getwd(), "/execute/single_typing.sh")), - wait = FALSE) - - scheme_loci <- list.files(path = scheme_select, full.names = TRUE) - - # Filter the files that have FASTA extensions - Typing$scheme_loci_f <- - scheme_loci[grep("\\.(fasta|fa|fna)$", scheme_loci, ignore.case = TRUE)] - - output$single_typing_progress <- renderUI({ - fluidRow( - br(), br(), - column(width = 1), - column( - width = 3, - h3(p("Pending Single Typing ..."), style = "color:white") - ), - br(), br(), br(), - fluidRow( - column(width = 1), - column( - width = 4, - br(), br(), br(), - fluidRow( - column( - width = 12, - uiOutput("reset_single_typing"), - HTML( - paste( - "", - as.character(Typing$single_path$name) - ) - ), - br(), br(), - progressBar( - "progress_bar", - value = 0, - display_pct = TRUE, - title = "" - ) - ) - ), - fluidRow( - column( - width = 12, - uiOutput("typing_formatting"), - uiOutput("typing_fin") - ) - ) - ), - column(1), - column( - width = 5, - br(), br(), br(), - uiOutput("single_typing_results") - ) - ) - ) - }) - } else { - log_print("Folder containing cgMLST alleles not in working directory") - - show_alert( - title = "Error", - text = paste0( - "Folder containing cgMLST alleles not in working directory.", - "\n", - "Download cgMLST Scheme for selected Organism first." - ), - type = "error" - ) - } - } - }) - - # Function to update Progress Bar - update <- reactive({ - invalidateLater(3000, session) - - # write progress in process tracker - cat( - c(length(list.files(paste0(getwd(), "/execute/blat_single/results"))), - readLines(paste0(getwd(), "/logs/progress.txt"))[-1]), - file = paste0(getwd(), "/logs/progress.txt"), - sep = "\n" - ) - - progress <- readLines(paste0(getwd(), "/logs/progress.txt")) - - # if typing with blat is finished -> "attaching" phase started - if(!is.na(progress[1])) { - if(!is.na(progress[2])) { - if(progress[2] == "888888") { - Typing$progress_format_start <- progress[2] - Typing$pending_format <- progress[2] - Typing$status <- "Attaching" - } - } - # "attaching" phase completed - if(!is.na(progress[3])) { - if(progress[3] == "999999") { - Typing$progress_format_end <- progress[3] - Typing$entry_added <- progress[3] - Typing$status <- "Finalized" - } - } - Typing$progress <- as.numeric(progress[1]) - floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) - } else { - floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) - } - }) - - # Observe Typing Progress - observe({ - - if(readLogFile()[1] == "0") { - # Update Progress Bar - updateProgressBar( - session = session, - id = "progress_bar", - value = update(), - total = 100, - title = paste0(as.character(Typing$progress), "/", length(Typing$scheme_loci_f), " loci screened") - ) - } - - if (Typing$progress_format_start == 888888) { - output$typing_formatting <- renderUI({ - column( - width = 12, - align = "center", - br(), - fluidRow( - column( - width = 6, - HTML(paste("", "Transforming data ...")) - ), - column( - width = 3, - align = "left", - HTML(paste('')) - ) - ) - ) - }) - } else { - output$typing_formatting <- NULL - } - - # Render when finalized - if (Typing$progress_format_end == 999999) { - - output$typing_formatting <- NULL - - output$typing_fin <- renderUI({ - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { - if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { - req(Typing$scheme_loci_f, Typing$typing_result_table) - if(sum(Typing$typing_result_table$Event != "New Variant") > (0.5 * length(Typing$scheme_loci_f))){ - HTML( - paste("", - sub(".*Successful", "Finished", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), - paste("", "Warning: Isolate contains large number of failed allele assignments."), - paste("", "Reset to start another typing process."), - sep = '
\n')) - } else { - HTML(paste("", - sub(".*Successful", "Successful", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), - "Reset to start another typing process.", sep = '
')) - } - } else { - HTML(paste("", - sub(".*typing", "Typing", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), - "Reset to start another typing process.", sep = '
')) - } - }, - br(), br(), - actionButton( - "reset_single_typing", - "Reset", - icon = icon("arrows-rotate") - ) - ) - ) - }) - } else { - output$typing_fin <- NULL - output$single_typing_results <- NULL - } - - }) - - #### Declare Metadata ---- - - observeEvent(input$conf_meta_single, { - - if(nchar(trimws(input$assembly_id)) < 1) { - ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) - } else { - ass_id <- trimws(input$assembly_id) - } - - if(nchar(trimws(input$assembly_name)) < 1) { - ass_name <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) - } else { - ass_name <- trimws(input$assembly_name) - } - - if(ass_id %in% unlist(DB$data["Assembly ID"])) { - show_toast( - title = "Assembly ID already present", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (isFALSE(Typing$reload)) { - show_toast( - title = "Reload Database first", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if (ass_id == "") { - show_toast( - title = "Empty Assembly ID", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { - show_toast( - title = "Invalid Assembly ID. No special characters allowed: ()/\\:*?\"<>|", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if(grepl(" ", ass_id)) { - show_toast( - title = "Empty spaces in Assembly ID not allowed", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if(Screening$status == "started") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - log_print("Single typing metadata confirmed") - - meta_info <- data.frame(assembly_id = ass_id, - assembly_name = ass_name, - cgmlst_typing = DB$scheme, - append_isodate = input$append_isodate, - append_host = trimws(input$append_host), - append_country = trimws(input$append_country), - append_city = trimws(input$append_city), - append_analysisdate = Sys.Date(), - db_directory = getwd()) - - saveRDS(meta_info, paste0( - getwd(), - "/execute/meta_info_single.rds" - )) - - show_toast( - title = "Metadata declared", - type = "success", - position = "bottom-end", - timer = 3000 - ) - - # Render Start Typing UI - output$start_typing_ui <- renderUI({ - div( - class = "multi_start_col", - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Start Typing"), style = "color:white"), - br(), - br(), - HTML( - paste( - "", - "Typing by ", - DB$scheme, - " scheme." - ) - ), - br(), br(), br(), br(), - div( - class = "save-assembly", - materialSwitch( - "save_assembly_st", - h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), - value = TRUE, - right = TRUE) - ), - HTML( - paste( - "", - "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." - ) - ), - br(), br(), br(), br(), - actionButton( - inputId = "typing_start", - label = "Start", - icon = icon("circle-play") - ) - ) - ) - }) - } - }) - - #### Events Single Typing ---- - - observeEvent(input$reset_single_typing, { - log_print("Reset single typing") - - Typing$status <- "Inactive" - - Typing$progress <- 0 - - Typing$progress_format <- 900000 - - output$single_typing_progress <- NULL - - output$typing_fin <- NULL - - output$single_typing_results <- NULL - - output$typing_formatting <- NULL - - Typing$single_path <- data.frame() - - # reset results file - if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { - unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) - # Resetting single typing progress logfile bar - con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") - - cat("0\n", file = con) - - close(con) - } - - output$initiate_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), - br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyFilesButton( - "genome_file", - "Browse" , - icon = icon("file"), - title = "Select the assembly in .fasta/.fna/.fa format:", - multiple = FALSE, - buttonType = "default", - class = NULL, - root = path_home() - ), - br(), - br(), - uiOutput("genome_path"), - br() - ) - ) - ) - }) - }) - - # Notification for finalized Single typing - Typing$single_end <- TRUE - Typing$progress_format_end <- 0 - - observe({ - if(Typing$single_end == FALSE) { - if (Typing$progress_format_end == 999999) { - show_toast( - title = "Single Typing finalized", - type = "success", - position = "bottom-end", - timer = 8000 - ) - Typing$single_end <- TRUE - } - } - }) - - ### Multi Typing ---- - - #### Render Multi Typing UI Elements ---- - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - # Render selection info - output$multi_select_info <- renderUI({ - - if(!is.null(Typing$multi_path)) { - if(length(Typing$multi_path) < 1) { - HTML(paste("", - "No files selected.")) - } else { - HTML(paste("", - sum(hot_to_r(input$multi_select_table)$Include == TRUE), - " files selected.")) - } - } - }) - - # Render multi selection table issues - output$multi_select_issues <- renderUI({ - req(Typing$multi_sel_table, input$multi_select_table) - if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & - any(duplicated(hot_to_r(input$multi_select_table)$Files))){ - HTML( - paste( - paste("", - "Some name(s) are already present in local database.
"), - paste("", - "Duplicated name(s).
") - ) - ) - } else if (any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & - !any(duplicated(hot_to_r(input$multi_select_table)$Files))) { - HTML( - paste("", - "Some name(s) are already present in local database.
") - ) - } else if (!any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & - any(duplicated(hot_to_r(input$multi_select_table)$Files))) { - HTML( - paste("", - "Duplicated name(s).
") - ) - } - }) - - output$multi_select_issue_info <- renderUI({ - req(Typing$multi_sel_table, input$multi_select_table) - - multi_select_table <- hot_to_r(input$multi_select_table) - - if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | - any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)])) | - any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - - if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - - if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | - any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - HTML(paste( - paste( - '', - paste("", - " Rename highlighted isolates or deselect them.
")), - paste( - '', - paste("", - " Filename(s) contain(s) empty spaces.")) - )) - } else { - HTML(paste( - '', - paste("", - " Filename(s) contain(s) empty spaces."))) - } - } else { - HTML(paste( - '', - paste("", - " Rename highlighted isolates or deselect them."))) - } - } else { - HTML(paste( - '', - paste("", - " Files ready for allelic typing."))) - } - }) - - # Render Metadata Select Box after Folder selection - observe({ - if(!is.null(Typing$multi_sel_table)) { - if (nrow(Typing$multi_sel_table) > 0) { - - output$multi_select_tab_ctrls <- renderUI( - fluidRow( - column(1), - column( - width = 2, - align = "left", - actionButton( - "sel_all_mt", - "All", - icon = icon("check") - ) - ), - column( - width = 2, - align = "left", - actionButton( - "desel_all_mt", - "None", - icon = icon("xmark") - ) - ), - column(2), - column( - width = 5, - align = "right", - br(), - uiOutput("multi_select_issues") - ) - ) - ) - - output$metadata_multi_box <- renderUI({ - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Declare Metadata"), style = "color:white;margin-left:-40px"), - br(), br(), - div( - class = "multi_meta_box", - box( - solidHeader = TRUE, - status = "primary", - width = "90%", - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - dateInput("append_isodate_multi", - label = "", - width = "80%", - max = Sys.Date()) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_host_multi", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table_country", - pickerInput( - "append_country_multi", - label = "", - choices = list("Common" = sel_countries, - "All Countries" = country_names), - options = list( - `live-search` = TRUE, - `actions-box` = TRUE, - size = 10, - style = "background-color: white; border-radius: 5px;" - ), - width = "90%" - ) - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - div( - class = "append_table", - textInput("append_city_multi", - label = "", - width = "80%") - ) - ) - ), - fluidRow( - column( - width = 5, - align = "left", - h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") - ), - column( - width = 7, - align = "left", - h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") - ) - ), - fluidRow( - column( - width = 12, - align = "center", - br(), br(), - actionButton( - inputId = "conf_meta_multi", - label = "Confirm" - ), - br(), br(), - uiOutput("multi_select_issue_info") - ) - ) - ) - ) - ) - }) - } else { - output$metadata_multi_box <- NULL - } - } - }) - - # Check if ongoing Multi Typing - Render accordingly - observe({ - # Get selected Genome in Multi Mode - shinyDirChoose(input, - "genome_file_multi", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - - Typing$multi_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi) - - files_selected <- list.files(as.character(Typing$multi_path)) - Typing$files_filtered <- files_selected[which(!endsWith(files_selected, ".gz") & - grepl("\\.fasta|\\.fna|\\.fa", files_selected))] - - Typing$multi_sel_table <- data.frame( - Include = rep(TRUE, length(Typing$files_filtered)), - Files = gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", - Typing$files_filtered), - Type = sub(".*(\\.fasta|\\.fasta\\.gz|\\.fna|\\.fna\\.gz|\\.fa|\\.fa\\.gz)$", - "\\1", Typing$files_filtered, perl = F)) - - if(nrow(Typing$multi_sel_table) > 0) { - output$multi_select_tab_ctrls <- renderUI( - fluidRow( - column(1), - column( - width = 2, - align = "left", - actionButton( - "sel_all_mt", - "All", - icon = icon("check") - ) - ), - column( - width = 2, - align = "left", - actionButton( - "desel_all_mt", - "None", - icon = icon("xmark") - ) - ), - column(2), - column( - width = 5, - align = "right", - br(), - uiOutput("multi_select_issues") - ) - ) - ) - } else { - output$multi_select_tab_ctrls <- NULL - } - - if(between(nrow(Typing$multi_sel_table), 1, 15)) { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", contextMenu = FALSE - ) %>% - hot_cols(columnSorting = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { - var hot = this.hot; - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - var highlightInvalidAndDuplicates = function(invalidValues) { - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - // Find all duplicate values - for (var i = 0; i < columnData.length; i++) { - var value = columnData[i]; - if (value !== null && value !== undefined) { - if (duplicates[value]) { - duplicates[value].push(i); - } else { - duplicates[value] = [i]; - } - } - } - - // Reset all cell backgrounds in the column - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - if (cell) { - cell.style.background = 'white'; - } - } - - // Highlight duplicates and invalid values - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - var value = columnData[i]; - if (cell) { - if (invalidValues.includes(value)) { - cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values - } else if (duplicates[value] && duplicates[value].length > 1) { - cell.style.background = '#FF7334'; // Highlight color for duplicates - } - } - } - }; - - var changefn = function(changes, source) { - if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { - highlightInvalidAndDuplicates(%s); - } - }; - - hot.addHook('afterChange', changefn); - hot.addHook('afterLoadData', function() { - highlightInvalidAndDuplicates(%s); - }); - hot.addHook('afterRender', function() { - highlightInvalidAndDuplicates(%s); - }); - - highlightInvalidAndDuplicates(%s); // Initial highlight on load - - Shiny.addCustomMessageHandler('setColumnValue', function(message) { - var colData = hot.getDataAtCol(0); - for (var i = 0; i < colData.length; i++) { - hot.setDataAtCell(i, 0, message.value); - } - hot.render(); // Re-render the table - }); - }", - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()))) - }) - - } else if(nrow(Typing$multi_sel_table) > 15) { - output$multi_select_table <- renderRHandsontable({ - rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, - stretchH = "all", height = 500, - contextMenu = FALSE - ) %>% - hot_cols(columnSorting = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(2, - readOnly = FALSE, - valign = "htBottom") %>% - hot_col(3, readOnly = TRUE) %>% - hot_col(1, - halign = "htCenter", - valign = "htTop", - colWidths = 60) - - htmlwidgets::onRender(rht, sprintf( - "function(el, x) { - var hot = this.hot; - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - var highlightInvalidAndDuplicates = function(invalidValues) { - - var columnData = hot.getDataAtCol(1); // Change column index if needed - var duplicates = {}; - - // Find all duplicate values - for (var i = 0; i < columnData.length; i++) { - var value = columnData[i]; - if (value !== null && value !== undefined) { - if (duplicates[value]) { - duplicates[value].push(i); - } else { - duplicates[value] = [i]; - } - } - } - - // Reset all cell backgrounds in the column - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - if (cell) { - cell.style.background = 'white'; - } - } - - // Highlight duplicates and invalid values - for (var i = 0; i < columnData.length; i++) { - var cell = hot.getCell(i, 1); // Change column index if needed - var value = columnData[i]; - if (cell) { - if (invalidValues.includes(value)) { - cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values - } else if (duplicates[value] && duplicates[value].length > 1) { - cell.style.background = '#FF7334'; // Highlight color for duplicates - } - } - } - }; - - var changefn = function(changes, source) { - if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { - highlightInvalidAndDuplicates(%s); - } - }; - - hot.addHook('afterChange', changefn); - hot.addHook('afterLoadData', function() { - highlightInvalidAndDuplicates(%s); - }); - hot.addHook('afterRender', function() { - highlightInvalidAndDuplicates(%s); - }); - - highlightInvalidAndDuplicates(%s); // Initial highlight on load - - Shiny.addCustomMessageHandler('setColumnValue', function(message) { - var colData = hot.getDataAtCol(0); - for (var i = 0; i < colData.length; i++) { - hot.setDataAtCell(i, 0, message.value); - } - hot.render(); // Re-render the table - }); - }", - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()), - jsonlite::toJSON(dupl_mult_id()))) - - }) - - } else { - output$multi_select_table <- NULL - } - }) - - observeEvent(input$conf_meta_multi, { - - multi_select_table <- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] - - if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", multi_select_table$Files)) %in% unlist(DB$data["Assembly ID"]))) { - show_toast( - title = "Assembly ID(s) already present", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (any(duplicated(multi_select_table$Files))) { - show_toast( - title = "Duplicated filename(s)", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (any(multi_select_table$Files == "")) { - show_toast( - title = "Empty filename(s)", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (any(grepl("[()/\\:*?\"<>|]", multi_select_table$Files))) { - show_toast( - title = "Invalid filename(s). No special characters allowed: ()/\\:*?\"<>|", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (!any(multi_select_table$Include == TRUE)) { - show_toast( - title = "No files selected", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { - show_toast( - title = "Empty spaces in filename(s) not allowed", - type = "error", - position = "bottom-end", - timer = 3000 - ) - } else if (isFALSE(Typing$reload)) { - show_toast( - title = "Reload Database first", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if(Screening$status == "started") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - - log_print("Multi typing metadata confirmed") - - meta_info <- data.frame(cgmlst_typing = DB$scheme, - append_isodate = trimws(input$append_isodate_multi), - append_host = trimws(input$append_host_multi), - append_country = trimws(input$append_country_multi), - append_city = trimws(input$append_city_multi), - append_analysisdate = Sys.Date(), - db_directory = getwd()) - - saveRDS(meta_info, paste0(getwd(), "/execute/meta_info.rds")) - - show_toast( - title = "Metadata declared", - type = "success", - position = "bottom-end", - timer = 3000 - ) - - output$start_multi_typing_ui <- renderUI({ - div( - class = "multi_start_col", - column( - width = 3, - align = "center", - br(), - br(), - h3(p("Start Typing"), style = "color:white"), - br(), - br(), - HTML( - paste( - "", - "Typing by ", - DB$scheme, - " scheme." - ) - ), - br(), br(), br(), br(), - div( - class = "save-assembly", - materialSwitch( - "save_assembly_mt", - h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), - value = TRUE, - right = TRUE) - ), - HTML( - paste( - "", - "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." - ) - ), - br(), br(), br(), br(), - actionButton( - "start_typ_multi", - "Start", - icon = icon("circle-play") - ) - ) - ) - }) - } - }) - - #### Events Multi Typing ---- - - observeEvent(input$sel_all_mt, { - session$sendCustomMessage(type = "setColumnValue", message = list(value = TRUE)) - }) - - observeEvent(input$desel_all_mt, { - session$sendCustomMessage(type = "setColumnValue", message = list(value = FALSE)) - }) - - # Print Log - output$print_log <- downloadHandler( - filename = function() { - log_print(paste0("Save multi typing log ", paste("Multi_Typing_", Sys.Date(), ".txt", sep = ""))) - paste("Multi_Typing_", Sys.Date(), ".txt", sep = "") - }, - content = function(file) { - writeLines(readLines(paste0(getwd(), "/logs/script_log.txt")), file) - } - ) - - # Reset Multi Typing - observeEvent(input$reset_multi, { - if(!grepl("Multi Typing", tail(readLines(paste0(getwd(),"/logs/script_log.txt")), n = 1))) { - showModal( - modalDialog( - paste0( - "A Multi Typing process is still pending. Stopping this process will cancel the processing." - ), - title = "Reset Multi Typing", - fade = TRUE, - easyClose = TRUE, - footer = tagList( - modalButton("Cancel"), - actionButton("conf_multi_kill", "Stop", class = "btn btn-danger") - ) - ) - ) - } else { - - log_print("Reset multi typing") - - # Reset multi typing result list - saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) - multi_help <- FALSE - Typing$result_list <- NULL - - # Null logfile - writeLines("0", paste0(getwd(), "/logs/script_log.txt")) - - # Reset User Feedback variable - Typing$pending_format <- 0 - Typing$multi_started <- FALSE - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - output$pending_typing <- NULL - output$multi_typing_results <- NULL - } - }) - - # Confirm Reset after - observeEvent(input$conf_multi_kill, { - removeModal() - - log_print("Kill multi typing") - - # Kill multi typing and reset logfile - system(paste("bash", paste0(getwd(), "/execute/kill_multi.sh")), - wait = TRUE) - - show_toast( - title = "Execution cancelled", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - - # Kill multi typing and reset logfile - writeLines("0", paste0(getwd(), "/logs/script_log.txt")) - - #Reset multi typing result list - saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) - multi_help <- FALSE - Typing$result_list <- NULL - - # Reset User Feedback variable - Typing$pending_format <- 0 - output$pending_typing <- NULL - output$multi_typing_results <- NULL - Typing$failures <- 0 - Typing$successes <- 0 - Typing$multi_started <- FALSE - - output$initiate_multi_typing_ui <- renderUI({ - column( - width = 4, - align = "center", - br(), - br(), - h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), - br(), br(), - p( - HTML( - paste( - tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') - ) - ) - ), - fluidRow( - column(1), - column( - width = 11, - align = "center", - shinyDirButton( - "genome_file_multi", - "Browse", - icon = icon("folder-open"), - title = "Select the folder containing the genome assemblies (FASTA)", - buttonType = "default", - root = path_home() - ), - br(), - br(), - uiOutput("multi_select_info"), - br() - ) - ), - uiOutput("multi_select_tab_ctrls"), - br(), - fluidRow( - column(1), - column( - width = 11, - align = "left", - rHandsontableOutput("multi_select_table") - ) - ) - ) - }) - - }) - - observeEvent(input$start_typ_multi, { - log_print("Initiate multi typing") - - if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { - show_toast( - title = "Pending Single Typing", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else if (Screening$status == "started") { - show_toast( - title = "Pending Gene Screening", - type = "warning", - position = "bottom-end", - timer = 6000 - ) - } else { - removeModal() - - show_toast( - title = "Multi Typing started", - type = "success", - position = "bottom-end", - timer = 10000 - ) - - Typing$new_table <- NULL - - # Remove Allelic Typing Controls - output$initiate_multi_typing_ui <- NULL - output$metadata_multi_box <- NULL - output$start_multi_typing_ui <- NULL - - # Activate entry detection - DB$check_new_entries <- TRUE - - # Initiate Feedback variables - Typing$multi_started <- TRUE - Typing$pending <- TRUE - Typing$failures <- 0 - Typing$successes <- 0 - - # get selected file table - multi_select_table <- hot_to_r(input$multi_select_table) - - filenames <- paste(multi_select_table$Files[which(multi_select_table$Include == TRUE)], collapse = " ") - - files <- Typing$multi_sel_table$Files[which(multi_select_table$Include == TRUE)] - type <- Typing$multi_sel_table$Type[which(multi_select_table$Include == TRUE)] - genome_names <- paste(paste0(gsub(" ", "~", files), type), collapse = " ") - - # Start Multi Typing Script - multi_typing_df <- data.frame( - db_path = DB$database, - wd = getwd(), - save = input$save_assembly_mt, - scheme = paste0(gsub(" ", "_", DB$scheme)), - genome_folder = as.character(parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi)), - filenames = paste0(filenames, collapse= " "), - genome_names = genome_names, - alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles") - ) - - saveRDS(multi_typing_df, "execute/multi_typing_df.rds") - - # Execute multi blat script - system(paste("bash", paste0(getwd(), "/execute/multi_typing.sh")), wait = FALSE) - } - }) - - - #### User Feedback ---- - - observe({ - if(file.exists(paste0(getwd(), "/logs/script_log.txt"))) { - if(Typing$multi_started == TRUE) { - check_multi_status() - } else { - Typing$status <- "Inactive" - } - } - }) - - check_multi_status <- reactive({ - - invalidateLater(3000, session) - - log <- readLines(paste0(getwd(), "/logs/script_log.txt")) - - # Determine if Single or Multi Typing - if(str_detect(log[1], "Multi")) { - Typing$pending_mode <- "Multi" - } else { - Typing$pending_mode <- "Single" - } - - # Check typing status - if(str_detect(tail(log, 1), "Attaching")) { - Typing$status <- "Attaching" - } else if(str_detect(tail(log, 1), "Successful")) { - Typing$multi_help <- TRUE - Typing$status <- "Successful" - show_toast( - title = paste0("Successful", sub(".*Successful", "", tail(log, 1))), - type = "success", - position = "bottom-end", - timer = 8000 - ) - } else if(str_detect(tail(log, 1), "failed")) { - Typing$status <- "Failed" - show_toast( - title = sub(".* - ", "", tail(log, 1)), - type = "error", - position = "bottom-end", - timer = 8000 - ) - } else if(str_detect(tail(log, 1), "Processing")) { - Typing$status <- "Processing" - - if(any(str_detect(tail(log, 2), "Successful"))) { - - if(!identical(Typing$last_success, tail(log, 2)[1])) { - Typing$multi_help <- TRUE - show_toast( - title = paste0("Successful", sub(".*Successful", "", tail(log, 2)[1])), - type = "success", - position = "bottom-end", - timer = 8000 - ) - - Typing$last_success <- tail(log, 2)[1] - } - } else if(any(str_detect(tail(log, 2), "failed"))) { - - if(!identical(Typing$last_failure, tail(log, 2)[1])) { - - show_toast( - title = sub(".* - ", "", tail(log, 2)[1]), - type = "error", - position = "bottom-end", - timer = 8000 - ) - - Typing$last_failure <- tail(log, 2)[1] - } - } - } else if(str_detect(tail(log, 1), "finalized")) { - Typing$multi_help <- TRUE - Typing$status <- "Finalized" - - if(Typing$pending == TRUE) { - show_toast( - title = "Typing finalized", - type = "success", - position = "bottom-end", - timer = 8000 - ) - - Typing$pending <- FALSE - } - } - }) - - ##### Render Multi Typing UI Feedback ---- - - observe({ - if(!is.null(input$multi_results_picker)) { - Typing$multi_table_length <- nrow(Typing$result_list[[input$multi_results_picker]]) - } else { - Typing$multi_table_length <- NULL - } - }) - - observe({ - if(!is.null(Typing$result_list)) { - if(length(Typing$result_list) > 0) { - if(is.null(Typing$multi_table_length)) { - output$multi_typing_result_table <- renderRHandsontable({ - rhandsontable(Typing$result_list[[input$multi_results_picker]], - rowHeaders = NULL, stretchH = "all", - readOnly = TRUE, contextMenu = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - - } else { - if(Typing$multi_table_length > 15) { - output$multi_typing_result_table <- renderRHandsontable({ - rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, - stretchH = "all", height = 500, - readOnly = TRUE, contextMenu = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } else { - output$multi_typing_result_table <- renderRHandsontable({ - rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, - stretchH = "all", readOnly = TRUE, - contextMenu = FALSE) %>% - hot_rows(rowHeights = 25) %>% - hot_col(1:3, valign = "htMiddle", halign = "htCenter", - cellWidths = list(100, 160, NULL)) %>% - hot_col("Value", renderer=htmlwidgets::JS( - "function(instance, td, row, col, prop, value, cellProperties) { - if (value.length > 8) { - value = value.slice(0, 4) + '...' + value.slice(value.length - 4); - } - td.innerHTML = value; - td.style.textAlign = 'center'; - return td; - }" - )) - }) - } - } - } else { - output$multi_typing_result_table <- NULL - } - } else { - output$multi_typing_result_table <- NULL - } - }) - - observe({ - if(!is.null(Typing$multi_result_status)) { - if(Typing$multi_result_status == "start" | Typing$multi_result_status == "finalized"){ - - if(Typing$multi_help == TRUE) { - Typing$result_list <- readRDS(paste0(getwd(), "/execute/event_list.rds")) - Typing$multi_help <- FALSE - } - } - } - }) - - - observe({ - #Render multi typing result feedback table - - if(!is.null(Typing$result_list)) { - if(length(Typing$result_list) > 0) { - output$multi_typing_results <- renderUI({ - column( - width = 12, - fluidRow( - column(1), - column( - width = 9, - br(), br(), - br(), br(), - br(), - div( - class = "mult_res_sel", - selectInput( - "multi_results_picker", - label = h5("Select Typing Results", style = "color:white"), - choices = names(Typing$result_list), - selected = names(Typing$result_list)[length(names(Typing$result_list))], - ) - ), - br(), br() - ) - ), - rHandsontableOutput("multi_typing_result_table") - ) - }) - } - } - }) - - observe({ - - # Render log content - output$logText <- renderPrint({ - cat(rev(paste0(tail(readLogFile(), 50), "\n"))) - }) - - output$logTextFull <- renderPrint({ - cat(rev(paste0(readLines(paste0(getwd(), "/logs/script_log.txt")), "\n"))) - }) - - # Render Pending UI - if(!grepl("Multi Typing", tail(readLogFile(), n = 1)) & grepl("Start Multi Typing", head(readLogFile(), n = 1))) { - - Typing$multi_result_status <- "start" - - output$initiate_multi_typing_ui <- NULL - - output$pending_typing <- renderUI({ - fluidRow( - fluidRow( - br(), br(), - column(width = 2), - column( - width = 4, - h3(p("Pending Typing ..."), style = "color:white"), - br(), br(), - fluidRow( - column( - width = 5, - HTML(paste('')) - ), - column( - width = 6, - align = "left", - actionButton( - "reset_multi", - "Terminate", - icon = icon("ban") - ) - ) - ), - ) - ), - br(), br(), - fluidRow( - column(width = 2), - column( - width = 10, - verbatimTextOutput("logText") - ) - ) - ) - }) - } else if(grepl("Multi Typing finalized", tail(readLogFile(), n = 1))) { - - Typing$multi_result_status <- "finalized" - - Typing$last_scheme <- NULL - - output$initiate_multi_typing_ui <- NULL - - output$pending_typing <- renderUI({ - - fluidRow( - fluidRow( - br(), br(), - column(width = 2), - column( - width = 4, - h3(p("Pending Multi Typing ..."), style = "color:white"), - br(), br(), - HTML(paste("", - paste("Typing of", sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Processing")), "assemblies finalized."), - paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Successful")), "successes."), - paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "failed")), "failures."), - "Reset to start another typing process.", - sep = '
')), - br(), br(), - fluidRow( - column( - width = 5, - actionButton( - "reset_multi", - "Reset", - icon = icon("arrows-rotate") - ) - ), - column( - width = 5, - downloadButton( - "print_log", - "Logfile", - icon = icon("floppy-disk") - ) - ) - ) - ) - ), - br(), br(), - fluidRow( - column(width = 2), - column( - width = 10, - verbatimTextOutput("logTextFull"), - ) - ) - ) - }) - } else if (!grepl("Start Multi Typing", head(readLogFile(), n = 1))){ - output$pending_typing <- NULL - Typing$multi_result_status <- "idle" - } - }) - - observe({ - # Get selected Genome in Multi Mode - shinyDirChoose(input, - "hash_dir", - roots = c(Home = path_home(), Root = "/"), - defaultRoot = "Home", - session = session, - filetypes = c('', 'fasta', 'fna', 'fa')) - }) - - observeEvent(input$hash_start, { - dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) - if (!is_empty(list.files(dir_path)) && all(endsWith(list.files(dir_path), ".fasta"))) { - log_print("Hashing directory using utilities") - shinyjs::hide("hash_start") - shinyjs::show("hash_loading") - show_toast( - title = "Hashing started!", - type = "success", - position = "bottom-end", - timer = 6000 - ) - hash_database(dir_path) - shinyjs::hide("hash_loading") - shinyjs::show("hash_start") - show_toast( - title = "Hashing completed!", - type = "success", - position = "bottom-end", - timer = 6000 - ) - } else { - show_toast( - title = "Incorrect folder selected!", - type = "error", - position = "bottom-end", - timer = 6000 - ) - } - }) - -} # end server - -# _______________________ #### - -# Shiny ---- - -shinyApp(ui = ui, server = server) +######## PhyloTrace ######### + +# _______________________ #### +# CRAN Packages +library(shiny) +library(R.utils) +library(igraph) +library(shinyWidgets) +library(shinydashboard) +library(dashboardthemes) +library(ggplot2) +library(ggnewscale) +library(ggplotify) +library(ape) +library(tidyverse) +library(rlang) +library(tidytree) +library(shinyFiles) +library(dplyr) +library(downloader) +library(rvest) +library(rmarkdown) +library(knitr) +library(kableExtra) +library(fs) +library(data.table) +library(zoo) +library(ggnetwork) +library(rhandsontable) +library(visNetwork) +library(proxy) +library(phangorn) +library(cowplot) +library(viridis) +library(RColorBrewer) +library(bslib) +library(bsicons) +library(DT) +library(shinyBS) +library(openssl) +library(logr) +# Bioconductor Packages +library(treeio) +library(ggtree) +library(ggtreeExtra) + +source(paste0(getwd(), "/www/resources.R")) + +options(ignore.negative.edge=TRUE) + +# User Interface ---- + +ui <- dashboardPage( + + title = "PhyloTrace 1.5.0", + + # Title + dashboardHeader( + + title = span( + div( + class = "img_logo", + img( + src = "PhyloTrace.jpg", width = 190 + ) + ) + ), + uiOutput("loaded_scheme"), + uiOutput("databasetext"), + uiOutput("statustext"), + tags$li(class = "dropdown", + tags$span(id = "currentTime", style = "color:white; font-weight:bold;")), + disable = FALSE + ), + + ## Sidebar ---- + dashboardSidebar( + tags$head(includeCSS("www/head.css")), + tags$style(includeCSS("www/body.css")), + tags$style(HTML( + "@keyframes pulsate { + 0% { transform: scale(1); } + 50% { transform: scale(1.1); } + 100% { transform: scale(1); } + } + .pulsating-button { + animation: pulsate 1s ease infinite; + } + .pulsating-button:hover { + animation: none; + }")), + br(), br(), + sidebarMenu( + id = "tabs", + sidebarMenuOutput("menu"), + uiOutput("menu_sep2"), + conditionalPanel( + "input.tabs==='db_browse_entries'", + uiOutput("entrytable_sidebar") + ), + conditionalPanel( + "input.tabs==='db_distmatrix'", + uiOutput("distmatrix_sidebar") + ), + conditionalPanel( + "input.tabs==='db_missing_values'", + uiOutput("missing_values_sidebar") + ), + conditionalPanel( + "input.tabs==='typing'", + uiOutput("typing_sidebar") + ), + conditionalPanel( + "input.tabs==='visualization'", + uiOutput("visualization_sidebar") + ), + conditionalPanel( + "input.tabs==='gs_profile'", + uiOutput("screening_sidebar") + ) + ) + ), + + dashboardBody( + tags$head(tags$link(rel = "shortcut icon", href = "favicon.ico")), + shinyjs::useShinyjs(), + + shinyDashboardThemeDIY( + ### general + appFontFamily = "Liberation Sans", + appFontColor = "#000000", + primaryFontColor = "#ffffff", + infoFontColor = "rgb(0,0,0)", + successFontColor = "rgb(0,0,0)", + warningFontColor = "rgb(0,0,0)", + dangerFontColor = "rgb(0,0,0)", + bodyBackColor = cssGradientThreeColors( + direction = "down", + colorStart = "#282f38", + colorMiddle = "#384454", + colorEnd = "#495d78", + colorStartPos = 0, + colorMiddlePos = 50, + colorEndPos = 100 + ), + + ### header + logoBackColor = "#282f38", + headerButtonBackColor = "#282f38", + headerButtonIconColor = "#18ece1", + headerButtonBackColorHover = "#282f38", + headerButtonIconColorHover = "#ffffff", + headerBackColor = "#282f38", + headerBoxShadowColor = "#aaaaaa", + headerBoxShadowSize = "0px 0px 0px", + + ### sidebar + sidebarBackColor = cssGradientThreeColors( + direction = "down", + colorStart = "#282f38", + colorMiddle = "#384454", + colorEnd = "#495d78", + colorStartPos = 0, + colorMiddlePos = 50, + colorEndPos = 100), + + sidebarPadding = 0, + sidebarMenuBackColor = "transparent", + sidebarMenuPadding = 0, + sidebarMenuBorderRadius = 0, + sidebarShadowRadius = "5px 5px 5px", + sidebarShadowColor = "#282f38", + sidebarUserTextColor = "#ffffff", + sidebarSearchBackColor = "rgb(55,72,80)", + sidebarSearchIconColor = "rgb(153,153,153)", + sidebarSearchBorderColor = "rgb(55,72,80)", + sidebarTabTextColor = "rgb(255,255,255)", + sidebarTabTextSize = 15, + sidebarTabBorderStyle = "none none solid none", + sidebarTabBorderColor = "rgb(35,106,135)", + sidebarTabBorderWidth = 0, + sidebarTabBackColorSelected = cssGradientThreeColors( + direction = "right", + colorStart = "rgba(44,222,235,1)", + colorMiddle = "rgba(44,222,235,1)", + colorEnd = "rgba(0,255,213,1)", + colorStartPos = 0, + colorMiddlePos = 30, + colorEndPos = 100 + ), + sidebarTabTextColorSelected = "rgb(0,0,0)", + sidebarTabRadiusSelected = "0px 0px 0px 0px", + sidebarTabBackColorHover = cssGradientThreeColors( + direction = "right", + colorStart = "rgba(44,222,235,1)", + colorMiddle = "rgba(44,222,235,1)", + colorEnd = "rgba(0,255,213,1)", + colorStartPos = 0, + colorMiddlePos = 30, + colorEndPos = 100 + ), + sidebarTabTextColorHover = "rgb(50,50,50)", + sidebarTabBorderStyleHover = "none none solid none", + sidebarTabBorderColorHover = "rgb(75,126,151)", + sidebarTabBorderWidthHover = 0, + sidebarTabRadiusHover = "0px 0px 0px 0px", + + ### boxes + boxBackColor = "#ffffff", + boxBorderRadius = 7, + boxShadowSize = "0px 0px 0px", + boxShadowColor = "#ffffff", + boxTitleSize = 20, + boxDefaultColor = "#00a65a", + boxPrimaryColor = "#ffffff", + boxInfoColor = "#00a65a", + boxSuccessColor = "#00a65a", + boxWarningColor = "#ffffff", + boxDangerColor = "#ffffff", + tabBoxTabColor = "#ffffff", + tabBoxTabTextSize = 14, + tabBoxTabTextColor = "rgb(0,0,0)", + tabBoxTabTextColorSelected = "rgb(0,0,0)", + tabBoxBackColor = "#ffffff", + tabBoxHighlightColor = "#ffffff", + tabBoxBorderRadius = 5, + + ### inputs + buttonBackColor = "#282F38", + buttonTextColor = "#ffffff", + buttonBorderColor = "#282F38", + buttonBorderRadius = 5, + buttonBackColorHover = cssGradientThreeColors( + direction = "right", + colorStart = "rgba(44,222,235,1)", + colorMiddle = "rgba(44,222,235,1)", + colorEnd = "rgba(0,255,213,1)", + colorStartPos = 0, + colorMiddlePos = 30, + colorEndPos = 100 + ), + buttonTextColorHover = "#000000", + buttonBorderColorHover = "transparent", + textboxBackColor = "#ffffff", + textboxBorderColor = "#ffffff", + textboxBorderRadius = 5, + textboxBackColorSelect = "#ffffff", + textboxBorderColorSelect = "#000000", + + ### tables + tableBackColor = "rgb(255,255,255)", + tableBorderColor = "rgb(240,240,240)", + tableBorderTopSize = 1, + tableBorderRowSize = 1 + ), + + uiOutput("start_message"), + + tabItems( + + ## Tab Database ---- + + ### Tab Browse Entries ---- + + tabItem( + tabName = "db_browse_entries", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Browse Local Database"), style = "color:white") + ) + ), + hr(), br(), + br(), + br(), + uiOutput("no_scheme_entries"), + uiOutput("db_no_entries"), + uiOutput("entry_table_controls"), + br(), br(), + fluidRow( + column(1), + column( + width = 8, + uiOutput("db_entries_table") + ), + column( + width = 3, + align = "left", + uiOutput("delete_box"), + uiOutput("compare_allele_box"), + uiOutput("download_entries"), + br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br() + ) + ), + br() + ), + + ### Tab Scheme Info ---- + + tabItem( + tabName = "db_schemeinfo", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Scheme Info"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + uiOutput("no_scheme_info"), + fluidRow( + column(2), + column( + width = 7, + align = "center", + fluidRow( + column( + width = 7, + align = "right", + uiOutput("scheme_header") + ), + column( + width = 2, + align = "left", + uiOutput("download_scheme_info") + ) + ), + br(), + br(), + uiOutput("scheme_info") + ) + ) + ), + + ### Tab Loci Info ---- + + tabItem( + tabName = "db_loci_info", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Loci Info"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + fluidRow( + column(1), + column( + width = 10, + align = "center", + fluidRow( + column( + width = 6, + align = "right", + uiOutput("loci_header") + ), + column( + width = 2, + align = "left", + uiOutput("download_loci") + ) + ), + br(), + div(class = "loci_table", + dataTableOutput("db_loci")) + ) + ), + br(), br(), + fluidRow( + column(1), + uiOutput("sequence_selector"), + column(1), + column( + width = 7, + br(), + uiOutput("loci_sequences") + ) + ) + ), + + ### Tab Distance Matrix ---- + + tabItem( + tabName = "db_distmatrix", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Distance Matrix"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + uiOutput("no_scheme_distancematrix"), + uiOutput("distancematrix_no_entries"), + fluidRow( + column(1), + uiOutput("distmatrix_show") + ), + br(), br() + ), + + ### Tab Missing Values ---- + + tabItem( + tabName = "db_missing_values", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Missing Values"), style = "color:white") + ) + ), + hr(), br(), br(), br(), + fluidRow( + column( + width = 3, + uiOutput("missing_values"), + fluidRow( + column( + width = 2, + div( + class = "rectangle-red-space" + ) + ), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 75px; position: relative; bottom: -12px", " = ≥ 5% of loci missing") + ) + ) + ) + ) + ) + ), + column( + width = 8, + rHandsontableOutput("table_missing_values") + ) + ) + ), + + ## Tab Manage Schemes ---- + + tabItem( + tabName = "init", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Select cgMLST Scheme"), style = "color:white") + ) + ), + hr(), + fluidRow( + column(1), + column( + width = 3, + br(), + br(), + br(), + pickerInput( + inputId = "select_cgmlst", + label = NULL, + choices = list( + "Acinetobacter baumanii", + "Bacillus anthracis", + "Bordetella pertussis", + "Brucella melitensis", + "Brucella spp.", + "Burkholderia mallei (FLI)", + "Burkholderia mallei (RKI)", + "Burkholderia pseudomallei", + "Campylobacter jejuni/coli", + "Clostridioides difficile", + "Clostridium perfringens", + "Corynebacterium diphtheriae", + "Cronobacter sakazakii/malonaticus", + "Enterococcus faecalis", + "Enterococcus faecium", + "Escherichia coli", + "Francisella tularensis", + "Klebsiella oxytoca sensu lato", + "Klebsiella pneumoniae sensu lato", + "Legionella pneumophila", + "Listeria monocytogenes", + "Mycobacterium tuberculosis complex", + "Mycobacteroides abscessus", + "Mycoplasma gallisepticum", + "Paenibacillus larvae", + "Pseudomonas aeruginosa", + "Salmonella enterica", + "Serratia marcescens", + "Staphylococcus aureus", + "Staphylococcus capitis", + "Streptococcus pyogenes" + ), + width = "300px", + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = FALSE + ) + ), + column( + width = 2, + br(), + br(), + br(), + h5(textOutput("scheme_update_info"), style = "color: white") + ), + column( + width = 2, + br(), + br(), + br(), + actionButton( + "download_cgMLST", + label = "Download", + icon = icon("download") + ), + shinyjs::hidden( + div(id = "loading", + HTML('')) + ) + ) + ), + fluidRow( + column(1), + column( + width = 6, + align = "center", + br(), + br(), + br(), + addSpinner( + tableOutput("cgmlst_scheme"), + spin = "dots", + color = "#ffffff" + ) + ) + ) + ), + + + + ## Tab Allelic Typing ---------------------------------------------- + + + tabItem( + tabName = "typing", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Generate Allelic Profile"), style = "color:white") + ) + ), + hr(), + uiOutput("typing_no_db"), + conditionalPanel( + "input.typing_mode == 'Single'", + fluidRow( + uiOutput("initiate_typing_ui"), + uiOutput("single_typing_progress"), + column(1), + uiOutput("metadata_single_box"), + column(1), + uiOutput("start_typing_ui") + ) + ), + conditionalPanel( + "input.typing_mode == 'Multi'", + fluidRow( + uiOutput("initiate_multi_typing_ui"), + uiOutput("multi_stop"), + column(1), + uiOutput("metadata_multi_box"), + column(1), + uiOutput("start_multi_typing_ui") + ), + fluidRow( + column( + width = 6, + uiOutput("pending_typing") + ), + column( + width = 6, + uiOutput("multi_typing_results") + ) + ) + ) + ), + + + ## Tab Visualization ------------------------------------------------------- + + + tabItem( + tabName = "visualization", + fluidRow( + tags$script(src = "javascript_functions.js"), + column( + width = 12, + align = "center", + br(), + conditionalPanel( + "input.tree_algo=='Minimum-Spanning'", + uiOutput("mst_field") + ), + conditionalPanel( + "input.tree_algo=='Neighbour-Joining'", + uiOutput("nj_field") + ), + conditionalPanel( + "input.tree_algo=='UPGMA'", + uiOutput("upgma_field") + ) + ) + ), + br(), + hr(), + + ### Control panels MST ---- + conditionalPanel( + "input.tree_algo=='Minimum-Spanning'", + fluidRow( + column( + width = 4, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + height = "500px", + h3(p("Layout"), style = "color:white; position:relative; right:-15px"), + hr(), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Title"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "mst_title", + label = "", + width = "100%", + placeholder = "Plot Title" + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_title_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_title_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + numericInput( + "mst_title_size", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 40, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Subtitle"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "mst_subtitle", + label = "", + width = "100%", + placeholder = "Plot Subtitle" + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_subtitle_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_subtitle_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + numericInput( + "mst_subtitle_size", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 20, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ) + ) + ) + ), + hr(), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Legend"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_legend_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_legend_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 11, + sliderInput( + "mst_font_size", + label = h5("Font Size", style = "color:white; margin-bottom: 0px;"), + value = 18, + min = 15, + max = 30, + step = 1, + ticks = FALSE, + width = "180px" + ) + ), + column(1) + ), + br(), + fluidRow( + column( + width = 11, + sliderInput( + "mst_symbol_size", + label = h5("Key Size", style = "color:white; margin-bottom: 0px;"), + value = 20, + min = 10, + max = 30, + step = 1, + ticks = FALSE, + width = "180px" + ) + ), + column(1) + ) + ) + ) + ), + fluidRow( + column( + width = 7, + selectInput( + "mst_legend_ori", + label = "", + width = "100%", + choices = c("Left" = "left", "Right" = "right") + ) + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Background"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 12, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "mst_background_transparent", + h5(p("Transparent"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_background_color", + width = "100%", + selected = "#ffffff", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 4, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + height = "500px", + h3(p("Nodes"), style = "color:white; position:relative; right:-15px"), + hr(), + fluidRow( + column( + width = 6, + column( + width = 12, + align = "left", + h4(p("Label"), style = "color:white;") + ), + column( + width = 12, + align = "center", + div( + class = "label_sel", + uiOutput("mst_node_label") + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "node_font_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + numericInput( + "node_label_fontsize", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 14, + min = 8, + max = 30, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 10, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "mst_color_var", + h5(p("Add Variable"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 2, + bslib::tooltip( + bsicons::bs_icon("info-circle", title = "Only categorical variables can \nbe mapped to the node color", color = "white", + height = "12px", width = "12px", position = "relative", top = "27px", right = "56px"), + "Text shown in the tooltip.", + show = FALSE, + id = "mst_node_col_info" + ) + ) + ), + uiOutput("mst_color_mapping") + ) + ) + ), br() + ) + ), + hr(), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Size"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 12, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "scale_nodes", + h5(p("Scale by Duplicates"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ) + ) + ) + ) + ), + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + align = "left", + conditionalPanel( + "input.scale_nodes==true", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Range') + ) + ) + ), + conditionalPanel( + "input.scale_nodes==false", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Size') + ) + ) + ) + ), + column( + width = 9, + align = "center", + conditionalPanel( + "input.scale_nodes==true", + div( + class = "mst_scale_slider", + sliderInput( + "mst_node_scale", + label = "", + min = 1, + max = 80, + value = c(20, 40), + ticks = FALSE + ) + ) + ), + conditionalPanel( + "input.scale_nodes==false", + div( + class = "mst_scale_slider", + sliderInput( + inputId = "mst_node_size", + label = "", + min = 1, + max = 100, + value = 30, + ticks = FALSE + ) + ) + ) + ) + ), + br() + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Other Elements"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 12, + align = "left", + div( + class = "mat-switch-mst-nodes", + materialSwitch( + "mst_shadow", + h5(p("Show Shadow"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + fluidRow( + column( + width = 3, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Shape') + ) + ) + ), + column( + width = 9, + align = "center", + div( + class = "mst_shape_sel", + selectInput( + "mst_node_shape", + "", + choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), + `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), + selected = c("Dot" = "dot"), + width = "85%" + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 4, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + height = "500px", + h3(p("Edges"), style = "color:white; position:relative; right:-15px"), + hr(), + fluidRow( + column( + width = 6, + column( + width = 12, + align = "left", + h4(p("Label"), style = "color:white;") + ), + column( + width = 12, + align = "center", + div( + class = "label_sel", + selectInput( + "mst_edge_label", + label = "", + choices = c( + `Allelic Distance` = "weight", + Index = "index", + `Assembly ID` = "assembly_id", + `Assembly Name` = "assembly_name", + `Isolation Date` = "isolation_date", + Host = "host", + Country = "country", + City = "city" + ), + selected = c(`Allelic Distance` = "weight"), + width = "100%" + ) + ), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "mst_edge_font_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_edgelabel_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + numericInput( + "mst_edge_font_size", + label = h5("Size", style = "color:white; margin-bottom: 0px;"), + value = 18, + step = 1, + min = 8, + max = 30, + width = "80px" + ) + ) + ) + ), + br() + ) + ), + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + div( + class = "node_color", + colorPickr( + inputId = "mst_color_edge", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_edgecolor_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + sliderInput( + "mst_edge_opacity", + label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), + value = 0.7, + step = 0.1, + min = 0, + max = 1, + ticks = FALSE, + width = "150px" + ) + ) + ) + ) + ) + ) + ) + ) + ), + hr(style = "margin-top: 3px !important"), + fluidRow( + column( + width = 6, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Length multiplier"), style = "color:white; position: relative; right: -15px; margin-bottom: -5px") + ) + ), + column( + width = 12, + align = "left", + br(), + div( + class = "switch-mst-edges", + materialSwitch( + "mst_scale_edges", + h5(p("Scale Allelic Distance"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + fluidRow( + column( + width = 3, + align = "left", + conditionalPanel( + "input.mst_scale_edges==true", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Multiplier') + ) + ) + ), + conditionalPanel( + "input.mst_scale_edges==false", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -16px; margin-left: 0px ', 'Length') + ) + ) + ) + ), + column( + width = 9, + align = "center", + conditionalPanel( + "input.mst_scale_edges==true", + div( + class = "slider_edge", + sliderInput( + inputId = "mst_edge_length_scale", + label = NULL, + min = 1, + max = 40, + value = 15, + ticks = FALSE + ) + ) + ), + conditionalPanel( + "input.mst_scale_edges==false", + div( + class = "slider_edge", + sliderTextInput( + inputId = "mst_edge_length", + label = NULL, + choices = append(seq(0.1, 1, 0.1), 2:100), + selected = 35, + hide_min_max = FALSE + ) + ) + ) + ) + ) + ) + ), + column( + width = 6, + fluidRow( + column( + width = 6, + align = "left", + h4(p("Clustering"), style = "color:white; text-align: left; position: relative; right: -15px") + ), + column( + width = 2, + bslib::tooltip( + bsicons::bs_icon("info-circle", + title = "Cluster threshold according to species-specific\nComplex Type Distance (cgMLST.org)", + color = "white", height = "14px", width = "14px", + position = "relative", top = "9px", right = "28px"), + "Text shown in the tooltip.", + show = FALSE, + id = "mst_cluster_info" + ) + ) + ), + br(), + fluidRow( + column( + width = 9, + div( + class = "mst-cluster-switch", + materialSwitch( + "mst_show_clusters", + h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "mst_cluster_col_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + fluidRow( + column( + width = 12, + align = "center", + selectInput( + "mst_cluster_col_scale", + label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), + choices = c("Viridis", "Rainbow"), + width = "150px" + ), + br(), + selectInput( + "mst_cluster_type", + label = h5("Cluster Type", style = "color:white; margin-bottom: 0px;"), + choices = c("Area", "Skeleton"), + width = "150px" + ), + br(), + conditionalPanel( + "input.mst_cluster_type=='Skeleton'", + sliderInput( + "mst_cluster width", + label = h5("Skeleton Width", style = "color:white; margin-bottom: 0px;"), + value = 5, + step = 1, + min = 1, + max = 10, + ticks = FALSE, + width = "150px" + ) + ) + ) + ) + ) + ) + ), + br(), + fluidRow( + column( + width = 4, + HTML( + paste( + tags$span(style='color: white; text-align: left; font-size: 14px; margin-left: 15px', 'Threshold') + ) + ) + ), + column( + width = 4, + uiOutput("mst_cluster") + ), + column( + width = 4, + actionButton( + "mst_cluster_reset", + label = "", + icon = icon("rotate") + ), + bsTooltip("mst_cluster_reset", + HTML("Reset to default Complex Type Distance"), + placement = "top", trigger = "hover") + ) + ) + ), + br(), + ) + ), br(), br(), br(), br(), br(), br() + ) + ) + ), + + ### Control Panels NJ ---- + + conditionalPanel( + "input.tree_algo=='Neighbour-Joining'", + fluidRow( + column( + width = 1, + radioGroupButtons( + inputId = "nj_controls", + label = "", + choices = c("Layout", "Label", "Elements", "Variables"), + direction = "vertical" + ) + ), + conditionalPanel( + "input.nj_controls=='Layout'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Theme"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + align = "center", + selectInput( + inputId = "nj_layout", + label = "", + choices = list( + Linear = list( + "Rectangular" = "rectangular", + "Roundrect" = "roundrect", + "Slanted" = "slanted", + "Ellipse" = "ellipse" + ), + Circular = list("Circular" = "circular", + "Inward" = "inward") + ), + selected = "rectangular", + width = "90%" + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "nj_rootedge_show", + h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_rootedge_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_rootedge_length"), + br(), + selectInput( + "nj_rootedge_line", + label = h5("Rootedge Line", style = "color:white"), + choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), + selected = c(Dotted = "solid"), + width = "100px" + ), + br(), + conditionalPanel( + "input.nj_layout=='circular'", + sliderInput( + "nj_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = -50, + max = 0, + value = -10, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_layout=='inward'", + sliderInput( + "nj_inward_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = 30, + max = 120, + value = 50, + ticks = FALSE, + width = "150px", + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-re", + materialSwitch( + "nj_ladder", + h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + colorPickr( + inputId = "nj_color", + width = "90%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + br(), + fluidRow( + column( + width = 5, + h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") + ), + column( + width = 7, + colorPickr( + inputId = "nj_bg", + width = "90%", + selected = "#ffffff", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + br() + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Title"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "nj_title", + label = "", + width = "100%", + placeholder = "Plot Title" + ), + textInput( + "nj_subtitle", + label = "", + width = "100%", + placeholder = "Plot Subtitle" + ), + br(), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "nj_title_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "nj_title_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "nj_title_size", + label = h5("Title Size", style = "color:white; margin-bottom: 0px"), + value = 30, + min = 15, + max = 40, + step = 1, + width = "80px" + ), + br(), + numericInput( + "nj_subtitle_size", + label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), + value = 20, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ), + br() + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + br(), + fluidRow( + column( + width = 3, + h5("Ratio", style = "color: white; font-size: 14px;") + ), + column( + width = 6, + align = "left", + div( + class = "ratio-sel", + selectInput( + "nj_ratio", + "", + choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "nj_size_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + sliderInput( + "nj_v", + label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "nj_h", + label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + sliderInput( + "nj_scale", + "", + min = 500, + max = 1200, + value = 800, + step = 5, + width = "95%", + ticks = FALSE + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + div( + class = "zoom-slider", + sliderInput( + "nj_zoom", + label = NULL, + min = 0.5, + max = 1.5, + step = 0.05, + value = 0.95, + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "nj_treescale_show", + h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + br() + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_treescale_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_treescale_width"), + br(), + uiOutput("nj_treescale_x"), + br(), + uiOutput("nj_treescale_y") + ) + ) + ) + ) + ) + ) + ), + column( + width = 12, + align = "left", + h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + align = "left", + prettyRadioButtons( + "nj_legend_orientation", + "", + choices = c(Horizontal = "horizontal", + Vertical = "vertical"), + selected = c(Vertical = "vertical"), + inline = FALSE + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "nj_legend_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "nj_legend_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + value = 10, + min = 5, + max = 25, + step = 1, + width = "80px" + ), + br(), + sliderInput( + "nj_legend_x", + label = h5("Horizontal Position", style = "color:white; margin-bottom: 0px"), + value = 0.9, + min = -0.9, + max = 1.9, + step = 0.2, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "nj_legend_y", + label = h5("Vertical Position", style = "color:white; margin-bottom: 0px"), + value = 0.2, + min = -1.5, + max = 1.5, + step = 0.1, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_controls=='Label'", + column( + width = 4, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Tips"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 4, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "nj_tiplab_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "center", + uiOutput("nj_tiplab") + ), + column( + width = 3, + div( + class = "mat-switch-align", + materialSwitch( + "nj_align", + h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 1, + align = "right", + dropMenu( + actionBttn( + "nj_labeltext_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "nj_tiplab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + width = "150px", + ticks = FALSE + ), + br(), + conditionalPanel( + "!(input.nj_layout=='inward'|input.nj_layout=='circular')", + sliderInput( + inputId = "nj_tiplab_nudge_x", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 0, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_layout=='circular'", + sliderInput( + inputId = "nj_tiplab_position", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = -0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_layout=='inward'", + sliderInput( + inputId = "nj_tiplab_position_inw", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 1.1, + width = "150px", + ticks = FALSE + ) + ), + br(), + sliderInput( + inputId = "nj_tiplab_angle", + label = h5("Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + ticks = FALSE, + width = "150px", + ) + ), + column( + width = 6, + align = "center", + uiOutput("nj_tiplab_size"), + br(), + selectInput( + "nj_tiplab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") + ), + column( + width = 4, + align = "center", + colorPickr( + inputId = "nj_tiplab_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + br(), + div( + class = "mat-switch-geom", + materialSwitch( + "nj_geom", + h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + colorPickr( + inputId = "nj_tiplab_fill", + width = "100%", + selected = "#84D9A0", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 3, + align = "left", + dropMenu( + actionBttn( + "nj_labelformat_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_tiplab_padding"), + br(), + sliderInput( + inputId = "nj_tiplab_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.2, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Branches"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "nj_show_branch_label", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 5, + align = "center", + uiOutput("nj_branch_label") + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "nj_branch_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "nj_branchlab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 0.65, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "nj_branch_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "nj_branch_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ) + ), + column( + width = 6, + align = "center", + uiOutput("nj_branch_size"), + selectInput( + "nj_branchlab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ), + br(), + sliderInput( + "nj_branch_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.5, + width = "250px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") + ), + column( + width = 5, + colorPickr( + inputId = "nj_branch_label_color", + width = "100%", + selected = "#FFB7B7", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 6, + textInput( + "nj_new_label_name", + "", + placeholder = "New Label" + ) + ), + column( + width = 3, + actionButton( + "nj_add_new_label", + "", + icon = icon("plus") + ) + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "nj_custom_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_custom_labelsize"), + br(), + uiOutput("nj_sliderInput_y"), + br(), + uiOutput("nj_sliderInput_x") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 6, + uiOutput("nj_custom_label_select") + ), + column( + width = 4, + uiOutput("nj_del_label"), + ) + ), + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_cust_label_save") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_controls=='Elements'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "nj_tippoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_tippoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "nj_tippoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 0.5, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("nj_tippoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "nj_tippoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + conditionalPanel( + "input.nj_tipshape_mapping_show==false", + selectInput( + "nj_tippoint_shape", + "", + width = "100%", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ) + ), + conditionalPanel( + "input.nj_tipshape_mapping_show==true", + h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "nj_nodepoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "nj_nodepoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "nj_nodepoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 1, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("nj_nodepoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "nj_nodepoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + selectInput( + "nj_nodepoint_shape", + "", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Tiles"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 5, + div( + class = "sel-tile-number", + selectInput( + "nj_tile_number", + "", + choices = 1:5, + width = "70px" + ) + ) + ), + column( + width = 7, + align = "right", + dropMenu( + actionBttn( + "nj_tile_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + conditionalPanel( + "input.nj_tile_num == 1", + sliderInput( + "nj_fruit_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + sliderInput( + "nj_fruit_alpha_2", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + sliderInput( + "nj_fruit_alpha_3", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + sliderInput( + "nj_fruit_alpha_4", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + sliderInput( + "nj_fruit_alpha_5", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 1", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width2"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_2"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width3"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_3"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width4"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_4"), + br() + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_width5"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("nj_fruit_offset_circ_5"), + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 3, + h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") + ), + column( + width = 6, + align = "center", + textInput( + "nj_heatmap_title", + label = "", + value = "Heatmap", + placeholder = "Heatmap" + ) + ), + column( + width = 3, + align = "right", + dropMenu( + actionBttn( + "nj_heatmap_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("nj_colnames_angle"), + br(), + uiOutput("nj_colnames_y") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") + ), + column( + width = 7, + uiOutput("nj_heatmap_width") + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") + ), + column( + width = 7, + uiOutput("nj_heatmap_offset") + ) + ), + br(), br() + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + div( + class = "mat-switch", + materialSwitch( + "nj_nodelabel_show", + h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") + ), + column( + width = 9, + uiOutput("nj_parentnode") + ) + ), + uiOutput("nj_clade_scale"), + fluidRow( + column( + width = 5, + h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + div( + class = "sel-clade", + selectInput( + "nj_clade_type", + "", + choices = c("Rect" = "rect", + "Round" = "roundrect"), + selected = c("Round" = "roundrect") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.nj_controls=='Variables'", + column( + width = 7, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + align = "center", + h4(p("Element"), style = "color:white; margin-bottom: 20px") + ), + column( + width = 3, + align = "center", + h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") + ), + column( + width = 6, + align = "center", + h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") + ) + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_mapping_show", + h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_color_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("nj_tiplab_scale") + ), + uiOutput("nj_tiplab_mapping_info"), + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_tipcolor_mapping_show", + h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_tipcolor_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("nj_tippoint_scale") + ), + uiOutput("nj_tipcolor_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_tipshape_mapping_show", + h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_tipshape_mapping") + ), + column( + width = 3, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') + ) + ) + ), + uiOutput("nj_tipshape_mapping_info") + ), + fluidRow( + column( + width = 3, + fluidRow( + column( + width = 8, + conditionalPanel( + "input.nj_tile_num == 1", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_1", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_2", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_3", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_4", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + div( + class = "mat-switch-v", + materialSwitch( + "nj_tiles_show_5", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + column( + width = 4, + align = "left", + div( + class = "tile-sel", + selectInput( + "nj_tile_num", + "", + choices = 1:5, + width = "50px" + ) + ) + ) + ) + ), + column( + width = 3, + align = "center", + conditionalPanel( + "input.nj_tile_num == 1", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable") + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable2") + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable3") + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable4") + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + div( + class = "heatmap-scale", + uiOutput("nj_fruit_variable5") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 1", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_1") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 2", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_2") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 3", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_3") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 4", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_4") + ) + ) + ), + conditionalPanel( + "input.nj_tile_num == 5", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_tiles_scale_5") + ) + ) + ), + uiOutput("nj_fruit_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "nj_heatmap_show", + h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("nj_heatmap_sel") + ), + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("nj_heatmap_scale") + ) + ), + uiOutput("nj_heatmap_mapping_info") + ) + ) + ) + ) + ) + ), + br(), br(), br(), br(), br(), br() + ), + + ### Control Panels UPGMA ---- + + conditionalPanel( + "input.tree_algo=='UPGMA'", + fluidRow( + column( + width = 1, + radioGroupButtons( + inputId = "upgma_controls", + label = "", + choices = c("Layout", "Label", "Elements", "Variables"), + direction = "vertical" + ) + ), + conditionalPanel( + "input.upgma_controls=='Layout'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Theme"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + align = "center", + selectInput( + inputId = "upgma_layout", + label = "", + choices = list( + Linear = list( + "Rectangular" = "rectangular", + "Roundrect" = "roundrect", + "Slanted" = "slanted", + "Ellipse" = "ellipse" + ), + Circular = list("Circular" = "circular", + "Inward" = "inward") + ), + selected = "rectangular", + width = "90%" + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "upgma_rootedge_show", + h5(p("Rootedge"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_rootedge_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_rootedge_length"), + br(), + selectInput( + "upgma_rootedge_line", + label = h5("Rootedge Line", style = "color:white"), + choices = c(Solid = "solid", Dashed = "dashed", Dotted = "dotted"), + selected = c(Dotted = "solid"), + width = "100px" + ), + br(), + conditionalPanel( + "input.upgma_layout=='circular'", + sliderInput( + "upgma_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = -50, + max = 0, + value = -10, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_layout=='inward'", + sliderInput( + "upgma_inward_xlim", + label = h5("Adjust Circular", style = "color:white"), + min = 30, + max = 120, + value = 50, + ticks = FALSE, + width = "150px", + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-re", + materialSwitch( + "upgma_ladder", + h5(p("Ladderize"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Color"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + h5(p("Lines/Text"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + colorPickr( + inputId = "upgma_color", + width = "90%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + br(), + fluidRow( + column( + width = 5, + h5(p("Background"), style = "color:white; position: relative; right: -15px; margin-top: 7px; margin-bottom: 38px") + ), + column( + width = 7, + colorPickr( + inputId = "upgma_bg", + width = "90%", + selected = "#ffffff", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Title"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + textInput( + "upgma_title", + label = "", + width = "100%", + placeholder = "Plot Title" + ), + textInput( + "upgma_subtitle", + label = "", + width = "100%", + placeholder = "Plot Subtitle" + ), + br(), + fluidRow( + column( + width = 7, + colorPickr( + inputId = "upgma_title_color", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "upgma_title_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "upgma_title_size", + label = h5("Title Size", style = "color:white; margin-bottom: 0px"), + value = 30, + min = 15, + max = 40, + step = 1, + width = "80px" + ), + br(), + numericInput( + "upgma_subtitle_size", + label = h5("Subtitle Size", style = "color:white; margin-bottom: 0px"), + value = 20, + min = 15, + max = 40, + step = 1, + width = "80px" + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Sizing"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + align = "center", + br(), + fluidRow( + column( + width = 3, + h5("Ratio", style = "color: white; font-size: 14px;") + ), + column( + width = 6, + align = "left", + div( + class = "ratio-sel", + selectInput( + "upgma_ratio", + "", + choices = c("16:10" = (16/10), "16:9" = (16/9), "4:3" = (4/3)) + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "upgma_size_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + sliderInput( + "upgma_v", + label = "Vertical Position", + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "upgma_h", + label = "Horizontal Position", + min = -0.5, + max = 0.5, + step = 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Size", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + sliderInput( + "upgma_scale", + "", + min = 500, + max = 1200, + value = 800, + step = 5, + width = "95%", + ticks = FALSE + ) + ) + ), + fluidRow( + column( + width = 3, + h5("Zoom", style = "color: white; font-size: 14px; margin-top: 30px") + ), + column( + width = 9, + div( + class = "zoom-slider", + sliderInput( + "upgma_zoom", + label = NULL, + min = 0.5, + max = 1.5, + step = 0.05, + value = 0.95, + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "250px", + column( + width = 12, + align = "left", + h4(p("Tree Scale"), style = "color:white; position: relative; right: -15px"), + column( + width = 12, + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch-layout", + materialSwitch( + "upgma_treescale_show", + h5(p("Show"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + br() + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_treescale_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_treescale_width"), + br(), + uiOutput("upgma_treescale_x"), + br(), + uiOutput("upgma_treescale_y") + ) + ) + ) + ) + ) + ) + ), + column( + width = 12, + align = "left", + h4(p("Legend"), style = "color:white; position: relative; right: -15px; margin-top: 10px; margin-bottom: -2px"), + column( + width = 12, + align = "center", + fluidRow( + column( + width = 7, + align = "left", + prettyRadioButtons( + "upgma_legend_orientation", + "", + choices = c(Horizontal = "horizontal", + Vertical = "vertical"), + selected = c(Vertical = "vertical"), + inline = FALSE + ) + ), + column( + width = 5, + align = "right", + dropMenu( + actionBttn( + "upgma_legend_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + numericInput( + "upgma_legend_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + value = 10, + min = 5, + max = 25, + step = 1, + width = "80px" + ), + br(), + sliderInput( + "upgma_legend_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + value = 0.9, + min = -0.9, + max = 1.9, + step = 0.2, + width = "150px", + ticks = FALSE + ), + br(), + sliderInput( + "upgma_legend_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + value = 0.2, + min = -1.5, + max = 1.5, + step = 0.1, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_controls=='Label'", + column( + width = 4, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Tips"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 4, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "upgma_tiplab_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "center", + uiOutput("upgma_tiplab") + ), + column( + width = 3, + div( + class = "mat-switch-align", + materialSwitch( + "upgma_align", + h5(p("Align"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 1, + align = "right", + dropMenu( + actionBttn( + "upgma_labeltext_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "upgma_tiplab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + width = "150px", + ticks = FALSE + ), + br(), + conditionalPanel( + "!(input.upgma_layout=='inward'|input.upgma_layout=='circular')", + sliderInput( + inputId = "upgma_tiplab_nudge_x", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 0, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_layout=='circular'", + sliderInput( + inputId = "upgma_tiplab_position", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = -0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_layout=='inward'", + sliderInput( + inputId = "upgma_tiplab_position_inw", + label = h5("Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + step = 0.05, + value = 1.1, + width = "150px", + ticks = FALSE + ) + ), + br(), + sliderInput( + inputId = "upgma_tiplab_angle", + label = h5("Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + ticks = FALSE, + width = "150px", + ) + ), + column( + width = 6, + align = "center", + uiOutput("upgma_tiplab_size"), + br(), + selectInput( + "upgma_tiplab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 5px; margin-top: 16px"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px") + ), + column( + width = 4, + align = "center", + colorPickr( + inputId = "upgma_tiplab_color", + width = "100%", + selected = "#000000", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 4, + align = "left", + br(), + div( + class = "mat-switch-geom", + materialSwitch( + "upgma_geom", + h5(p("Panels"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + colorPickr( + inputId = "upgma_tiplab_fill", + width = "100%", + selected = "#84D9A0", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ), + column( + width = 3, + align = "left", + dropMenu( + actionBttn( + "upgma_labelformat_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_tiplab_padding"), + br(), + sliderInput( + inputId = "upgma_tiplab_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.2, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Branches"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 5, + align = "left", + div( + class = "mat-switch-lab", + materialSwitch( + "upgma_show_branch_label", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 5, + align = "center", + uiOutput("upgma_branch_label") + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "upgma_branch_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 6, + align = "center", + sliderInput( + "upgma_branchlab_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 0.65, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "upgma_branch_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ), + br(), + sliderInput( + inputId = "upgma_branch_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = -3, + max = 3, + value = 0, + width = "250px", + ticks = FALSE + ) + ), + column( + width = 6, + align = "center", + uiOutput("upgma_branch_size"), + selectInput( + "upgma_branchlab_fontface", + label = h5("Fontface", style = "color:white; margin-bottom: 0px;"), + width = "250px", + choices = c(Plain = "plain", Bold = "bold", Italic = "italic", `B & I` = "bold.italic") + ), + br(), + sliderInput( + "upgma_branch_labelradius", + label = h5("Smooth edge", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 0.5, + value = 0.5, + width = "250px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -14px; margin-top: 23px; margin-bottom: 109px") + ), + column( + width = 5, + colorPickr( + inputId = "upgma_branch_label_color", + width = "100%", + selected = "#FFB7B7", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ), + br(), br() + ) + ) + ) + ) + ), + column( + width = 3, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "280px", + column( + width = 12, + fluidRow( + column( + width = 12, + align = "left", + h4(p("Custom Labels"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 6, + textInput( + "upgma_new_label_name", + "", + placeholder = "New Label" + ) + ), + column( + width = 3, + actionButton( + "upgma_add_new_label", + "", + icon = icon("plus") + ) + ), + column( + width = 2, + align = "right", + dropMenu( + actionBttn( + "upgma_custom_label_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_custom_labelsize"), + br(), + uiOutput("upgma_sliderInput_y"), + br(), + uiOutput("upgma_sliderInput_x") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 6, + uiOutput("upgma_custom_label_select") + ), + column( + width = 4, + uiOutput("upgma_del_label"), + ) + ), + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_cust_label_save") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_controls=='Elements'", + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Tip Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "upgma_tippoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_tippoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "upgma_tippoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 0.5, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("upgma_tippoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "upgma_tippoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + conditionalPanel( + "input.upgma_tipshape_mapping_show==false", + selectInput( + "upgma_tippoint_shape", + "", + width = "100%", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ) + ), + conditionalPanel( + "input.upgma_tipshape_mapping_show==true", + h5(p("Variable assigned"), style = "color:white; position: relative; right: -15px; margin-top: 30px; font-style: italic") + ), + br() + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Node Points"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "mat-switch", + materialSwitch( + "upgma_nodepoint_show", + h5(p("Show"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 4, + align = "right", + dropMenu( + actionBttn( + "upgma_nodepoint_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + sliderInput( + "upgma_nodepoint_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + value = 1, + min = 0.1, + max = 1, + width = "150px", + ticks = FALSE + ), + br(), + uiOutput("upgma_nodepoint_size") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Color"), style = "color:white; position: relative; right: -15px; margin-top: 36px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "upgma_nodepoint_color", + width = "100%", + selected = "#3A4657", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + fluidRow( + column( + width = 5, + h5(p("Shape"), style = "color:white; position: relative; right: -15px; margin-top: 30px; margin-bottom: 48px") + ), + column( + width = 7, + align = "center", + selectInput( + "upgma_nodepoint_shape", + "", + choices = c( + Circle = "circle", + Square = "square", + Diamond = "diamond", + Triangle = "triangle", + Cross = "cross", + Asterisk = "asterisk" + ) + ), + br() + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Tiles"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 5, + div( + class = "sel-tile-number", + selectInput( + "upgma_tile_number", + "", + choices = 1:5, + width = "70px" + ) + ) + ), + column( + width = 7, + align = "right", + dropMenu( + actionBttn( + "upgma_tile_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + conditionalPanel( + "input.upgma_tile_num == 1", + sliderInput( + "upgma_fruit_alpha", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + sliderInput( + "upgma_fruit_alpha_2", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + sliderInput( + "upgma_fruit_alpha_3", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + sliderInput( + "upgma_fruit_alpha_4", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + sliderInput( + "upgma_fruit_alpha_5", + label = h5("Opacity", style = "color:white; margin-bottom: 0px"), + min = 0.1, + max = 1, + value = 1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 1", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 68px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width2"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_2"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width3"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_3"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width4"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_4"), + br() + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + fluidRow( + column( + width = 5, + h5("Width", style = "color:white; margin-left: 15px; margin-top: 27px;") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_width5"), + br() + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 32px; margin-bottom: 54px") + ), + column( + width = 7, + align = "center", + uiOutput("upgma_fruit_offset_circ_5"), + br() + ) + ) + ) + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 6, + h4(p("Heatmap"), style = "color:white; position: relative; right: -15px") + ) + ), + fluidRow( + column( + width = 3, + h5("Title", style = "color:white; margin-left: 15px; margin-top: 32px;") + ), + column( + width = 6, + align = "center", + textInput( + "upgma_heatmap_title", + label = "", + value = "Heatmap", + placeholder = "Heatmap" + ) + ), + column( + width = 3, + align = "right", + dropMenu( + actionBttn( + "upgma_heatmap_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-end", + theme = "translucent", + fluidRow( + column( + width = 12, + align = "center", + uiOutput("upgma_colnames_angle"), + br(), + uiOutput("upgma_colnames_y") + ) + ) + ) + ) + ), + fluidRow( + column( + width = 5, + h5("Width", style = "color: white; margin-left: 15px; margin-top: 40px;") + ), + column( + width = 7, + uiOutput("upgma_heatmap_width") + ) + ), + fluidRow( + column( + width = 5, + h5("Position", style = "color:white; margin-left: 15px; margin-top: 36px;") + ), + column( + width = 7, + uiOutput("upgma_heatmap_offset") + ) + ), + br(), br() + ) + ) + ), + column( + width = 2, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + height = "295px", + column( + width = 12, + align = "left", + h4(p("Clade Highlight"), style = "color:white; position: relative; right: -15px"), + fluidRow( + column( + width = 12, + div( + class = "mat-switch", + materialSwitch( + "upgma_nodelabel_show", + h5(p("Toggle Node View"), style = "color:white; padding-left: 5px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + fluidRow( + column( + width = 3, + h5(p("Nodes"), style = "color:white; position: relative; right: -15px; margin-top: 20px") + ), + column( + width = 9, + uiOutput("upgma_parentnode") + ) + ), + uiOutput("upgma_clade_scale"), + fluidRow( + column( + width = 5, + h5(p("Form"), style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + div( + class = "sel-clade", + selectInput( + "upgma_clade_type", + "", + choices = c("Rect" = "rect", + "Round" = "roundrect"), + selected = c("Round" = "roundrect") + ) + ) + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.upgma_controls=='Variables'", + column( + width = 7, + box( + solidHeader = TRUE, + status = "info", + width = "100%", + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + align = "center", + h4(p("Element"), style = "color:white; margin-bottom: 20px") + ), + column( + width = 3, + align = "center", + h4(p("Variable"), style = "color:white; margin-bottom: 20px; margin-right: 30px;") + ), + column( + width = 6, + align = "center", + h4(p("Color Scale"), style = "color:white; margin-bottom: 20px") + ) + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_mapping_show", + h5(p("Tip Label Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_color_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tiplab_scale") + ), + uiOutput("upgma_tiplab_mapping_info"), + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tipcolor_mapping_show", + h5(p("Tip Point Color"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tipcolor_mapping") + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tippoint_scale") + ), + uiOutput("upgma_tipcolor_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tipshape_mapping_show", + h5(p("Tip Point Shape"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_tipshape_mapping") + ), + column( + width = 3, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; font-style: italic; position: relative; bottom: -16px; right: -40px;', 'No scale for shapes') + ) + ) + ), + uiOutput("upgma_tipshape_mapping_info") + ), + fluidRow( + column( + width = 3, + fluidRow( + column( + width = 8, + conditionalPanel( + "input.upgma_tile_num == 1", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_1", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px; margin-right: 10px"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_2", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_3", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_4", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + div( + class = "mat-switch-v", + materialSwitch( + "upgma_tiles_show_5", + h5(p("Tile"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ) + ), + column( + width = 4, + align = "left", + div( + class = "tile-sel", + selectInput( + "upgma_tile_num", + "", + choices = 1:5, + width = "50px" + ) + ) + ) + ) + ), + column( + width = 3, + align = "center", + conditionalPanel( + "input.upgma_tile_num == 1", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable2") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable3") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable4") + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + div( + class = "heatmap-scale", + uiOutput("upgma_fruit_variable5") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 1", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_1") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 2", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_2") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 3", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_3") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 4", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_4") + ) + ) + ), + conditionalPanel( + "input.upgma_tile_num == 5", + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_tiles_scale_5") + ) + ) + ), + uiOutput("upgma_fruit_mapping_info") + ), + fluidRow( + column( + width = 3, + div( + class = "mat-switch-v", + materialSwitch( + "upgma_heatmap_show", + h5(p("Heatmap"), style = "color:white; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + ), + column( + width = 3, + align = "center", + uiOutput("upgma_heatmap_sel") + ), + column( + width = 3, + align = "center", + div( + class = "heatmap-scale", + uiOutput("upgma_heatmap_scale") + ) + ), + uiOutput("upgma_heatmap_mapping_info") + ) + ) + ) + ) + ) + ), + br(), br(), br(), br(), br(), br() + ) + ), + + ## Tab Utilities ------------------------------------------------------- + + tabItem( + tabName = "utilities", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Utilities"), style = "color:white") + ) + ), + br(), + hr(), + column( + width = 5, + align = "left", + shinyDirButton( + "hash_dir", + "Choose folder with .fasta files", + title = "Locate folder with loci", + buttonType = "default", + style = "border-color: white; margin: 10px; min-width: 200px; text-align: center" + ), + actionButton("hash_start", "Start Hashing", icon = icon("circle-play")), + shinyjs::hidden( + div(id = "hash_loading", + HTML('')) + ) + ) + # br(), + # actionButton( + # "backup_database", + # "Create backup", + # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + # ), + # br(), + # actionButton( + # "import_db_backup", + # "Restore backup", + # style = "border-color: white; margin: 10px; min-width: 200px; text-align: left" + # ) + ), + + + ## Tab Screening ------------------------------------------------------- + + tabItem( + tabName = "gs_screening", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Screening"), style = "color:white; margin-bottom: -20px;") + ), + column( + width = 7, + align = "left", + uiOutput("gene_screening_info") + ) + ), + br(), + hr(), + fluidRow( + uiOutput("screening_interface") + ) + ), + + ## Tab Resistance Profile ------------------------------------------------------- + + tabItem( + tabName = "gs_profile", + fluidRow( + column( + width = 3, + align = "center", + h2(p("Browse Entries"), style = "color:white; margin-bottom: -20px") + ), + column( + width = 7, + align = "left", + uiOutput("gene_resistance_info") + ) + ), + br(), + hr(), + br(), br(), + uiOutput("gs_table_selection"), + fluidRow( + column(1), + uiOutput("gs_profile_display") + ) + ) + ) # End tabItems + ) # End dashboardPage +) # end UI + +# _______________________ #### + +# Server ---- + +server <- function(input, output, session) { + + phylotraceVersion <- paste("1.5.0") + + #TODO Enable this, or leave disabled + # Kill server on session end + session$onSessionEnded( function() { + stopApp() + }) + + # Disable various user inputs (visualization control) + shinyjs::disable('mst_edge_label') + + ## Functions ---- + + # Function to read and format FASTA sequences + format_fasta <- function(filepath) { + fasta <- readLines(filepath) + formatted_fasta <- list() + current_sequence <- "" + + for (line in fasta) { + if (startsWith(line, ">")) { + if (current_sequence != "") { + formatted_fasta <- append(formatted_fasta, list(current_sequence)) + current_sequence <- "" + } + formatted_fasta <- append(formatted_fasta, list(line)) + } else { + current_sequence <- paste0(current_sequence, line) + } + } + if (current_sequence != "") { + formatted_fasta <- append(formatted_fasta, list(current_sequence)) + } + + formatted_fasta + } + + # Function to color-code the bases in a sequence + color_sequence <- function(sequence) { + sequence <- gsub("A", "A", sequence) + sequence <- gsub("T", "T", sequence) + sequence <- gsub("G", "G", sequence) + sequence <- gsub("C", "C", sequence) + sequence + } + + # Function to log messages to logfile + log_message <- function(log_file, message, append = TRUE) { + cat(format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "-", message, "\n", file = log_file, append = append) + } + + # Modified gheatmap function + gheatmap.mod <- function(p, data, offset=0, width=1, low="green", high="red", color="white", + colnames=TRUE, colnames_position="bottom", colnames_angle=0, colnames_level=NULL, + colnames_offset_x = 0, colnames_offset_y = 0, font.size=4, family="", hjust=0.5, legend_title = "value", + colnames_color = "black") { + + colnames_position %<>% match.arg(c("bottom", "top")) + variable <- value <- lab <- y <- NULL + + ## if (is.null(width)) { + ## width <- (p$data$x %>% range %>% diff)/30 + ## } + + ## convert width to width of each cell + width <- width * (p$data$x %>% range(na.rm=TRUE) %>% diff) / ncol(data) + + isTip <- x <- y <- variable <- value <- from <- to <- NULL + + ## handle the display of heatmap on collapsed nodes + ## https://github.com/GuangchuangYu/ggtree/issues/242 + ## extract data on leaves (& on collapsed internal nodes) + ## (the latter is extracted only when the input data has data on collapsed + ## internal nodes) + df <- p$data + nodeCo <- intersect(df %>% filter(is.na(x)) %>% + select(.data$parent, .data$node) %>% unlist(), + df %>% filter(!is.na(x)) %>% + select(.data$parent, .data$node) %>% unlist()) + labCo <- df %>% filter(.data$node %in% nodeCo) %>% + select(.data$label) %>% unlist() + selCo <- intersect(labCo, rownames(data)) + isSel <- df$label %in% selCo + + df <- df[df$isTip | isSel, ] + start <- max(df$x, na.rm=TRUE) + offset + + dd <- as.data.frame(data) + ## dd$lab <- rownames(dd) + i <- order(df$y) + + ## handle collapsed tree + ## https://github.com/GuangchuangYu/ggtree/issues/137 + i <- i[!is.na(df$y[i])] + + lab <- df$label[i] + ## dd <- dd[lab, , drop=FALSE] + ## https://github.com/GuangchuangYu/ggtree/issues/182 + dd <- dd[match(lab, rownames(dd)), , drop = FALSE] + + + dd$y <- sort(df$y) + dd$lab <- lab + ## dd <- melt(dd, id=c("lab", "y")) + dd <- gather(dd, variable, value, -c(lab, y)) + + i <- which(dd$value == "") + if (length(i) > 0) { + dd$value[i] <- NA + } + if (is.null(colnames_level)) { + dd$variable <- factor(dd$variable, levels=colnames(data)) + } else { + dd$variable <- factor(dd$variable, levels=colnames_level) + } + V2 <- start + as.numeric(dd$variable) * width + mapping <- data.frame(from=dd$variable, to=V2) + mapping <- unique(mapping) + + dd$x <- V2 + dd$width <- width + dd[[".panel"]] <- factor("Tree") + if (is.null(color)) { + p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, inherit.aes=FALSE) + } else { + p2 <- p + geom_tile(data=dd, aes(x, y, fill=value), width=width, color=color, inherit.aes=FALSE) + } + if (is(dd$value,"numeric")) { + p2 <- p2 + scale_fill_gradient(low=low, high=high, na.value=NA, name = legend_title) # "white") + } else { + p2 <- p2 + scale_fill_discrete(na.value=NA, name = legend_title) #"white") + } + + if (colnames) { + if (colnames_position == "bottom") { + y <- 0 + } else { + y <- max(p$data$y) + 1 + } + mapping$y <- y + mapping[[".panel"]] <- factor("Tree") + p2 <- p2 + geom_text(data=mapping, aes(x=to, y = y, label=from), color = colnames_color, size=font.size, family=family, inherit.aes = FALSE, + angle=colnames_angle, nudge_x=colnames_offset_x, nudge_y = colnames_offset_y, hjust=hjust) + } + + p2 <- p2 + theme(legend.position="right") + ## p2 <- p2 + guides(fill = guide_legend(override.aes = list(colour = NULL))) + + if (!colnames) { + ## https://github.com/GuangchuangYu/ggtree/issues/204 + p2 <- p2 + scale_y_continuous(expand = c(0,0)) + } + + attr(p2, "mapping") <- mapping + return(p2) + } + + # Get rhandsontable + get.entry.table.meta <- reactive({ + if(!is.null(hot_to_r(input$db_entries))){ + table <- hot_to_r(input$db_entries) + select(select(table, -13), 1:(12 + nrow(DB$cust_var))) + } + }) + + # Function to find columns with varying values + var_alleles <- function(dataframe) { + + varying_columns <- c() + + for (col in 1:ncol(dataframe)) { + unique_values <- unique(dataframe[, col]) + + if (length(unique_values) > 1) { + varying_columns <- c(varying_columns, col) + } + } + + return(varying_columns) + } + + # Functions to compute hamming distances dependent on missing value handling + hamming.dist <- function(x, y) { + sum(x != y) + } + + hamming.distIgnore <- function(x, y) { + sum( (x != y) & !is.na(x) & !is.na(y) ) + } + + hamming.distCategory <- function(x, y) { + sum((x != y | xor(is.na(x), is.na(y))) & !(is.na(x) & is.na(y))) + } + + compute.distMatrix <- function(profile, hamming.method) { + mat <- as.matrix(profile) + n <- nrow(mat) + dist_mat <- matrix(0, n, n) + for (i in 1:(n-1)) { + for (j in (i+1):n) { + dist_mat[i, j] <- hamming.method(x = mat[i, ], y = mat[j, ]) + dist_mat[j, i] <- dist_mat[i, j] + } + } + return(dist_mat) + } + + # Function to determine entry table height + table_height <- reactive({ + if (input$table_height == TRUE) { + NULL + } else {900} + }) + + # Function to determine distance matrix height + distancematrix_height <- reactive({ + if(DB$distancematrix_nrow > 33) { + 800 + } else {NULL} + }) + + # Function to missing value table height + miss.val.height <- reactive({ + if(input$miss_val_height == TRUE) { + NULL + } else {800} + }) + + #Function to check custom variable classes + column_classes <- function(df) { + sapply(df, function(x) { + if (class(x) == "numeric") { + return("cont") + } else if (class(x) == "character") { + return("categ") + } else { + return(class(x)) + } + }) + } + + # Function to hash database + hash_database <- function(folder) { + loci_files <- list.files(folder) + loci_names <- sapply(strsplit(loci_files, "[.]"), function(x) x[1]) + loci_paths <- file.path(folder, loci_files) + + hashes <- sapply(loci_paths, hash_locus) + names(hashes) <- loci_names + hashes + } + + # Function to hash a locus + hash_locus <- function(locus_path) { + locus_file <- readLines(locus_path) + seq_list <- locus_file[seq(2, length(locus_file), 3)] + seq_hash <- sha256(seq_list) + seq_idx <- paste0(">", seq_hash) + + locus_file[seq(1, length(locus_file), 3)] <- seq_idx + writeLines(locus_file, locus_path) + + seq_hash + } + + # Get locus hashes + get_locus_hashes <- function(locus_path) { + locus_file <- readLines(locus_path) + hash_list <- locus_file[seq(1, length(locus_file), 3)] + hash_list <- sapply(strsplit(hash_list, "[>]"), function(x) x[2]) + } + + extract_seq <- function(locus_path, hashes) { + locus_file <- readLines(locus_path) + hash_list <- sapply(strsplit(locus_file[seq(1, length(locus_file), 3)], "[>]"), function(x) x[2]) + seq_list <- locus_file[seq(2, length(locus_file), 3)] + seq_idx <- hash_list %in% hashes + + list( + idx = hash_list[seq_idx], + seq = seq_list[seq_idx] + ) + } + + add_new_sequences <- function(locus_path, sequences) { + locus_file <- file(locus_path, open = "a+") + for (i in seq_along(sequences$idx)) { + writeLines(c("", paste0(">", sequences$idx[i]), sequences$seq[i]), locus_file) + } + close(locus_file) + } + + # Compute clusters to use in visNetwork + compute_clusters <- function(nodes, edges, threshold) { + groups <- rep(0, length(nodes$id)) + edges_groups <- rep(0, length(edges$from)) + + edges_table <- data.frame( + from = edges$from, + to = edges$to, + weight = edges$weight + ) + + count <- 0 + while (any(groups == 0)) { + group_na <- groups == 0 + labels <- nodes$id[group_na] + + cluster <- nodes$id[group_na][1] # Initialize with 1 label + while (!is_empty(labels)) { + sub_tb <- edges_table[(edges_table$from %in% cluster | edges_table$to %in% cluster) & edges_table$weight <= threshold,] + + if (nrow(sub_tb) == 0 | length(unique(c(sub_tb$from, sub_tb$to))) == length(cluster)) { + count <- count + 1 + groups[nodes$id %in% cluster] <- paste("Group", count) + edges_groups[edges$from %in% cluster & edges$to %in% cluster] <- paste("Group", count) + break + } else { + cluster <- unique(c(sub_tb$from, sub_tb$to)) + } + } + } + list(groups = groups, + edges = edges_groups) + } + + # Check gene screening status + check_status <- function(isolate) { + iso_name <- gsub(".zip", "", basename(isolate)) + if(file.exists(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", iso_name, "status.txt"))) { + if(str_detect(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", iso_name, "status.txt"))[1], + "successfully")) { + return("success") + } else { + return("fail") + } + } else {return("unfinished")} + } + + # Reset gene screening status + remove.screening.status <- function(isolate) { + if(file.exists(file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Isolates", + isolate, + "status.txt"))) { + file.remove( + file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Isolates", + isolate, + "status.txt") + ) + } + } + + # Truncate hashes + truncHash <- function(hash) { + if(!is.na(hash)) { + paste0(str_sub(hash, 1, 4), "...", str_sub(hash, nchar(hash) - 3, nchar(hash))) + } else {NA} + } + + # Function to check for duplicate isolate IDs for multi typing start + dupl_mult_id <- reactive({ + req(Typing$multi_sel_table) + if(!is.null(DB$data)) { + selection <- Typing$multi_sel_table[which(unlist(Typing$multi_sel_table$Files) %in% unlist(DB$data["Assembly ID"])),] + selection$Files + } else {""} + }) + + # Function to check single typing log file + check_new_entry <- reactive({ + + invalidateLater(5000, session) + + if(!is.null(DB$database)) { + if(file_exists(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds"))) { + + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) + + if(is.null(DB$data)) { + if(nrow(Database[["Typing"]]) >= 1) { + TRUE + } else {FALSE} + } else { + if(nrow(DB$data) < nrow(Database[["Typing"]])) { + TRUE + } else { + FALSE + } + } + } else {FALSE} + } + }) + + # Render Entry Table Highlights + + diff_allele <- reactive({ + if (!is.null(DB$data) & !is.null(input$compare_select) & !is.null(DB$cust_var)) { + var_alleles(select(DB$data, input$compare_select)) + (13 + nrow(DB$cust_var)) + } + }) + + err_thresh <- reactive({ + if (!is.null(DB$data) & !is.null(DB$number_loci)) { + which(as.numeric(DB$data[["Errors"]]) >= (DB$number_loci * 0.05)) + } + }) + + err_thresh_na <- reactive({ + if (!is.null(DB$na_table) & !is.null(DB$number_loci)) { + which(as.numeric(DB$na_table[["Errors"]]) >= (DB$number_loci * 0.05)) + } + }) + + true_rows <- reactive({ + if (!is.null(DB$data)) { + which(DB$data$Include == TRUE) + } + }) + + duplicated_names <- reactive({ + if (!is.null(DB$meta)) { + which(duplicated(DB$meta$`Assembly Name`) | duplicated(DB$meta$`Assembly Name`, fromLast = TRUE)) + } + }) + + duplicated_ids <- reactive({ + if (!is.null(DB$meta)) { + which(duplicated(DB$meta$`Assembly ID`) | duplicated(DB$meta$`Assembly ID`, fromLast = TRUE)) + } + }) + + # _______________________ #### + + ## Startup ---- + shinyjs::addClass(selector = "body", class = "sidebar-collapse") + shinyjs::removeClass(selector = "body", class = "sidebar-toggle") + + output$messageMenu <- renderText({ + HTML(format(Sys.time(), "%Y-%m-%d %H:%M:%S %Z")) + }) + + # Initiate logging + if(!dir_exists(paste0(getwd(), "/logs"))) { + dir_create(paste0(getwd(), "/logs")) + } + + logfile <- file.path(paste0(getwd(), "/logs/phylotrace.log")) + + log <- log_open(logfile, logdir = FALSE) + + log_print("Session started") + + # Clear screening file + if(file.exists(paste0(getwd(), "/execute/screening/output_file.tsv"))) { + file.remove(paste0(getwd(), "/execute/screening/output_file.tsv")) + } + + if(file.exists(paste0(getwd(), "/execute/screening/error.txt"))) { + file.remove(paste0(getwd(), "/execute/screening/error.txt")) + } + + # Declare reactive variables + Startup <- reactiveValues(sidebar = TRUE, + header = TRUE) # reactive variables related to startup process + + DB <- reactiveValues(data = NULL, + block_db = FALSE, + load_selected = TRUE, + no_na_switch = FALSE, + first_look = FALSE) # reactive variables related to local database + + Typing <- reactiveValues(table = data.frame(), + single_path = data.frame(), + progress = 0, + progress_format_start = 0, + progress_format_end = 0, + result_list = NULL, + status = "") # reactive variables related to typing process + + Screening <- reactiveValues(status = "idle", + picker_status = TRUE, + first_result = NULL) # reactive variables related to gene screening + + Vis <- reactiveValues(cluster = NULL, + metadata = list(), + custom_label_nj = data.frame(), + nj_label_pos_y = list(), + nj_label_pos_x = list(), + nj_label_size = list(), + custom_label_upgma = data.frame(), + upgma_label_pos_y = list(), + upgma_label_pos_x = list(), + upgma_label_size = list()) # reactive variables related to visualization + + Report <- reactiveValues() # reactive variables related to report functions + + Scheme <- reactiveValues() # reactive variables related to scheme functions + + # Load last used database if possible + if(paste0(getwd(), "/execute/last_db.rds") %in% dir_ls(paste0(getwd(), "/execute"))) { + DB$last_db <- TRUE + } + + # Locate local Database + observe({ + shinyDirChoose(input, + "db_location", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session) + + if(!is.null(DB$select_new)) { + if(DB$select_new == FALSE) { + if(DB$block_db == FALSE) { + DB$database <- as.character( + parseDirPath( + roots = c(Home = path_home(), Root = "/"), + input$db_location + ) + ) + + DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present + + DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available + } + + } else if (DB$select_new == TRUE) { + DB$database <- paste0(DB$new_database, "/Database") + + } + } else { + if(!is.null(DB$last_db) & file.exists(paste0(getwd(), "/execute/last_db.rds"))) { + + DB$database <- readRDS(paste0(getwd(), "/execute/last_db.rds")) + + if(dir_exists(DB$database)) { + DB$exist <- (length(dir_ls(DB$database)) == 0) # Logical any local database present + + DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) # List of local schemes available + } + } + } + }) + + ### Set up typing environment ---- + + # Null typing progress trackers + writeLines("0", paste0(getwd(), "/logs/script_log.txt")) + writeLines("0\n", paste0(getwd(), "/logs/progress.txt")) + + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + } + + # Reset typing feedback values + Typing$pending <- FALSE + Typing$multi_started <- FALSE + Typing$multi_help <- FALSE + saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) + Typing$last_success <- "0" # Null last multi typing success name + Typing$last_failure <- "0" # Null last multi typing failure name + + ### Landing page UI ---- + observe({ + if (Startup$sidebar == FALSE) { + shinyjs::removeClass(selector = "body", class = "sidebar-collapse") + shinyjs::addClass(selector = "body", class = "sidebar-toggle") + } + }) + + output$start_message <- renderUI({ + column( + width = 12, + align = "center", + br(), br(), br(), br(), br(), br(), + div( + class = "image", + imageOutput("imageOutput") + ), + br(), br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 16px;', 'Proceed by loading a compatible local database or create a new one.') + ) + ) + ), + br(), + fluidRow( + column( + width = 6, + align = "right", + shinyDirButton( + "db_location", + "Browse", + icon = icon("folder-open"), + title = "Locate the database folder", + buttonType = "default", + root = path_home() + ) + ), + column( + width = 6, + align = "left", + shinyDirButton( + "create_new_db", + "Create New", + icon = icon("plus"), + title = "Choose location for new PhyloTrace database", + buttonType = "default", + root = path_home() + ) + ) + ), + br(), br(), + fluidRow( + column( + width = 12, + align = "center", + uiOutput("load_db"), + br(), br(), br(), br(), br(), br(), br() + ) + ) + ) + }) + + # User selection new db or load db + observeEvent(input$create_new_db, { + log_print("Input create_new_db") + DB$select_new <- TRUE + }) + + observeEvent(input$db_location, { + log_print("Input db_location") + DB$select_new <- FALSE + }) + + # Load db & scheme selection UI + output$load_db <- renderUI({ + if(!is.null(DB$select_new)) { + if(length(DB$new_database) > 0 & DB$select_new) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px;', + HTML( + paste( + 'New database will be created in', + DB$new_database + ) + ) + ) + ), + br(), + actionButton( + "load", + "Create", + class = "load-start" + ) + ) + } else if(length(DB$available) > 0 & !(DB$select_new)) { + if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Selected:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), + p( + HTML( + paste( + tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', + 'Warning: Folder contains invalid elements.') + ) + ) + ), + br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } else { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Selected:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } + } + } else if((!is.null(DB$last_db)) & (!is.null(DB$available))) { + if (DB$last_db == TRUE & (length(DB$available) > 0)) { + if(any(!(gsub(" ", "_", DB$available) %in% schemes))) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Last used:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), + p( + HTML( + paste( + tags$span(style='color: #E18B00; font-size: 13px; font-style: italic;', + 'Warning: Folder contains invalid elements.') + ) + ) + ), + br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } else { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Last used:', DB$database) + ) + ) + ), + uiOutput("scheme_db"), + br(), br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } + } else if (DB$last_db == TRUE & (length(DB$available) == 0)) { + column( + width = 12, + p( + tags$span( + style='color: white; font-size: 15px; font-style: italic;', + HTML( + paste('Last used:', DB$database) + ) + ) + ), + br(), + actionButton( + "load", + "Load", + class = "load-start" + ) + ) + } + } + }) + + output$imageOutput <- renderImage({ + # Path to your PNG image with a transparent background + image_path <- paste0(getwd(), "/www/PhyloTrace.png") + + # Use HTML to display the image with the tag + list(src = image_path, + height = 180) + }, deleteFile = FALSE) + + ### Load app event ---- + + observeEvent(input$load, { + + # Reset reactive screening variables + output$screening_start <- NULL + output$screening_result_sel <- NULL + output$screening_result <- NULL + output$screening_fail <- NULL + Screening$status_df <- NULL + Screening$choices <- NULL + Screening$picker_status <- TRUE + Screening$status <- "idle" + Screening$first_result <- NULL + if(!is.null(input$screening_select)) { + if(!is.null(DB$data)) { + updatePickerInput(session, "screening_select", selected = character(0)) + } + } + + log_print("Input load") + + # set typing start control variable + Typing$reload <- TRUE + + # reset typing status on start( + if(Typing$status == "Finalized") {Typing$status <- "Inactive"} + if(!is.null(Typing$single_path)) {Typing$single_path <- data.frame()} + + #### Render status bar ---- + observe({ + req(DB$scheme) + + if(is.null(input$scheme_position)) { + output$loaded_scheme <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Selected scheme:   ", + DB$scheme, + "")), + style = "color:white;") + ) + ) + }) + } + + if(!is.null(input$scheme_position)) { + output$loaded_scheme <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Selected scheme:   ", + DB$scheme, + "")), + style = "color:white;"), + div( + class = "reload-bttn", + style = paste0("margin-left:", 30 + input$scheme_position, "px; position: relative; top: -24px;"), + actionButton( + "reload_db", + label = "", + icon = icon("rotate") + ) + ) + ) + ) + }) + } + }) + + observe({ + if(!is.null(DB$database)){ + if(nchar(DB$database) > 60) { + database <- paste0(substring(DB$database, first = 1, last = 60), "...") + } else { + database <- DB$database + } + output$databasetext <- renderUI({ + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Database:   ", + database, + "")), + style = "color:white;") + ), + if(nchar(database) > 60) {bsTooltip("databasetext", + HTML(DB$database), + placement = "bottom", + trigger = "hover")} + ) + }) + } + }) + + observe({ + if(!is.null(DB$database)) { + if(Typing$status == "Finalized"){ + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    typing finalized")), + style = "color:white;") + ) + ) + ) + } else if(Typing$status == "Attaching"){ + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    evaluating typing results")), + style = "color:white;") + ) + ) + ) + } else if(Typing$status == "Processing") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    pending typing")), + style = "color:white;") + ) + ) + ) + } else if(Screening$status == "started") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    pending gene screening")), + style = "color:white;") + ) + ) + ) + } else if(Screening$status == "finished") { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    gene screening finalized")), + style = "color:white;") + ) + ) + ) + } else { + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    ready")), + style = "color:white;") + ) + ) + ) + } + } + }) + + # Null single typing status + if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + Typing$progress <- 0 + + Typing$progress_format <- 900000 + + output$single_typing_progress <- NULL + + output$typing_fin <- NULL + + output$single_typing_results <- NULL + + output$typing_formatting <- NULL + + Typing$single_path <- data.frame() + + # reset results file + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + # Resetting single typing progress logfile bar + con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") + + cat("0\n", file = con) + + close(con) + } + } + + shinyjs::runjs( + 'if(document.querySelector("#loaded_scheme > div > li > span") !== null) { + // Select the span element + let spanElement = document.querySelector("#loaded_scheme > div > li > span"); + + // Get the bounding rectangle of the span element + let rect = spanElement.getBoundingClientRect(); + + // Extract the width + let width = rect.width; + + Shiny.setInputValue("scheme_position", width); + }' + ) + + # Load app elements based on database availability and missing value presence + if(!is.null(DB$select_new)) { + if(DB$select_new & (paste0(DB$new_database, "/Database") %in% dir_ls(DB$new_database))) { + + log_print("Directory already contains a database") + + show_toast( + title = "Directory already contains a database", + type = "error", + position = "bottom-end", + timer = 6000 + ) + DB$load_selected <- FALSE + + } else if(DB$select_new | (DB$select_new == FALSE & is.null(input$scheme_db))) { + + log_print(paste0("New database created in ", DB$new_database)) + + DB$check_new_entries <- TRUE + DB$data <- NULL + DB$meta_gs <- NULL + DB$meta <- NULL + DB$meta_true <- NULL + DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL + DB$allelic_profile_true <- NULL + + # null Distance matrix, entry table and plots + output$db_distancematrix <- NULL + output$db_entries_table <- NULL + output$tree_mst <- NULL + output$tree_nj <- NULL + output$tree_upgma <- NULL + + # null report values + Report$report_list_mst <- list() + Report$report_list_nj <- list() + Report$report_list_upgma <- list() + + # null plots + Vis$nj <- NULL + Vis$upgma <- NULL + Vis$ggraph_1 <- NULL + + removeModal() + + #### Render Menu Items ---- + + Startup$sidebar <- FALSE + Startup$header <- FALSE + + output$menu_sep2 <- renderUI(hr()) + + # Hide start message + output$start_message <- NULL + + DB$load_selected <- FALSE + + # Declare database path + DB$database <- file.path(DB$new_database, "Database") + + # Set database availability screening variables to present database + DB$block_db <- TRUE + DB$select_new <- FALSE + + # Render menu with Manage Schemes as start tab and no Missing values tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + # Dont render these elements + output$db_no_entries <- NULL + output$distancematrix_no_entries <- NULL + output$db_entries <- NULL + output$edit_index <- NULL + output$edit_scheme_d <- NULL + output$edit_entries <- NULL + output$compare_select <- NULL + output$delete_select <- NULL + output$del_bttn <- NULL + output$compare_allele_box <- NULL + output$download_entries <- NULL + output$missing_values <- NULL + output$delete_box <- NULL + output$missing_values_sidebar <- NULL + output$distmatrix_sidebar <- NULL + output$download_scheme_info <- NULL + output$download_loci <- NULL + output$entry_table_controls <- NULL + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$pending_typing <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + } + } else { + log_print(paste0("Loading existing ", input$scheme_db, " database from ", DB$database)) + } + + if(DB$load_selected == TRUE) { + + if(gsub(" ", "_", input$scheme_db) %in% schemes) { #Check if selected scheme valid + + # Save database path for next start + saveRDS(DB$database, paste0(getwd(), "/execute/last_db.rds")) + + DB$check_new_entries <- TRUE + DB$data <- NULL + DB$meta_gs <- NULL + DB$meta <- NULL + DB$meta_true <- NULL + DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL + DB$allelic_profile_true <- NULL + DB$scheme <- input$scheme_db + + # null Distance matrix, entry table and plots + output$db_distancematrix <- NULL + output$db_entries_table <- NULL + output$tree_mst <- NULL + output$tree_nj <- NULL + output$tree_upgma <- NULL + + # null typing initiation UI + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$pending_typing <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + # null report values + Report$report_list_mst <- list() + Report$report_list_nj <- list() + Report$report_list_upgma <- list() + + # null plots + Vis$nj <- NULL + Vis$upgma <- NULL + Vis$ggraph_1 <- NULL + + removeModal() + + #### Render Menu Items ---- + + Startup$sidebar <- FALSE + Startup$header <- FALSE + + output$menu_sep2 <- renderUI(hr()) + + # Hide start message + output$start_message <- NULL + + if(any(grepl(gsub(" ", "_", DB$scheme), dir_ls(DB$database)))) { + + if(!any(grepl("alleles", dir_ls(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme)))))) { + + log_print("Missing loci files") + + # Show message that loci files are missing + showModal( + modalDialog( + paste0("Whoops! No loci files are present in the local ", + DB$scheme, + " folder. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } else if (!any(grepl("scheme_info.html", dir_ls(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme)))))) { + + output$download_scheme_info <- NULL + + log_print("Scheme info file missing") + + # Show message that scheme info is missing + showModal( + modalDialog( + paste0("Whoops! Scheme info of the local ", + DB$scheme, + " database is missing. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + } else if (!any(grepl("targets.csv", dir_ls(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme)))))) { + + # Dont render target download button + output$download_loci <- NULL + + log_print("Missing loci info (targets.csv)") + + # Show message that scheme info is missing + showModal( + modalDialog( + paste0("Whoops! Loci info of the local ", + DB$scheme, + " database is missing. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + } else { + # Produce Scheme Info Table + schemeinfo <- + read_html(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme), + "/scheme_info.html" + )) %>% + html_table(header = FALSE) %>% + as.data.frame(stringsAsFactors = FALSE) + names(schemeinfo) <- NULL + DB$schemeinfo <- schemeinfo + number_loci <- as.vector(DB$schemeinfo[6, 2]) + DB$number_loci <- as.numeric(gsub(",", "", number_loci)) + + # Produce Loci Info table + DB$loci_info <- read.csv( + file.path(DB$database, gsub(" ", "_", DB$scheme), "targets.csv"), + header = TRUE, + sep = "\t", + row.names = NULL, + colClasses = c( + "NULL", + "character", + "character", + "integer", + "integer", + "character", + "integer", + "NULL" + ) + ) + + # Check if number of loci/fastq-files of alleles is coherent with number of targets in scheme + if(DB$number_loci > length(dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles")))) { + + log_print(paste0("Loci files are missing in the local ", DB$scheme, " folder")) + + # Show message that loci files are missing + showModal( + modalDialog( + paste0("Whoops! Some loci files are missing in the local ", + DB$scheme, + " folder. Download the scheme again (no influence on already typed assemblies)."), + title = "Local Database Error", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Okay") + ) + ) + ) + + # Render menu with Manage Schemes as start tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group"), + selected = TRUE + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + } else { + ###### Alle checks bestanden -> Laden der DTB + # If typed entries present + if (any(grepl("Typing.rds", dir_ls(paste0( + DB$database, "/", gsub(" ", "_", DB$scheme) + ))))) { + + # Load database from files + Database <- readRDS(file.path(DB$database, + gsub(" ", "_", DB$scheme), + "Typing.rds")) + + DB$data <- Database[["Typing"]] + + if(!is.null(DB$data)){ + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + } else { + DB$cust_var <- data.frame() + } + } + + DB$change <- FALSE + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + + # Null pipe + con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") + + cat("0\n", file = con) + + # Close the file connection + close(con) + + # Reset other reactive typing variables + Typing$progress_format_end <- 0 + Typing$progress_format_start <- 0 + Typing$pending_format <- 0 + Typing$entry_added <- 0 + Typing$progress <- 0 + Typing$progress_format <- 900000 + output$single_typing_progress <- NULL + output$typing_fin <- NULL + output$single_typing_results <- NULL + output$typing_formatting <- NULL + Typing$single_path <- data.frame() + + # Null multi typing feedback variable + Typing$reset <- TRUE + + # Check need for new missing vlaue display + if(DB$first_look == TRUE) { + if(sum(apply(DB$data, 1, anyNA)) >= 1) { + DB$no_na_switch <- TRUE + } else { + DB$no_na_switch <- FALSE + } + } + + DB$first_look <- TRUE + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + if(!anyNA(DB$allelic_profile)) { + + # no NA's -> dont render missing values sidebar elements + output$missing_values_sidebar <- NULL + + # Render menu if no NA's present + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } else { + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries", + selected = TRUE + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } + + # Render custom variable display + output$show_cust_var <- renderTable( + width = "100%", + { + if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { + if(nrow(DB$cust_var) > 5) { + low <- -4 + high <- 0 + for (i in 1:input$cust_var_select) { + low <- low + 5 + if((nrow(DB$cust_var) %% 5) != 0) { + if(i == ceiling(nrow(DB$cust_var) / 5 )) { + high <- high + nrow(DB$cust_var) %% 5 + } else { + high <- high + 5 + } + } else { + high <- high + 5 + } + } + DB$cust_var[low:high,] + } else { + DB$cust_var + } + } else if (!is.null(DB$cust_var)) { + DB$cust_var + } + }) + + # render visualization sidebar elements + observe({ + Vis$tree_algo <- input$tree_algo + }) + + output$visualization_sidebar <- renderUI({ + if(!is.null(DB$data)) { + column( + width = 12, + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + prettyRadioButtons( + "tree_algo", + choices = c("Minimum-Spanning", "Neighbour-Joining", "UPGMA"), + label = "", + selected = if(!is.null(Vis$tree_algo)){Vis$tree_algo} else {"Minimum-Spanning"} + ), + ) + ), + br(), + fluidRow( + column( + width = 12, + align = "center", + tags$div( + id = "button-wrapper", + actionButton( + "create_tree", + h5("Create Tree", style = "position: relative; left: 15px; color: white; font-size: 15px;"), + width = "100%" + ), + tags$img( + src = "phylo.png", + alt = "icon", + class = "icon" + ) + ) + ) + ), + br(), + hr(), + conditionalPanel( + "input.tree_algo=='Minimum-Spanning'", + fluidRow( + column( + width = 12, + align = "left", + br(), + HTML( + paste( + tags$span(style='color: white; font-size: 16px; margin-left: 15px', "Sizing") + ) + ) + ) + ), + fluidRow( + column( + width = 12, + radioGroupButtons( + "mst_ratio", + "", + choiceNames = c("16:10", "16:9", "4:3"), + choiceValues = c((16/10), (16/9), (4/3)), + width = "100%" + ), + br(), + sliderInput( + "mst_scale", + "", + min = 500, + max = 1200, + step = 5, + value = 800, + width = "95%", + ticks = FALSE + ) + ) + ), + br(), + hr(), + fluidRow( + column( + width = 12, + column( + width = 5, + align = "left", + conditionalPanel( + "input.mst_plot_format=='jpeg'", + actionBttn( + "save_plot_jpeg", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + conditionalPanel( + "input.mst_plot_format=='png'", + actionBttn( + "save_plot_png", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + conditionalPanel( + "input.mst_plot_format=='bmp'", + actionBttn( + "save_plot_bmp", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + conditionalPanel( + "input.mst_plot_format=='html'", + downloadBttn( + "save_plot_html", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ) + ), + column( + width = 7, + div( + style = "max-width: 150px", + class = "format", + selectInput( + inputId = "mst_plot_format", + label = "", + choices = c("html", "jpeg", "png", "bmp") + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.tree_algo=='Neighbour-Joining'", + fluidRow( + column( + width = 12, + column( + width = 5, + align = "left", + downloadBttn( + "download_nj", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + column( + width = 7, + div( + style = "max-width: 150px", + class = "format", + selectInput( + inputId = "filetype_nj", + label = "", + choices = c("png", "jpeg", "bmp", "svg") + ) + ) + ) + ) + ) + ), + conditionalPanel( + "input.tree_algo=='UPGMA'", + fluidRow( + column( + width = 12, + column( + width = 5, + align = "left", + downloadBttn( + "download_upgma", + style = "simple", + label = "Save Plot", + size = "sm", + icon = NULL, + color = "primary" + ) + ), + column( + width = 7, + div( + style = "max-width: 150px", + class = "format", + selectInput( + inputId = "filetype_upgma", + label = "", + choices = c("png", "jpeg", "bmp", "svg") + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 6, + align = "left", + br(), + actionButton( + "create_rep", + "Print Report" + ) + ) + ) + ) + } + }) + + # Render entry table sidebar elements + output$entrytable_sidebar <- renderUI({ + if(!is.null(DB$data)) { + column( + width = 12, + align = "center", + br(), + fluidRow( + column(1), + column( + width = 10, + align = "left", + if(nrow(DB$data) > 40) { + div( + class = "mat-switch-db-tab", + materialSwitch( + "table_height", + h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + } + ) + ), + br(), br(), + fluidRow( + column( + width = 12, + HTML( + paste( + tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Custom Variables') + ) + ) + ) + ), + fluidRow( + column( + width = 8, + textInput( + "new_var_name", + label = "", + placeholder = "New Variable" + ) + ), + column( + width = 2, + actionButton( + "add_new_variable", + "", + icon = icon("plus") + ) + ) + ), + fluidRow( + column( + width = 8, + align = "left", + div( + class = "textinput_var", + selectInput( + "del_which_var", + "", + DB$cust_var$Variable + ) + ) + ), + column( + width = 2, + align = "left", + actionButton( + "delete_new_variable", + "", + icon = icon("minus") + ) + ) + ), + br(), + fluidRow( + column(1), + column( + width = 4, + uiOutput("cust_var_info") + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + tableOutput("show_cust_var") + ) + ), + fluidRow( + column(4), + column( + width = 7, + align = "center", + uiOutput("cust_var_select") + ) + ) + ) + } + }) + + # Render missing values sidebar elements + output$missing_values_sidebar <- renderUI({ + column( + width = 12, + fluidRow( + column( + width = 12, + br(), + materialSwitch( + "miss_val_height", + h5(p("Show Full Table"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + br() + ), + fluidRow( + column( + width = 6, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: -23px; right: -15px', + 'Download CSV') + ) + ) + ), + column( + width = 4, + downloadBttn( + "download_na_matrix", + style = "simple", + label = "", + size = "sm", + icon = icon("download") + ) + ) + ) + ) + }) + + # Render scheme info download button + output$download_loci <- renderUI({ + column( + 12, + downloadBttn( + "download_loci_info", + style = "simple", + label = "", + size = "sm", + icon = icon("download"), + color = "primary" + ), + bsTooltip("download_loci_info_bttn", HTML("Save loci information
(without sequence)"), placement = "top", trigger = "hover") + ) + }) + + # Render scheme info download button + output$download_scheme_info <- renderUI({ + downloadBttn( + "download_schemeinfo", + style = "simple", + label = "", + size = "sm", + icon = icon("download"), + color = "primary" + ) + }) + + # Render distance matrix sidebar + output$distmatrix_sidebar <- renderUI({ + column( + width = 12, + align = "left", + fluidRow( + column( + width = 12, + align = "center", + selectInput( + "distmatrix_label", + label = "", + choices = c("Index", "Assembly Name", "Assembly ID"), + selected = c("Assembly Name"), + width = "100%" + ), + br() + ) + ), + div( + class = "mat-switch-dmatrix", + materialSwitch( + "distmatrix_true", + h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + div( + class = "mat-switch-dmatrix", + materialSwitch( + "distmatrix_triangle", + h5(p("Show Upper Triangle"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + div( + class = "mat-switch-dmatrix-last", + materialSwitch( + "distmatrix_diag", + h5(p("Show Diagonal"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = TRUE, + right = TRUE + ) + ), + fluidRow( + column( + width = 6, + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: relative; bottom: 37px; right: -15px', + 'Download CSV') + ) + ) + ), + column( + width = 4, + downloadBttn( + "download_distmatrix", + style = "simple", + label = "", + size = "sm", + icon = icon("download") + ) + ) + ) + ) + }) + + # Render select input to choose displayed loci + output$compare_select <- renderUI({ + + if(nrow(DB$data) == 1) { + HTML( + paste( + tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to compare") + ) + ) + } else { + if(!is.null(input$compare_difference)) { + if (input$compare_difference == FALSE) { + pickerInput( + inputId = "compare_select", + label = "", + width = "85%", + choices = names(DB$allelic_profile), + selected = names(DB$allelic_profile)[1:20], + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + } else { + pickerInput( + inputId = "compare_select", + label = "", + width = "85%", + choices = names(DB$allelic_profile), + selected = names(DB$allelic_profile)[var_alleles(DB$allelic_profile)], + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + } + } + } + }) + + #### Render Entry Data Table ---- + output$db_entries_table <- renderUI({ + if(!is.null(DB$data)) { + if(between(nrow(DB$data), 1, 30)) { + rHandsontableOutput("db_entries") + } else { + addSpinner( + rHandsontableOutput("db_entries"), + spin = "dots", + color = "#ffffff" + ) + } + } + }) + + if (!is.null(DB$data)) { + + observe({ + + if (!is.null(DB$data)) { + if (nrow(DB$data) == 1) { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else if (between(nrow(DB$data), 2, 40)) { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + highlightCol = TRUE, + highlightRow = TRUE, + contextMenu = FALSE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + valign = "htMiddle", + halign = "htCenter", + readOnly = TRUE) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + strict = TRUE, + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }" + ) %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names()- 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } else { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + rowHeaders = NULL, + height = table_height(), + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + readOnly = TRUE, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + height = table_height(), + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", halign = "htCenter") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } + } + + # Dynamic save button when rhandsontable changes or new entries + output$edit_entry_table <- renderUI({ + if(check_new_entry() & DB$check_new_entries) { + Typing$reload <- FALSE + fluidRow( + column( + width = 8, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', + 'New entries - reload database') + ) + ) + ), + column( + width = 4, + actionButton( + "load", + "", + icon = icon("rotate"), + class = "pulsating-button" + ) + ) + ) + } else if(Typing$status == "Attaching") { + fluidRow( + column( + width = 11, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 14px; position: absolute; bottom: -30px; right: -5px', 'No database changes possible - pending entry addition') + ) + ) + ), + column( + width = 1, + HTML(paste('')) + ) + ) + } else if((DB$change == TRUE) | !identical(get.entry.table.meta(), select(DB$meta, -13))) { + + if(!is.null(input$db_entries)) { + fluidRow( + column( + width = 5, + HTML( + paste( + tags$span(style='color: white; font-size: 16px; position: absolute; bottom: -30px; right: -5px', 'Confirm changes') + ) + ) + ), + column( + width = 3, + actionButton( + "edit_button", + "", + icon = icon("bookmark"), + class = "pulsating-button" + ) + ), + column( + width = 4, + actionButton( + "undo_changes", + "Undo", + icon = icon("repeat") + ) + ) + ) + } + } else {NULL} + }) + + }) + + # Hide no entry message + output$db_no_entries <- NULL + output$distancematrix_no_entries <- NULL + + } else { + + # If database loading not successful dont show entry table + output$db_entries_table <- NULL + output$entry_table_controls <- NULL + } + + # Render Entry table controls + output$entry_table_controls <- renderUI({ + fluidRow( + column(1), + column( + width = 3, + align = "center", + fluidRow( + column( + width = 4, + align = "center", + actionButton( + "sel_all_entries", + "Select All", + icon = icon("check") + ) + ), + column( + width = 4, + align = "left", + actionButton( + "desel_all_entries", + "Deselect All", + icon = icon("xmark") + ) + ) + ) + ), + column( + width = 3, + uiOutput("edit_entry_table") + ) + ) + }) + + #### Render Distance Matrix ---- + observe({ + if(!is.null(DB$data)) { + + if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { + output$db_distancematrix <- NULL + + if( (sum(duplicated(DB$meta$`Assembly Name`)) > 0) & (sum(duplicated(DB$meta$`Assembly ID`)) == 0) ) { + duplicated_txt <- paste0( + paste( + paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), + DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] + ), + "
" + ) + } else if ( (sum(duplicated(DB$meta$`Assembly ID`)) > 0) & (sum(duplicated(DB$meta$`Assembly Name`)) == 0) ){ + duplicated_txt <- paste0( + paste( + paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), + DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] + ), + "
" + ) + } else { + duplicated_txt <- c( + paste0( + paste( + paste0("Name # ", which(duplicated(DB$meta$`Assembly Name`)), " - "), + DB$meta$`Assembly Name`[which(duplicated(DB$meta$`Assembly Name`))] + ), + "
" + ), + paste0( + paste( + paste0("ID # ", which(duplicated(DB$meta$`Assembly ID`)), " - "), + DB$meta$`Assembly ID`[which(duplicated(DB$meta$`Assembly ID`))] + ), + "
" + ) + ) + } + + output$distancematrix_duplicated <- renderUI({ + column( + width = 12, + tags$span(style = "font-size: 15; color: white", + "Change duplicated entry names to display distance matrix."), + br(), br(), br(), + actionButton("change_entries", "Go to Entry Table", class = "btn btn-default"), + br(), br(), br(), + tags$span( + style = "font-size: 15; color: white", + HTML( + append( + "Duplicated:", + append( + "
", + duplicated_txt + ) + ) + ) + ) + ) + }) + } else { + output$distancematrix_duplicated <- NULL + if(!is.null(DB$data) & !is.null(DB$allelic_profile) & !is.null(DB$allelic_profile_true) & !is.null(DB$cust_var) & !is.null(input$distmatrix_label) & !is.null(input$distmatrix_diag) & !is.null(input$distmatrix_triangle)) { + output$db_distancematrix <- renderRHandsontable({ + rhandsontable(hamming_df(), + digits = 1, + readOnly = TRUE, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE, + height = distancematrix_height(), rowHeaders = NULL) %>% + hot_heatmap(renderer = paste0(" + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + heatmapScale = chroma.scale(['#17F556', '#ED6D47']); + + if (instance.heatmap[col]) { + mn = ", DB$matrix_min, "; + mx = ", DB$matrix_max, "; + + pt = (parseInt(value, 10) - mn) / (mx - mn); + + td.style.backgroundColor = heatmapScale(pt).hex(); + } + }")) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1:(dim(DB$ham_matrix)[1]+1), + halign = "htCenter", + valign = "htMiddle") %>% + hot_col(1, renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + td.style.background = '#F0F0F0' + }" + ) + }) + } + } + + # Render Distance Matrix UI + + output$distmatrix_show <- renderUI({ + if(!is.null(DB$data)) { + if(nrow(DB$data) > 1) { + column( + width = 10, + uiOutput("distancematrix_duplicated"), + div( + class = "distmatrix", + rHandsontableOutput("db_distancematrix") + ) + ) + } else { + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px;', "Type at least two assemblies to display a distance matrix.") + ) + ) + ), + br(), + br() + ) + } + } + }) + + } + }) + + + # Render delete entry box UI + output$delete_box <- renderUI({ + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + column( + width = 12, + align = "center", + h3(p("Delete Entries"), style = "color:white") + ) + ), + hr(), + fluidRow( + column( + width = 2, + offset = 1, + align = "right", + br(), + h5("Index", style = "color:white; margin-bottom: 0px;") + ), + column( + width = 6, + align = "center", + uiOutput("delete_select") + ), + column( + width = 2, + align = "center", + br(), + uiOutput("del_bttn") + ) + ), + br() + ) + }) + + # Render loci comparison box UI + output$compare_allele_box <- renderUI({ + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + column( + width = 12, + align = "center", + h3(p("Compare Loci"), style = "color:white") + ) + ), + hr(), + column( + width = 12, + align = "center", + br(), + uiOutput("compare_select"), + br(), + column(2), + column( + width = 10, + align = "left", + uiOutput("compare_difference_box") + ) + ), + br() + ) + }) + + # Render entry table download box UI + output$download_entries <- renderUI({ + fluidRow( + column( + width = 12, + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + column( + width = 12, + align = "center", + h3(p("Download Table"), style = "color:white") + ) + ), + hr(), + fluidRow( + column(2), + column( + width = 10, + align = "left", + br(), + div( + class = "mat-switch-db", + materialSwitch( + "download_table_include", + h5(p("Only Included Entries"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + div( + class = "mat-switch-db", + materialSwitch( + "download_table_loci", + h5(p("Include Displayed Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ), + br(), + ) + ), + fluidRow( + column( + width = 12, + align = "center", + downloadBttn( + "download_entry_table", + style = "simple", + label = "", + size = "sm", + icon = icon("download"), + color = "primary" + ) + ) + ), + br() + ) + ), + column( + width = 12, + fluidRow( + column( + width = 2, + div( + class = "rectangle-blue" + ), + div( + class = "rectangle-orange" + ), + div( + class = "rectangle-red" + ), + div( + class = "rectangle-green" + ) + ), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -12px", " = included for analyses") + ) + ) + ), + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -13px", " = duplicated name/ID") + ) + ) + ), + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -14px", " = ≥ 5% of loci missing") + ) + ) + ), + p( + HTML( + paste( + tags$span(style="color: white; font-size: 15px; margin-left: 25px; position: relative; bottom: -15px", " = locus contains multiple variants") + ) + ) + ), + ) + ) + ) + ) + }) + + # Render entry deletion select input + output$delete_select <- renderUI({ + pickerInput("select_delete", + label = "", + choices = DB$data[, "Index"], + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE) + }) + + # Render delete entry button + output$del_bttn <- renderUI({ + actionBttn( + "del_button", + label = "", + color = "danger", + size = "sm", + style = "material-circle", + icon = icon("xmark") + ) + }) + + #### Missing Values UI ---- + + # Missing values calculations and table + observe({ + + if (!is.null(DB$allelic_profile)) { + NA_table <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) != 0] + + NA_table <- NA_table[rowSums(is.na(NA_table)) != 0,] + + NA_table[is.na(NA_table)] <- "NA" + + NA_table <- NA_table %>% + cbind("Assembly Name" = DB$meta[rownames(NA_table),]$`Assembly Name`) %>% + cbind("Errors" = DB$meta[rownames(NA_table),]$Errors) %>% + relocate("Assembly Name", "Errors") + + DB$na_table <- NA_table + + if(!is.null(input$miss_val_height)) { + if(nrow(DB$na_table) < 31) { + output$table_missing_values <- renderRHandsontable({ + rhandsontable( + DB$na_table, + readOnly = TRUE, + rowHeaders = NULL, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE, + error_highlight = err_thresh_na() - 1 + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% + hot_col(2, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } else { + output$table_missing_values <- renderRHandsontable({ + rhandsontable( + DB$na_table, + readOnly = TRUE, + rowHeaders = NULL, + height = miss.val.height(), + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE, + error_highlight = err_thresh() - 1 + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1:ncol(DB$na_table), valign = "htMiddle", halign = "htLeft") %>% + hot_col(2, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(3:ncol(DB$na_table), renderer = htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } + } + } + + }) + + # Render missing value informatiojn box UI + output$missing_values <- renderUI({ + div( + class = "miss_val_box", + box( + solidHeader = TRUE, + status = "primary", + width = "100%", + fluidRow( + div( + class = "white", + column( + width = 12, + align = "left", + br(), + HTML( + paste0("There are ", + strong(as.character(sum(is.na(DB$data)))), + " unsuccessful allele allocations (NA). ", + strong(sum(sapply(DB$allelic_profile, anyNA))), + " out of ", + strong(ncol(DB$allelic_profile)), + " total loci in this scheme contain NA's (", + strong(round((sum(sapply(DB$allelic_profile, anyNA)) / ncol(DB$allelic_profile) * 100), 1)), + " %). ", + "Decide how these missing values should be treated:") + + ), + br() + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "left", + br(), + prettyRadioButtons( + "na_handling", + "", + choiceNames = c("Ignore missing values for pairwise comparison", + "Omit loci with missing values for all assemblies", + "Treat missing values as allele variant"), + choiceValues = c("ignore_na", "omit", "category"), + shape = "curve", + selected = c("ignore_na") + ), + br() + ) + ) + ) + ) + }) + + } else { + #if no typed assemblies present + + # null underlying database + + DB$data <- NULL + DB$meta <- NULL + DB$meta_gs <- NULL + DB$meta_true <- NULL + DB$allelic_profile <- NULL + DB$allelic_profile_trunc <- NULL + DB$allelic_profile_true <- NULL + + # Render menu without missing values tab + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + selected = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + + observe({ + if(is.null(DB$data)) { + if(check_new_entry()) { + output$db_no_entries <- renderUI( + column( + width = 12, + fluidRow( + column(1), + column( + width = 3, + align = "left", + HTML( + paste( + tags$span(style='color: white; font-size: 15px; position: absolute; bottom: -30px; right: -5px', 'New entries - reload database') + ) + ) + ), + column( + width = 4, + actionButton( + "load", + "", + icon = icon("rotate"), + class = "pulsating-button" + ) + ) + ) + ) + ) + } else { + output$db_no_entries <- renderUI( + column( + width = 12, + fluidRow( + column(1), + column( + width = 11, + align = "left", + HTML( + paste( + "", + "No Entries for this scheme available.\n", + "Type a genome in the section Allelic Typing and add the result to the local database.", + sep = '
' + ) + ) + ) + ) + ) + ) + } + } + }) + + output$distancematrix_no_entries <- renderUI( + fluidRow( + column(1), + column( + width = 11, + align = "left", + HTML(paste( + "", + "No Entries for this scheme available.", + "Type a genome in the section Allelic Typing and add the result to the local database.", + sep = '
' + )) + ) + ) + ) + + output$db_entries <- NULL + output$edit_index <- NULL + output$edit_scheme_d <- NULL + output$edit_entries <- NULL + output$compare_select <- NULL + output$delete_select <- NULL + output$del_bttn <- NULL + output$compare_allele_box <- NULL + output$download_entries <- NULL + output$missing_values <- NULL + output$delete_box <- NULL + output$entry_table_controls <- NULL + output$multi_stop <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + output$pending_typing <- NULL + output$multi_typing_results <- NULL + output$single_typing_progress <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + } + } + } + } + } else { + + log_print("Invalid scheme folder") + show_toast( + title = "Invalid scheme folder", + type = "warning", + position = "bottom-end", + timer = 4000 + ) + } + } + + }) + + # _______________________ #### + + ## Database ---- + + ### Conditional UI Elements rendering ---- + + # Contro custom variables table + output$cust_var_select <- renderUI({ + if(nrow(DB$cust_var) > 5) { + selectInput( + "cust_var_select", + "", + choices = 1:ceiling(nrow(DB$cust_var) / 5 ) + ) + } + }) + + output$cust_var_info <- renderUI({ + if((!is.null(DB$cust_var)) & (!is.null(input$cust_var_select))) { + if(nrow(DB$cust_var) > 5) { + low <- -4 + high <- 0 + for (i in 1:input$cust_var_select) { + low <- low + 5 + if((nrow(DB$cust_var) %% 5) != 0) { + if(i == ceiling(nrow(DB$cust_var) / 5 )) { + high <- high + nrow(DB$cust_var) %% 5 + } else { + high <- high + 5 + } + } else { + high <- high + 5 + } + } + h5(paste0("Showing ", low, " to ", high," of ", nrow(DB$cust_var), " variables"), style = "color: white; font-size: 10px;") + } + } + }) + + # Message on Database tabs if no scheme available yet + observe({ + if(!is.null(DB$exist)) { + if(DB$exist){ + + # Message for tab Browse Entries + output$no_scheme_entries <- renderUI({ + fluidRow( + column(1), + column( + width = 4, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'No scheme available.') + ) + ) + ), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'Download a scheme first and type assemblies in the section Allelic Typing.') + ) + ) + ) + ) + ) + }) + + # Message for Tab Scheme Info + output$no_scheme_info <- renderUI({ + fluidRow( + column(1), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'No scheme available.') + ) + ) + ), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'Download a scheme first and type assemblies in the section Allelic Typing.') + ) + ) + ) + ) + ) + }) + + # Message for Tab Distance Matrix + output$no_scheme_distancematrix <- renderUI({ + fluidRow( + column(1), + column( + width = 10, + align = "left", + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'No scheme available.') + ) + ) + ), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; ', + 'Download a scheme first and type assemblies in the section Allelic Typing.') + ) + ) + ) + ) + ) + }) + + } else { + output$no_scheme_entries <- NULL + output$no_scheme_info <- NULL + output$no_scheme_distancematrix <- NULL + } + } + + }) + + observe({ + # Conditional Missing Values Tab + if(!is.null(DB$allelic_profile)) { + if(anyNA(DB$allelic_profile)) { + if(DB$no_na_switch == FALSE) { + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ), + menuSubItem( + text = "Missing Values", + tabName = "db_missing_values", + selected = TRUE, + icon = icon("triangle-exclamation") + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } + + } else { + output$menu <- renderMenu( + sidebarMenu( + menuItem( + text = "Database Browser", + tabName = "database", + icon = icon("hard-drive"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "db_browse_entries" + ), + menuSubItem( + text = "Scheme Info", + tabName = "db_schemeinfo" + ), + menuSubItem( + text = "Loci Info", + tabName = "db_loci_info" + ), + menuSubItem( + text = "Distance Matrix", + tabName = "db_distmatrix" + ) + ), + menuItem( + text = "Manage Schemes", + tabName = "init", + icon = icon("layer-group") + ), + menuItem( + text = "Allelic Typing", + tabName = "typing", + icon = icon("gears") + ), + menuItem( + text = "Resistance Profile", + tabName = "gene_screening", + icon = icon("dna"), + startExpanded = TRUE, + menuSubItem( + text = "Browse Entries", + tabName = "gs_profile" + ), + menuSubItem( + text = "Screening", + tabName = "gs_screening" + ) + ), + menuItem( + text = "Visualization", + tabName = "visualization", + icon = icon("circle-nodes") + ), + menuItem( + text = "Utilities", + tabName = "utilities", + icon = icon("screwdriver-wrench") + ) + ) + ) + } + } + + }) + + observe({ + + if (!is.null(DB$available)) { + output$scheme_db <- renderUI({ + if (length(DB$available) > 5) { + selectInput( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} + ) + } else { + prettyRadioButtons( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}} + ) + } + }) + + if (!is.null(DB$schemeinfo)) { + + output$scheme_info <- renderTable({ + DB$schemeinfo + }) + + output$scheme_header <- renderUI(h3(p("cgMLST Scheme"), style = "color:white")) + + } else { + + output$scheme_info <- NULL + output$scheme_header <- NULL + + } + + if (!is.null(DB$loci_info)) { + loci_info <- DB$loci_info + names(loci_info)[6] <- "Allele Count" + + output$db_loci <- renderDataTable( + loci_info, + selection = "single", + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + + output$loci_header <- renderUI(h3(p("Loci"), style = "color:white")) + + } else { + output$db_loci <- NULL + output$loci_header <- NULL + } + } + }) + + # If only one entry available disable varying loci checkbox + + output$compare_difference_box <- renderUI({ + if(!is.null(DB$data)) { + if(nrow(DB$data) > 1) { + div( + class = "mat-switch-db", + materialSwitch( + "compare_difference", + h5(p("Only Varying Loci"), style = "color:white; padding-left: 0px; position: relative; top: -4px; right: -5px;"), + value = FALSE, + right = TRUE + ) + ) + } + } + }) + + ### Database Events ---- + + # Invalid entries table input + observe({ + req(DB$data, input$db_entries) + if (isTRUE(input$invalid_date)) { + show_toast( + title = "Invalid date", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + DB$inhibit_change <- TRUE + } else if (isTRUE(input$empty_name)) { + show_toast( + title = "Empty name", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + DB$inhibit_change <- TRUE + } else if (isTRUE(input$empty_id)) { + show_toast( + title = "Empty ID", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + DB$inhibit_change <- TRUE + } else { + DB$inhibit_change <- FALSE + } + }) + + # Change scheme + observeEvent(input$reload_db, { + log_print("Input reload_db") + + if(tail(readLines(paste0(getwd(), "/logs/script_log.txt")), 1)!= "0") { + show_toast( + title = "Pending Multi Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Screening", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + showModal( + modalDialog( + selectInput( + "scheme_db", + label = "", + choices = DB$available, + selected = DB$scheme), + title = "Select a local database to load.", + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("load", "Load", class = "btn btn-default") + ) + ) + ) + } + }) + + # Create new database + observe({ + shinyDirChoose(input, + "create_new_db", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session) + + if(!is.null(input$create_new_db)) { + DB$new_database <- as.character( + parseDirPath( + roots = c(Home = path_home(), Root = "/"), + input$create_new_db + ) + ) + } + }) + + # Undo db changes + observeEvent(input$undo_changes, { + log_print("Input undo_changes") + + DB$inhibit_change <- FALSE + + Data <- readRDS(paste0( + DB$database, "/", + gsub(" ", "_", DB$scheme), + "/Typing.rds" + )) + + DB$data <- Data[["Typing"]] + + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + } else { + DB$cust_var <- data.frame() + } + + DB$change <- FALSE + DB$count <- 0 + DB$no_na_switch <- TRUE + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + DB$deleted_entries <- character(0) + + observe({ + if (!is.null(DB$data)) { + if (nrow(DB$data) == 1) { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgbA(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else if (between(nrow(DB$data), 1, 40)) { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + rowHeaders = NULL, + highlightCol = TRUE, + highlightRow = TRUE, + contextMenu = FALSE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + valign = "htMiddle", + halign = "htCenter", + readOnly = TRUE) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + strict = TRUE, + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }" + ) %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names()- 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } else { + if (length(input$compare_select) > 0) { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height) & !is.null(input$compare_select)) { + output$db_entries <- renderRHandsontable({ + + entry_data <- DB$data %>% + select(1:(13 + nrow(DB$cust_var))) %>% + add_column(select(DB$allelic_profile_trunc, input$compare_select)) + + rhandsontable( + entry_data, + col_highlight = diff_allele() - 1, + rowHeaders = NULL, + height = table_height(), + row_highlight = true_rows() - 1, + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_col((14 + nrow(DB$cust_var)):((13 + nrow(DB$cust_var)) + length(input$compare_select)), + readOnly = TRUE, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", + halign = "htCenter", + allowInvalid = FALSE, + copyable = TRUE) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(diff_allele(), + renderer = " + function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.NumericRenderer.apply(this, arguments); + + if (instance.params) { + hcols = instance.params.col_highlight; + hcols = hcols instanceof Array ? hcols : [hcols]; + } + + if (instance.params && hcols.includes(col)) { + td.style.background = 'rgb(116, 188, 139)'; + } + }") + }) + } + } else { + if(!is.null(DB$data) & !is.null(DB$cust_var) & !is.null(input$table_height)) { + output$db_entries <- renderRHandsontable({ + rhandsontable( + select(DB$data, 1:(13 + nrow(DB$cust_var))), + rowHeaders = NULL, + height = table_height(), + dup_names_high = duplicated_names() - 1, + dup_ids_high = duplicated_ids() - 1, + row_highlight = true_rows() - 1, + error_highlight = err_thresh() - 1, + contextMenu = FALSE, + highlightCol = TRUE, + highlightRow = TRUE + ) %>% + hot_cols(fixedColumnsLeft = 1) %>% + hot_col(1, + valign = "htMiddle", + halign = "htCenter") %>% + hot_col(c(1, 5, 10, 11, 12, 13), + readOnly = TRUE) %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(3, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_id', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_id', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(4, validator = " + function(value, callback) { + try { + if (value === null || value.trim() === '') { + callback(false); // Cell is empty + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } else { + callback(true); // Cell is not empty + Shiny.setInputValue('empty_name', false); // Reset to false when cell is not empty + } + } catch (err) { + console.log(err); + callback(false); // In case of error, consider it as invalid + Shiny.setInputValue('empty_name', true); // Notify Shiny of empty cell + } + } + ") %>% + hot_col(8, type = "dropdown", source = country_names) %>% + hot_col(6, dateFormat = "YYYY-MM-DD", type = "date", strict = TRUE, allowInvalid = TRUE, + validator = " + function (value, callback) { + var today_date = new Date(); + today_date.setHours(0, 0, 0, 0); + + var new_date = new Date(value); + new_date.setHours(0, 0, 0, 0); + + try { + if (new_date <= today_date) { + callback(true); + Shiny.setInputValue('invalid_date', false); + } else { + callback(false); + Shiny.setInputValue('invalid_date', true); + } + } catch (err) { + console.log(err); + callback(false); + Shiny.setInputValue('invalid_date', true); + } + }") %>% + hot_col(3:(13 + nrow(DB$cust_var)), + valign = "htMiddle", + halign = "htLeft") %>% + hot_rows(fixedRowsTop = 0) %>% + hot_col(1, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.row_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(44, 222, 235, 0.6)' + } + } + }") %>% + hot_col(2, type = "checkbox", width = "auto", + valign = "htTop", halign = "htCenter") %>% + hot_col(4, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_names_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(3, renderer = " + function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + + if (instance.params) { + hrows = instance.params.dup_ids_high + hrows = hrows instanceof Array ? hrows : [hrows] + + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgb(224, 179, 0)' + } + } + }") %>% + hot_col(12, renderer = "function (instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + if (instance.params) { + hrows = instance.params.error_highlight + hrows = hrows instanceof Array ? hrows : [hrows] + if (hrows.includes(row)) { + td.style.backgroundColor = 'rgba(255, 80, 1, 0.8)' + } + } + }") + }) + } + } + } + } + }) + }) + + observe({ + if(!is.null(DB$data)){ + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + + } else { + DB$cust_var <- data.frame() + } + } + }) + + DB$count <- 0 + + observeEvent(input$add_new_variable, { + log_print("Input add_new_variable") + + if(nchar(input$new_var_name) > 12) { + log_print("Add variable; max. 10 character") + show_toast( + title = "Max. 10 characters", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + if (input$new_var_name == "") { + log_print("Add variable; min. 1 character") + show_toast( + title = "Min. 1 character", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + if(trimws(input$new_var_name) %in% names(DB$meta)) { + log_print("Add variable; name already existing") + show_toast( + title = "Variable name already existing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + showModal( + modalDialog( + selectInput( + "new_var_type", + label = "", + choices = c("Categorical (character)", + "Continous (numeric)")), + title = paste0("Select Data Type"), + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_new_var", "Confirm", class = "btn btn-default") + ) + ) + ) + } + } + } + }) + + observeEvent(input$conf_new_var, { + log_print("Input conf_new_var") + + # User feedback variables + removeModal() + DB$count <- DB$count + 1 + DB$change <- TRUE + + # Format variable name + name <- trimws(input$new_var_name) + + if(input$new_var_type == "Categorical (character)") { + DB$data <- DB$data %>% + mutate("{name}" := character(nrow(DB$data)), .after = 13) + + DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "categ")) + } else { + DB$data <- DB$data %>% + mutate("{name}" := numeric(nrow(DB$data)), .after = 13) + + DB$cust_var <- rbind(DB$cust_var, data.frame(Variable = name, Type = "cont")) + } + + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + + log_print(paste0("New custom variable added: ", input$new_var_name)) + + show_toast( + title = paste0("Variable ", trimws(input$new_var_name), " added"), + type = "success", + position = "bottom-end", + timer = 6000 + ) + + }) + + observeEvent(input$delete_new_variable, { + log_print("Input delete_new_variable") + + if (input$del_which_var == "") { + log_print("Delete custom variables; no custom variable") + show_toast( + title = "No custom variables", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + showModal( + modalDialog( + paste0( + "Confirmation will lead to irreversible deletion of the custom ", + input$del_which_var, + " variable. Continue?" + ), + title = "Delete custom variables", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_var_del", "Delete", class = "btn btn-danger") + ) + ) + ) + } + }) + + observeEvent(input$conf_var_del, { + log_print("Input conf_var_del") + + DB$change <- TRUE + + removeModal() + + if(DB$count >= 1) { + DB$count <- DB$count - 1 + } + + show_toast( + title = paste0("Variable ", input$del_which_var, " removed"), + type = "warning", + position = "bottom-end", + timer = 6000 + ) + + log_print(paste0("Variable ", input$del_which_var, " removed")) + + DB$cust_var <- DB$cust_var[-which(DB$cust_var$Variable == input$del_which_var),] + DB$data <- select(DB$data, -(input$del_which_var)) + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + }) + + # Select all button + + observeEvent(input$sel_all_entries, { + log_print("Input sel_all_entries") + + DB$data$Include <- TRUE + }) + + observeEvent(input$desel_all_entries, { + log_print("Input desel_all_entries") + + DB$data$Include <- FALSE + }) + + # Switch to entry table + + observeEvent(input$change_entries, { + log_print("Input change_entries") + + removeModal() + updateTabItems(session, "tabs", selected = "db_browse_entries") + }) + + #### Save Missing Value as CSV ---- + + output$download_na_matrix <- downloadHandler( + filename = function() { + log_print(paste0("Save missing values table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv"))) + paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Missing_Values.csv") + }, + content = function(file) { + download_matrix <- hot_to_r(input$table_missing_values) + write.csv(download_matrix, file, sep = ",", row.names=FALSE, quote=FALSE) + } + ) + + #### Save scheme info table as CSV ---- + + output$download_schemeinfo <- downloadHandler( + filename = function() { + log_print(paste0("Save scheme info table ", paste0(gsub(" ", "_", DB$scheme), "_scheme.csv"))) + + paste0(gsub(" ", "_", DB$scheme), "_scheme.csv") + }, + content = function(file) { + pub_index <- which(DB$schemeinfo[,1] == "Publications") + write.table( + DB$schemeinfo[1:(pub_index-1),], + file, + sep = ";", + row.names = FALSE, + quote = FALSE + ) + } + ) + + #### Save Loci info table as CSV ---- + + output$download_loci_info <- downloadHandler( + filename = function() { + log_print(paste0("Save loci info table ", paste0(gsub(" ", "_", DB$scheme), "_Loci.csv"))) + + paste0(gsub(" ", "_", DB$scheme), "_Loci.csv") + }, + content = function(file) { + write.table( + DB$loci_info, + file, + sep = ";", + row.names = FALSE, + quote = FALSE + ) + } + ) + + #### Save entry table as CSV ---- + + output$download_entry_table <- downloadHandler( + filename = function() { + log_print(paste0("Save entry table ", paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv"))) + + paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Entries.csv") + }, + content = function(file) { + download_matrix <- hot_to_r(input$db_entries) + + if (input$download_table_include == TRUE) { + download_matrix <- download_matrix[which(download_matrix$Include == TRUE),] + } + + if (input$download_table_loci == FALSE) { + download_matrix <- select(download_matrix, 1:(13 + nrow(DB$cust_var))) + } + + write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) + } + ) + + # Save Edits Button + + observeEvent(input$edit_button, { + if(nrow(hot_to_r(input$db_entries)) > nrow(DB$data)) { + show_toast( + title = "Invalid rows entered. Saving not possible.", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + if(!isTRUE(DB$inhibit_change)) { + log_print("Input edit_button") + + showModal( + modalDialog( + if(length(DB$deleted_entries > 0)) { + paste0( + "Overwriting previous metadata of local ", + DB$scheme, + " database. Deleted entries will be irreversibly removed. Continue?" + ) + } else { + paste0( + "Overwriting previous metadata of local ", + DB$scheme, + " database. Continue?" + ) + }, + title = "Save Database", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_db_save", "Save", class = "btn btn-default") + ) + ) + ) + } else { + log_print("Input edit_button, invalid values.") + show_toast( + title = "Invalid values entered. Saving not possible.", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } + }) + + observeEvent(input$Cancel, { + log_print("Input Cancel") + removeModal() + }) + + observeEvent(input$conf_db_save, { + log_print("Input conf_db_save") + + # Remove isolate assembly file if present + if(!is.null(DB$remove_iso)) { + if(length(DB$remove_iso) > 0) { + lapply(DB$remove_iso, unlink, recursive = TRUE, force = FALSE, expand = TRUE) + } + } + DB$remove_iso <- NULL + + Data <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme),"Typing.rds")) + + if ((ncol(Data[["Typing"]]) - 13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_vars_pre <- select(Data[["Typing"]], + 14:(ncol(Data[["Typing"]]) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + cust_vars_pre <- names(cust_vars_pre) + } else { + cust_vars_pre <- character() + } + + Data[["Typing"]] <- select(Data[["Typing"]], -(1:(13 + length(cust_vars_pre)))) + + meta_hot <- hot_to_r(input$db_entries) + + if(length(DB$deleted_entries > 0)) { + + meta_hot <- mutate(meta_hot, Index = as.character(1:nrow(DB$data))) + + Data[["Typing"]] <- mutate(Data[["Typing"]][-as.numeric(DB$deleted_entries), ], + meta_hot, .before = 1) + rownames(Data[["Typing"]]) <- Data[["Typing"]]$Index + } else { + Data[["Typing"]] <- mutate(Data[["Typing"]], meta_hot, .before = 1) + } + + # Ensure correct logical data type + Data[["Typing"]][["Include"]] <- as.logical(Data[["Typing"]][["Include"]]) + saveRDS(Data, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + # Load database from files + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + DB$data <- Database[["Typing"]] + + if(!is.null(DB$data)){ + if ((ncol(DB$data)-13) != as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2])))) { + cust_var <- select(DB$data, 14:(ncol(DB$data) - as.numeric(gsub(",", "", as.vector(DB$schemeinfo[6, 2]))))) + DB$cust_var <- data.frame(Variable = names(cust_var), Type = column_classes(cust_var)) + } else { + DB$cust_var <- data.frame() + } + } + + DB$change <- FALSE + DB$count <- 0 + DB$no_na_switch <- TRUE + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + DB$deleted_entries <- character(0) + + removeModal() + + show_toast( + title = "Database successfully saved", + type = "success", + position = "bottom-end", + timer = 4000 + ) + }) + + observeEvent(input$del_button, { + log_print("Input del_button") + + if (length(input$select_delete) < 1) { + log_print("Delete entries; no entry selected") + show_toast( + title = "No entry selected", + type = "warning", + position = "bottom-end", + timer = 4000 + ) + } else if((readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") | + (tail(readLogFile(), 1) != "0")) { + log_print("Delete entries; pending typing") + + show_toast( + title = "Pending Typing", + type = "warning", + position = "bottom-end", + timer = 4000 + ) + } else { + if( (length(input$select_delete) - nrow(DB$data) ) == 0) { + showModal( + modalDialog( + paste0("Deleting will lead to removal of all entries and assemblies from local ", DB$scheme, " database. The data can not be recovered afterwards. Continue?"), + easyClose = TRUE, + title = "Deleting Entries", + footer = tagList( + modalButton("Cancel"), + actionButton("conf_delete_all", "Delete", class = "btn btn-danger") + ) + ) + ) + } else { + showModal( + modalDialog( + paste0( + "Confirmation will lead to irreversible removal of selected entries and the respectively saved assembly. Continue?" + ), + title = "Deleting Entries", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton( + "conf_delete", + "Delete", + class = "btn btn-danger") + ) + ) + ) + } + } + }) + + observeEvent(input$conf_delete_all, { + log_print("Input conf_delete_all") + + # remove file with typing data + file.remove(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + unlink(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates"), recursive = TRUE, force = FALSE, expand =TRUE) + + showModal( + modalDialog( + selectInput( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {DB$scheme} else {DB$available[1]}}), + title = "All entries have been removed. Select a local database to load.", + footer = tagList( + actionButton("load", "Load", class = "btn btn-default") + ) + ) + ) + + }) + + DB$deleted_entries <- character(0) + + observeEvent(input$conf_delete, { + + log_print("Input conf_delete") + + # Get isolates selected for deletion + DB$deleted_entries <- append(DB$deleted_entries, DB$data$Index[as.numeric(input$select_delete)]) + + # Set reactive status variables + DB$no_na_switch <- TRUE + DB$change <- TRUE + DB$check_new_entries <- FALSE + + # Set isolate directory deletion variables + isopath <- dir_ls(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates")) + DB$remove_iso <- isopath[which(basename(isopath) == DB$data$`Assembly ID`[as.numeric(input$select_delete)])] + + # Reload updated database reactive variables + DB$data <- DB$data[!(DB$data$Index %in% as.numeric(input$select_delete)),] + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + DB$allelic_profile <- select(DB$data, -(1:(13 + nrow(DB$cust_var)))) + DB$allelic_profile_trunc <- as.data.frame(lapply(DB$allelic_profile, function(x) sapply(x, truncHash))) + DB$allelic_profile_true <- DB$allelic_profile[which(DB$data$Include == TRUE),] + + # User feedback + removeModal() + + if(length(input$select_delete) > 1) { + show_toast( + title = "Entries deleted", + type = "success", + position = "bottom-end", + timer = 4000 + ) + } else { + show_toast( + title = "Entry deleted", + type = "success", + position = "bottom-end", + timer = 4000 + ) + } + }) + + + ### Distance Matrix ---- + + hamming_df <- reactive({ + if(input$distmatrix_true == TRUE) { + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + + allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] + + hamming_mat <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) + + } else if(input$na_handling == "ignore_na"){ + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) + + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) + + } + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) + } + } else { + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + hamming_mat <- compute.distMatrix(allelic_profile_noNA, hamming.dist) + } else if(input$na_handling == "ignore_na"){ + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distIgnore) + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.distCategory) + } + } else { + hamming_mat <- compute.distMatrix(DB$allelic_profile, hamming.dist) + } + } + + # Extreme values for distance matrix heatmap display + DB$matrix_min <- min(hamming_mat, na.rm = TRUE) + DB$matrix_max <- max(hamming_mat, na.rm = TRUE) + + if(input$distmatrix_triangle == FALSE) { + hamming_mat[upper.tri(hamming_mat, diag = !input$distmatrix_diag)] <- NA + } + + # Row- and colnames change + if(input$distmatrix_true == TRUE) { + rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label][which(DB$data$Include == TRUE),]) + } else { + rownames(hamming_mat) <- unlist(DB$data[input$distmatrix_label]) + } + colnames(hamming_mat) <- rownames(hamming_mat) + + mode(hamming_mat) <- "integer" + + DB$ham_matrix <- hamming_mat %>% + as.data.frame() %>% + mutate(Index = colnames(hamming_mat)) %>% + relocate(Index) + DB$distancematrix_nrow <- nrow(DB$ham_matrix) + + DB$ham_matrix + }) + + output$download_distmatrix <- downloadHandler( + filename = function() { + paste0(Sys.Date(), "_", gsub(" ", "_", DB$scheme), "_Distance_Matrix.csv") + }, + content = function(file) { + download_matrix <- hot_to_r(input$db_distancematrix) + download_matrix[is.na(download_matrix)] <- "" + write.csv(download_matrix, file, row.names=FALSE, quote=FALSE) + } + ) + + # _______________________ #### + + ## Locus sequences ---- + + observe({ + if(!is.null(DB$database) & !is.null(DB$scheme)) { + DB$loci <- list.files( + path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), + pattern = "\\.(fasta|fa|fna)$", + full.names = TRUE + ) + } + }) + + output$loci_sequences <- renderUI({ + req(input$db_loci_rows_selected, DB$database, DB$scheme, input$seq_sel) + + DB$loci <- list.files( + path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), + pattern = "\\.(fasta|fa|fna)$", + full.names = TRUE + ) + + fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) + + seq <- fasta[[which(fasta == paste0(">", gsub("Allele ", "", sub(" -.*", "", input$seq_sel)))) + 1]] + + DB$seq <- seq + + column( + width = 12, + HTML( + paste( + tags$span(style='color: white; font-size: 15px; position: relative; top: -15px; left: -50px', + sub(" -.*", "", input$seq_sel)) + ) + ), + tags$pre(HTML(color_sequence(seq)), class = "sequence") + ) + }) + + output$sequence_selector <- renderUI({ + if(!is.null(input$db_loci_rows_selected)) { + + req(input$db_loci_rows_selected, DB$database, DB$scheme) + + DB$loci <- list.files( + path = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles"), + pattern = "\\.(fasta|fa|fna)$", + full.names = TRUE + ) + + fasta <- format_fasta(DB$loci[input$db_loci_rows_selected]) + + seq_names <- c() + for (i in seq_along(fasta)) { + if (startsWith(fasta[[i]], ">")) { + name <- sub(">", "", fasta[[i]]) + seq_names <- c(seq_names, name) + } + } + + var_count <- table(DB$allelic_profile[gsub(".fasta", "", (basename(DB$loci[input$db_loci_rows_selected])))]) + + vec <- prop.table(var_count) + + perc <- sapply(unname(vec), scales::percent, accuracy = 0.1) + + names(perc) <- names(vec) + + choices <- seq_names + + present <- which(choices %in% names(vec)) + absent <- which(!(choices %in% names(vec))) + + choices[present] <- paste0("Allele ", choices[present], " - ", unname(var_count), " times in DB (", unname(perc), ")") + + choices[absent] <- paste0("Allele ", choices[absent], " - not present") + + choices <- c(choices[present], choices[absent]) + + names(choices) <- sapply(choices, function(x) { + x <- strsplit(x, " ")[[1]] + x[2] <- paste0(substr(x[2], 1, 4), "...", substr(x[2], nchar(x[2])-3, nchar(x[2]))) + paste(x, collapse = " ") + }) + + column( + width = 3, + selectInput( + "seq_sel", + h5("Select Variant", style = "color:white;"), + choices = choices, + width = "80%" + ), + br(), + fluidRow( + column( + width = 8, + align = "left", + actionButton("copy_seq", "Copy Sequence", + icon = icon("copy")), + bsTooltip("copy_seq", "Copy the variant sequence
to clipboard", placement = "top", trigger = "hover") + ) + ), + br(), + fluidRow( + column( + width = 8, + align = "left", + downloadBttn( + "get_locus", + style = "simple", + label = "Save .fasta", + size = "sm", + icon = icon("download") + ), + bsTooltip("get_locus_bttn", "Save locus file with all variants", placement = "top", trigger = "hover") + ) + ), + br(), br(), br(), br(), br(), br(), br() + ) + } + }) + + observeEvent(input$copy_seq, { + if(!is.null(DB$seq)) { + session$sendCustomMessage("txt", DB$seq) + } + show_toast( + title = "Copied sequence", + type = "success", + position = "bottom-end", + timer = 3000 + ) + }) + + output$get_locus <- downloadHandler( + filename = function() { + fname <- basename(DB$loci[input$db_loci_rows_selected]) + log_print(paste0("Get locus fasta ", fname)) + fname + }, + content = function(file) { + cont <- readLines(DB$loci[input$db_loci_rows_selected]) + writeLines(cont, file) + } + ) + + # _______________________ #### + + ## Download cgMLST ---- + + observe({ + if (input$select_cgmlst == "Acinetobacter baumanii") { + species <- "Abaumannii1907" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- Scheme$folder_name <- "Acinetobacter_baumanii" + } else if (input$select_cgmlst == "Bacillus anthracis") { + species <- "Banthracis1917" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Bacillus_anthracis" + } else if (input$select_cgmlst == "Bordetella pertussis") { + species <- "Bpertussis1917" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Bordetella_pertussis" + } else if (input$select_cgmlst == "Brucella melitensis") { + species <- "Bmelitensis1912" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Brucella_melitensis" + } else if (input$select_cgmlst == "Brucella spp.") { + species <- "Brucella1914" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Brucella_spp" + } else if (input$select_cgmlst == "Burkholderia mallei (FLI)") { + species <- "Bmallei_fli1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Burkholderia_mallei_FLI" + } else if (input$select_cgmlst == "Burkholderia mallei (RKI)") { + species <- "Bmallei_rki1909" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Burkholderia_mallei_RKI" + } else if (input$select_cgmlst == "Burkholderia pseudomallei") { + species <- "Bpseudomallei1906" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Burkholderia_pseudomallei" + } else if (input$select_cgmlst == "Campylobacter jejuni/coli") { + species <- "Cjejuni1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Campylobacter_jejuni_coli" + } else if (input$select_cgmlst == "Clostridioides difficile") { + species <- "Cdifficile1905" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Clostridioides_difficile" + } else if (input$select_cgmlst == "Clostridium perfringens") { + species <- "Cperfringens1907" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Clostridium_perfringens" + } else if (input$select_cgmlst == "Corynebacterium diphtheriae") { + species <- "Cdiphtheriae1907" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Corynebacterium_diphtheriae" + } else if (input$select_cgmlst == "Cronobacter sakazakii/malonaticus") { + species <- "Csakazakii1910" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Cronobacter_sakazakii_malonaticus" + } else if (input$select_cgmlst == "Enterococcus faecalis") { + species <- "Efaecalis1912" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Enterococcus_faecalis" + } else if (input$select_cgmlst == "Enterococcus faecium") { + species <- "Efaecium1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Enterococcus_faecium" + } else if (input$select_cgmlst == "Escherichia coli") { + species <- "Ecoli1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Escherichia_coli" + } else if (input$select_cgmlst == "Francisella tularensis") { + species <- "Ftularensis1913" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Francisella_tularensis" + } else if (input$select_cgmlst == "Klebsiella oxytoca sensu lato") { + species <- "Koxytoca717" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Klebsiella_oxytoca_sensu_lato" + } else if (input$select_cgmlst == "Klebsiella pneumoniae sensu lato") { + species <- "Kpneumoniae1909" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Klebsiella_pneumoniae_sensu_lato" + } else if (input$select_cgmlst == "Legionella pneumophila") { + species <- "Lpneumophila1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Legionella_pneumophila" + } else if (input$select_cgmlst == "Listeria monocytogenes") { + species <- "Lmonocytogenes1910" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Listeria_monocytogenes" + } else if (input$select_cgmlst == "Mycobacterium tuberculosis complex") { + species <- "Mtuberculosis1909" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Mycobacterium_tuberculosis_complex" + } else if (input$select_cgmlst == "Mycobacteroides abscessus") { + species <- "Mabscessus1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Mycobacteroides_abscessus" + } else if (input$select_cgmlst == "Mycoplasma gallisepticum") { + species <- "Mgallisepticum1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Mycoplasma_gallisepticum" + } else if (input$select_cgmlst == "Paenibacillus larvae") { + species <- "Plarvae1902" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Paenibacillus_larvae" + } else if (input$select_cgmlst == "Pseudomonas aeruginosa") { + species <- "Paeruginosa1911" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Pseudomonas_aeruginosa" + } else if (input$select_cgmlst == "Salmonella enterica") { + species <- "Senterica1913" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Salmonella_enterica" + } else if (input$select_cgmlst == "Serratia marcescens") { + species <- "Smarcescens1912" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Serratia_marcescens" + } else if (input$select_cgmlst == "Staphylococcus aureus") { + species <- "Saureus1908" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Staphylococcus_aureus" + } else if (input$select_cgmlst == "Staphylococcus capitis") { + species <- "Scapitis1905" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Staphylococcus_capitis" + } else if (input$select_cgmlst == "Streptococcus pyogenes") { + species <- "Spyogenes1904" + Scheme$link_scheme <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/") + Scheme$link_cgmlst <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/alleles/") + Scheme$link_targets <- paste0("https://www.cgmlst.org/ncs/schema/", species, "/locus/?content-type=csv") + Scheme$folder_name <- "Streptococcus_pyogenes" + } + }) + + observeEvent(input$download_cgMLST, { + log_print(paste0("Started download of scheme for ", Scheme$folder_name)) + + shinyjs::hide("download_cgMLST") + shinyjs::show("loading") + + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    Downloading scheme...")), + style = "color:white;") + ) + ) + ) + + show_toast( + title = "Download started", + type = "success", + position = "bottom-end", + timer = 5000 + ) + + if(length(DB$available) == 0) { + saveRDS(DB$new_database, paste0(getwd(), "/execute/new_db.rds")) + dir.create(file.path(readRDS(paste0(getwd(), "/execute/new_db.rds")), "Database"), recursive = TRUE) + } + + DB$load_selected <- TRUE + + # Check if .downloaded_schemes folder exists and if not create it + if (!dir.exists(file.path(DB$database, ".downloaded_schemes"))) { + dir.create(file.path(DB$database, ".downloaded_schemes"), recursive = TRUE) + } + + # Check if remains of old temporary folder exists and remove them + if (dir.exists(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")))) { + unlink(file.path(DB$database, Scheme$folder_name, paste0(Scheme$folder_name, ".tmp")), recursive = TRUE) + } + + # Download Loci Fasta Files + options(timeout = 600) + + tryCatch({ + download.file(Scheme$link_cgmlst, + file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip"))) + "Download successful!" + }, error = function(e) { + paste("Error: ", e$message) + }) + + # Unzip the scheme in temporary folder + unzip( + zipfile = file.path(DB$database, ".downloaded_schemes", paste0(Scheme$folder_name, ".zip")), + exdir = file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp") + ) + ) + + log_print("Hashing downloaded database") + # Hash temporary folder + hash_database(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Get list from local database + local_db_filelist <- list.files(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) + if (!is_empty(local_db_filelist)) { + # Get list from temporary database + tmp_db_filelist <- list.files(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Find the difference (extra files in local database) + local_db_extra <- setdiff(local_db_filelist, tmp_db_filelist) + + # Copy extra files to temporary folder + file.copy(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), local_db_extra), + file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"))) + + # Check differences in file pairs + local_db_hashes <- tools::md5sum(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + local_db_filelist)) + tmp_db_hashes <- tools::md5sum(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + local_db_filelist)) + + diff_files <- local_db_hashes %in% tmp_db_hashes + diff_loci <- names(local_db_hashes)[diff_files == FALSE] + diff_loci <- sapply(strsplit(diff_loci, "/"), function(x) x[length(x)]) + + # Check locus hashes + for (locus in diff_loci) { + local_db_hashes <- get_locus_hashes(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + locus)) + tmp_db_hashes <- get_locus_hashes(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + locus)) + diff_hashes <- setdiff(local_db_hashes, tmp_db_hashes) + + sequences <- extract_seq(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"), + locus), diff_hashes) + if (!is_empty(sequences$idx) && !is_empty(sequences$seq) && + length(sequences$idx) == length(sequences$seq)) { + add_new_sequences(file.path(DB$database, + Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp"), + locus), sequences) + } + } + } + + unlink(file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles")), recursive = TRUE) + + file.rename(file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, ".tmp")), + file.path(DB$database, Scheme$folder_name, + paste0(Scheme$folder_name, "_alleles"))) + + # Download Scheme Info + download( + Scheme$link_scheme, + dest = file.path(DB$database, Scheme$folder_name, "scheme_info.html"), + mode = "wb" + ) + + # Download Loci Info + download( + Scheme$link_targets, + dest = file.path(DB$database, Scheme$folder_name, "targets.csv"), + mode = "wb" + ) + + # Send downloaded scheme to database browser overview + DB$available <- gsub("_", " ", basename(dir_ls(DB$database))) + + Scheme$target_table <- read.csv( + file.path(DB$database, Scheme$folder_name, "targets.csv"), + header = TRUE, + sep = "\t", + row.names = NULL, + colClasses = c( + "NULL", + "character", + "character", + "integer", + "integer", + "character", + "integer", + "NULL" + ) + ) + + DB$exist <- length(dir_ls(DB$database)) == 0 + + shinyjs::show("download_cgMLST") + shinyjs::hide("loading") + + output$statustext <- renderUI( + fluidRow( + tags$li( + class = "dropdown", + tags$span(HTML( + paste('', + "Status:    ready")), + style = "color:white;") + ) + ) + ) + + show_toast( + title = "Download successful", + type = "success", + position = "bottom-end", + timer = 5000 + ) + + log_print("Download successful") + + showModal( + modalDialog( + selectInput( + "scheme_db", + label = "", + choices = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {DB$available}, + selected = if(!is.null(Typing$last_scheme)) { + Typing$last_scheme + } else {if(!is.null(DB$scheme)) {input$select_cgmlst} else {DB$available[1]}}), + title = "Select a local database to load.", + footer = tagList( + actionButton("load", "Load", class = "btn btn-default") + ) + ) + ) + }) + + # Download Target Info (CSV Table) + observe({ + input$download_cgMLST + + scheme_overview <- read_html(Scheme$link_scheme) %>% + html_table(header = FALSE) %>% + as.data.frame(stringsAsFactors = FALSE) + + last_scheme_change <- strptime(scheme_overview$X2[scheme_overview$X1 == "Last Change"], + format = "%B %d, %Y, %H:%M %p") + names(scheme_overview) <- NULL + + last_file_change <- format( + file.info(file.path(DB$database, + ".downloaded_schemes", + paste0(Scheme$folder_name, ".zip")))$mtime, "%Y-%m-%d %H:%M %p") + + output$cgmlst_scheme <- renderTable({scheme_overview}) + output$scheme_update_info <- renderText({ + req(last_file_change) + if (last_file_change < last_scheme_change) { + "(Newer scheme available \u274c)" + } else { + "(Scheme is up-to-date \u2705)" + } + }) + }) + + # _______________________ #### + + ## Visualization ---- + + # Render placeholder image + + output$placeholder <- renderImage({ + # Path to your PNG image with a transparent background + image_path <- paste0(getwd(), "/www/PhyloTrace.png") + + # Use HTML to display the image with the tag + list(src = image_path, + height = 180) + }, deleteFile = FALSE) + + # Render tree plot fields + + output$nj_field <- renderUI( + fluidRow( + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br() + ) + ) + + output$mst_field <- renderUI( + fluidRow( + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br() + ) + ) + + output$upgma_field <- renderUI( + fluidRow( + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), + br(), br(), br(), br(), br(), br(), br(), br(), br(), br() + ) + ) + + ### Render Visualization Controls ---- + + #### NJ and UPGMA controls ---- + + # Control enable/disable of variable mapping inputs + observe({ + shinyjs::toggleState(id = "nj_color_mapping", condition = isTRUE(input$nj_mapping_show)) + shinyjs::toggleState(id = "nj_tiplab_scale", condition = isTRUE(input$nj_mapping_show)) + shinyjs::toggleState(id = "upgma_color_mapping", condition = isTRUE(input$upgma_mapping_show)) + shinyjs::toggleState(id = "upgma_tiplab_scale", condition = isTRUE(input$upgma_mapping_show)) + + shinyjs::toggleState(id = "nj_tipcolor_mapping", condition = isTRUE(input$nj_tipcolor_mapping_show)) + shinyjs::toggleState(id = "nj_tippoint_scale", condition = isTRUE(input$nj_tipcolor_mapping_show)) + shinyjs::toggleState(id = "upgma_tipcolor_mapping", condition = isTRUE(input$upgma_tipcolor_mapping_show)) + shinyjs::toggleState(id = "upgma_tippoint_scale", condition = isTRUE(input$upgma_tipcolor_mapping_show)) + + shinyjs::toggleState(id = "nj_tipshape_mapping", condition = isTRUE(input$nj_tipshape_mapping_show)) + shinyjs::toggleState(id = "upgma_tipshape_mapping", condition = isTRUE(input$upgma_tipshape_mapping_show)) + + shinyjs::toggleState(id = "nj_fruit_variable", condition = isTRUE(input$nj_tiles_show_1)) + shinyjs::toggleState(id = "upgma_fruit_variable", condition = isTRUE(input$upgma_tiles_show_1)) + shinyjs::toggleState(id = "nj_fruit_variable_2", condition = isTRUE(input$nj_tiles_show_2)) + shinyjs::toggleState(id = "upgma_fruit_variable_2", condition = isTRUE(input$upgma_tiles_show_2)) + shinyjs::toggleState(id = "nj_fruit_variable_3", condition = isTRUE(input$nj_tiles_show_3)) + shinyjs::toggleState(id = "upgma_fruit_variable_3", condition = isTRUE(input$upgma_tiles_show_3)) + shinyjs::toggleState(id = "nj_fruit_variable_4", condition = isTRUE(input$nj_tiles_show_4)) + shinyjs::toggleState(id = "upgma_fruit_variable_4", condition = isTRUE(input$upgma_tiles_show_4)) + shinyjs::toggleState(id = "nj_fruit_variable_5", condition = isTRUE(input$nj_tiles_show_5)) + shinyjs::toggleState(id = "upgma_fruit_variable_5", condition = isTRUE(input$upgma_tiles_show_5)) + shinyjs::toggleState(id = "nj_tiles_scale_1", condition = isTRUE(input$nj_tiles_show_1)) + shinyjs::toggleState(id = "upgma_tiles_scale_1", condition = isTRUE(input$upgma_tiles_show_1)) + shinyjs::toggleState(id = "nj_tiles_scale_2", condition = isTRUE(input$nj_tiles_show_2)) + shinyjs::toggleState(id = "upgma_tiles_scale_2", condition = isTRUE(input$upgma_tiles_show_2)) + shinyjs::toggleState(id = "nj_tiles_scale_3", condition = isTRUE(input$nj_tiles_show_3)) + shinyjs::toggleState(id = "upgma_tiles_scale_3", condition = isTRUE(input$upgma_tiles_show_3)) + shinyjs::toggleState(id = "nj_tiles_scale_4", condition = isTRUE(input$nj_tiles_show_4)) + shinyjs::toggleState(id = "upgma_tiles_scale_4", condition = isTRUE(input$upgma_tiles_show_4)) + shinyjs::toggleState(id = "nj_tiles_scale_5", condition = isTRUE(input$nj_tiles_show_5)) + shinyjs::toggleState(id = "upgma_tiles_scale_5", condition = isTRUE(input$upgma_tiles_show_5)) + + shinyjs::toggleState(id = "nj_heatmap_sel", condition = isTRUE(input$nj_heatmap_show)) + shinyjs::toggleState(id = "nj_heatmap_scale", condition = isTRUE(input$nj_heatmap_show)) + shinyjs::toggleState(id = "upgma_heatmap_sel", condition = isTRUE(input$upgma_heatmap_show)) + shinyjs::toggleState(id = "upgma_heatmap_scale", condition = isTRUE(input$upgma_heatmap_show)) + }) + + # Size scaling NJ + observe({ + req(input$nj_ratio) + if(input$nj_ratio == "1.6") { + updateSliderInput(session, "nj_scale", + step = 5, value = 800, min = 500, max = 1200) + } else if(input$nj_ratio == "1.77777777777778") { + updateSliderInput(session, "nj_scale", + step = 9, value = 801, min = 504, max = 1197) + } else if(input$nj_ratio == "1.33333333333333"){ + updateSliderInput(session, "nj_scale", + step = 3, value = 801, min = 501, max = 1200) + } + }) + + # Size scaling UPGMA + observe({ + req(input$upgma_ratio) + if(input$upgma_ratio == "1.6") { + updateSliderInput(session, "upgma_scale", + step = 5, value = 800, min = 500, max = 1200) + } else if(input$upgma_ratio == "1.77777777777778") { + updateSliderInput(session, "upgma_scale", + step = 9, value = 801, min = 504, max = 1197) + } else if(input$upgma_ratio == "1.33333333333333"){ + updateSliderInput(session, "upgma_scale", + step = 3, value = 801, min = 501, max = 1200) + } + }) + + # Size scaling MST + observe({ + req(input$mst_ratio) + if(input$mst_ratio == "1.6") { + updateSliderInput(session, "mst_scale", + step = 5, value = 800, min = 500, max = 1200) + } else if(input$mst_ratio == "1.77777777777778") { + updateSliderInput(session, "mst_scale", + step = 9, value = 801, min = 504, max = 1197) + } else if(input$mst_ratio == "1.33333333333333"){ + updateSliderInput(session, "mst_scale", + step = 3, value = 801, min = 501, max = 1200) + } + }) + + # Custom Labels + + # Add custom label + observeEvent(input$nj_add_new_label, { + + if(nchar(input$nj_new_label_name) > 0) { + if(!(input$nj_new_label_name %in% Vis$custom_label_nj)) { + Vis$custom_label_nj <- rbind(Vis$custom_label_nj, input$nj_new_label_name) + if(!(nrow(Vis$custom_label_nj) == 1)) { + updateSelectInput(session, "nj_custom_label_sel", selected = input$nj_new_label_name) + } + } else { + show_toast( + title = "Label already exists", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } else { + show_toast( + title = "Min. 1 character", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + + observeEvent(input$upgma_add_new_label, { + + if(nchar(input$upgma_new_label_name) > 0) { + if(!(input$upgma_new_label_name %in% Vis$custom_label_upgma)) { + Vis$custom_label_upgma <- rbind(Vis$custom_label_upgma, input$upgma_new_label_name) + if(!(nrow(Vis$custom_label_upgma) == 1)) { + updateSelectInput(session, "upgma_custom_label_sel", selected = input$upgma_new_label_name) + } + } else { + show_toast( + title = "Label already exists", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } else { + show_toast( + title = "Min. 1 character", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + + # Delete custom label + observeEvent(input$nj_del_label, { + + if(nrow(Vis$custom_label_nj) > 1) { + Vis$custom_label_nj <- Vis$custom_label_nj[-which(Vis$custom_label_nj[,1] == input$nj_custom_label_sel), , drop = FALSE] + } else if (nrow(Vis$custom_label_nj) == 1) { + Vis$nj_label_pos_x <- list() + Vis$nj_label_pos_y <- list() + Vis$nj_label_size <- list() + Vis$custom_label_nj <- data.frame() + } + }) + + observeEvent(input$upgma_del_label, { + + if(nrow(Vis$custom_label_upgma) > 1) { + Vis$custom_label_upgma <- Vis$custom_label_upgma[-which(Vis$custom_label_upgma[,1] == input$upgma_custom_label_sel), , drop = FALSE] + } else if (nrow(Vis$custom_label_upgma) == 1) { + Vis$upgma_label_pos_x <- list() + Vis$upgma_label_pos_y <- list() + Vis$upgma_label_size <- list() + Vis$custom_label_upgma <- data.frame() + } + }) + + # Select custom labels + output$nj_custom_label_select <- renderUI({ + if(nrow(Vis$custom_label_nj) > 0) { + selectInput( + "nj_custom_label_sel", + "", + choices = Vis$custom_label_nj[,1] + ) + } + }) + + output$upgma_custom_label_select <- renderUI({ + if(nrow(Vis$custom_label_upgma) > 0) { + selectInput( + "upgma_custom_label_sel", + "", + choices = Vis$custom_label_upgma[,1] + ) + } + }) + + # Select custom labels + output$nj_cust_label_save <- renderUI({ + if(nrow(Vis$custom_label_nj) > 0) { + actionButton( + "nj_cust_label_save", + "Apply" + ) + } else { + column( + width = 12, + br(), br(), br(), br(), br(), br(), + h5("test", style = "color: transparent; margin-bottom: 3px") + ) + } + }) + + output$upgma_cust_label_save <- renderUI({ + if(nrow(Vis$custom_label_upgma) > 0) { + actionButton( + "upgma_cust_label_save", + "Apply" + ) + } else { + column( + width = 12, + br(), br(), br(), br(), br(), br(), + h5("test", style = "color: transparent; margin-bottom: 3px") + ) + } + }) + + # Custom Label Size + output$nj_custom_labelsize <- renderUI({ + if(length(Vis$custom_label_nj) > 0) { + if(!is.null(Vis$nj_label_size[[input$nj_custom_label_sel]])) { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, + value = Vis$nj_label_size[[input$nj_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, value = 5, + width = "150px") + } + } + }) + + output$upgma_custom_labelsize <- renderUI({ + if(length(Vis$custom_label_upgma) > 0) { + if(!is.null(Vis$upgma_label_size[[input$upgma_custom_label_sel]])) { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, + value = Vis$upgma_label_size[[input$upgma_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_size"), + label = h5("Size", style = "color: white; margin-bottom: 0px;"), + min = 0, max = 10, step = 0.5, ticks = F, value = 5, + width = "150px") + } + } + }) + + # Render slider input based on selected label + output$nj_sliderInput_y <- renderUI({ + if(length(Vis$custom_label_nj) > 0) { + if(!is.null(Vis$nj_label_pos_y[[input$nj_custom_label_sel]])) { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$nj_label_pos_y[[input$nj_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = sum(DB$data$Include), step = 1, ticks = F, + value = sum(DB$data$Include) / 2, + width = "150px") + } + } + }) + + output$upgma_sliderInput_y <- renderUI({ + if(length(Vis$custom_label_upgma) > 0) { + if(!is.null(Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]])) { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_y"), + label = h5("Vertical", style = "color: white; margin-bottom: 5px;"), + min = 0, max = sum(DB$data$Include), step = 1, ticks = F, + value = sum(DB$data$Include) / 2, + width = "150px") + } + } + }) + + output$nj_sliderInput_x <- renderUI({ + if(length(Vis$custom_label_nj) > 0) { + if(!is.null(Vis$nj_label_pos_x[[input$nj_custom_label_sel]])) { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$nj_label_pos_x[[input$nj_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("nj_slider_", input$nj_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = round(Vis$nj_max_x, 0), step = 1, ticks = F, + value = round(Vis$nj_max_x / 2, 0), + width = "150px") + } + } + }) + + output$upgma_sliderInput_x <- renderUI({ + if(length(Vis$custom_label_upgma) > 0) { + if(!is.null(Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]])) { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = 50, step = 1, ticks = F, + value = Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]], + width = "150px") + } else { + sliderInput(inputId = paste0("upgma_slider_", input$upgma_custom_label_sel, "_x"), + label = h5("Horizontal", style = "color: white; margin-bottom: 5px;"), + min = 0, max = round(Vis$upgma_max_x, 0), step = 1, ticks = F, + value = round(Vis$upgma_max_x / 2, 0), + width = "150px") + } + } + }) + + # Apply custom label changes + observeEvent(input$nj_cust_label_save, { + + if(!is.null(Vis$nj_label_pos_y) & + !is.null(Vis$nj_label_pos_x) & + !is.null(Vis$nj_label_size) & + !is.null(input$nj_custom_label_sel)) { + Vis$nj_label_pos_y[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_y")]] + Vis$nj_label_pos_x[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_x")]] + Vis$nj_label_size[[input$nj_custom_label_sel]] <- input[[paste0("nj_slider_", input$nj_custom_label_sel, "_size")]] + } + }) + + observeEvent(input$upgma_cust_label_save, { + + if(!is.null(Vis$upgma_label_pos_y) & + !is.null(Vis$upgma_label_pos_x) & + !is.null(Vis$upgma_label_size) & + !is.null(input$upgma_custom_label_sel)) { + Vis$upgma_label_pos_y[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_y")]] + Vis$upgma_label_pos_x[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_x")]] + Vis$upgma_label_size[[input$upgma_custom_label_sel]] <- input[[paste0("upgma_slider_", input$upgma_custom_label_sel, "_size")]] + } + }) + + # Show delete custom label button if custam label added + output$nj_del_label <- renderUI({ + if(nrow(Vis$custom_label_nj) > 0) { + actionButton( + "nj_del_label", + "", + icon = icon("minus") + ) + } else {NULL} + }) + + output$upgma_del_label <- renderUI({ + if(nrow(Vis$custom_label_upgma) > 0) { + actionButton( + "upgma_del_label", + "", + icon = icon("minus") + ) + } else {NULL} + }) + + # Mapping value number information + output$nj_tiplab_mapping_info <- renderUI({ + if(!is.null(input$nj_color_mapping) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_color_mapping]))) { + if(input$nj_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_color_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$upgma_tiplab_mapping_info <- renderUI({ + if(!is.null(input$upgma_color_mapping) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) { + if(input$upgma_tiplab_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_color_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$nj_tipcolor_mapping_info <- renderUI({ + if(!is.null(input$nj_tipcolor_mapping) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) { + if(input$nj_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tipcolor_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$upgma_tipcolor_mapping_info <- renderUI({ + if(!is.null(input$upgma_tipcolor_mapping) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) { + if(input$upgma_tippoint_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tipcolor_mapping_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$nj_tipshape_mapping_info <- renderUI({ + if(!is.null(input$nj_tipshape_mapping) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) { + column( + width = 3, + h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))) > 6) { + column( + width = 3, + h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$upgma_tipshape_mapping_info <- renderUI({ + if(!is.null(input$upgma_tipshape_mapping) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) { + column( + width = 3, + h5("Mapping continous variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))) > 6) { + column( + width = 3, + h5("Mapping > 6 variables to shape not possible", style = "color: #E18B00; font-style: italic; font-size: 12px; margin-top: 15px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_tipshape_mapping]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + }) + + output$nj_fruit_mapping_info <- renderUI({ + if(input$nj_tile_num == 1) { + if(!is.null(input$nj_fruit_variable) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable]))) { + if(input$nj_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_1", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 2) { + if(!is.null(input$nj_fruit_variable_2) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) { + if(input$nj_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_2", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 3) { + if(!is.null(input$nj_fruit_variable_3) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) { + if(input$nj_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_3", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 4) { + if(!is.null(input$nj_fruit_variable_4) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) { + if(input$nj_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_4", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$nj_tile_num == 5) { + if(!is.null(input$nj_fruit_variable_5) & (!is.null(Vis$meta_nj))) { + if(is.numeric(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) { + if(input$nj_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_tiles_mapping_div_mid_5", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } + }) + + output$upgma_fruit_mapping_info <- renderUI({ + if(input$upgma_tile_num == 1) { + if(!is.null(input$upgma_fruit_variable) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) { + if(input$upgma_tiles_scale_1 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_1", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 2) { + if(!is.null(input$upgma_fruit_variable_2) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) { + if(input$upgma_tiles_scale_2 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_2", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 3) { + if(!is.null(input$upgma_fruit_variable_3) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) { + if(input$upgma_tiles_scale_3 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_3", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 4) { + if(!is.null(input$upgma_fruit_variable_4) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) { + if(input$upgma_tiles_scale_4 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_4", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } else if (input$upgma_tile_num == 5) { + if(!is.null(input$upgma_fruit_variable_5) & (!is.null(Vis$meta_upgma))) { + if(is.numeric(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) { + if(input$upgma_tiles_scale_5 %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_tiles_mapping_div_mid_5", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { + column( + width = 3, + h5(paste0("> 7 (", length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), ") categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5(paste0(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))), paste0(" categorical values")), style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } else {NULL} + } + }) + + output$nj_heatmap_mapping_info <- renderUI({ + if(!is.null(input$nj_heatmap_select) & (!is.null(Vis$meta_nj))) { + if (any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { + column( + width = 3, + h5("Heatmap with categorical and continous values not possible", + style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") + ) + } else { + if(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric))) { + if(input$nj_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "nj_heatmap_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { + column( + width = 3, + h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } + } else {NULL} + }) + + output$upgma_heatmap_mapping_info <- renderUI({ + if(!is.null(input$upgma_heatmap_select) & (!is.null(Vis$meta_upgma))) { + if (any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { + column( + width = 3, + h5("Heatmap with categorical and continous values not possible", + style = "color: #E18B00; font-size: 12px; font-style: italic; margin-top: 15px; margin-left: 40px") + ) + } else { + if(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric))) { + if(input$upgma_heatmap_scale %in% c('Spectral', 'RdYlGn', 'RdYlBu', 'RdGy', 'RdBu', 'PuOr', 'PRGn', 'PiYG', 'BrBG')) { + column( + width = 3, + fluidRow( + column( + width = 4, + h5("Midpoint", style = "color: white; margin-top: 22px;") + ), + column( + width = 8, + div( + class = "divmid-sel1", + selectInput( + "upgma_heatmap_div_mid", + label = "", + choices = c("Zero", "Mean", "Median"), + selected = "Mean" + ) + ) + ) + ) + ) + } else { + column( + width = 3, + h5("Continous values", style = "color: white; font-size: 14px; margin-top: 23px; margin-left: 40px") + ) + } + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { + column( + width = 3, + h5(paste0("> 7 categorical values"), style = "color: #E18B00; font-size: 12px; margin-top: 23px; margin-left: 40px") + ) + } else { + column( + width = 3, + h5("Categorical values", style = "color: white; font-size: 14px; margin-top: 20px; margin-left: 40px") + ) + } + } + } + } else {NULL} + }) + + # Tiles offset + output$nj_fruit_offset_circ <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ", + label = "", + min = min, + max = max, + step= step, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.1 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.05 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ", + label = "", + min = min, + max = max, + step= step, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ", + label = "", + min = -0.2, + max = 0.2, + step= 0.05, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_2 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_2", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_2", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_2 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_2", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_2", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_3 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_3", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_3", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_3 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_3", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_3", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_4 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_4", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_4", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_4 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_4", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_4", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_fruit_offset_circ_5 <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "nj_fruit_offset_circ_5", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_offset_circ_5", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_fruit_offset_circ_5 <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } else { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } + + sliderInput( + "upgma_fruit_offset_circ_5", + label = "", + min = min, + max = max, + step= step, + value = offset, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_offset_circ_5", + label = "", + min = -0.2, + max = 0.2, + step= 0.01, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + # For Layout change update tiles offset position + observeEvent(input$nj_layout, { + + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } else { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } + + updateSliderInput(session, "nj_fruit_offset_circ", min = min, step = step, max = max) + updateSliderInput(session, "nj_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "nj_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "nj_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "nj_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) + }) + + observeEvent(input$upgma_layout, { + + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + offset <- 0.05 + step <- 0.01 + min <- -0.2 + max <- 0.2 + } else { + offset <- 0.15 + step <- 0.03 + min <- -0.6 + max <- 0.6 + } + + updateSliderInput(session, "upgma_fruit_offset_circ", min = min, step = step, max = max) + updateSliderInput(session, "upgma_fruit_offset_circ_2", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "upgma_fruit_offset_circ_3", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "upgma_fruit_offset_circ_4", min = min, step = step, max = max, value = offset) + updateSliderInput(session, "upgma_fruit_offset_circ_5", min = min, step = step, max = max, value = offset) + }) + + # Heatmap width + output$nj_heatmap_width <- renderUI({ + if(!is.null(input$nj_heatmap_select)) { + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + + sliderInput( + "nj_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = width, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = 0.1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_heatmap_width <- renderUI({ + if(!is.null(input$upgma_heatmap_select)) { + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + + sliderInput( + "upgma_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = width, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_heatmap_width", + label = "", + min = 0.05, + max = 1.5, + value = 0.1, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + }) + + # Update value if new variables added + observeEvent(input$nj_heatmap_select, { + + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "nj_heatmap_width", value = width) + }) + + observeEvent(input$upgma_heatmap_select, { + + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "upgma_heatmap_width", value = width) + }) + + # Update value if layout changed + observeEvent(input$nj_layout, { + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "nj_heatmap_width", value = width) + }) + + observeEvent(input$upgma_layout, { + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + width <- 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + width <- min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 1.5 + } + } + } else { + if(length_input < 3) { + width <- 0.3 + } else if (length_input >= 3 && length_input <= 27) { + width <- min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + width <- 3 + } + } + updateSliderInput(session, "upgma_heatmap_width", value = width) + }) + + # Heatmap column titles position + observeEvent(input$nj_layout, { + if(!(input$nj_layout == "inward" | input$nj_layout == "circular")) { + updateSliderInput(session, "nj_colnames_y", value = -1) + } else { + updateSliderInput(session, "nj_colnames_y", value = 0) + } + }) + + observeEvent(input$upgma_layout, { + if(!(input$upgma_layout == "inward" | input$upgma_layout == "circular")) { + updateSliderInput(session, "upgma_colnames_y", value = -1) + } else { + updateSliderInput(session, "upgma_colnames_y", value = 0) + } + }) + + output$nj_colnames_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + if(input$nj_layout == "inward" | input$nj_layout == "circular") { + min <- 0 + val <- 0 + } else { + val <- -1 + if((sum(DB$data$Include) * -0.1) > -2) { + min <- -2 + } else { + min <- round(sum(DB$data$Include) * -0.1, 0) + } + } + sliderInput( + "nj_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = min, + max = sum(DB$data$Include), + value = val, + step = 1, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = -10, + max = 10, + value = 0, + step = 1, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_colnames_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { + min <- 0 + val <- 0 + } else { + val <- -1 + if((sum(DB$data$Include) * -0.1) > -2) { + min <- -2 + } else { + min <- round(sum(DB$data$Include) * -0.1, 0) + } + } + sliderInput( + "upgma_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = min, + max = sum(DB$data$Include), + value = val, + step = 1, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_colnames_y", + label = h5("Names Y-Position", style = "color:white; margin-bottom: 0px"), + min = -10, + max = 10, + value = 0, + step = 1, + width = "150px", + ticks = FALSE + ) + } + }) + + # Heatmap column titles angle + output$nj_colnames_angle <- renderUI({ + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + angle <- 90 + } else {angle <- -90} + sliderInput( + "nj_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = angle, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_colnames_angle <- renderUI({ + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + angle <- 90 + } else {angle <- -90} + sliderInput( + "upgma_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = angle, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_colnames_angle", + label = h5("Names Angle", style = "color:white; margin-bottom: 0px"), + min = -90, + max = 90, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + # Change heatmap column titles angle and label align when switching layout + observeEvent(input$nj_layout, { + if(input$nj_layout == "circular" | input$nj_layout == "inward"){ + angle <- 90 + val <- TRUE + } else { + angle <- -90 + val <- FALSE + } + updateSwitchInput(session, "nj_align", value = val) + updateSliderInput(session, "nj_colnames_angle", value = angle) + }) + + observeEvent(input$upgma_layout, { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward"){ + angle <- 90 + val <- TRUE + } else { + angle <- -90 + val <- FALSE + } + updateSwitchInput(session, "upgma_align", value = val) + updateSliderInput(session, "upgma_colnames_angle", value = angle) + }) + + # Tile number selector update each other + observeEvent(input$nj_tile_num, { + updateSelectInput(session, "nj_tile_number", selected = input$nj_tile_num) + }) + + observeEvent(input$nj_tile_number, { + updateSelectInput(session, "nj_tile_num", selected = input$nj_tile_number) + }) + + observeEvent(input$upgma_tile_num, { + updateSelectInput(session, "upgma_tile_number", selected = input$upgma_tile_num) + }) + + observeEvent(input$upgma_tile_number, { + updateSelectInput(session, "upgma_tile_num", selected = input$upgma_tile_number) + }) + + # Clade coloring + output$nj_clade_scale <- renderUI({ + if(length(input$nj_parentnode) <= 1) { + fluidRow( + column( + width = 5, + h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "nj_clade_scale", + selected = "#D0F221", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ) + ) + } else { + fluidRow( + column( + width = 5, + h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + div( + class = "sel-clade-scale", + selectInput( + "nj_clade_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + ) + ) + } + }) + + output$upgma_clade_scale <- renderUI({ + if(length(input$upgma_parentnode) <= 1) { + fluidRow( + column( + width = 5, + h5("Color", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + colorPickr( + inputId = "upgma_clade_scale", + selected = "#D0F221", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start", + width = "100%" + ) + ) + ) + } else { + fluidRow( + column( + width = 5, + h5("Scale", style = "color:white; position: relative; right: -15px; margin-top: 30px") + ), + column( + width = 7, + align = "center", + div( + class = "sel-clade-scale", + selectInput( + "upgma_clade_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + ) + ) + } + }) + + # Heatmap variable color scale + output$nj_heatmap_scale <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_heatmap_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_heatmap_select]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_heatmap_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_heatmap_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Paired" + ) + ) + } + } + }) + + output$upgma_heatmap_scale <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_heatmap_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_heatmap_select]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_heatmap_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_heatmap_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Paired" + ) + ) + } + } + }) + + # Tiles variable color scale + output$nj_tiles_scale_1 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_1", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_1", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_1", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_1 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_1", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_1", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_1", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_2 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_2", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_2]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_2", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_2", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_2 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_2", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_2", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_2", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_3 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_3", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_3]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_3", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_3", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_3 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_3", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_3", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_3", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_4 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_4])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_4", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_4]))) > 7) { + shinyjs::disabled(selectInput( + "nj_tiles_scale_4", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + )) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_4", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_4 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_4", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_4]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_4", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_4", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$nj_tiles_scale_5 <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_5", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_fruit_variable_5]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_5", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiles_scale_5", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + output$upgma_tiles_scale_5 <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_5", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_5", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiles_scale_5", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Accent" + ) + ) + } + } + }) + + # Tip Labels Variable Color Scale + output$nj_tiplab_scale <- renderUI({ + if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tiplab_scale", + "", + selectize = FALSE, + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_color_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tiplab_scale", + "", + selectize = FALSE, + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tiplab_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + } + } + }) + + output$upgma_tiplab_scale <- renderUI({ + if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tiplab_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_color_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tiplab_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tiplab_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ) + ) + ) + } + } + }) + + # Tippoint Scale + output$nj_tippoint_scale <- renderUI({ + if(!is.null(Vis$meta_nj)) { + if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ) + ) + ) + } else { + if(length(unique(unlist(Vis$meta_nj[input$nj_tipcolor_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + } + } else { + shinyjs::disabled( + selectInput( + "nj_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + }) + + output$upgma_tippoint_scale <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Continous = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ), + Diverging = list( + "Spectral", + "RdYlGn", + "RdYlBu", + "RdGy", + "RdBu", + "PuOr", + "PRGn", + "PiYG", + "BrBG" + ) + ), + selected = c("Viridis" = "viridis") + ) + ) + } else { + if(length(unique(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping]))) > 7) { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Gradient = list( + "Magma" = "magma", + "Inferno" = "inferno", + "Plasma" = "plasma", + "Viridis" = "viridis", + "Cividis" = "cividis", + "Rocket" = "rocket", + "Mako" = "mako", + "Turbo" = "turbo" + ) + ), + selected = "turbo" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + } + } else { + shinyjs::disabled( + selectInput( + "upgma_tippoint_scale", + "", + choices = list( + Qualitative = list( + "Set1", + "Set2", + "Set3", + "Pastel1", + "Pastel2", + "Paired", + "Dark2", + "Accent" + ), + Sequential = list( + "YlOrRd", + "YlOrBr", + "YlGnBu", + "YlGn", + "Reds", + "RdPu", + "Purples", + "PuRd", + "PuBuGn", + "PuBu", + "OrRd", + "Oranges", + "Greys", + "Greens", + "GnBu", + "BuPu", + "BuGn", + "Blues" + ) + ), + selected = "Set2" + ) + ) + } + }) + + # Clade Highlights + output$nj_parentnode <- renderUI({ + if(!is.null(Vis$nj_parentnodes)) { + pickerInput( + "nj_parentnode", + label = "", + choices = sort(unique(as.numeric(Vis$nj_parentnodes))), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } else { + pickerInput( + "nj_parentnode", + label = "", + choices = c(), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } + }) + + output$upgma_parentnode <- renderUI({ + if(!is.null(Vis$upgma_parentnodes)) { + pickerInput( + "upgma_parentnode", + label = "", + choices = sort(unique(as.numeric(Vis$upgma_parentnodes))), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } else { + pickerInput( + "upgma_parentnode", + label = "", + choices = c(), + multiple = TRUE, + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "99%" + ) + } + }) + + # Branch label size + output$nj_branch_size <- renderUI( + numericInput( + "nj_branch_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 2, + max = 10, + step = 0.5, + value = Vis$branch_size_nj, + width = "80px" + ) + ) + + output$upgma_branch_size <- renderUI( + numericInput( + "upgma_branch_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 2, + max = 10, + step = 0.5, + value = Vis$branch_size_upgma, + width = "80px" + ) + ) + + # Tippanel size + output$nj_tiplab_padding <- renderUI( + if(!is.null(Vis$tiplab_padding_nj)) { + sliderInput( + inputId = "nj_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = Vis$tiplab_padding_nj, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "nj_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = 0.2, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + ) + + output$upgma_tiplab_padding <- renderUI( + if(!is.null(Vis$tiplab_padding_upgma)) { + sliderInput( + inputId = "upgma_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = Vis$tiplab_padding_upgma, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "upgma_tiplab_padding", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 0.05, + max = 1, + value = 0.2, + step = 0.05, + width = "150px", + ticks = FALSE + ) + } + ) + + # Nodepoint size + output$nj_nodepoint_size <- renderUI( + if(!is.null(Vis$nodepointsize_nj)) { + sliderInput( + inputId = "nj_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = Vis$nodepointsize_nj, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "nj_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = 2.5, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } + ) + + output$upgma_nodepoint_size <- renderUI( + if(!is.null(Vis$nodepointsize_upgma)) { + sliderInput( + inputId = "upgma_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = Vis$nodepointsize_upgma, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "upgma_nodepoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + value = 2.5, + step = 0.5, + width = "150px", + ticks = FALSE + ) + } + ) + + # Tippoint size + output$nj_tippoint_size <- renderUI( + if(!is.null(Vis$tippointsize_nj)) { + sliderInput( + inputId = "nj_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = Vis$tippointsize_nj, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "nj_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = 4, + width = "150px", + ticks = FALSE + ) + } + ) + + output$upgma_tippoint_size <- renderUI( + if(!is.null(Vis$tippointsize_upgma)) { + sliderInput( + inputId = "upgma_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = Vis$tippointsize_upgma, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + inputId = "upgma_tippoint_size", + label = h5("Size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 20, + step = 0.5, + value = 4, + width = "150px", + ticks = FALSE + ) + } + ) + + # Tiplabel size + output$nj_tiplab_size <- renderUI( + if(!is.null(Vis$labelsize_nj)) { + numericInput( + "nj_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = Vis$labelsize_nj, + width = "80px" + ) + } else { + numericInput( + "nj_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = 4, + width = "80px" + ) + } + ) + + output$upgma_tiplab_size <- renderUI( + if(!is.null(Vis$labelsize_upgma)) { + numericInput( + "upgma_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = Vis$labelsize_upgma, + width = "80px" + ) + } else { + numericInput( + "upgma_tiplab_size", + label = h5("Label size", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + step = 0.5, + value = 4, + width = "80px" + ) + } + ) + + # Rootedge length + output$nj_rootedge_length <- renderUI({ + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.02, 0) < 1) { + min <- 1 + } else { + min <- round(ceiling(Vis$nj_max_x) * 0.02, 0) + } + max <- round(ceiling(Vis$nj_max_x) * 0.2, 0) + sliderInput( + "nj_rootedge_length", + label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), + min = min, + max = max, + value = round(ceiling(Vis$nj_max_x) * 0.05, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_rootedge_length", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_rootedge_length <- renderUI({ + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.02, 0) < 1) { + min <- 1 + } else { + min <- round(ceiling(Vis$upgma_max_x) * 0.02, 0) + } + max <- round(ceiling(Vis$upgma_max_x) * 0.2, 0) + sliderInput( + "upgma_rootedge_length", + label = h5("Rootedge Length", style = "color:white; margin-bottom: 0px"), + min = min, + max = max, + value = round(ceiling(Vis$upgma_max_x) * 0.05, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_rootedge_length", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + # Treescale + output$nj_treescale_width <- renderUI({ + if(!is.null(Vis$nj_max_x)) { + numericInput( + "nj_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = round(ceiling(Vis$nj_max_x) * 0.1, 0), + min = 1, + max = round(floor(Vis$nj_max_x) * 0.5, 0), + step = 1, + width = "80px" + ) + } else { + numericInput( + "nj_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = 2, + min = 1, + max = 10, + step = 1, + width = "80px" + ) + } + }) + + output$upgma_treescale_width <- renderUI({ + if(!is.null(Vis$upgma_max_x)) { + numericInput( + "upgma_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = round(ceiling(Vis$upgma_max_x) * 0.1, 0), + min = 1, + max = round(floor(Vis$upgma_max_x) * 0.5, 0), + step = 1, + width = "80px" + ) + } else { + numericInput( + "upgma_treescale_width", + label = h5("Length", style = "color:white; margin-bottom: 0px"), + value = 2, + min = 1, + max = 10, + step = 1, + width = "80px" + ) + } + }) + + output$nj_treescale_x <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(ceiling(Vis$nj_min_x) < 1) { + floor <- 1 + } else { + floor <- ceiling(Vis$nj_min_x) + } + sliderInput( + "nj_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = floor, + max = round(floor(Vis$nj_max_x)), + value = round(ceiling(Vis$nj_max_x) * 0.2, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_treescale_x <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(ceiling(Vis$upgma_min_x) < 1) { + floor <- 1 + } else { + floor <- ceiling(Vis$upgma_min_x) + } + sliderInput( + "upgma_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = floor, + max = round(floor(Vis$upgma_max_x)), + value = round(ceiling(Vis$upgma_max_x) * 0.2, 0), + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_treescale_x", + label = h5("X Position", style = "color:white; margin-bottom: 0px"), + min = 1, + max = 10, + value = 2, + width = "150px", + ticks = FALSE + ) + } + }) + + output$nj_treescale_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + sliderInput( + "nj_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = sum(DB$data$Include), + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 10, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_treescale_y <- renderUI({ + if(!is.null(sum(DB$data$Include))) { + sliderInput( + "upgma_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = sum(DB$data$Include), + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_treescale_y", + label = h5("Y Position", style = "color:white; margin-bottom: 0px"), + min = 0, + max = 10, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + ### Heatmap + # Heatmap picker + output$nj_heatmap_sel <- renderUI({ + if(!is.null(Vis$meta_nj)) { + meta <- select(Vis$meta_nj, -c(taxa, Index, `Assembly ID`, `Assembly Name`, + Scheme, `Typing Date`, Successes, Errors)) + + # Identify numeric columns + numeric_columns <- sapply(meta, is.numeric) + + numeric_column_names <- names(meta[numeric_columns]) + + non_numeric_column_names <- names(meta)[!numeric_columns] + + choices <- list() + + # Add Continuous list only if there are numeric columns + if (length(numeric_column_names) > 0) { + choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) + } + + # Add Diverging list + choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) + + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "nj_heatmap_select", + label = "", + width = "100%", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else {choices}, + options = list( + `dropdown-align-center` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + ) + } else { + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "nj_heatmap_select", + label = "", + width = "100%", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + multiple = TRUE + ) + ) + ) + } + }) + + output$upgma_heatmap_sel <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + meta <- select(Vis$meta_upgma, -c(taxa, Index, `Assembly ID`, `Assembly Name`, + Scheme, `Typing Date`, Successes, Errors)) + + # Identify numeric columns + numeric_columns <- sapply(meta, is.numeric) + + numeric_column_names <- names(meta[numeric_columns]) + + non_numeric_column_names <- names(meta)[!numeric_columns] + + choices <- list() + + # Add Continuous list only if there are numeric columns + if (length(numeric_column_names) > 0) { + choices$Continuous <- as.list(setNames(numeric_column_names, numeric_column_names)) + } + + # Add Diverging list + choices$Categorical <- as.list(setNames(non_numeric_column_names, non_numeric_column_names)) + + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "upgma_heatmap_select", + label = "", + width = "100%", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else {choices}, + options = list( + `dropdown-align-center` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + ) + } else { + div( + class = "heatmap-picker", + shinyjs::disabled( + pickerInput( + inputId = "upgma_heatmap_select", + label = "", + width = "100%", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + multiple = TRUE + ) + ) + ) + } + }) + + # Heatmap offset + output$nj_heatmap_offset <- renderUI({ + if(!is.null(Vis$nj_max_x)) { + sliderInput( + "nj_heatmap_offset", + label = "", + min = 0, + max = round(ceiling(Vis$nj_max_x)*1.5, 0), + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_heatmap_offset", + label = "", + min = 0, + max = 10, + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + output$upgma_heatmap_offset <- renderUI({ + if(!is.null(Vis$upgma_max_x)) { + sliderInput( + "upgma_heatmap_offset", + label = "", + min = 0, + max = round(ceiling(Vis$upgma_max_x)*1.5, 0), + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_heatmap_offset", + label = "", + min = 0, + max = 10, + step = 1, + value = 0, + width = "150px", + ticks = FALSE + ) + } + }) + + ### Tiling + # Geom Fruit select Variable + output$nj_fruit_variable <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable2 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_2", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_2", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable3 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_3", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_3", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable4 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_4", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_4", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$nj_fruit_variable5 <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_5", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_fruit_variable_5", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable2 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_2", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_2", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable3 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled(selectInput( + "upgma_fruit_variable_3", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + )) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_3", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable4 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_4", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_4", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + output$upgma_fruit_variable5 <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_5", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Isolation Date` = "Isolation Date"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_fruit_variable_5", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + ) + ) + } + }) + + # Geom Fruit Width + output$nj_fruit_width <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width2 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_2", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width3 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_3", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width4 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_4", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$nj_fruit_width5 <- renderUI({ + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "nj_fruit_width_circ_5", + label = "", + min = 1, + max = round(ceiling(Vis$nj_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + sliderInput( + "nj_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "nj_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width2 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_2", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_2", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width3 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_3", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_3", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width4 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_4", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_4", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + output$upgma_fruit_width5 <- renderUI({ + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + if(width_calc < 1) {width <- 1} + } else { + width_calc <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + if(width_calc < 1) {width <- 1} + } + } + sliderInput( + "upgma_fruit_width_circ_5", + label = "", + min = 1, + max = round(ceiling(Vis$upgma_max_x) * 0.5, 0), + value = width, + width = "150px", + ticks = FALSE + ) + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + sliderInput( + "upgma_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 3, + width = "150px", + ticks = FALSE + ) + } else { + sliderInput( + "upgma_fruit_width_circ_5", + label = "", + min = 1, + max = 10, + value = 1, + width = "150px", + ticks = FALSE + ) + } + } + }) + + # For Layout change update tiles + observeEvent(input$nj_layout, { + if((!is.null(Vis$nj_min_x)) & (!is.null(Vis$nj_max_x))) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) * 3 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } + + updateSliderInput(session, "nj_fruit_width_circ", value = width) + updateSliderInput(session, "nj_fruit_width_circ_2", value = width) + updateSliderInput(session, "nj_fruit_width_circ_3", value = width) + updateSliderInput(session, "nj_fruit_width_circ_4", value = width) + updateSliderInput(session, "nj_fruit_width_circ_5", value = width) + } + }) + + observeEvent(input$upgma_layout, { + if((!is.null(Vis$upgma_min_x)) & (!is.null(Vis$upgma_max_x))) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- 3 + } else { + width <- 1 + } + } else { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) * 3 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } + + updateSliderInput(session, "upgma_fruit_width_circ", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_2", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_3", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_4", value = width) + updateSliderInput(session, "upgma_fruit_width_circ_5", value = width) + } + }) + + # Tip color mapping + output$nj_tipcolor_mapping <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_tipcolor_mapping", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(City = "City"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tipcolor_mapping", + "", + choices = c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(City = "City") + ) + ) + } + }) + + output$upgma_tipcolor_mapping <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_tipcolor_mapping", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Assembly Name` = "Assembly Name", `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(City = "City"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tipcolor_mapping", + "", + choices = c( + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(City = "City") + ) + ) + } + }) + + # Tip shape Mapping + output$nj_tipshape_mapping <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_tipshape_mapping", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_tipshape_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } + }) + + output$upgma_tipshape_mapping <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_tipshape_mapping", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_tipshape_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + ) + } + }) + + # Branch label + output$nj_branch_label <- renderUI({ + if(!is.null(Vis$meta_nj)) { + selectInput( + "nj_branch_label", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + } else { + selectInput( + "nj_branch_label", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + } + }) + + output$upgma_branch_label <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + selectInput( + "upgma_branch_label", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c("Host" = "Host"), + width = "100%" + ) + } else { + selectInput( + "upgma_branch_label", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c("Host" = "Host"), + width = "100%" + ) + } + }) + + # Color mapping + output$nj_color_mapping <- renderUI({ + if(!is.null(Vis$meta_nj)) { + shinyjs::disabled( + selectInput( + "nj_color_mapping", + "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(Country = "Country"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "nj_color_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(Country = "Country"), + width = "100%" + ) + ) + } + }) + + output$upgma_color_mapping <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + shinyjs::disabled( + selectInput( + "upgma_color_mapping", + "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(`Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(Country = "Country"), + width = "100%" + ) + ) + } else { + shinyjs::disabled( + selectInput( + "upgma_color_mapping", + "", + choices = c( + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(Country = "Country"), + width = "100%" + ) + ) + } + }) + + # Tip labels + output$nj_tiplab <- renderUI({ + if(!is.null(Vis$meta_nj)) { + selectInput( + "nj_tiplab", + label = "", + choices = if(ncol(Vis$meta_nj) == 11) { + c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_nj)[13:ncol(Vis$meta_nj)]) + }, + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } else { + selectInput( + "nj_tiplab", + label = "", + choices = c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } + }) + + output$upgma_tiplab <- renderUI({ + if(!is.null(Vis$meta_upgma)) { + selectInput( + "upgma_tiplab", + label = "", + choices = if(ncol(Vis$meta_upgma) == 11) { + c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ) + } else { + append(c(Index = "Index", `Assembly ID` = "Assembly ID", `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", Host = "Host", Country = "Country", City = "City"), + names(Vis$meta_upgma)[13:ncol(Vis$meta_upgma)]) + }, + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } else { + selectInput( + "upgma_tiplab", + label = "", + choices = c( + Index = "Index", + `Assembly ID` = "Assembly ID", + `Assembly Name` = "Assembly Name", + `Isolation Date` = "Isolation Date", + Host = "Host", + Country = "Country", + City = "City" + ), + selected = c(`Assembly Name` = "Assembly Name"), + width = "100%" + ) + } + }) + + #### MST controls ---- + + # Clustering UI + output$mst_cluster <- renderUI({ + req(DB$schemeinfo) + numericInput( + inputId = "mst_cluster_threshold", + label = NULL, + value = as.numeric(DB$schemeinfo[7, 2]), + min = 1, + max = 99 + ) + }) + + # MST color mapping + output$mst_color_mapping <- renderUI({ + if(input$mst_color_var == FALSE) { + fluidRow( + column( + width = 7, + div( + class = "node_color", + colorPickr( + inputId = "mst_color_node", + width = "100%", + selected = "#B2FACA", + label = "", + update = "changestop", + interaction = list(clear = FALSE, + save = FALSE), + position = "right-start" + ) + ) + ), + column( + width = 5, + dropMenu( + actionBttn( + "mst_node_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + numericInput( + "node_opacity", + label = h5("Opacity", style = "color:white; margin-bottom: 0px;"), + value = 1, + step = 0.1, + min = 0, + max = 1, + width = "80px" + ) + ) + ) + ) + } else { + fluidRow( + column( + width = 9, + div( + class = "mst_col_sel", + selectInput( + "mst_col_var", + label = "", + choices = if(any(DB$cust_var[DB$cust_var$Variable[which(DB$cust_var$Variable %in% c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]))],]$Type != "categ")) { + selection <- c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)]) + cust_vars <- DB$cust_var$Variable[which(DB$cust_var$Variable %in% selection)] + selection[-which(selection == cust_vars[DB$cust_var[cust_vars,]$Type != "categ"])] + } else {c("Isolation Date", names(DB$meta)[-c(1, 2, 3, 4, 5, 6, 10, 11, 12)])}, + width = "100%" + ) + ) + ), + column( + width = 3, + dropMenu( + actionBttn( + "mst_col_menu", + label = "", + color = "default", + size = "sm", + style = "material-flat", + icon = icon("sliders") + ), + placement = "top-start", + theme = "translucent", + width = 5, + selectInput( + "mst_col_scale", + label = h5("Color Scale", style = "color:white; margin-bottom: 0px;"), + choices = c("Viridis", "Rainbow"), + width = "150px" + ), + br(), br(), br(), br() + ) + ) + ) + } + }) + + observeEvent(input$mst_color_var, { + + if(input$mst_color_var == TRUE) { + updateSelectizeInput(session, inputId = "mst_node_shape", choices = c("Pie Nodes" = "custom")) + updateSelectizeInput(session, inputId = "mst_node_label", choices = c("Assembly Name")) + } else { + updateSelectizeInput(session, inputId = "mst_node_shape", + choices = list(`Label inside` = c("Circle" = "circle", "Box" = "box", "Text" = "text"), + `Label outside` = c("Diamond" = "diamond", "Hexagon" = "hexagon","Dot" = "dot", "Square" = "square")), + selected = c("Dot" = "dot")) + updateSelectizeInput(session, inputId = "mst_node_label", + choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], + selected = "Assembly Name") + } + }) + + # MST node labels + output$mst_node_label <- renderUI({ + selectInput( + "mst_node_label", + label = "", + choices = names(DB$meta)[c(1, 3, 4, 6, 7, 8, 9)], + selected = "Assembly Name", + width = "100%" + ) + }) + + ### Plot Reactives ---- + + #### MST ---- + + mst_tree <- reactive({ + data <- toVisNetworkData(Vis$ggraph_1) + data$nodes <- mutate(data$nodes, + label = label_mst(), + value = mst_node_scaling(), + opacity = node_opacity()) + + ctxRendererJS <- htmlwidgets::JS("({ctx, id, x, y, state: { selected, hover }, style, font, label, metadata}) => { + var pieData = JSON.parse(metadata); + var radius = style.size; + var centerX = x; + var centerY = y; + var total = pieData.reduce((sum, slice) => sum + slice.value, 0) + var startAngle = 0; + + const drawNode = () => { + // Set shadow properties + if (style.shadow) { + var shadowSize = style.shadowSize; + ctx.shadowColor = style.shadowColor; + ctx.shadowBlur = style.shadowSize; + ctx.shadowOffsetX = style.shadowX; + ctx.shadowOffsetY = style.shadowY; + + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); + ctx.fill(); + + ctx.shadowColor = 'transparent'; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; + } + + pieData.forEach(slice => { + var sliceAngle = 2 * Math.PI * (slice.value / total); + ctx.beginPath(); + ctx.moveTo(centerX, centerY); + ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle); + ctx.closePath(); + ctx.fillStyle = slice.color; + ctx.fill(); + if (pieData.length > 1) { + ctx.strokeStyle = 'black'; + ctx.lineWidth = 1; + ctx.stroke(); + } + startAngle += sliceAngle; + }); + + // Draw a border + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); + ctx.strokeStyle = 'black'; + ctx.lineWidth = 1; + ctx.stroke(); + }; + drawLabel = () => { + //Draw the label + var lines = label.split(`\n`); + var lineHeight = font.size; + ctx.font = `${font.size}px ${font.face}`; + ctx.fillStyle = font.color; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + lines.forEach((line, index) => { + ctx.fillText(line, centerX, + centerY + radius + (index + 1) * lineHeight); + }) + } + + return { + drawNode, + drawExternalLabel: drawLabel, + nodeDimensions: { width: 2 * radius, height: 2 * radius }, + }; + }") + + Vis$var_cols <- NULL + + # Generate pie charts as nodes + if(input$mst_color_var == TRUE & (!is.null(input$mst_col_var))) { + + group <- character(nrow(data$nodes)) + for (i in 1:length(unique(Vis$meta_mst[[input$mst_col_var]]))) { + group[i] <- unique(Vis$meta_mst[[input$mst_col_var]])[i] + } + + data$nodes <- cbind(data$nodes, data.frame(metadata = character(nrow(data$nodes)))) + + if(length(which(data$nodes$group == "")) != 0) { + data$nodes$group[which(data$nodes$group == "")] <- data$nodes$group[1] + } + + if(is.null(input$mst_col_scale)) { + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) + } else if (input$mst_col_scale == "Rainbow") { + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + color = rainbow(length(unique(Vis$meta_mst[[input$mst_col_var]])))) + } else if (input$mst_col_scale == "Viridis") { + Vis$var_cols <- data.frame(value = unique(Vis$meta_mst[[input$mst_col_var]]), + color = viridis(length(unique(Vis$meta_mst[[input$mst_col_var]])))) + } + + for(i in 1:nrow(data$nodes)) { + + iso_subset <- strsplit(data$nodes$label[i], split = "\n")[[1]] + variable <- Vis$meta_mst[[input$mst_col_var]] + values <- variable[which(Vis$meta_mst$`Assembly Name` %in% iso_subset)] + + for(j in 1:length(unique(values))) { + + share <- sum(unique(values)[j] == values) / length(values) * 100 + color <- Vis$var_cols$color[Vis$var_cols$value == unique(values)[j]] + + if(j == 1) { + pie_vec <- paste0('{"value":', share,',"color":"', color,'"}') + } else { + pie_vec <- paste0(pie_vec, ',{"value":', share,',"color":"', color,'"}') + } + } + + data$nodes$metadata[i] <- paste0('[', pie_vec, ']') + } + } + + data$edges <- mutate(data$edges, + length = if(input$mst_scale_edges == FALSE) { + input$mst_edge_length + } else { + data$edges$weight * input$mst_edge_length_scale + }, + label = as.character(data$edges$weight), + opacity = input$mst_edge_opacity) + + if (input$mst_show_clusters) { + clusters <- compute_clusters(data$nodes, data$edges, input$mst_cluster_threshold) + if (input$mst_cluster_type == "Area") { + data$nodes$group <- clusters$group + } + } + + visNetwork_graph <- visNetwork(data$nodes, data$edges, + main = mst_title(), + background = mst_background_color(), + submain = mst_subtitle()) %>% + visNodes(size = mst_node_size(), + shape = input$mst_node_shape, + shadow = input$mst_shadow, + color = mst_color_node(), + ctxRenderer = ctxRendererJS, + scaling = list(min = mst_node_size_min(), + max = mst_node_size_max()), + font = list(color = node_font_color(), + size = input$node_label_fontsize)) %>% + visEdges(color = mst_color_edge(), + font = list(color = mst_edge_font_color(), + size = mst_edge_font_size(), + strokeWidth = 4)) %>% + visOptions(collapse = TRUE) %>% + visInteraction(hover = TRUE) %>% + visLayout(randomSeed = 1) %>% + visLegend(useGroups = FALSE, + zoom = TRUE, + width = legend_width(), + position = input$mst_legend_ori, + ncol = legend_col(), + addNodes = mst_legend()) + + if (input$mst_show_clusters) { + if (input$mst_cluster_col_scale == "Viridis") { + color_palette <- viridis(length(unique(data$nodes$group))) + } else { + color_palette <- rainbow(length(unique(data$nodes$group))) + } + + if (input$mst_cluster_type == "Area") { + for (i in 1:length(unique(data$nodes$group))) { + visNetwork_graph <- visNetwork_graph %>% + visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) + } + } else { + thin_edges <- data$edges + thin_edges$width <- 1 + thin_edges$color <- "black" + + thick_edges <- data$edges + thick_edges$width <- 24 + + thick_edges$color <- rep("rgba(0, 0, 0, 0)", length(data$edges$from)) + color_palette <- rainbow(length(unique(clusters$edges))) + for (i in 1:length(unique(clusters$edges))) { + print(clusters$edges) + if (unique(clusters$edges)[i] != "0") { + edge_color <- paste(col2rgb(color_palette[i]), collapse=", ") + thick_edges$color[clusters$edges == unique(clusters$edges)[i]] <- paste0("rgba(", edge_color, ", 0.5)") + } + } + merged_edges <- rbind(thick_edges, thin_edges) + data$edges <- merged_edges + visNetwork_graph <- visNetwork(data$nodes, data$edges, + main = mst_title(), + background = mst_background_color(), + submain = mst_subtitle()) %>% + visNodes(size = mst_node_size(), + shape = input$mst_node_shape, + shadow = input$mst_shadow, + color = mst_color_node(), + ctxRenderer = ctxRendererJS, + scaling = list(min = mst_node_size_min(), + max = mst_node_size_max()), + font = list(color = node_font_color(), + size = input$node_label_fontsize)) %>% + visEdges(color = mst_color_edge(), + font = list(color = mst_edge_font_color(), + size = mst_edge_font_size(), + strokeWidth = 4), + smooth = FALSE, + physics = FALSE) %>% + visOptions(collapse = TRUE) %>% + visInteraction(hover = TRUE) %>% + visLayout(randomSeed = 1) %>% + visLegend(useGroups = FALSE, + zoom = TRUE, + width = legend_width(), + position = input$mst_legend_ori, + ncol = legend_col(), + addNodes = mst_legend()) + } + } + visNetwork_graph + }) + + # MST legend + legend_col <- reactive({ + if(!is.null(Vis$var_cols)) { + if(nrow(Vis$var_cols) > 10) { + 3 + } else if(nrow(Vis$var_cols) > 5) { + 2 + } else { + 1 + } + } else {1} + }) + + mst_legend <- reactive({ + if(is.null(Vis$var_cols)) { + NULL + } else { + legend <- Vis$var_cols + names(legend)[1] <- "label" + mutate(legend, shape = "dot", + font.color = input$mst_legend_color, + size = input$mst_symbol_size, + font.size = input$mst_font_size) + } + }) + + # Set MST legend width + legend_width <- reactive({ + 0.2 + }) + + # Set MST node shape + mst_node_shape <- reactive({ + if(input$mst_node_shape == "Pie Nodes"){ + "dot" + } else if(input$mst_node_shape %in% c("circle", "database", "box", "text")) { + shinyjs::disable('scale_nodes') + updateCheckboxInput(session, "scale_nodes", value = FALSE) + shinyjs::disable('mst_node_size') + shinyjs::disable('mst_node_scale') + input$mst_node_shape + } else { + shinyjs::enable('scale_nodes') + shinyjs::enable('mst_node_size') + shinyjs::enable('mst_node_scale') + input$mst_node_shape + } + }) + + # Set MST label + label_mst <- reactive({ + Vis$unique_meta[, colnames(Vis$unique_meta) %in% input$mst_node_label] + }) + + # Set node color + mst_color_node <- reactive({ + input$mst_color_node + }) + + # Node Label Color + node_font_color <- reactive({ + input$node_font_color + }) + + + # Node Size Scaling + mst_node_scaling <- reactive({ + if(input$scale_nodes == TRUE){ + Vis$unique_meta$size + } else {NULL} + }) + + # Node Size Min/May + mst_node_size_min <- reactive({ + input$mst_node_scale[1] + }) + + mst_node_size_max <- reactive({ + input$mst_node_scale[2] + }) + + # Node Size + mst_node_size <- reactive({ + input$mst_node_size + }) + + # Node Alpha/Opacity + node_opacity <- reactive({ + input$node_opacity + }) + + # Set Title + mst_title <- reactive({ + if(!is.null(input$mst_title)) { + if(nchar(input$mst_title) < 1) { + list(text = "title", + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_title_size), "px", + "; color: ", as.character(mst_background_color())) + ) + } else { + list(text = input$mst_title, + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_title_size), "px", + "; color: ", as.character(input$mst_title_color)) + ) + } + } else { + list(text = "title", + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_title_size), "px", + "; color: ", as.character(mst_background_color())) + ) + } + }) + + # Set Subtitle + mst_subtitle <- reactive({ + list(text = input$mst_subtitle, + style = paste0( + "font-family:Georgia, Times New Roman, Times, serif;", + "text-align:center;", + "font-size: ", as.character(input$mst_subtitle_size), "px", + "; color: ", as.character(input$mst_subtitle_color)) + ) + }) + + # Background color + + mst_background_color <- reactive({ + if(input$mst_background_transparent == TRUE) { + 'rgba(0, 0, 0, 0)' + } else{ + input$mst_background_color + } + }) + + # Edge font color + mst_edge_font_color <- reactive({ + input$mst_edge_font_color + }) + + # Edge color + mst_color_edge <- reactive({ + input$mst_color_edge + }) + + # Edge font size + mst_edge_font_size <- reactive({ + input$mst_edge_font_size + }) + + #### NJ ---- + + nj_tree <- reactive({ + + # Convert negative edges + Vis$nj[["edge.length"]] <- abs(Vis$nj[["edge.length"]]) + + if(input$nj_nodelabel_show == TRUE) { + ggtree(Vis$nj, alpha = 0.2, layout = layout_nj()) + + geom_nodelab(aes(label = node), color = "#29303A", size = nj_tiplab_size() + 1, hjust = 0.7) + + nj_limit() + + nj_inward() + } else { + tree <- + ggtree(Vis$nj, + color = input$nj_color, + layout = layout_nj(), + ladderize = input$nj_ladder) %<+% Vis$meta_nj + + nj_clades() + + nj_tiplab() + + nj_tiplab_scale() + + new_scale_color() + + nj_limit() + + nj_inward() + + nj_label_branch() + + nj_treescale() + + nj_nodepoint() + + nj_tippoint() + + nj_tippoint_scale() + + new_scale_color() + + nj_clip_label() + + nj_rootedge() + + ggtitle(label = input$nj_title, + subtitle = input$nj_subtitle) + + theme_tree(bgcolor = input$nj_bg) + + theme(plot.title = element_text(colour = input$nj_title_color, + size = input$nj_title_size), + plot.subtitle = element_text(colour = input$nj_title_color, + size = input$nj_subtitle_size), + legend.background = element_rect(fill = input$nj_bg), + legend.direction = input$nj_legend_orientation, + legend.title = element_text(color = input$nj_color, + size = input$nj_legend_size*1.2), + legend.title.align = 0.5, + legend.position = nj_legend_pos(), + legend.text = element_text(color = input$nj_color, + size = input$nj_legend_size), + legend.key = element_rect(fill = input$nj_bg), + legend.box.spacing = unit(1.5, "cm"), + legend.key.size = unit(0.05*input$nj_legend_size, 'cm'), + plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) + + new_scale_fill() + + nj_fruit() + + nj_gradient() + + new_scale_fill() + + nj_fruit2() + + nj_gradient2() + + new_scale_fill() + + nj_fruit3() + + nj_gradient3() + + new_scale_fill() + + nj_fruit4() + + nj_gradient4() + + new_scale_fill() + + nj_fruit5() + + nj_gradient5() + + new_scale_fill() + + # Add custom labels + if(length(Vis$custom_label_nj) > 0) { + + for(i in Vis$custom_label_nj[,1]) { + + if(!is.null(Vis$nj_label_pos_x[[i]])) { + x_pos <- Vis$nj_label_pos_x[[i]] + } else { + x_pos <- round(Vis$nj_max_x / 2, 0) + } + + if(!is.null(Vis$nj_label_pos_y[[i]])) { + y_pos <- Vis$nj_label_pos_y[[i]] + } else { + y_pos <- sum(DB$data$Include) / 2 + } + + if(!is.null(Vis$nj_label_size[[i]])) { + size <- Vis$nj_label_size[[i]] + } else { + size <- 5 + } + + tree <- tree + annotate("text", + x = x_pos, + y = y_pos, + label = i, + size = size) + } + } + + # Add heatmap + if(input$nj_heatmap_show == TRUE & length(input$nj_heatmap_select) > 0) { + if (!(any(sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_nj[input$nj_heatmap_select], is.numeric)))) { + tree <- gheatmap.mod(tree, + data = select(Vis$meta_nj, input$nj_heatmap_select), + offset = nj_heatmap_offset(), + width = nj_heatmap_width(), + legend_title = input$nj_heatmap_title, + colnames_angle = -nj_colnames_angle(), + colnames_offset_y = nj_colnames_y(), + colnames_color = input$nj_color) + + nj_heatmap_scale() + } + } + + # Sizing control + Vis$nj_plot <- ggplotify::as.ggplot(tree, + scale = input$nj_zoom, + hjust = input$nj_h, + vjust = input$nj_v) + + Vis$nj_true <- TRUE + + # Correct background color if zoomed out + cowplot::ggdraw(Vis$nj_plot) + + theme(plot.background = element_rect(fill = input$nj_bg, color = input$nj_bg)) + } + }) + + # Heatmap width + nj_heatmap_width <- reactive({ + if(!is.null(input$nj_heatmap_width)) { + input$nj_heatmap_width + } else { + length_input <- length(input$nj_heatmap_select) + if((!(input$nj_layout == "circular")) & (!(input$nj_layout == "inward"))) { + if(length_input < 3) { + 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + 1.5 + } + } + } else { + if(length_input < 3) { + 0.3 + } else if (length_input >= 3 && length_input <= 27) { + min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + 3 + } + } + } + }) + + # Heatmap column titles position + nj_colnames_y <- reactive({ + if(!is.null(input$nj_colnames_y)) { + input$nj_colnames_y + } else { + if(input$nj_layout == "inward" | input$nj_layout == "circular") { + 0 + } else {-1} + } + }) + + # Heatmap column titles angle + nj_colnames_angle <- reactive({ + if(!is.null(input$nj_colnames_angle)) { + input$nj_colnames_angle + } else { + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "inward" | input$nj_layout == "circular") { + 90 + } else {-90} + } else {-90} + } + }) + + # Heatmap scale + nj_heatmap_scale <- reactive({ + if(!is.null(input$nj_heatmap_scale) & !is.null(input$nj_heatmap_div_mid)) { + if(input$nj_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_heatmap_div_mid == "Zero") { + midpoint <- 0 + } else if(input$nj_heatmap_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_heatmap_select]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$nj_heatmap_scale)[1], + mid = brewer.pal(3, input$nj_heatmap_scale)[2], + high = brewer.pal(3, input$nj_heatmap_scale)[3], + midpoint = midpoint, + name = input$nj_heatmap_title) + } else { + if(input$nj_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_heatmap_select])) == "numeric") { + if(input$nj_heatmap_scale == "magma") { + scale_fill_viridis(option = "A", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "inferno") { + scale_fill_viridis(option = "B", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "plasma") { + scale_fill_viridis(option = "C", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "viridis") { + scale_fill_viridis(option = "D", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "cividis") { + scale_fill_viridis(option = "E", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "rocket") { + scale_fill_viridis(option = "F", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "mako") { + scale_fill_viridis(option = "G", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "turbo") { + scale_fill_viridis(option = "H", + name = input$nj_heatmap_title) + } + } else { + if(input$nj_heatmap_scale == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G", + name = input$nj_heatmap_title) + } else if(input$nj_heatmap_scale == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H", + name = input$nj_heatmap_title) + } + } + } else { + scale_fill_brewer(palette = input$nj_heatmap_scale, + name = input$nj_heatmap_title) + } + } + } + }) + + # Tippoint Scale + nj_tippoint_scale <- reactive({ + if(!is.null(input$nj_tippoint_scale) & !is.null(input$nj_tipcolor_mapping_div_mid)) { + if(input$nj_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tipcolor_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$nj_tipcolor_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_tipcolor_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$nj_tippoint_scale)[1], + mid = brewer.pal(3, input$nj_tippoint_scale)[2], + high = brewer.pal(3, input$nj_tippoint_scale)[3], + midpoint = midpoint) + } else { + if(input$nj_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_tipcolor_mapping])) == "numeric") { + if(input$nj_tippoint_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$nj_tippoint_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$nj_tippoint_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$nj_tippoint_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$nj_tippoint_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$nj_tippoint_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$nj_tippoint_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$nj_tippoint_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$nj_tippoint_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tippoint_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tippoint_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tippoint_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tippoint_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tippoint_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tippoint_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tippoint_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$nj_tippoint_scale) + } + } + } + }) + + # Tiplab Scale + nj_tiplab_scale <- reactive({ + if(!is.null(input$nj_tiplab_scale) & !is.null(input$nj_color_mapping_div_mid)) { + if(input$nj_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_color_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$nj_color_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_color_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$nj_tiplab_scale)[1], + mid = brewer.pal(3, input$nj_tiplab_scale)[2], + high = brewer.pal(3, input$nj_tiplab_scale)[3], + midpoint = midpoint) + } else { + if(input$nj_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_color_mapping])) == "numeric") { + if(input$nj_tiplab_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$nj_tiplab_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$nj_tiplab_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$nj_tiplab_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$nj_tiplab_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$nj_tiplab_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$nj_tiplab_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$nj_tiplab_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$nj_tiplab_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiplab_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiplab_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiplab_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiplab_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiplab_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiplab_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiplab_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$nj_tiplab_scale) + } + } + } + }) + + # Clade Highlight + nj_clades <- reactive({ + if(!is.null(input$nj_parentnode)) { + if(!length(input$nj_parentnode) == 0) { + if(length(input$nj_parentnode) == 1) { + fill <- input$nj_clade_scale + } else if (length(input$nj_parentnode) == 2) { + if(startsWith(input$nj_clade_scale, "#")) { + fill <- brewer.pal(3, "Set1")[1:2] + } else { + fill <- brewer.pal(3, input$nj_clade_scale)[1:2] + } + } else { + fill <- brewer.pal(length(input$nj_parentnode), input$nj_clade_scale) + } + geom_hilight(node = as.numeric(input$nj_parentnode), + fill = fill, + type = input$nj_clade_type, + to.bottom = TRUE + ) + } else {NULL} + } + }) + + # Legend Position + nj_legend_pos <- reactive({ + if(!is.null(input$nj_legend_x) & !is.null(input$nj_legend_y)) { + c(input$nj_legend_x, input$nj_legend_y) + } else { + c(0.1, 1) + } + }) + + # Heatmap offset + nj_heatmap_offset <- reactive({ + if(is.null(input$nj_heatmap_offset)) { + 0 + } else {input$nj_heatmap_offset} + }) + + # Tiles fill color gradient + nj_gradient <- reactive({ + if(!is.null(input$nj_tiles_show_1) & + !is.null(input$nj_fruit_variable) & + !is.null(input$nj_tiles_scale_1) & + !is.null(input$nj_tiles_mapping_div_mid_1)) { + if(input$nj_tiles_show_1 == TRUE) { + if(input$nj_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_1 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_1 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_1)[1], + mid = brewer.pal(3, input$nj_tiles_scale_1)[2], + high = brewer.pal(3, input$nj_tiles_scale_1)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { + if(input$nj_tiles_scale_1 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_1 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_1 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_1 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_1 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_1 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_1 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_1 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_1 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_1 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_1 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_1 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_1 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_1 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_1 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_1 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_1) + } + } + } else {NULL} + } + }) + + nj_gradient2 <- reactive({ + if(!is.null(input$nj_tiles_show_2) & + !is.null(input$nj_fruit_variable_2) & + !is.null(input$nj_tiles_scale_2) & + !is.null(input$nj_tiles_mapping_div_mid_2)) { + if(input$nj_tiles_show_2 == TRUE) { + if(input$nj_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_2 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_2 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_2]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$nj_tiles_scale_2)[1], + mid = brewer.pal(3, input$nj_tiles_scale_2)[2], + high = brewer.pal(3, input$nj_tiles_scale_2)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_2])) == "numeric") { + if(input$nj_tiles_scale_2 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_2 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_2 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_2 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_2 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_2 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_2 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_2 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_2 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_2 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_2 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_2 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_2 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_2 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_2 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_2 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_2) + } + } + } else {NULL} + } + }) + + nj_gradient3 <- reactive({ + if(!is.null(input$nj_tiles_show_3) & + !is.null(input$nj_fruit_variable_3) & + !is.null(input$nj_tiles_scale_3 & + !is.null(input$nj_tiles_mapping_div_mid_3))) { + if(input$nj_tiles_show_3 == TRUE) { + if(input$nj_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_3 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_3 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_3]), na.rm = TRUE) + } + scale_fill_gradient3(low = brewer.pal(3, input$nj_tiles_scale_3)[1], + mid = brewer.pal(3, input$nj_tiles_scale_3)[2], + high = brewer.pal(3, input$nj_tiles_scale_3)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_3])) == "numeric") { + if(input$nj_tiles_scale_3 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_3 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_3 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_3 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_3 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_3 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_3 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_3 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_3 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_3 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_3 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_3 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_3 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_3 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_3 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_3 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_3) + } + } + } else {NULL} + } + }) + + nj_gradient4 <- reactive({ + if(!is.null(input$nj_tiles_show_4) & + !is.null(input$nj_fruit_variable_4) & + !is.null(input$nj_tiles_scale_4) & + !is.null(input$nj_tiles_mapping_div_mid_4)) { + if(input$nj_tiles_show_4 == TRUE) { + if(input$nj_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_4 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_4 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_4]), na.rm = TRUE) + } + scale_fill_gradient4(low = brewer.pal(3, input$nj_tiles_scale_4)[1], + mid = brewer.pal(3, input$nj_tiles_scale_4)[2], + high = brewer.pal(3, input$nj_tiles_scale_4)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable])) == "numeric") { + if(input$nj_tiles_scale_4 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_4 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_4 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_4 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_4 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_4 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_4 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_4 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_4 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_4 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_4 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_4 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_4 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_4 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_4 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_4 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_4) + } + } + } else {NULL} + } + }) + + nj_gradient5 <- reactive({ + if(!is.null(input$nj_tiles_show_5) & + !is.null(input$nj_fruit_variable_5) & + !is.null(input$nj_tiles_scale_5) & + !is.null(input$nj_tiles_mapping_div_mid_5)) { + if(input$nj_tiles_show_5 == TRUE) { + if(input$nj_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$nj_tiles_mapping_div_mid_5 == "Zero") { + midpoint <- 0 + } else if(input$nj_tiles_mapping_div_mid_5 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_nj[input$nj_fruit_variable_5]), na.rm = TRUE) + } + scale_fill_gradient5(low = brewer.pal(3, input$nj_tiles_scale_5)[1], + mid = brewer.pal(3, input$nj_tiles_scale_5)[2], + high = brewer.pal(3, input$nj_tiles_scale_5)[3], + midpoint = midpoint) + } else { + if(input$nj_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_nj[input$nj_fruit_variable_5])) == "numeric") { + if(input$nj_tiles_scale_5 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$nj_tiles_scale_5 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$nj_tiles_scale_5 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$nj_tiles_scale_5 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$nj_tiles_scale_5 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$nj_tiles_scale_5 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$nj_tiles_scale_5 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$nj_tiles_scale_5 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$nj_tiles_scale_5 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$nj_tiles_scale_5 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$nj_tiles_scale_5 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$nj_tiles_scale_5 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$nj_tiles_scale_5 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$nj_tiles_scale_5 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$nj_tiles_scale_5 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$nj_tiles_scale_5 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$nj_tiles_scale_5) + } + } + } else {NULL} + } + }) + + # No label clip off for linear NJ tree + nj_clip_label <- reactive({ + if(!(input$nj_layout == "circular" | input$nj_layout == "inward")) { + coord_cartesian(clip = "off") + } else {NULL} + }) + + # Geom Fruit + nj_fruit <- reactive({ + if((!is.null(input$nj_tiles_show_1)) & + (!is.null(input$nj_fruit_variable)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ)) & + (!is.null(input$nj_fruit_width_circ)) & + (!is.null(input$nj_fruit_alpha))) { + if(input$nj_tiles_show_1 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = input$nj_fruit_offset_circ, + width = input$nj_fruit_width_circ, + alpha = input$nj_fruit_alpha + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = input$nj_fruit_offset_circ, + width = input$nj_fruit_width_circ, + alpha = input$nj_fruit_alpha + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_1 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = 0, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable)), + offset = 0, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Geom Fruit + nj_fruit2 <- reactive({ + if((!is.null(input$nj_tiles_show_2)) & + (!is.null(input$nj_fruit_variable_2)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_2)) & + (!is.null(input$nj_fruit_width_circ_2)) & + (!is.null(input$nj_fruit_alpha_2))) { + if(input$nj_tiles_show_2 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), + offset = input$nj_fruit_offset_circ_2, + width = input$nj_fruit_width_circ_2, + alpha = input$nj_fruit_alpha_2 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_2)), + offset = input$nj_fruit_offset_circ_2, + width = input$nj_fruit_width_circ_2, + alpha = input$nj_fruit_alpha_2 + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_2 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_2)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + nj_fruit3 <- reactive({ + if((!is.null(input$nj_tiles_show_3)) & + (!is.null(input$nj_fruit_variable_3)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_3)) & + (!is.null(input$nj_fruit_width_circ_3)) & + (!is.null(input$nj_fruit_alpha_3))) { + if(input$nj_tiles_show_3 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), + offset = input$nj_fruit_offset_circ_3, + width = input$nj_fruit_width_circ_3, + alpha = input$nj_fruit_alpha_3 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_3)), + offset = input$nj_fruit_offset_circ_3, + width = input$nj_fruit_width_circ_3, + alpha = input$nj_fruit_alpha_3 + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_3 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_3)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + nj_fruit4 <- reactive({ + if((!is.null(input$nj_tiles_show_4)) & + (!is.null(input$nj_fruit_variable_4)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_4)) & + (!is.null(input$nj_fruit_width_circ_4)) & + (!is.null(input$nj_fruit_alpha_4))) { + if(input$nj_tiles_show_4 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), + offset = input$nj_fruit_offset_circ_4, + width = input$nj_fruit_width_circ_4, + alpha = input$nj_fruit_alpha_4 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_4)), + offset = input$nj_fruit_offset_circ_4, + width = input$nj_fruit_width_circ_4, + alpha = input$nj_fruit_alpha_4 + ) + } + } else { + if(input$nj_tiles_show_4 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_4)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + } + }) + + nj_fruit5 <- reactive({ + if((!is.null(input$nj_tiles_show_5)) & + (!is.null(input$nj_fruit_variable_5)) & + (!is.null(input$nj_layout)) & + (!is.null(input$nj_fruit_offset_circ_5)) & + (!is.null(input$nj_fruit_width_circ_5)) & + (!is.null(input$nj_fruit_alpha_5))) { + if(input$nj_tiles_show_5 == TRUE) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), + offset = input$nj_fruit_offset_circ_5, + width = input$nj_fruit_width_circ_5, + alpha = input$nj_fruit_alpha_5 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$nj_fruit_variable_5)), + offset = input$nj_fruit_offset_circ_5, + width = input$nj_fruit_width_circ_5, + alpha = input$nj_fruit_alpha_5 + ) + } + } else {NULL} + } else { + if(input$nj_tiles_show_5 == TRUE) { + if(!is.null(Vis$nj_max_x)) { + if(round(ceiling(Vis$nj_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$nj_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$nj_fruit_variable_5)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Xlim + nj_limit <- reactive({ + if(input$nj_layout == "circular") { + xlim(input$nj_xlim, NA) + } else {NULL} + }) + + # Treescale + nj_treescale <- reactive({ + if(!input$nj_layout == "circular") { + if(input$nj_treescale_show == TRUE) { + geom_treescale(x = nj_treescale_x(), + y = nj_treescale_y(), + width = nj_treescale_width(), + color = input$nj_color, + fontsize = 4) + } else {NULL} + } else {NULL} + }) + + # Treescale Y Position + nj_treescale_y <- reactive({ + if(is.null(input$nj_treescale_y)) { + 0 + } else {input$nj_treescale_y} + }) + + # Treescale X Position + nj_treescale_x <- reactive({ + if(is.null(input$nj_treescale_x)) { + round(ceiling(Vis$nj_max_x) * 0.2, 0) + } else {input$nj_treescale_x} + }) + + # Treescale width + nj_treescale_width <- reactive({ + if(!is.null(input$nj_treescale_width)) { + input$nj_treescale_width + } else { + round(ceiling(Vis$nj_max_x) * 0.1, 0) + } + }) + + # Label branches + nj_label_branch <- reactive({ + if(!input$nj_layout == "circular" | !input$nj_layout == "inward") { + if(input$nj_show_branch_label == TRUE) { + geom_label( + aes( + x=!!sym("branch"), + label= !!sym(input$nj_branch_label)), + fill = input$nj_branch_label_color, + size = nj_branch_size(), + label.r = unit(input$nj_branch_labelradius, "lines"), + nudge_x = input$nj_branch_x, + nudge_y = input$nj_branch_y, + fontface = input$nj_branchlab_fontface, + alpha = input$nj_branchlab_alpha + ) + } else {NULL} + } else {NULL} + }) + + # Branch label size + nj_branch_size <- reactive({ + if(!is.null(input$nj_branch_size)) { + input$nj_branch_size + } else { + Vis$branch_size_nj + } + }) + + # Rootedge + nj_rootedge <- reactive({ + if(input$nj_rootedge_show == TRUE) { + if(is.null(input$nj_rootedge_length)) { + geom_rootedge(rootedge = round(ceiling(Vis$nj_max_x) * 0.05, 0), + linetype = input$nj_rootedge_line) + } else { + geom_rootedge(rootedge = input$nj_rootedge_length, + linetype = input$nj_rootedge_line) + } + } else {NULL} + }) + + # Tippoints + nj_tippoint <- reactive({ + if(input$nj_tippoint_show == TRUE | input$nj_tipcolor_mapping_show == TRUE | input$nj_tipshape_mapping_show == TRUE) { + if(input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == FALSE) { + geom_tippoint( + aes(color = !!sym(input$nj_tipcolor_mapping)), + alpha = input$nj_tippoint_alpha, + shape = input$nj_tippoint_shape, + size = nj_tippoint_size() + ) + } else if (input$nj_tipcolor_mapping_show == FALSE & input$nj_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$nj_tipshape_mapping)), + alpha = input$nj_tippoint_alpha, + color = input$nj_tippoint_color, + size = nj_tippoint_size() + ) + } else if (input$nj_tipcolor_mapping_show == TRUE & input$nj_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$nj_tipshape_mapping), + color = !!sym(input$nj_tipcolor_mapping)), + alpha = input$nj_tippoint_alpha, + size = nj_tippoint_size() + ) + } else { + geom_tippoint( + alpha = input$nj_tippoint_alpha, + colour = input$nj_tippoint_color, + fill = input$nj_tippoint_color, + shape = input$nj_tippoint_shape, + size = nj_tippoint_size() + ) + } + } else {NULL} + }) + + # Nodepoints + nj_nodepoint <- reactive({ + if(input$nj_nodepoint_show == TRUE) { + geom_nodepoint( + alpha = input$nj_nodepoint_alpha, + color = input$nj_nodepoint_color, + shape = input$nj_nodepoint_shape, + size = nj_nodepoint_size() + ) + } else {NULL} + }) + + # Nodepoint size + nj_nodepoint_size <- reactive({ + if(!is.null(input$nj_nodepoint_size)) { + input$nj_nodepoint_size + } else { + Vis$nodepointsize_nj + } + }) + + # NJ circular or not + nj_tiplab <- reactive({ + if(input$nj_tiplab_show == TRUE) { + if(input$nj_layout == "circular") { + if(input$nj_mapping_show == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position), + check.overlap = input$nj_tiplab_overlap + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + color = input$nj_tiplab_color, + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position), + check.overlap = input$nj_tiplab_overlap + ) + } + } else if (input$nj_layout == "inward") { + if(input$nj_mapping_show == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position_inw), + check.overlap = input$nj_tiplab_overlap + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + color = input$nj_tiplab_color, + geom = "text", + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + hjust = as.numeric(input$nj_tiplab_position_inw), + check.overlap = input$nj_tiplab_overlap + ) + } + } else { + if(input$nj_mapping_show == TRUE) { + if(input$nj_geom == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap, + label.padding = unit(nj_tiplab_padding(), "lines"), + label.r = unit(input$nj_tiplab_labelradius, "lines"), + fill = input$nj_tiplab_fill + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap + ) + } + } else { + if(input$nj_geom == TRUE) { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + color = input$nj_tiplab_color, + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap, + label.padding = unit(nj_tiplab_padding(), "lines"), + label.r = unit(input$nj_tiplab_labelradius, "lines"), + fill = input$nj_tiplab_fill + ) + } else { + geom_tiplab( + nj_mapping_tiplab(), + geom = nj_geom(), + color = input$nj_tiplab_color, + angle = input$nj_tiplab_angle, + size = nj_tiplab_size(), + alpha = input$nj_tiplab_alpha, + fontface = input$nj_tiplab_fontface, + align = as.logical(input$nj_align), + nudge_x = input$nj_tiplab_nudge_x, + check.overlap = input$nj_tiplab_overlap + ) + } + } + } + } else {NULL} + }) + + # Tip panel size + nj_tiplab_padding <- reactive({ + if(!is.null(input$nj_tiplab_padding)) { + input$nj_tiplab_padding + } else { + Vis$tiplab_padding_nj + } + }) + + # Tiplab size + nj_tiplab_size <- reactive({ + if(!is.null(input$nj_tiplab_size)) { + input$nj_tiplab_size + } else { + Vis$labelsize_nj + } + }) + + # Tippoint size + nj_tippoint_size <- reactive({ + if(!is.null(input$nj_tippoint_size)) { + input$nj_tippoint_size + } else { + Vis$tippointsize_nj + } + }) + + # Show Label Panels? + nj_geom <- reactive({ + if(input$nj_geom == TRUE) { + "label" + } else {"text"} + }) + + # NJ Tiplab color + nj_mapping_tiplab <- reactive({ + if(input$nj_mapping_show == TRUE) { + if(!is.null(input$nj_tiplab)) { + aes(label = !!sym(input$nj_tiplab), + color = !!sym(input$nj_color_mapping)) + } else { + aes(label = !!sym("Assembly Name"), + color = !!sym(input$nj_color_mapping)) + } + } else { + if(!is.null(input$nj_tiplab)) { + aes(label = !!sym(input$nj_tiplab)) + } else { + aes(label = !!sym("Assembly Name")) + } + } + }) + + # NJ Tree Layout + layout_nj <- reactive({ + if(input$nj_layout == "inward") { + "circular" + } else {input$nj_layout} + }) + + # NJ inward circular + nj_inward <- reactive({ + if (input$nj_layout == "inward") { + layout_inward_circular(xlim = input$nj_inward_xlim) + } else { + NULL + } + }) + + #### UPGMA ---- + + upgma_tree <- reactive({ + if(input$upgma_nodelabel_show == TRUE) { + ggtree(Vis$upgma, alpha = 0.2, layout = layout_upgma()) + + geom_nodelab(aes(label = node), color = "#29303A", size = upgma_tiplab_size() + 1, hjust = 0.7) + + upgma_limit() + + upgma_inward() + } else { + tree <- + ggtree(Vis$upgma, + color = input$upgma_color, + layout = layout_upgma(), + ladderize = input$upgma_ladder) %<+% Vis$meta_upgma + + upgma_tiplab() + + upgma_tiplab_scale() + + new_scale_color() + + upgma_limit() + + upgma_inward() + + upgma_label_branch() + + upgma_treescale() + + upgma_nodepoint() + + upgma_tippoint() + + upgma_tippoint_scale() + + new_scale_color() + + upgma_clip_label() + + upgma_rootedge() + + upgma_clades() + + ggtitle(label = input$upgma_title, + subtitle = input$upgma_subtitle) + + theme_tree(bgcolor = input$upgma_bg) + + theme(plot.title = element_text(colour = input$upgma_title_color, + size = input$upgma_title_size), + plot.subtitle = element_text(colour = input$upgma_title_color, + size = input$upgma_subtitle_size), + legend.background = element_rect(fill = input$upgma_bg), + legend.direction = input$upgma_legend_orientation, + legend.title = element_text(color = input$upgma_color, + size = input$upgma_legend_size*1.2), + legend.title.align = 0.5, + legend.position = upgma_legend_pos(), + legend.text = element_text(color = input$upgma_color, + size = input$upgma_legend_size), + legend.key = element_rect(fill = input$upgma_bg), + legend.box.spacing = unit(1.5, "cm"), + legend.key.size = unit(0.05*input$upgma_legend_size, 'cm'), + plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) + + new_scale_fill() + + upgma_fruit() + + upgma_gradient() + + new_scale_fill() + + upgma_fruit2() + + upgma_gradient2() + + new_scale_fill() + + upgma_fruit3() + + upgma_gradient3() + + new_scale_fill() + + upgma_fruit4() + + upgma_gradient4() + + new_scale_fill() + + upgma_fruit5() + + upgma_gradient5() + + new_scale_fill() + + # Add custom labels + if(length(Vis$custom_label_upgma) > 0) { + + for(i in Vis$custom_label_upgma[,1]) { + + if(!is.null(Vis$upgma_label_pos_x[[i]])) { + x_pos <- Vis$upgma_label_pos_x[[i]] + } else { + x_pos <- round(Vis$upgma_max_x / 2, 0) + } + + if(!is.null(Vis$upgma_label_pos_y[[i]])) { + y_pos <- Vis$upgma_label_pos_y[[i]] + } else { + y_pos <- sum(DB$data$Include) / 2 + } + + if(!is.null(Vis$upgma_label_size[[i]])) { + size <- Vis$upgma_label_size[[i]] + } else { + size <- 5 + } + + tree <- tree + annotate("text", + x = x_pos, + y = y_pos, + label = i, + size = size) + } + } + + # Add heatmap + if(input$upgma_heatmap_show == TRUE & length(input$upgma_heatmap_select) > 0) { + if (!(any(sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)) & + any(!sapply(Vis$meta_upgma[input$upgma_heatmap_select], is.numeric)))) { + tree <- gheatmap.mod(tree, + data = select(Vis$meta_upgma, input$upgma_heatmap_select), + offset = upgma_heatmap_offset(), + width = upgma_heatmap_width(), + legend_title = input$upgma_heatmap_title, + colnames_angle = -upgma_colnames_angle(), + colnames_offset_y = upgma_colnames_y(), + colnames_color = input$upgma_color) + + upgma_heatmap_scale() + } + } + + # Sizing control + Vis$upgma_plot <- ggplotify::as.ggplot(tree, + scale = input$upgma_zoom, + hjust = input$upgma_h, + vjust = input$upgma_v) + + # Correct background color if zoomed out + cowplot::ggdraw(Vis$upgma_plot) + + theme(plot.background = element_rect(fill = input$upgma_bg, color = input$upgma_bg)) + } + }) + + # Heatmap width + upgma_heatmap_width <- reactive({ + if(!is.null(input$upgma_heatmap_width)) { + input$upgma_heatmap_width + } else { + length_input <- length(input$upgma_heatmap_select) + if((!(input$upgma_layout == "circular")) & (!(input$upgma_layout == "inward"))) { + if(length_input < 3) { + 0.1 + } else { + if (length_input >= 3 && length_input <= 50) { + min(0.15 + 0.05 * floor((length_input - 3) / 2), 1.5) + } else { + 1.5 + } + } + } else { + if(length_input < 3) { + 0.3 + } else if (length_input >= 3 && length_input <= 27) { + min(0.6 + 0.2 * floor((length_input - 3) / 2), 1.5) + } else { + 3 + } + } + } + }) + + # Heatmap column titles position + upgma_colnames_y <- reactive({ + if(!is.null(input$upgma_colnames_y)) { + input$upgma_colnames_y + } else { + if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { + 0 + } else {-1} + } + }) + + # Heatmap column titles angle + upgma_colnames_angle <- reactive({ + if(!is.null(input$upgma_colnames_angle)) { + input$upgma_colnames_angle + } else { + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "inward" | input$upgma_layout == "circular") { + 90 + } else {-90} + } else {-90} + } + }) + + # Heatmap scale + upgma_heatmap_scale <- reactive({ + if(!is.null(input$upgma_heatmap_scale) & !is.null(input$upgma_heatmap_div_mid)) { + if(input$upgma_heatmap_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_heatmap_div_mid == "Zero") { + midpoint <- 0 + } else if(input$upgma_heatmap_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_heatmap_select]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$upgma_heatmap_scale)[1], + mid = brewer.pal(3, input$upgma_heatmap_scale)[2], + high = brewer.pal(3, input$upgma_heatmap_scale)[3], + midpoint = midpoint, + name = input$upgma_heatmap_title) + } else { + if(input$upgma_heatmap_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_heatmap_select])) == "numeric") { + if(input$upgma_heatmap_scale == "magma") { + scale_fill_viridis(option = "A", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "inferno") { + scale_fill_viridis(option = "B", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "plasma") { + scale_fill_viridis(option = "C", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "viridis") { + scale_fill_viridis(option = "D", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "cividis") { + scale_fill_viridis(option = "E", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "rocket") { + scale_fill_viridis(option = "F", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "mako") { + scale_fill_viridis(option = "G", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "turbo") { + scale_fill_viridis(option = "H", + name = input$upgma_heatmap_title) + } + } else { + if(input$upgma_heatmap_scale == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G", + name = input$upgma_heatmap_title) + } else if(input$upgma_heatmap_scale == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H", + name = input$upgma_heatmap_title) + } + } + } else { + scale_fill_brewer(palette = input$upgma_heatmap_scale, + name = input$upgma_heatmap_title) + } + } + } + }) + + # Tippoint Scale + upgma_tippoint_scale <- reactive({ + if(!is.null(input$upgma_tippoint_scale) & !is.null(input$upgma_tipcolor_mapping_div_mid)) { + if(input$upgma_tippoint_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tipcolor_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$upgma_tipcolor_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_tipcolor_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$upgma_tippoint_scale)[1], + mid = brewer.pal(3, input$upgma_tippoint_scale)[2], + high = brewer.pal(3, input$upgma_tippoint_scale)[3], + midpoint = midpoint) + } else { + if(input$upgma_tippoint_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_tipcolor_mapping])) == "numeric") { + if(input$upgma_tippoint_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$upgma_tippoint_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$upgma_tippoint_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$upgma_tippoint_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$upgma_tippoint_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$upgma_tippoint_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$upgma_tippoint_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$upgma_tippoint_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$upgma_tippoint_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tippoint_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tippoint_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tippoint_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tippoint_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tippoint_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tippoint_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tippoint_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$upgma_tippoint_scale) + } + } + } + }) + + # Tiplab Scale + upgma_tiplab_scale <- reactive({ + if(!is.null(input$upgma_tiplab_scale) & !is.null(input$upgma_color_mapping_div_mid)) { + if(input$upgma_tiplab_scale %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_color_mapping_div_mid == "Zero") { + midpoint <- 0 + } else if(input$upgma_color_mapping_div_mid == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_color_mapping]), na.rm = TRUE) + } + scale_color_gradient2(low = brewer.pal(3, input$upgma_tiplab_scale)[1], + mid = brewer.pal(3, input$upgma_tiplab_scale)[2], + high = brewer.pal(3, input$upgma_tiplab_scale)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiplab_scale %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_color_mapping])) == "numeric") { + if(input$upgma_tiplab_scale == "magma") { + scale_color_viridis(option = "A") + } else if(input$upgma_tiplab_scale == "inferno") { + scale_color_viridis(option = "B") + } else if(input$upgma_tiplab_scale == "plasma") { + scale_color_viridis(option = "C") + } else if(input$upgma_tiplab_scale == "viridis") { + scale_color_viridis(option = "D") + } else if(input$upgma_tiplab_scale == "cividis") { + scale_color_viridis(option = "E") + } else if(input$upgma_tiplab_scale == "rocket") { + scale_color_viridis(option = "F") + } else if(input$upgma_tiplab_scale == "mako") { + scale_color_viridis(option = "G") + } else if(input$upgma_tiplab_scale == "turbo") { + scale_color_viridis(option = "H") + } + } else { + if(input$upgma_tiplab_scale == "magma") { + scale_color_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiplab_scale == "inferno") { + scale_color_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiplab_scale == "plasma") { + scale_color_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiplab_scale == "viridis") { + scale_color_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiplab_scale == "cividis") { + scale_color_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiplab_scale == "rocket") { + scale_color_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiplab_scale == "mako") { + scale_color_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiplab_scale == "turbo") { + scale_color_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_color_brewer(palette = input$upgma_tiplab_scale) + } + } + } + }) + + # Clade Highlight + upgma_clades <- reactive({ + if(!is.null(input$upgma_parentnode)) { + if(!length(input$upgma_parentnode) == 0) { + if(length(input$upgma_parentnode) == 1) { + fill <- input$upgma_clade_scale + } else if (length(input$upgma_parentnode) == 2) { + if(startsWith(input$upgma_clade_scale, "#")) { + fill <- brewer.pal(3, "Set1")[1:2] + } else { + fill <- brewer.pal(3, input$upgma_clade_scale)[1:2] + } + } else { + fill <- brewer.pal(length(input$upgma_parentnode), input$upgma_clade_scale) + } + geom_hilight(node = as.numeric(input$upgma_parentnode), + fill = fill, + type = input$upgma_clade_type, + to.bottom = TRUE) + } else {NULL} + } + }) + + # Legend Position + upgma_legend_pos <- reactive({ + if(!is.null(input$upgma_legend_x) & !is.null(input$upgma_legend_y)) { + c(input$upgma_legend_x, input$upgma_legend_y) + } else { + c(0.1, 1) + } + }) + + # Heatmap offset + upgma_heatmap_offset <- reactive({ + if(is.null(input$upgma_heatmap_offset)) { + 0 + } else {input$upgma_heatmap_offset} + }) + + # Tiles fill color gradient + upgma_gradient <- reactive({ + if(!is.null(input$upgma_tiles_show_1) & + !is.null(input$upgma_fruit_variable) & + !is.null(input$upgma_tiles_scale_1) & + !is.null(input$upgma_tiles_mapping_div_mid_1)) { + if(input$upgma_tiles_show_1 == TRUE) { + if(input$upgma_tiles_scale_1 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_1 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_1 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_1)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_1)[2], + high = brewer.pal(3, input$upgma_tiles_scale_1)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_1 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { + if(input$upgma_tiles_scale_1 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_1 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_1 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_1 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_1 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_1 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_1 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_1 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_1 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_1 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_1 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_1 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_1 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_1 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_1 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_1 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_1) + } + } + } else {NULL} + } + }) + + upgma_gradient2 <- reactive({ + if(!is.null(input$upgma_tiles_show_2) & + !is.null(input$upgma_fruit_variable_2) & + !is.null(input$upgma_tiles_scale_2) & + !is.null(input$upgma_tiles_mapping_div_mid_2)) { + if(input$upgma_tiles_show_2 == TRUE) { + if(input$upgma_tiles_scale_2 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_2 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_2 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_2]), na.rm = TRUE) + } + scale_fill_gradient2(low = brewer.pal(3, input$upgma_tiles_scale_2)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_2)[2], + high = brewer.pal(3, input$upgma_tiles_scale_2)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_2 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_2])) == "numeric") { + if(input$upgma_tiles_scale_2 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_2 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_2 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_2 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_2 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_2 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_2 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_2 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_2 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_2 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_2 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_2 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_2 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_2 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_2 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_2 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_2) + } + } + } else {NULL} + } + }) + + upgma_gradient3 <- reactive({ + if(!is.null(input$upgma_tiles_show_3) & + !is.null(input$upgma_fruit_variable_3) & + !is.null(input$upgma_tiles_scale_3) & + !is.null(input$upgma_tiles_mapping_div_mid_3)) { + if(input$upgma_tiles_show_3 == TRUE) { + if(input$upgma_tiles_scale_3 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_3 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_3 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_3]), na.rm = TRUE) + } + scale_fill_gradient3(low = brewer.pal(3, input$upgma_tiles_scale_3)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_3)[2], + high = brewer.pal(3, input$upgma_tiles_scale_3)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_3 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_3])) == "numeric") { + if(input$upgma_tiles_scale_3 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_3 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_3 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_3 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_3 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_3 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_3 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_3 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_3 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_3 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_3 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_3 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_3 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_3 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_3 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_3 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_3) + } + } + } else {NULL} + } + }) + + upgma_gradient4 <- reactive({ + if(!is.null(input$upgma_tiles_show_4) & + !is.null(input$upgma_fruit_variable_4) & + !is.null(input$upgma_tiles_scale_4) & + !is.null(input$upgma_tiles_mapping_div_mid_4)) { + if(input$upgma_tiles_show_4 == TRUE) { + if(input$upgma_tiles_scale_4 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_4 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_4 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_4]), na.rm = TRUE) + } + scale_fill_gradient4(low = brewer.pal(3, input$upgma_tiles_scale_4)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_4)[2], + high = brewer.pal(3, input$upgma_tiles_scale_4)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_4 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable])) == "numeric") { + if(input$upgma_tiles_scale_4 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_4 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_4 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_4 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_4 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_4 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_4 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_4 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_4 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_4 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_4 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_4 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_4 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_4 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_4 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_4 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_4) + } + } + } else {NULL} + } + }) + + upgma_gradient5 <- reactive({ + if(!is.null(input$upgma_tiles_show_5) & + !is.null(input$upgma_fruit_variable_5) & + !is.null(input$upgma_tiles_scale_5) & + !is.null(input$upgma_tiles_mapping_div_mid_5)) { + if(input$upgma_tiles_show_5 == TRUE) { + if(input$upgma_tiles_scale_5 %in% c("Spectral", "RdYlGn", "RdYlBu", "RdGy", "RdBu", "PuOr", "PRGn", "PiYG", "BrBG")) { + if(input$upgma_tiles_mapping_div_mid_5 == "Zero") { + midpoint <- 0 + } else if(input$upgma_tiles_mapping_div_mid_5 == "Mean") { + midpoint <- mean(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) + } else { + midpoint <- median(as.matrix(Vis$meta_upgma[input$upgma_fruit_variable_5]), na.rm = TRUE) + } + scale_fill_gradient5(low = brewer.pal(3, input$upgma_tiles_scale_5)[1], + mid = brewer.pal(3, input$upgma_tiles_scale_5)[2], + high = brewer.pal(3, input$upgma_tiles_scale_5)[3], + midpoint = midpoint) + } else { + if(input$upgma_tiles_scale_5 %in% c("magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")) { + if(class(unlist(Vis$meta_upgma[input$upgma_fruit_variable_5])) == "numeric") { + if(input$upgma_tiles_scale_5 == "magma") { + scale_fill_viridis(option = "A") + } else if(input$upgma_tiles_scale_5 == "inferno") { + scale_fill_viridis(option = "B") + } else if(input$upgma_tiles_scale_5 == "plasma") { + scale_fill_viridis(option = "C") + } else if(input$upgma_tiles_scale_5 == "viridis") { + scale_fill_viridis(option = "D") + } else if(input$upgma_tiles_scale_5 == "cividis") { + scale_fill_viridis(option = "E") + } else if(input$upgma_tiles_scale_5 == "rocket") { + scale_fill_viridis(option = "F") + } else if(input$upgma_tiles_scale_5 == "mako") { + scale_fill_viridis(option = "G") + } else if(input$upgma_tiles_scale_5 == "turbo") { + scale_fill_viridis(option = "H") + } + } else { + if(input$upgma_tiles_scale_5 == "magma") { + scale_fill_viridis(discrete = TRUE, option = "A") + } else if(input$upgma_tiles_scale_5 == "inferno") { + scale_fill_viridis(discrete = TRUE, option = "B") + } else if(input$upgma_tiles_scale_5 == "plasma") { + scale_fill_viridis(discrete = TRUE, option = "C") + } else if(input$upgma_tiles_scale_5 == "viridis") { + scale_fill_viridis(discrete = TRUE, option = "D") + } else if(input$upgma_tiles_scale_5 == "cividis") { + scale_fill_viridis(discrete = TRUE, option = "E") + } else if(input$upgma_tiles_scale_5 == "rocket") { + scale_fill_viridis(discrete = TRUE, option = "F") + } else if(input$upgma_tiles_scale_5 == "mako") { + scale_fill_viridis(discrete = TRUE, option = "G") + } else if(input$upgma_tiles_scale_5 == "turbo") { + scale_fill_viridis(discrete = TRUE, option = "H") + } + } + } else { + scale_fill_brewer(palette = input$upgma_tiles_scale_5) + } + } + } else {NULL} + } + }) + + # No label clip off for linear upgma tree + upgma_clip_label <- reactive({ + if(!(input$upgma_layout == "circular" | input$upgma_layout == "inward")) { + coord_cartesian(clip = "off") + } else {NULL} + }) + + # Geom Fruit + upgma_fruit <- reactive({ + if((!is.null(input$upgma_tiles_show_1)) & + (!is.null(input$upgma_fruit_variable)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ)) & + (!is.null(input$upgma_fruit_width_circ)) & + (!is.null(input$upgma_fruit_alpha))) { + if(input$upgma_tiles_show_1 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = input$upgma_fruit_offset_circ, + width = input$upgma_fruit_width_circ, + alpha = input$upgma_fruit_alpha + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = input$upgma_fruit_offset_circ, + width = input$upgma_fruit_width_circ, + alpha = input$upgma_fruit_alpha + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_1 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = 0, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable)), + offset = 0, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Geom Fruit + upgma_fruit2 <- reactive({ + if((!is.null(input$upgma_tiles_show_2)) & + (!is.null(input$upgma_fruit_variable_2)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_2)) & + (!is.null(input$upgma_fruit_width_circ_2)) & + (!is.null(input$upgma_fruit_alpha_2))) { + if(input$upgma_tiles_show_2 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), + offset = input$upgma_fruit_offset_circ_2, + width = input$upgma_fruit_width_circ_2, + alpha = input$upgma_fruit_alpha_2 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_2)), + offset = input$upgma_fruit_offset_circ_2, + width = input$upgma_fruit_width_circ_2, + alpha = input$upgma_fruit_alpha_2 + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_2 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_2)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + upgma_fruit3 <- reactive({ + if((!is.null(input$upgma_tiles_show_3)) & + (!is.null(input$upgma_fruit_variable_3)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_3)) & + (!is.null(input$upgma_fruit_width_circ_3)) & + (!is.null(input$upgma_fruit_alpha_3))) { + if(input$upgma_tiles_show_3 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), + offset = input$upgma_fruit_offset_circ_3, + width = input$upgma_fruit_width_circ_3, + alpha = input$upgma_fruit_alpha_3 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_3)), + offset = input$upgma_fruit_offset_circ_3, + width = input$upgma_fruit_width_circ_3, + alpha = input$upgma_fruit_alpha_3 + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_3 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_3)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + upgma_fruit4 <- reactive({ + if((!is.null(input$upgma_tiles_show_4)) & + (!is.null(input$upgma_fruit_variable_4)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_4)) & + (!is.null(input$upgma_fruit_width_circ_4)) & + (!is.null(input$upgma_fruit_alpha_4))) { + if(input$upgma_tiles_show_4 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), + offset = input$upgma_fruit_offset_circ_4, + width = input$upgma_fruit_width_circ_4, + alpha = input$upgma_fruit_alpha_4 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_4)), + offset = input$upgma_fruit_offset_circ_4, + width = input$upgma_fruit_width_circ_4, + alpha = input$upgma_fruit_alpha_4 + ) + } + } else { + if(input$upgma_tiles_show_4 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_4)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + } + }) + + upgma_fruit5 <- reactive({ + if((!is.null(input$upgma_tiles_show_5)) & + (!is.null(input$upgma_fruit_variable_5)) & + (!is.null(input$upgma_layout)) & + (!is.null(input$upgma_fruit_offset_circ_5)) & + (!is.null(input$upgma_fruit_width_circ_5)) & + (!is.null(input$upgma_fruit_alpha_5))) { + if(input$upgma_tiles_show_5 == TRUE) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), + offset = input$upgma_fruit_offset_circ_5, + width = input$upgma_fruit_width_circ_5, + alpha = input$upgma_fruit_alpha_5 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill = !!sym(input$upgma_fruit_variable_5)), + offset = input$upgma_fruit_offset_circ_5, + width = input$upgma_fruit_width_circ_5, + alpha = input$upgma_fruit_alpha_5 + ) + } + } else {NULL} + } else { + if(input$upgma_tiles_show_5 == TRUE) { + if(!is.null(Vis$upgma_max_x)) { + if(round(ceiling(Vis$upgma_max_x) * 0.1, 0) < 1) { + width <- 1 + } else { + width <- round(ceiling(Vis$upgma_max_x) * 0.033, 0) + } + } else { + width <- 2 + } + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), + offset = 0.15, + width = width * 3, + alpha = 1 + ) + } else { + geom_fruit( + geom = geom_tile, + mapping = aes(fill= !!sym(input$upgma_fruit_variable_5)), + offset = 0.05, + width = width, + alpha = 1 + ) + } + } else {NULL} + } + }) + + # Xlim + upgma_limit <- reactive({ + if(input$upgma_layout == "circular") { + xlim(input$upgma_xlim, NA) + } else {NULL} + }) + + # Treescale + upgma_treescale <- reactive({ + if(!input$upgma_layout == "circular") { + if(input$upgma_treescale_show == TRUE) { + geom_treescale(x = upgma_treescale_x(), + y = upgma_treescale_y(), + width = upgma_treescale_width(), + color = input$upgma_color, + fontsize = 4) + } else {NULL} + } else {NULL} + }) + + # Treescale Y Position + upgma_treescale_y <- reactive({ + if(is.null(input$upgma_treescale_y)) { + 0 + } else {input$upgma_treescale_y} + }) + + # Treescale X Position + upgma_treescale_x <- reactive({ + if(is.null(input$upgma_treescale_x)) { + round(ceiling(Vis$upgma_max_x) * 0.2, 0) + } else {input$upgma_treescale_x} + }) + + # Treescale width + upgma_treescale_width <- reactive({ + if(!is.null(input$upgma_treescale_width)) { + input$upgma_treescale_width + } else { + round(ceiling(Vis$upgma_max_x) * 0.1, 0) + } + }) + + # Label branches + upgma_label_branch <- reactive({ + if(!input$upgma_layout == "circular" | !input$upgma_layout == "inward") { + if(input$upgma_show_branch_label == TRUE) { + geom_label( + aes( + x=!!sym("branch"), + label= !!sym(input$upgma_branch_label)), + fill = input$upgma_branch_label_color, + size = upgma_branch_size(), + label.r = unit(input$upgma_branch_labelradius, "lines"), + nudge_x = input$upgma_branch_x, + nudge_y = input$upgma_branch_y, + fontface = input$upgma_branchlab_fontface, + alpha = input$upgma_branchlab_alpha + ) + } else {NULL} + } else {NULL} + }) + + # Branch label size + upgma_branch_size <- reactive({ + if(!is.null(input$upgma_branch_size)) { + input$upgma_branch_size + } else { + Vis$branch_size_upgma + } + }) + + # Rootedge + upgma_rootedge <- reactive({ + if(input$upgma_rootedge_show == TRUE) { + if(is.null(input$upgma_rootedge_length)) { + geom_rootedge(rootedge = round(ceiling(Vis$upgma_max_x) * 0.05, 0), + linetype = input$upgma_rootedge_line) + } else { + geom_rootedge(rootedge = input$upgma_rootedge_length, + linetype = input$upgma_rootedge_line) + } + } else {NULL} + }) + + # Tippoints + upgma_tippoint <- reactive({ + if(input$upgma_tippoint_show == TRUE | input$upgma_tipcolor_mapping_show == TRUE | input$upgma_tipshape_mapping_show == TRUE) { + if(input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == FALSE) { + geom_tippoint( + aes(color = !!sym(input$upgma_tipcolor_mapping)), + alpha = input$upgma_tippoint_alpha, + shape = input$upgma_tippoint_shape, + size = upgma_tippoint_size() + ) + } else if (input$upgma_tipcolor_mapping_show == FALSE & input$upgma_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$upgma_tipshape_mapping)), + alpha = input$upgma_tippoint_alpha, + color = input$upgma_tippoint_color, + size = upgma_tippoint_size() + ) + } else if (input$upgma_tipcolor_mapping_show == TRUE & input$upgma_tipshape_mapping_show == TRUE) { + geom_tippoint( + aes(shape = !!sym(input$upgma_tipshape_mapping), + color = !!sym(input$upgma_tipcolor_mapping)), + alpha = input$upgma_tippoint_alpha, + size = upgma_tippoint_size() + ) + } else { + geom_tippoint( + alpha = input$upgma_tippoint_alpha, + colour = input$upgma_tippoint_color, + fill = input$upgma_tippoint_color, + shape = input$upgma_tippoint_shape, + size = upgma_tippoint_size() + ) + } + } else {NULL} + }) + + # Nodepoints + upgma_nodepoint <- reactive({ + if(input$upgma_nodepoint_show == TRUE) { + geom_nodepoint( + alpha = input$upgma_nodepoint_alpha, + color = input$upgma_nodepoint_color, + shape = input$upgma_nodepoint_shape, + size = upgma_nodepoint_size() + ) + } else {NULL} + }) + + # Nodepoint size + upgma_nodepoint_size <- reactive({ + if(!is.null(input$upgma_nodepoint_size)) { + input$upgma_nodepoint_size + } else { + Vis$nodepointsize_upgma + } + }) + + # upgma circular or not + upgma_tiplab <- reactive({ + if(input$upgma_tiplab_show == TRUE) { + if(input$upgma_layout == "circular") { + if(input$upgma_mapping_show == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position), + check.overlap = input$upgma_tiplab_overlap + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + color = input$upgma_tiplab_color, + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position), + check.overlap = input$upgma_tiplab_overlap + ) + } + } else if (input$upgma_layout == "inward") { + if(input$upgma_mapping_show == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position_inw), + check.overlap = input$upgma_tiplab_overlap + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + color = input$upgma_tiplab_color, + geom = "text", + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + hjust = as.numeric(input$upgma_tiplab_position_inw), + check.overlap = input$upgma_tiplab_overlap + ) + } + } else { + if(input$upgma_mapping_show == TRUE) { + if(input$upgma_geom == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap, + label.padding = unit(upgma_tiplab_padding(), "lines"), + label.r = unit(input$upgma_tiplab_labelradius, "lines"), + fill = input$upgma_tiplab_fill + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap + ) + } + } else { + if(input$upgma_geom == TRUE) { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + color = input$upgma_tiplab_color, + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap, + label.padding = unit(upgma_tiplab_padding(), "lines"), + label.r = unit(input$upgma_tiplab_labelradius, "lines"), + fill = input$upgma_tiplab_fill + ) + } else { + geom_tiplab( + upgma_mapping_tiplab(), + geom = upgma_geom(), + color = input$upgma_tiplab_color, + angle = input$upgma_tiplab_angle, + size = upgma_tiplab_size(), + alpha = input$upgma_tiplab_alpha, + fontface = input$upgma_tiplab_fontface, + align = as.logical(input$upgma_align), + nudge_x = input$upgma_tiplab_nudge_x, + check.overlap = input$upgma_tiplab_overlap + ) + } + } + } + } else {NULL} + }) + + # Tip panel size + upgma_tiplab_padding <- reactive({ + if(!is.null(input$upgma_tiplab_padding)) { + input$upgma_tiplab_padding + } else { + Vis$tiplab_padding_upgma + } + }) + + # Tiplab size + upgma_tiplab_size <- reactive({ + if(!is.null(input$upgma_tiplab_size)) { + input$upgma_tiplab_size + } else { + Vis$labelsize_upgma + } + }) + + # Tippoint size + upgma_tippoint_size <- reactive({ + if(!is.null(input$upgma_tippoint_size)) { + input$upgma_tippoint_size + } else { + Vis$tippointsize_upgma + } + }) + + # Show Label Panels? + upgma_geom <- reactive({ + if(input$upgma_geom == TRUE) { + "label" + } else {"text"} + }) + + # upgma Tiplab color + upgma_mapping_tiplab <- reactive({ + if(input$upgma_mapping_show == TRUE) { + if(!is.null(input$upgma_tiplab)) { + aes(label = !!sym(input$upgma_tiplab), + color = !!sym(input$upgma_color_mapping)) + } else { + aes(label = !!sym("Assembly Name"), + color = !!sym(input$upgma_color_mapping)) + } + } else { + if(!is.null(input$upgma_tiplab)) { + aes(label = !!sym(input$upgma_tiplab)) + } else { + aes(label = !!sym("Assembly Name")) + } + } + }) + + # upgma Tree Layout + layout_upgma <- reactive({ + if(input$upgma_layout == "inward") { + "circular" + } else {input$upgma_layout} + }) + + # upgma inward circular + upgma_inward <- reactive({ + if (input$upgma_layout == "inward") { + layout_inward_circular(xlim = input$upgma_inward_xlim) + } else { + NULL + } + }) + + ### Save MST Plot ---- + output$save_plot_html <- downloadHandler( + filename = function() { + log_print(paste0("Save MST;", paste0("MST_", Sys.Date(), ".html"))) + paste0("MST_", Sys.Date(), ".html") + }, + content = function(file) { + mst_tree() %>% visSave(file = file, background = mst_background_color()) + } + ) + + ### Save NJ Plot ---- + + # Define download handler to save the plot + + output$download_nj <- downloadHandler( + filename = function() { + log_print(paste0("Save NJ;", paste0("NJ_", Sys.Date(), ".", input$filetype_nj))) + paste0("NJ_", Sys.Date(), ".", input$filetype_nj) + }, + content = function(file) { + if (input$filetype_nj == "png") { + png(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) + print(nj_tree()) + dev.off() + } else if (input$filetype_nj == "jpeg") { + jpeg(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) + print(nj_tree()) + dev.off() + } else if (input$filetype_nj == "svg") { + plot <- print(nj_tree()) + ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio))/96, + height = as.numeric(input$nj_scale)/96)) + } else if (input$filetype_nj == "bmp") { + bmp(file, width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale)) + print(nj_tree()) + dev.off() + } + } + ) + + ### Save UPGMA Plot ---- + + # Define download handler to save the plot + + output$download_upgma <- downloadHandler( + filename = function() { + log_print(paste0("Save UPGMA;", paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma))) + paste0("UPGMA_", Sys.Date(), ".", input$filetype_upgma) + }, + content = function(file) { + if (input$filetype_upgma == "png") { + png(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) + print(upgma_tree()) + dev.off() + } else if (input$filetype_upgma == "jpeg") { + jpeg(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) + print(upgma_tree()) + dev.off() + } else if (input$filetype_upgma == "svg") { + plot <- print(upgma_tree()) + ggsave(file=file, plot=plot, device = svg(width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio))/96, + height = as.numeric(input$upgma_scale)/96)) + } else if (input$filetype_upgma == "bmp") { + bmp(file, width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale)) + print(upgma_tree()) + dev.off() + } + } + ) + + ### Reactive Events ---- + + # MST cluster reset button + observeEvent(input$mst_cluster_reset, { + if(!is.null(DB$schemeinfo)) + updateNumericInput(session, "mst_cluster_threshold", value = as.numeric(DB$schemeinfo[7, 2])) + }) + + # Shut off "Align Labels" control for UPGMA trees + shinyjs::disable('upgma_align') + shinyjs::disable('upgma_tiplab_linesize') + shinyjs::disable('upgma_tiplab_linetype') + + # Conditional disabling of control elemenmts + observe({ + + # Tiles for inward layout + if(input$nj_layout == "inward") { + shinyjs::disable('nj_tiles_show') + shinyjs::disable('nj_tiles_show_2') + shinyjs::disable('nj_tiles_show_3') + shinyjs::disable('nj_tiles_show_4') + shinyjs::disable('nj_tiles_show_5') + shinyjs::disable('nj_fruit_variable') + shinyjs::disable('nj_fruit_variable_2') + shinyjs::disable('nj_fruit_variable_3') + shinyjs::disable('nj_fruit_variable_4') + shinyjs::disable('nj_fruit_variable_5') + shinyjs::disable('nj_fruit_width') + shinyjs::disable('nj_fruit_width_2') + shinyjs::disable('nj_fruit_width_3') + shinyjs::disable('nj_fruit_width_4') + shinyjs::disable('nj_fruit_width_5') + shinyjs::disable('nj_fruit_offset') + shinyjs::disable('nj_fruit_offset_2') + shinyjs::disable('nj_fruit_offset_3') + shinyjs::disable('nj_fruit_offset_4') + shinyjs::disable('nj_fruit_offset_5') + } else { + shinyjs::enable('nj_tiles_show') + shinyjs::enable('nj_tiles_show_2') + shinyjs::enable('nj_tiles_show_3') + shinyjs::enable('nj_tiles_show_4') + shinyjs::enable('nj_tiles_show_5') + shinyjs::enable('nj_fruit_variable') + shinyjs::enable('nj_fruit_variable_2') + shinyjs::enable('nj_fruit_variable_3') + shinyjs::enable('nj_fruit_variable_4') + shinyjs::enable('nj_fruit_variable_5') + shinyjs::enable('nj_fruit_width') + shinyjs::enable('nj_fruit_width_2') + shinyjs::enable('nj_fruit_width_3') + shinyjs::enable('nj_fruit_width_4') + shinyjs::enable('nj_fruit_width_5') + shinyjs::enable('nj_fruit_offset') + shinyjs::enable('nj_fruit_offset_2') + shinyjs::enable('nj_fruit_offset_3') + shinyjs::enable('nj_fruit_offset_4') + shinyjs::enable('nj_fruit_offset_5') + } + + if(input$upgma_layout == "inward") { + shinyjs::disable('upgma_tiles_show') + shinyjs::disable('upgma_tiles_show_2') + shinyjs::disable('upgma_tiles_show_3') + shinyjs::disable('upgma_tiles_show_4') + shinyjs::disable('upgma_tiles_show_5') + shinyjs::disable('upgma_fruit_variable') + shinyjs::disable('upgma_fruit_variable_2') + shinyjs::disable('upgma_fruit_variable_3') + shinyjs::disable('upgma_fruit_variable_4') + shinyjs::disable('upgma_fruit_variable_5') + shinyjs::disable('upgma_fruit_width') + shinyjs::disable('upgma_fruit_width_2') + shinyjs::disable('upgma_fruit_width_3') + shinyjs::disable('upgma_fruit_width_4') + shinyjs::disable('upgma_fruit_width_5') + shinyjs::disable('upgma_fruit_offset') + shinyjs::disable('upgma_fruit_offset_2') + shinyjs::disable('upgma_fruit_offset_3') + shinyjs::disable('upgma_fruit_offset_4') + shinyjs::disable('upgma_fruit_offset_5') + } else { + shinyjs::enable('upgma_tiles_show') + shinyjs::enable('upgma_tiles_show_2') + shinyjs::enable('upgma_tiles_show_3') + shinyjs::enable('upgma_tiles_show_4') + shinyjs::enable('upgma_tiles_show_5') + shinyjs::enable('upgma_fruit_variable') + shinyjs::enable('upgma_fruit_variable_2') + shinyjs::enable('upgma_fruit_variable_3') + shinyjs::enable('upgma_fruit_variable_4') + shinyjs::enable('upgma_fruit_variable_5') + shinyjs::enable('upgma_fruit_width') + shinyjs::enable('upgma_fruit_width_2') + shinyjs::enable('upgma_fruit_width_3') + shinyjs::enable('upgma_fruit_width_4') + shinyjs::enable('upgma_fruit_width_5') + shinyjs::enable('upgma_fruit_offset') + shinyjs::enable('upgma_fruit_offset_2') + shinyjs::enable('upgma_fruit_offset_3') + shinyjs::enable('upgma_fruit_offset_4') + shinyjs::enable('upgma_fruit_offset_5') + } + + # Shut off branch labels for NJ and UPGMA plots for circular layout + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + shinyjs::disable('nj_show_branch_label') + } else { + shinyjs::enable('nj_show_branch_label') + } + + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + shinyjs::disable('upgma_show_branch_label') + } else { + shinyjs::enable('upgma_show_branch_label') + } + }) + + #### Generate Plot ---- + + hamming_nj <- reactive({ + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + + allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] + + compute.distMatrix(allelic_profile_noNA_true, hamming.dist) + + } else if(input$na_handling == "ignore_na"){ + compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) + + } else { + compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) + } + + } else {compute.distMatrix(DB$allelic_profile_true, hamming.dist)} + }) + + hamming_mst <- reactive({ + if(anyNA(DB$allelic_profile)) { + if(input$na_handling == "omit") { + allelic_profile_noNA <- DB$allelic_profile[, colSums(is.na(DB$allelic_profile)) == 0] + + allelic_profile_noNA_true <- allelic_profile_noNA[which(DB$data$Include == TRUE),] + + dist <- compute.distMatrix(allelic_profile_noNA_true, hamming.dist) + + } else if (input$na_handling == "ignore_na") { + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distIgnore) + } else { + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.distCategory) + } + } else { + dist <- compute.distMatrix(DB$allelic_profile_true, hamming.dist) + } + + # Find indices of pairs with a distance of 0 + zero_distance_pairs <- as.data.frame(which(as.matrix(dist) == 0, arr.ind = TRUE)) + + zero_distance_pairs <- zero_distance_pairs[zero_distance_pairs$row != zero_distance_pairs$col, ] + + if(nrow(zero_distance_pairs) > 0) { + + # Sort each row so that x <= y + df_sorted <- t(apply(zero_distance_pairs, 1, function(row) sort(row))) + + # Remove duplicate rows + df_unique <- as.data.frame(unique(df_sorted)) + + colnames(df_unique) <- c("col", "row") + + # get metadata in df + vector_col <- character(0) + count <- 1 + for (i in df_unique$col) { + vector_col[count] <- Vis$meta_mst$`Assembly Name`[i] + count <- count + 1 + } + + vector_row <- character(0) + count <- 1 + for (i in df_unique$row) { + vector_row[count] <- Vis$meta_mst$`Assembly Name`[i] + count <- count + 1 + } + + col_id <- character(0) + count <- 1 + for (i in df_unique$col) { + col_id[count] <- Vis$meta_mst$`Assembly ID`[i] + count <- count + 1 + } + + row_id <- character(0) + count <- 1 + for (i in df_unique$row) { + row_id[count] <- Vis$meta_mst$`Assembly ID`[i] + count <- count + 1 + } + + col_index <- character(0) + count <- 1 + for (i in df_unique$col) { + col_index[count] <- Vis$meta_mst$Index[i] + count <- count + 1 + } + + row_index <- character(0) + count <- 1 + for (i in df_unique$row) { + row_index[count] <- Vis$meta_mst$Index[i] + count <- count + 1 + } + + col_date <- character(0) + count <- 1 + for (i in df_unique$col) { + col_date[count] <- Vis$meta_mst$`Isolation Date`[i] + count <- count + 1 + } + + row_date <- character(0) + count <- 1 + for (i in df_unique$row) { + row_date[count] <- Vis$meta_mst$`Isolation Date`[i] + count <- count + 1 + } + + col_host <- character(0) + count <- 1 + for (i in df_unique$col) { + col_host[count] <- Vis$meta_mst$Host[i] + count <- count + 1 + } + + row_host <- character(0) + count <- 1 + for (i in df_unique$row) { + row_host[count] <- Vis$meta_mst$Host[i] + count <- count + 1 + } + + col_country <- character(0) + count <- 1 + for (i in df_unique$col) { + col_country[count] <- Vis$meta_mst$Country[i] + count <- count + 1 + } + + row_country <- character(0) + count <- 1 + for (i in df_unique$row) { + row_country[count] <- Vis$meta_mst$Country[i] + count <- count + 1 + } + + col_city <- character(0) + count <- 1 + for (i in df_unique$col) { + col_city[count] <- Vis$meta_mst$City[i] + count <- count + 1 + } + + row_city <- character(0) + count <- 1 + for (i in df_unique$row) { + row_city[count] <- Vis$meta_mst$City[i] + count <- count + 1 + } + + df_unique <- cbind(df_unique, col_name = vector_col, row_name = vector_row, + col_index = col_index, row_index = row_index, col_id = col_id, + row_id = row_id, col_date = col_date, row_date = row_date, + col_host = col_host, row_host = row_host, col_country = col_country, + row_country = row_country, col_city = col_city, row_city = row_city) + + # Add groups + grouped_df <- df_unique %>% + group_by(col) %>% + mutate(group_id = cur_group_id()) + + # Merge groups + name <- character(0) + index <- character(0) + id <- character(0) + count <- 1 + for (i in grouped_df$group_id) { + name[count] <- paste(unique(append(grouped_df$col_name[which(grouped_df$group_id == i)], + grouped_df$row_name[which(grouped_df$group_id == i)])), + collapse = "\n") + + id[count] <- paste(unique(append(grouped_df$col_id[which(grouped_df$group_id == i)], + grouped_df$row_id[which(grouped_df$group_id == i)])), + collapse = "\n") + + index[count] <- paste(unique(append(grouped_df$col_index[which(grouped_df$group_id == i)], + grouped_df$row_index[which(grouped_df$group_id == i)])), + collapse = "\n") + + count <- count + 1 + } + + merged_names <- cbind(grouped_df, "Index" = index, "Assembly Name" = name, "Assembly ID" = id) + + # remove duplicate groups + + final <- merged_names[!duplicated(merged_names$group_id), ] + + final_cleaned <- final[!(final$col_name %in% final$row_name),] + + final_cleaned <- select(final_cleaned, 3, 17:20) + + # adapt metadata + Date_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + Date <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + Date <- append(Date, Vis$meta_mst$`Isolation Date`[which(Vis$meta_mst$Index == i)]) + } + Date_merged <- append(Date_merged, paste(Date, collapse = "\n")) + } + + Host_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + Host <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + Host <- append(Host, Vis$meta_mst$Host[which(Vis$meta_mst$Index == i)]) + } + Host_merged <- append(Host_merged, paste(Host, collapse = "\n")) + } + + Country_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + Country <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + Country <- append(Country, Vis$meta_mst$Country[which(Vis$meta_mst$Index == i)]) + } + Country_merged <- append(Country_merged, paste(Country, collapse = "\n")) + } + + City_merged <- character(0) + for(j in 1:length(final_cleaned$Index)) { + City <- character(0) + for(i in strsplit(final_cleaned$Index, "\n")[[j]]) { + City <- append(City, Vis$meta_mst$City[which(Vis$meta_mst$Index == i)]) + } + City_merged <- append(City_merged, paste(City, collapse = "\n")) + } + + final_meta <- cbind(final_cleaned, "Isolation Date" = Date_merged, + "Host" = Host_merged, "Country" = Country_merged, "City" = City_merged) + + + # Merging with original data frame / allelic profile + + allelic_profile_true <- DB$allelic_profile_true + meta_true <- Vis$meta_mst + + rownames(allelic_profile_true) <- Vis$meta_mst$`Assembly Name` + rownames(meta_true) <- Vis$meta_mst$`Assembly Name` + + omit <- unique(append(df_unique$col_name, df_unique$row_name)) %in% final_cleaned$col_name + + omit_id <- unique(append(df_unique$col_name, df_unique$row_name))[!omit] + + remove <- !(rownames(allelic_profile_true) %in% omit_id) + + allelic_profile_clean <- allelic_profile_true[remove, ] + + meta_clean <- meta_true[remove, ] + + # substitute meta assembly names with group names + + count <- 1 + for(i in which(rownames(meta_clean) %in% final_meta$col_name)) { + meta_clean$Index[i] <- final_meta$Index[count] + meta_clean$`Assembly Name`[i] <- final_meta$`Assembly Name`[count] + meta_clean$`Assembly ID`[i] <- final_meta$`Assembly ID`[count] + meta_clean$`Isolation Date`[i] <- final_meta$`Isolation Date`[count] + meta_clean$Host[i] <- final_meta$Host[count] + meta_clean$Country[i] <- final_meta$Country[count] + meta_clean$City[i] <- final_meta$City[count] + count <- count + 1 + } + + # Metadata completion + # get group size + + size_vector <- numeric(0) + for(i in 1:nrow(meta_clean)) { + if (str_count(meta_clean$`Assembly Name`[i], "\n") == 0) { + size_vector[i] <- 1 + } else { + size_vector[i] <- str_count(meta_clean$`Assembly Name`[i], "\n") +1 + } + } + + meta_clean <- mutate(meta_clean, size = size_vector) + + # get font size dependent on group size + + font_size <- numeric(nrow(meta_clean)) + + for (i in 1:length(font_size)) { + if(meta_clean$size[i] < 3) { + font_size[i] <- 12 + } else { + font_size[i] <- 11 + } + } + + # get v-align dependent on group size + valign <- numeric(nrow(meta_clean)) + + for (i in 1:length(valign)) { + if(meta_clean$size[i] == 1) { + valign[i] <- -30 + } else if(meta_clean$size[i] == 2) { + valign[i] <- -38 + } else if(meta_clean$size[i] == 3) { + valign[i] <- -46 + } else if(meta_clean$size[i] == 4) { + valign[i] <- -54 + } else if(meta_clean$size[i] == 5) { + valign[i] <- -62 + } else if(meta_clean$size[i] > 5) { + valign[i] <- -70 + } + } + + Vis$unique_meta <- meta_clean %>% + cbind(font_size = font_size, valign = valign) + + # final dist calculation + + if(anyNA(DB$allelic_profile)){ + if(input$na_handling == "omit") { + allelic_profile_clean_noNA_names <- allelic_profile_clean[, colSums(is.na(allelic_profile_clean)) == 0] + compute.distMatrix(allelic_profile_clean_noNA_names, hamming.dist) + } else if (input$na_handling == "ignore_na") { + compute.distMatrix(allelic_profile_clean, hamming.distIgnore) + } else { + compute.distMatrix(allelic_profile_clean, hamming.distCategory) + } + } else {compute.distMatrix(allelic_profile_clean, hamming.dist)} + + + } else { + font_size <- rep(12, nrow(Vis$meta_mst)) + valign <- rep(-30, nrow(Vis$meta_mst)) + size <- rep(1, nrow(Vis$meta_mst)) + Vis$unique_meta <- Vis$meta_mst %>% + cbind(size , font_size, valign) + + dist + } + + }) + + observeEvent(input$create_tree, { + log_print("Input create_tree") + + if(is.null(DB$data)) { + log_print("Missing data") + + show_toast( + title = "Missing data", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else if(nrow(DB$allelic_profile_true) < 3) { + log_print("Min. of 3 entries required for visualization") + + show_toast( + title = "Min. of 3 entries required for visualization", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } else { + + if(any(duplicated(DB$meta$`Assembly Name`)) | any(duplicated(DB$meta$`Assembly ID`))) { + log_print("Duplicated assemblies") + + dup_name <- which(duplicated(DB$meta_true$`Assembly Name`)) + dup_id <- which(duplicated(DB$meta_true$`Assembly ID`)) + + showModal( + modalDialog( + if((length(dup_name) + length(dup_id)) == 1) { + if(length(dup_name) == 1) { + HTML(paste0("Entry #", dup_name, + " contains a duplicated assembly name:", "

", + DB$meta_true$`Assembly Name`[dup_name])) + } else { + HTML(paste0("Entry #", dup_id, + " contains a duplicated assembly ID:", "

", + DB$meta_true$`Assembly ID`[dup_id])) + } + } else { + if(length(dup_name) == 0) { + HTML(c("Entries contain duplicated IDs

", + paste0(unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) + } else if(length(dup_id) == 0) { + HTML(c("Entries contain duplicated names

", + paste0(unique(DB$meta_true$`Assembly Name`[dup_name]), "
"))) + } else { + HTML(c("Entries contain duplicated names and IDs

", + paste0("Name: ", unique(DB$meta_true$`Assembly Name`[dup_name]), "
"), + paste0("ID: ", unique(DB$meta_true$`Assembly ID`[dup_id]), "
"))) + } + }, + title = "Duplicate entries", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("change_entries", "Go to Entry Table", class = "btn btn-default") + ) + ) + ) + } else { + + set.seed(1) + + if (input$tree_algo == "Neighbour-Joining") { + + log_print("Rendering NJ tree") + + output$nj_field <- renderUI({ + addSpinner( + plotOutput("tree_nj", width = paste0(as.character(as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), "px"), height = paste0(as.character(input$nj_scale), "px")), + spin = "dots", + color = "#ffffff" + ) + }) + + Vis$meta_nj <- select(DB$meta_true, -2) + + if(length(unique(gsub(" ", "_", colnames(Vis$meta_nj)))) < length(gsub(" ", "_", colnames(Vis$meta_nj)))) { + show_toast( + title = "Conflicting Custom Variable Names", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + # Create phylogenetic tree data + Vis$nj <- ape::nj(hamming_nj()) + + # Create phylogenetic tree meta data + Vis$meta_nj <- mutate(Vis$meta_nj, taxa = Index) %>% + relocate(taxa) + + # Get number of included entries calculate start values for tree + if(!is.null(input$nj_layout)) { + if(input$nj_layout == "circular" | input$nj_layout == "inward") { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_nj <- 5.5 + Vis$tippointsize_nj <- 5.5 + Vis$nodepointsize_nj <- 4 + Vis$tiplab_padding_nj <- 0.25 + Vis$branch_size_nj <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_nj <- 5 + Vis$tippointsize_nj <- 5 + Vis$nodepointsize_nj <- 3.5 + Vis$tiplab_padding_nj <- 0.2 + Vis$branch_size_nj <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_nj <- 4.5 + Vis$tippointsize_nj <- 4.5 + Vis$nodepointsize_nj <- 3 + Vis$tiplab_padding_nj <- 0.15 + Vis$branch_size_nj <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_nj <- 4 + Vis$tippointsize_nj <- 4 + Vis$nodepointsize_nj <- 2.5 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_nj <- 3.5 + Vis$tippointsize_nj <- 3.5 + Vis$nodepointsize_nj <- 2 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 2.5 + } else { + Vis$labelsize_nj <- 3 + Vis$tippointsize_nj <- 3 + Vis$nodepointsize_nj <- 1.5 + Vis$tiplab_padding_nj <- 0.05 + Vis$branch_size_nj <- 2 + } + } else { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_nj <- 5 + Vis$tippointsize_nj <- 5 + Vis$nodepointsize_nj <- 4 + Vis$tiplab_padding_nj <- 0.25 + Vis$branch_size_nj <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_nj <- 4.5 + Vis$tippointsize_nj <- 4.5 + Vis$nodepointsize_nj <- 3.5 + Vis$tiplab_padding_nj <- 0.2 + Vis$branch_size_nj <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_nj <- 4 + Vis$tippointsize_nj <- 4 + Vis$nodepointsize_nj <- 3 + Vis$tiplab_padding_nj <- 0.15 + Vis$branch_size_nj <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_nj <- 3.5 + Vis$tippointsize_nj <- 3.5 + Vis$nodepointsize_nj <- 2.5 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_nj <- 3 + Vis$tippointsize_nj <- 3 + Vis$nodepointsize_nj <- 2 + Vis$tiplab_padding_nj <- 0.1 + Vis$branch_size_nj <- 2.5 + } else { + Vis$labelsize_nj <- 2.5 + Vis$tippointsize_nj <- 2.5 + Vis$nodepointsize_nj <- 1.5 + Vis$tiplab_padding_nj <- 0.05 + Vis$branch_size_nj <- 2 + } + } + } else { + Vis$labelsize_nj <- 4 + Vis$tippointsize_nj <- 4 + Vis$nodepointsize_nj <- 2.5 + Vis$tiplab_padding_nj <- 0.2 + Vis$branch_size_nj <- 3.5 + } + + Vis$nj_tree <- ggtree(Vis$nj) + + # Get upper and lower end of x range + Vis$nj_max_x <- max(Vis$nj_tree$data$x) + Vis$nj_min_x <- min(Vis$nj_tree$data$x) + + # Get parent node numbers + Vis$nj_parentnodes <- Vis$nj_tree$data$parent + + # Update visualization control inputs + if(!is.null(input$nj_tiplab_size)) { + updateNumericInput(session, "nj_tiplab_size", value = Vis$labelsize_nj) + } + if(!is.null(input$nj_tippoint_size)) { + updateSliderInput(session, "nj_tippoint_size", value = Vis$tippointsize_nj) + } + if(!is.null(input$nj_nodepoint_size)) { + updateSliderInput(session, "nj_nodepoint_size", value = Vis$nodepointsize_nj) + } + if(!is.null(input$nj_tiplab_padding)) { + updateSliderInput(session, "nj_tiplab_padding", value = Vis$tiplab_padding_nj) + } + if(!is.null(input$nj_branch_size)) { + updateNumericInput(session, "nj_branch_size", value = Vis$branch_size_nj) + } + if(!is.null(input$nj_treescale_width)) { + updateNumericInput(session, "nj_treescale_width", value = round(ceiling(Vis$nj_max_x) * 0.1, 0)) + } + if(!is.null(input$nj_rootedge_length)) { + updateSliderInput(session, "nj_rootedge_length", value = round(ceiling(Vis$nj_max_x) * 0.05, 0)) + } + + output$tree_nj <- renderPlot({ + nj_tree() + }) + + Vis$nj_true <- TRUE + } + } else if (input$tree_algo == "UPGMA") { + + log_print("Rendering UPGMA tree") + + output$upgma_field <- renderUI({ + addSpinner( + plotOutput("tree_upgma", width = paste0(as.character(as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), "px"), height = paste0(as.character(input$upgma_scale), "px")), + spin = "dots", + color = "#ffffff" + ) + }) + + Vis$meta_upgma <- select(DB$meta_true, -2) + + if(length(unique(gsub(" ", "_", colnames(Vis$meta_upgma)))) < length(gsub(" ", "_", colnames(Vis$meta_upgma)))) { + show_toast( + title = "Conflicting Custom Variable Names", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + # Create phylogenetic tree data + Vis$upgma <- phangorn::upgma(hamming_nj()) + + # Create phylogenetic tree meta data + Vis$meta_upgma <- mutate(Vis$meta_upgma, taxa = Index) %>% + relocate(taxa) + + # Get number of included entries calculate start values for tree + if(!is.null(input$upgma_layout)) { + if(input$upgma_layout == "circular" | input$upgma_layout == "inward") { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_upgma <- 5.5 + Vis$tippointsize_upgma <- 5.5 + Vis$nodepointsize_upgma <- 4 + Vis$tiplab_padding_upgma <- 0.25 + Vis$branch_size_upgma <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_upgma <- 5 + Vis$tippointsize_upgma <- 5 + Vis$nodepointsize_upgma <- 3.5 + Vis$tiplab_padding_upgma <- 0.2 + Vis$branch_size_upgma <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_upgma <- 4.5 + Vis$tippointsize_upgma <- 4.5 + Vis$nodepointsize_upgma <- 3 + Vis$tiplab_padding_upgma <- 0.15 + Vis$branch_size_upgma <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_upgma <- 4 + Vis$tippointsize_upgma <- 4 + Vis$nodepointsize_upgma <- 2.5 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_upgma <- 3.5 + Vis$tippointsize_upgma <- 3.5 + Vis$nodepointsize_upgma <- 2 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 2.5 + } else { + Vis$labelsize_upgma <- 3 + Vis$tippointsize_upgma <- 3 + Vis$nodepointsize_upgma <- 1.5 + Vis$tiplab_padding_upgma <- 0.05 + Vis$branch_size_upgma <- 2 + } + } else { + if(sum(DB$data$Include) < 21) { + Vis$labelsize_upgma <- 5 + Vis$tippointsize_upgma <- 5 + Vis$nodepointsize_upgma <- 4 + Vis$tiplab_padding_upgma <- 0.25 + Vis$branch_size_upgma <- 4.5 + } else if (between(sum(DB$data$Include), 21, 40)) { + Vis$labelsize_upgma <- 4.5 + Vis$tippointsize_upgma <- 4.5 + Vis$nodepointsize_upgma <- 3.5 + Vis$tiplab_padding_upgma <- 0.2 + Vis$branch_size_upgma <- 4 + } else if (between(sum(DB$data$Include), 41, 60)) { + Vis$labelsize_upgma <- 4 + Vis$tippointsize_upgma <- 4 + Vis$nodepointsize_upgma <- 3 + Vis$tiplab_padding_upgma <- 0.15 + Vis$branch_size_upgma <- 3.5 + } else if (between(sum(DB$data$Include), 61, 80)) { + Vis$labelsize_upgma <- 3.5 + Vis$tippointsize_upgma <- 3.5 + Vis$nodepointsize_upgma <- 2.5 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 3 + } else if (between(sum(DB$data$Include), 81, 100)) { + Vis$labelsize_upgma <- 3 + Vis$tippointsize_upgma <- 3 + Vis$nodepointsize_upgma <- 2 + Vis$tiplab_padding_upgma <- 0.1 + Vis$branch_size_upgma <- 2.5 + } else { + Vis$labelsize_upgma <- 2.5 + Vis$tippointsize_upgma <- 2.5 + Vis$nodepointsize_upgma <- 1.5 + Vis$tiplab_padding_upgma <- 0.05 + Vis$branch_size_upgma <- 2 + } + } + } else { + Vis$labelsize_upgma <- 4 + Vis$tippointsize_upgma <- 4 + Vis$nodepointsize_upgma <- 2.5 + Vis$tiplab_padding_upgma <- 0.2 + Vis$branch_size_upgma <- 3.5 + } + + Vis$upgma_tree <- ggtree(Vis$upgma) + + # Get upper and lower end of x range + Vis$upgma_max_x <- max(Vis$upgma_tree$data$x) + Vis$upgma_min_x <- min(Vis$upgma_tree$data$x) + + # Get parent node numbers + Vis$upgma_parentnodes <- Vis$upgma_tree$data$parent + + # Update visualization control inputs + if(!is.null(input$upgma_tiplab_size)) { + updateNumericInput(session, "upgma_tiplab_size", value = Vis$labelsize_upgma) + } + if(!is.null(input$upgma_tippoint_size)) { + updateSliderInput(session, "upgma_tippoint_size", value = Vis$tippointsize_upgma) + } + if(!is.null(input$upgma_nodepoint_size)) { + updateSliderInput(session, "upgma_nodepoint_size", value = Vis$nodepointsize_upgma) + } + if(!is.null(input$upgma_tiplab_padding)) { + updateSliderInput(session, "upgma_tiplab_padding", value = Vis$tiplab_padding_upgma) + } + if(!is.null(input$upgma_branch_size)) { + updateNumericInput(session, "upgma_branch_size", value = Vis$branch_size_upgma) + } + if(!is.null(input$upgma_treescale_width)) { + updateNumericInput(session, "upgma_treescale_width", value = round(ceiling(Vis$upgma_max_x) * 0.1, 0)) + } + if(!is.null(input$upgma_rootedge_length)) { + updateSliderInput(session, "upgma_rootedge_length", value = round(ceiling(Vis$upgma_max_x) * 0.05, 0)) + } + + output$tree_upgma <- renderPlot({ + upgma_tree() + }) + + Vis$upgma_true <- TRUE + } + } else { + + log_print("Rendering MST graph") + + output$mst_field <- renderUI({ + if(input$mst_background_transparent == TRUE) { + visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")) + } else { + addSpinner( + visNetworkOutput("tree_mst", width = paste0(as.character(as.numeric(input$mst_scale) * as.numeric(input$mst_ratio)), "px"), height = paste0(as.character(input$mst_scale), "px")), + spin = "dots", + color = "#ffffff" + ) + } + }) + + if(nrow(DB$meta_true) > 100) { + + log_print("Over 100 isolates in MST graph") + + show_toast( + title = "Computation might take a while", + type = "warning", + position = "bottom-end", + timer = 10000 + ) + } + + meta_mst <- DB$meta_true + Vis$meta_mst <- meta_mst + + # prepare igraph object + Vis$ggraph_1 <- hamming_mst() |> + as.matrix() |> + graph.adjacency(weighted = TRUE) |> + igraph::mst() + + output$tree_mst <- renderVisNetwork({ + mst_tree() + }) + + Vis$mst_true <- TRUE + } + } + } + }) + + # _______________________ #### + + ## Report ---- + + observe({ + if(!is.null(DB$data)) { + if(!is.null(input$tree_algo)) { + if(input$tree_algo == "Minimum-Spanning") { + shinyjs::disable("rep_plot_report") + updateCheckboxInput(session, "rep_plot_report", value = FALSE) + } else { + shinyjs::enable("rep_plot_report") + } + } + } + }) + + ### Report creation UI ---- + + observeEvent(input$create_rep, { + + if((input$tree_algo == "Minimum-Spanning" & isTRUE(Vis$mst_true)) | + (input$tree_algo == "UPGMA" & isTRUE(Vis$upgma_true)) | + (input$tree_algo == "Neighbour-Joining" & isTRUE(Vis$nj_true))) { + # Get currently selected missing value handling option + if(input$na_handling == "ignore_na") { + na_handling <- "Ignore missing values for pairwise comparison" + } else if(input$na_handling == "omit") { + na_handling <- "Omit loci with missing values for all assemblies" + } else if(input$na_handling == "category") { + na_handling <- "Treat missing values as allele variant" + } + + extra_var <- character() + if(input$tree_algo == "Minimum-Spanning") { + shinyjs::runjs("mstReport();") + if(isTRUE(input$mst_color_var)) { + extra_var <- c(extra_var, input$mst_col_var) + } + } else if(input$tree_algo == "Neighbour-Joining") { + if(isTRUE(input$nj_mapping_show)) { + extra_var <- c(extra_var, input$nj_color_mapping) + } + if(isTRUE(input$nj_tipcolor_mapping_show)) { + extra_var <- c(extra_var, input$nj_tipcolor_mapping) + } + if(isTRUE(input$nj_tipshape_mapping_show)) { + extra_var <- c(extra_var, input$nj_tipshape_mapping) + } + if(isTRUE(input$nj_tiles_show_1)) { + extra_var <- c(extra_var, input$nj_fruit_variable) + } + if(isTRUE(input$nj_tiles_show_2)) { + extra_var <- c(extra_var, input$nj_fruit_variable_2) + } + if(isTRUE(input$nj_tiles_show_3)) { + extra_var <- c(extra_var, input$nj_fruit_variable_3) + } + if(isTRUE(input$nj_tiles_show_4)) { + extra_var <- c(extra_var, input$nj_fruit_variable_4) + } + if(isTRUE(input$nj_tiles_show_5)) { + extra_var <- c(extra_var, input$nj_fruit_variable_5) + } + if(isTRUE(input$nj_heatmap_show)) { + extra_var <- c(extra_var, input$nj_heatmap_select) + } + } else if(input$tree_algo == "UPGMA") { + if(isTRUE(input$UPGMA_mapping_show)) { + extra_var <- c(extra_var, input$UPGMA_color_mapping) + } + if(isTRUE(input$UPGMA_tipcolor_mapping_show)) { + extra_var <- c(extra_var, input$UPGMA_tipcolor_mapping) + } + if(isTRUE(input$UPGMA_tipshape_mapping_show)) { + extra_var <- c(extra_var, input$UPGMA_tipshape_mapping) + } + if(isTRUE(input$UPGMA_tiles_show_1)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable) + } + if(isTRUE(input$UPGMA_tiles_show_2)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_2) + } + if(isTRUE(input$UPGMA_tiles_show_3)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_3) + } + if(isTRUE(input$UPGMA_tiles_show_4)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_4) + } + if(isTRUE(input$UPGMA_tiles_show_5)) { + extra_var <- c(extra_var, input$UPGMA_fruit_variable_5) + } + if(isTRUE(input$UPGMA_heatmap_show)) { + extra_var <- c(extra_var, input$UPGMA_heatmap_select) + } + } + + showModal( + modalDialog( + fluidRow( + column( + width = 12, + fluidRow( + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color:black; font-size: 15px; font-weight: 900', 'General') + ) + ) + ), + column( + width = 3, + align = "left", + checkboxInput( + "rep_general", + label = "", + value = TRUE + ) + ) + ), + fluidRow( + column( + width = 12, + align = "left", + fluidRow( + column( + width = 3, + checkboxInput( + "rep_date_general", + label = h5("Date", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 7, + dateInput( + "mst_date_general_select", + "", + max = Sys.Date() + ) + ) + ), + fluidRow( + column( + width = 3, + checkboxInput( + "rep_operator_general", + label = h5("Operator", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + textInput( + "mst_operator_general_select", + "" + ) + ) + ), + fluidRow( + column( + width = 3, + checkboxInput( + "rep_institute_general", + label = h5("Institute", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + textInput( + "mst_institute_general_select", + "" + ) + ) + ), + fluidRow( + column( + width = 3, + checkboxInput( + "rep_comm_general", + label = h5("Comment", style = "color:black;") + ) + ), + column( + width = 8, + textAreaInput( + inputId = "mst_comm_general_select", + label = "", + width = "100%", + height = "60px", + cols = NULL, + rows = NULL, + placeholder = NULL, + resize = "vertical" + ) + ) + ) + ) + ), + hr(), + fluidRow( + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Isolate Table') + ) + ) + ), + column( + width = 3, + align = "left", + checkboxInput( + "rep_entrytable", + label = "", + value = TRUE + ) + ), + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Include Plot') + ) + ) + ), + column( + width = 1, + align = "left", + checkboxInput( + "rep_plot_report", + label = "", + value = TRUE + ) + ) + ), + fluidRow( + column( + width = 6, + align = "left", + div( + class = "rep_tab_sel", + pickerInput("select_rep_tab", + label = "", + choices = names(DB$meta)[-2], + selected = c("Assembly Name", "Scheme", "Isolation Date", + "Host", "Country", "City", extra_var), + options = list( + size = 10, + `actions-box` = TRUE, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE) + ) + ) + ), + hr(), + fluidRow( + column( + width = 4, + align = "left", + HTML( + paste( + tags$span(style='color: black; font-size: 15px; font-weight: 900', 'Analysis Parameter') + ) + ) + ), + column( + width = 3, + align = "left", + checkboxInput( + "rep_analysis", + label = "", + value = TRUE + ) + ) + ), + fluidRow( + column( + width = 6, + align = "left", + fluidRow( + column( + width = 4, + checkboxInput( + "rep_cgmlst_analysis", + label = h5("Scheme", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic', DB$scheme) + ) + ) + ) + ), + fluidRow( + column( + width = 4, + checkboxInput( + "rep_tree_analysis", + label = h5("Tree", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 8, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic', input$tree_algo) + ) + ) + ) + ) + ), + column( + width = 6, + align = "left", + fluidRow( + column(2), + column( + width = 4, + checkboxInput( + "rep_distance", + label = h5("Distance", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 5, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic', 'Hamming') + ) + ) + ) + ), + fluidRow( + column(2), + column( + width = 4, + checkboxInput( + "rep_version", + label = h5("Version", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 5, + align = "right", + HTML( + paste( + tags$span(style='color:black; position: relative; top: 17px; font-style: italic', phylotraceVersion) + ) + ) + ) + ) + ) + ), + fluidRow( + column( + width = 3, + align = "left", + checkboxInput( + "rep_missval", + label = h5("NA handling", style = "color:black;"), + value = TRUE + ) + ), + column( + width = 7, + align = "right", + HTML( + paste( + tags$span(style='color: black; position: relative; top: 17px; font-style: italic; right: 35px;', na_handling) + ) + ) + ) + ) + ) + ), + title = "cgMLST Report Generation", + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + downloadBttn( + "download_report", + style = "simple", + label = "Save", + size = "sm", + icon = icon("download") + ) + ) + ) + ) + } else { + show_toast( + title = "No tree created", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + + observe({ + if(!is.null(input$rep_general)) { + if(isFALSE(input$rep_general)) { + shinyjs::disable('rep_date_general') + shinyjs::disable('rep_operator_general') + shinyjs::disable('rep_institute_general') + shinyjs::disable('rep_comm_general') + shinyjs::disable('mst_date_general_select') + shinyjs::disable('mst_operator_general_select') + shinyjs::disable('mst_institute_general_select') + shinyjs::disable('mst_comm_general_select') + } else { + shinyjs::enable('rep_date_general') + shinyjs::enable('rep_operator_general') + shinyjs::enable('rep_institute_general') + shinyjs::enable('rep_comm_general') + shinyjs::enable('mst_date_general_select') + shinyjs::enable('mst_operator_general_select') + shinyjs::enable('mst_institute_general_select') + shinyjs::enable('mst_comm_general_select') + } + } + + if(!is.null(input$rep_analysis)) { + if(isFALSE(input$rep_analysis)) { + shinyjs::disable('rep_cgmlst_analysis') + shinyjs::disable('rep_tree_analysis') + shinyjs::disable('rep_distance') + shinyjs::disable('rep_missval') + shinyjs::disable('rep_version') + } else { + shinyjs::enable('rep_cgmlst_analysis') + shinyjs::enable('rep_tree_analysis') + shinyjs::enable('rep_distance') + shinyjs::enable('rep_missval') + shinyjs::enable('rep_version') + } + } + + if(length(input$select_rep_tab) > 0) { + updateCheckboxInput(session, "rep_entrytable", value = TRUE) + } else { + updateCheckboxInput(session, "rep_entrytable", value = FALSE) + } + }) + + ### Save Report ---- + + #### Get Report elements ---- + + observe({ + if(!is.null(DB$data)){ + if(!is.null(input$tree_algo)) { + req(c(input$rep_entrytable, input$rep_general, + input$rep_date_general, input$rep_operator_general, + input$rep_institute_general, input$rep_comm_general, + input$rep_analysis, input$rep_cgmlst_analysis, + input$rep_tree_analysis, input$rep_distance, + input$rep_missval, input$rep_version, + input$rep_plot_report, input$select_rep_tab)) + Report$report_df <- data.frame(Element = c("entry_table", "general_show", + "general_date", "operator", + "institute", "comment", + "analysis_show", "scheme", + "tree", "distance", "na_handling", "version", + "plot"), + Include = c(input$rep_entrytable, input$rep_general, + input$rep_date_general, input$rep_operator_general, + input$rep_institute_general, input$rep_comm_general, + input$rep_analysis, input$rep_cgmlst_analysis, + input$rep_tree_analysis, input$rep_distance, + input$rep_missval, input$rep_version, + input$rep_plot_report)) + } + } + }) + + #### Get Report values ---- + + observeEvent(input$create_tree, { + if(input$tree_algo == "Minimum-Spanning") { + Report$report_list_mst <- list(entry_table = DB$meta_true, + scheme = DB$schemeinfo, + tree = input$tree_algo, + na_handling = if(anyNA(DB$allelic_profile_true)){input$na_handling} else {NULL}, + distance = "Hamming Distances", + version = c(phylotraceVersion, "2.5.1"), + plot = "MST") + } else if(input$tree_algo == "Neighbour-Joining") { + Report$report_list_nj <- list(entry_table = DB$meta_true, + scheme = DB$schemeinfo, + tree = input$tree_algo, + na_handling = input$na_handling, + distance = "Hamming Distances", + version = c(phylotraceVersion, "2.5.1"), + plot = "NJ") + } else { + Report$report_list_upgma <- list(entry_table = DB$meta_true, + scheme = DB$schemeinfo, + tree = input$tree_algo, + na_handling = input$na_handling, + distance = "Hamming Distances", + version = c(phylotraceVersion, "2.5.1"), + plot = "UPGMA") + } + }) + + # Save plot for Report + plot.report <- reactive({ + if(input$tree_algo == "Neighbour-Joining") { + jpeg(paste0(getwd(), "/Report/NJ.jpeg"), width = (as.numeric(input$nj_scale) * as.numeric(input$nj_ratio)), height = as.numeric(input$nj_scale), quality = 100) + print(nj_tree()) + dev.off() + } else if(input$tree_algo == "UPGMA") { + jpeg(paste0(getwd(), "/Report/UPGMA.jpeg"), width = (as.numeric(input$upgma_scale) * as.numeric(input$upgma_ratio)), height = as.numeric(input$upgma_scale), quality = 100) + print(upgma_tree()) + dev.off() + } else if (input$tree_algo == "Minimum-Spanning") { + shinyjs::runjs("mstReport();") + decoded_data <- base64enc::base64decode(input$canvas_data) + writeBin(decoded_data, paste0(getwd(), "/Report/MST.jpg")) + } + }) + + #### Event Save Report ---- + output$download_report <- downloadHandler( + filename = function() { + if(input$tree_algo == "Minimum-Spanning") { + paste0("MST_Report_", Sys.Date(), ".html") + } else if(input$tree_algo == "Neighbour-Joining") { + paste0("NJ_Report_", Sys.Date(), ".html") + } else {paste0("UPGMA_Report_", Sys.Date(), ".html")} + }, + content = function(file) { + if(input$tree_algo == "Minimum-Spanning") { + plot.report() + + report <- c(Report$report_list_mst, + "general_date" = as.character(input$mst_date_general_select), + "operator" = input$mst_operator_general_select, + "institute" = input$mst_institute_general_select, + "comment" = input$mst_comm_general_select, + "report_df" = Report$report_df) + + report[["table_columns"]] <- input$select_rep_tab + + # Save data to an RDS file if any elements were selected + if (!is.null(report)) { + + log_print("Creating MST report") + + saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) + + rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) + + file.copy(paste0(getwd(), "/Report/Report.html"), file) + } else { + log_print("Creating MST report failed (report is null)") + } + } else if(input$tree_algo == "Neighbour-Joining") { + plot.report() + report <- c(Report$report_list_nj, + "general_date" = as.character(input$mst_date_general_select), + "operator" = input$mst_operator_general_select, + "institute" = input$mst_institute_general_select, + "comment" = input$mst_comm_general_select, + "report_df" = Report$report_df) + + report[["table_columns"]] <- input$select_rep_tab + + # Save data to an RDS file if any elements were selected + if (!is.null(report)) { + log_print("Creating NJ report") + + saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) + + rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) + + file.copy(paste0(getwd(), "/Report/Report.html"), file) + } else { + log_print("Creating NJ report failed (report is null)") + } + + } else { + plot.report() + report <- c(Report$report_list_upgma, + "general_date" = as.character(input$mst_date_general_select), + "operator" = input$mst_operator_general_select, + "institute" = input$mst_institute_general_select, + "comment" = input$mst_comm_general_select, + "report_df" = Report$report_df) + + report[["table_columns"]] <- input$select_rep_tab + + # Save data to an RDS file if any elements were selected + if (!is.null(report)) { + log_print("Creating UPGMA report") + + saveRDS(report, file = paste0(getwd(), "/Report/selected_elements.rds")) + + rmarkdown::render(paste0(getwd(), "/Report/Report.Rmd")) + + file.copy(paste0(getwd(), "/Report/Report.html"), file) + } else { + log_print("Creating UPGMA report failed (report is null)") + } + + } + removeModal() + } + ) + + + # _______________________ #### + + ## Gene Screening ---- + + ### Render UI Elements ---- + + # Rendering results table + output$gs_results_table <- renderUI({ + req(DB$data) + if(!is.null(Screening$selected_isolate)) { + if(length(Screening$selected_isolate) > 0) { + fluidRow( + div(class = "loci_table", + DT::dataTableOutput("gs_profile_table")), + br(), + HTML( + paste0("", + 'RSL = Reference Sequence Length  |  ', + '%CRS = % Coverage of Reference Sequence  |  ', + '%IRS = % Identity to Reference Sequence  |  ', + 'ACS = Accession of Closest Sequence  |  ', + 'NCS = Name of Closest Sequence') + + ) + ) + } else { + fluidRow( + br(), br(), + p( + HTML( + paste0("", + 'Select entry from the table to display resistance profile') + + ) + ) + ) + } + } else { + fluidRow( + br(), br(), + p( + HTML( + paste0("", + 'Select entry from the table to display resistance profile') + + ) + ) + ) + } + }) + + # Gene screening download button + output$gs_download <- renderUI({ + req(DB$data) + if(!is.null(Screening$selected_isolate)) { + if(length(Screening$selected_isolate) > 0) { + fluidRow( + downloadBttn( + "download_resistance_profile", + style = "simple", + label = "Profile Table", + size = "sm", + icon = icon("download"), + color = "primary" + ), + bsTooltip("download_resistance_profile_bttn", + HTML(paste0("Save resistance profile table for
", + Screening$selected_isolate)), + placement = "bottom", trigger = "hover") + ) + } else {NULL} + } else {NULL} + }) + + # Conditionally render table selectiom interface + output$gs_table_selection <- renderUI({ + req(DB$data, input$gs_view) + if(input$gs_view == "Table") { + fluidRow( + column(1), + column( + width = 10, + div(class = "loci_table", + dataTableOutput("gs_isolate_table")) + ) + ) + } else {NULL} + }) + + # Resistance profile table output display + output$gs_profile_display <- renderUI({ + req(DB$data) + if(!is.null(DB$meta_gs) & !is.null(input$gs_view)) { + if(input$gs_view == "Table") { + column( + width = 10, + hr(), + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) + ) + ), + column( + width = 4, + uiOutput("gs_download") + ) + ), + br(), + uiOutput("gs_results_table") + ) + } else { + column( + width = 10, + fluidRow( + column( + width = 4, + p( + HTML( + paste0("", + "Gene Screening Results
", + "", + "Comprising genes for resistance, virulence, stress, etc.") + ) + ) + ), + column( + width = 4, + div( + class = "gs-picker", + pickerInput( + "gs_profile_select", + "", + choices = list( + Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] + } + ), + choicesOpt = list( + disabled = c( + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) + ) + ), + options = list( + `live-search` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ) + ) + ) + ), + column( + width = 3, + uiOutput("gs_download") + ) + ), + br(), + uiOutput("gs_results_table") + ) + } + } else {NULL} + }) + + # Screening sidebar + output$screening_sidebar <- renderUI({ + req(DB$data) + if(!is.null(DB$meta_gs)) { + column( + width = 12, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Toggle View') + ) + ) + ), + radioGroupButtons( + inputId = "gs_view", + choices = c("Picker", "Table"), + selected = "Picker", + checkIcon = list( + yes = icon("square-check"), + no = icon("square") + ) + ), + br() + ) + } else {NULL} + }) + + # Resistance profile table + observe({ + req(DB$meta_gs, Screening$selected_isolate, DB$database, DB$scheme, DB$data) + + if(length(Screening$selected_isolate) > 0 & any(Screening$selected_isolate %in% DB$data$`Assembly ID`)) { + iso_select <- Screening$selected_isolate + iso_path <- file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", + iso_select, "resProfile.tsv") + + res_profile <- read.delim(iso_path) + + colnames(res_profile) <- c( + "Protein Identifier", "Contig ID", "Start", "Stop", "Strand", "Gene Symbol", + "Sequence Name", "Scope", "Element Type", "Element Subtype", "Class", + "Subclass", "Method", "Target Length", "RSL", "%CRS", "%IRS", + "Alignment Length", "ACS", "Name of Closest Sequence", "HMM ID", "HMM Description") + + Screening$res_profile <- res_profile %>% + relocate(c("Gene Symbol", "Sequence Name", "Element Subtype", "Class", + "Subclass", "Scope", "Contig ID", "Target Length", "Alignment Length", + "Start", "Stop", "Strand")) + + # Generate gene profile table + output$gs_profile_table <- DT::renderDataTable( + Screening$res_profile, + selection = "single", + rownames= FALSE, + options = list(pageLength = 10, scrollX = TRUE, + autoWidth = TRUE, + columnDefs = list(list(width = '400px', targets = c("Sequence Name", + "Name of Closest Sequence"))), + columnDefs = list(list(width = 'auto', targets = "_all")), + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + # "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + # "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + } else { + output$gs_profile_table <- NULL + } + }) + + #Resistance profile selection table + observe({ + req(DB$meta, DB$data) + output$gs_isolate_table <- renderDataTable( + select(DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ], -c(3, 4, 10, 11, 12)), + selection = "single", + rownames= FALSE, + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + )) + ) + }) + + observe({ + req(input$screening_res_sel, DB$database, DB$scheme, DB$data) + if(!is.null(Screening$status_df) & + !is.null(input$screening_res_sel) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate)) { + if(length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + results <- read.delim(file.path(DB$database, gsub(" ", "_", DB$scheme), "Isolates", + input$screening_res_sel, "resProfile.tsv")) + + output$screening_table <- renderDataTable( + select(results, c(6, 7, 8, 9, 11)), + selection = "single", + options = list(pageLength = 10, + columnDefs = list(list(searchable = TRUE, + targets = "_all")), + initComplete = DT::JS( + "function(settings, json) {", + "$('th:first-child').css({'border-top-left-radius': '5px'});", + "$('th:last-child').css({'border-top-right-radius': '5px'});", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ), + drawCallback = DT::JS( + "function(settings) {", + "$('tbody tr:last-child td:first-child').css({'border-bottom-left-radius': '5px'});", + "$('tbody tr:last-child td:last-child').css({'border-bottom-right-radius': '5px'});", + "}" + ))) + } else {output$screening_table <- NULL} + } + } else { + output$screening_table <- NULL + } + } else { + output$screening_table <- NULL + } + + }) + + # Availablity feedback + output$gene_screening_info <- renderUI({ + req(DB$data) + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } else { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } + }) + + output$gene_resistance_info <- renderUI({ + req(DB$data) + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, "available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } else { + p( + HTML( + paste( + '', + tags$span(style="color: white; font-size: 15px; position:relative; top:25px", + paste(DB$scheme, " not available for gene screening with NCBI/AMRFinder.")) + ) + ) + ) + } + }) + + # Screening Interface + + output$screening_interface <- renderUI({ + req(DB$data) + if(gsub(" ", "_", DB$scheme) %in% amrfinder_species) { + column( + width = 12, + fluidRow( + column(1), + column( + width = 3, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px', 'Select Isolates for Screening') + ) + ) + ), + if(Screening$picker_status) { + div( + class = "screening_div", + pickerInput( + "screening_select", + "", + choices = list( + Unscreened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + Screened = if (length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] + } + ), + choicesOpt = list( + disabled = c( + rep(FALSE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "No")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")])), + rep(TRUE, length(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")])) + ) + ), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + } else { + div( + class = "screening_div", + pickerInput( + "screening_select", + "", + choices = Screening$picker_choices, + selected = Screening$picker_selected, + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + multiple = TRUE + ) + ) + }, + br(), br(), + uiOutput("genome_path_gs") + ), + column( + width = 3, + uiOutput("screening_start") + ), + column( + width = 3, + align = "center", + br(), br(), + uiOutput("screening_result_sel") + ), + column(1) + ), + fluidRow( + column(1), + column( + width = 10, + br(), br(), + uiOutput("screening_result"), + br(), br(), br(), br() + ) + ) + ) + } + }) + + ### Screening Events ---- + + observe({ + req(DB$data, input$gs_view) + if(input$gs_view == "Table") { + meta_gs <- DB$meta_gs[which(DB$meta_gs$Screened == "Yes"), ] + Screening$selected_isolate <- meta_gs$`Assembly ID`[input$gs_isolate_table_rows_selected] + } else if(input$gs_view == "Picker") { + Screening$selected_isolate <- input$gs_profile_select + } + }) + + output$download_resistance_profile <- downloadHandler( + filename = function() { + log_print(paste0("Save resistance profile table ", Screening$selected_isolate, "_Profile.csv")) + + paste0(format(Sys.Date()), "_", Screening$selected_isolate, "_Profile.csv") + }, + content = function(file) { + write.table( + Screening$res_profile, + file, + sep = ";", + row.names = FALSE, + quote = FALSE + ) + } + ) + + # Reset screening + observeEvent(input$screening_reset_bttn, { + log_print("Reset gene screening") + + # reset status file + sapply(Screening$status_df$isolate, remove.screening.status) + + # set feedback variables + Screening$status <- "idle" + Screening$status_df <- NULL + Screening$choices <- NULL + Screening$picker_status <- TRUE + Screening$first_result <- NULL + + # change reactive UI + output$screening_table <- NULL + output$screening_result <- NULL + output$screening_fail <- NULL + + updatePickerInput(session, "screening_select", selected = character(0)) + + # disable isolate picker + shinyjs::runjs("$('#screening_select').prop('disabled', false);") + shinyjs::runjs("$('#screening_select').selectpicker('refresh');") + }) + + # Cancel screening + observeEvent(input$screening_cancel, { + showModal( + modalDialog( + paste0( + "Gene screening is still pending. Stopping this process will cancel the screening." + ), + title = "Reset Multi Typing", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_screening_cancel", "Stop", class = "btn btn-danger") + ) + ) + ) + }) + + observeEvent(input$conf_screening_cancel, { + log_print("Cancelled gene screening") + removeModal() + + show_toast( + title = "Gene Screening Terminated", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + + # terminate screening + system(paste("kill $(pgrep -f 'execute/screening.sh')"), wait = FALSE) + system(paste("killall -TERM tblastn"), wait = FALSE) + + # reset status file + sapply(Screening$status_df$isolate, remove.screening.status) + + # set feedback variables + Screening$status <- "idle" + Screening$status_df <- NULL + Screening$choices <- NULL + Screening$picker_status <- TRUE + Screening$first_result <- NULL + + # change reactive UI + output$screening_table <- NULL + output$screening_result <- NULL + + updatePickerInput(session, "screening_select", selected = character(0)) + + # disable isolate picker + shinyjs::runjs("$('#screening_select').prop('disabled', false);") + shinyjs::runjs("$('#screening_select').selectpicker('refresh');") + }) + + # Get selected assembly + observe({ + req(DB$data, Screening$status) + if (length(input$screening_select) < 1) { + output$genome_path_gs <- renderUI(HTML( + paste("", length(input$screening_select), " isolate(s) queried for screening") + )) + + output$screening_start <- NULL + + } else if (length(input$screening_select) > 0) { + + output$screening_start <- renderUI({ + + fluidRow( + column( + width = 12, + br(), br(), + if(length(input$screening_select) < 1) { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Select Isolate(s) for Screening"))) + ) + ) + } else if(Screening$status == "finished") { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Reset to Perform Screening Again"))) + ), + actionButton( + "screening_reset_bttn", + "Reset", + icon = icon("arrows-rotate") + ), + if(!is.null(Screening$status_df)) { + p( + HTML(paste("", + sum(Screening$status_df$status != "unfinished"), "/", + nrow(Screening$status_df), " Isolate(s) screened")) + ) + } + ) + } else if(Screening$status == "idle") { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Screening Ready"))) + ), + actionButton( + inputId = "screening_start_button", + label = "Start", + icon = icon("circle-play") + ) + ) + } else if(Screening$status == "started") { + column( + width = 12, + align = "center", + p( + HTML(paste( + '', + paste("", + "  Running Screening ..."))) + ), + fluidRow( + column(3), + column( + width = 3, + actionButton( + inputId = "screening_cancel", + label = "Terminate", + icon = icon("ban") + ) + ), + column( + width = 3, + HTML(paste('')) + ) + ), + if(!is.null(Screening$status_df)) { + p( + HTML(paste("", + sum(Screening$status_df$status != "unfinished"), "/", + nrow(Screening$status_df), " isolate(s) screened")) + ) + } + ) + } + ) + ) + }) + } else {NULL} + }) + + #### Running Screening ---- + + observeEvent(input$screening_start_button, { + + if(tail(readLogFile(), 1) != "0") { + show_toast( + title = "Pending Multi Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + log_print("Started gene screening") + + Screening$status <- "started" + Screening$picker_choices <- list( + Unscreened = if (sum(DB$data$Screened == "No") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "No")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "No")] + }, + Screened = if (sum(DB$data$Screened == "Yes") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "Yes")] + }, + `No Assembly File` = if (sum(DB$data$Screened == "NA") == 1) { + as.list(DB$data$`Assembly ID`[which(DB$data$Screened == "NA")]) + } else { + DB$data$`Assembly ID`[which(DB$data$Screened == "NA")] + } + ) + Screening$picker_selected <- input$screening_select + Screening$picker_status <- FALSE + + show_toast( + title = "Gene screening started", + type = "success", + position = "bottom-end", + timer = 6000 + ) + + Screening$meta_df <- data.frame(wd = getwd(), + selected = paste( + file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_select, + paste0(input$screening_select, ".zip")), + collapse = " "), + species = gsub(" ", "_", DB$scheme)) + + Screening$status_df <- data.frame(isolate = basename(gsub(".zip", "", str_split_1(Screening$meta_df$selected, " "))), + status = "unfinished") + + # Reset screening status + sapply(Screening$status_df$isolate, remove.screening.status) + + saveRDS(Screening$meta_df, paste0(getwd(), "/execute/screening_meta.rds")) + + # Disable pickerInput + shinyjs::delay(200, shinyjs::runjs("$('#screening_select').prop('disabled', true);")) + shinyjs::delay(200, shinyjs::runjs("$('#screening_select').selectpicker('refresh');")) + + # System execution screening.sh + system(paste("bash", paste0(getwd(), "/execute/screening.sh")), wait = FALSE) + } + }) + + observe({ + req(DB$data, Screening$status, input$screening_res_sel, Screening$status_df) + if(!is.null(Screening$status_df) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate) & + !is.null(input$screening_res_sel)) { + if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "success") { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + dataTableOutput("screening_table") + ) + ) + } else { + output$screening_result <- renderUI( + column( + width = 12, + hr(), br(), + verbatimTextOutput("screening_fail") + ) + ) + } + } + } else { + output$screening_result <- NULL + } + } else { + output$screening_result <- NULL + } + }) + + observe({ + req(DB$data, Screening$status, input$screening_res_sel) + if(!is.null(Screening$status_df) & + !is.null(Screening$status_df$status) & + !is.null(Screening$status_df$isolate) & + !is.null(input$screening_res_sel)) { + if(Screening$status != "idle" & length(input$screening_res_sel) > 0) { + if(any(Screening$status_df$isolate == input$screening_res_sel)) { + if(Screening$status_df$status[which(Screening$status_df$isolate == input$screening_res_sel)] == "fail") { + output$screening_fail <- renderPrint({ + cat(paste(readLines(file.path(DB$database, gsub(" ", "_", DB$scheme), + "Isolates", input$screening_res_sel, "status.txt")),"\n")) + }) + } + } + } else { + output$screening_fail <- NULL + } + } else { + output$screening_fail <- NULL + } + }) + + observe({ + req(DB$data) + if(!is.null(Screening$status)) { + if(Screening$status != "idle") { + + # start status screening for user feedback + check_screening() + + if(isTRUE(Screening$first_result)) { + output$screening_result_sel <- renderUI( + column( + width = 12, + align = "center", + selectInput( + "screening_res_sel", + label = h5("Select Result", style = "color:white; margin-bottom: 28px; margin-top: -10px;"), + choices = "" + ), + if(!is.null(Screening$status_df)) { + p(HTML(paste("", + if(sum(Screening$status_df$status == "success") == 1) { + "1 success   /  " + } else { + paste0(sum(Screening$status_df$status == "success"), " successes   /  ") + }, + if(sum(Screening$status_df$status == "fail") == 1) { + "1 failure" + } else { + paste0(sum(Screening$status_df$status == "fail"), " failures") + }))) + } + ) + ) + + Screening$first_result <- FALSE + } + } else if(Screening$status == "idle") { + output$screening_result_sel <- NULL + } + } + }) + + check_screening <- reactive({ + invalidateLater(500, session) + + req(Screening$status_df) + + if(Screening$status == "started") { + + Screening$status_df$status <- sapply(Screening$status_df$isolate, check_status) + + if(any("unfinished" != Screening$status_df$status) & + !identical(Screening$choices, Screening$status_df$isolate[which(Screening$status_df$status != "unfinished")])) { + + status_df <- Screening$status_df[which(Screening$status_df$status != "unfinished"),] + + Screening$choices <- Screening$status_df$isolate[which(Screening$status_df$status == "success" | + Screening$status_df$status == "fail")] + + if(sum(Screening$status_df$status != "unfinished") > 0) { + if(is.null(Screening$first_result)) { + Screening$first_result <- TRUE + } + } + + if(tail(status_df$status, 1) == "success") { + + # Changing "Screened" metadata variable in database + Database <- readRDS(file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + Database[["Typing"]]$Screened[which(Database[["Typing"]]["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + + saveRDS(Database, file.path(DB$database, gsub(" ", "_", DB$scheme), "Typing.rds")) + + DB$data$Screened[which(DB$data["Assembly ID"] == tail(Screening$choices, 1))] <- "Yes" + + DB$meta_gs <- select(DB$data, c(1, 3:13)) + DB$meta <- select(DB$data, 1:(13 + nrow(DB$cust_var))) + DB$meta_true <- DB$meta[which(DB$data$Include == TRUE),] + + show_toast( + title = paste("Successful screening of", tail(Screening$choices, 1)), + type = "success", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + + } else if(tail(status_df$status, 1) == "fail") { + + show_toast( + title = paste("Failed screening of", tail(status_df$isolate, 1)), + type = "error", + position = "bottom-end", + timer = 6000) + + updateSelectInput(session = session, + inputId = "screening_res_sel", + choices = Screening$choices, + selected = tail(Screening$choices, 1)) + } + + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } else { + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } + + if(sum("unfinished" != Screening$status_df$status) == length(Screening$status_df$status)) { + Screening$status <- "finished" + } + } + }) + + + # _______________________ #### + + ## Typing ---- + + # Render Single/Multi Switch + + readLogFile <- reactive({ + invalidateLater(5000, session) + readLines(paste0(getwd(), "/logs/script_log.txt")) + }) + + # Render sidebar dependent on data presence + # No sidebar + output$typing_sidebar <- renderUI({ + if(!is.null(DB$exist)) { + if(DB$exist) { + NULL + } else { + column( + width = 12, + align = "center", + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 18px; margin-bottom: 0px', 'Typing Mode') + ) + ) + ), + radioGroupButtons( + inputId = "typing_mode", + choices = c("Single", "Multi"), + selected = "Single", + checkIcon = list( + yes = icon("square-check"), + no = icon("square") + ) + ), + br() + ) + } + } + + }) + + # No db typing message + output$typing_no_db <- renderUI({ + if(!is.null(DB$exist)) { + if(DB$exist) { + column( + width = 4, + align = "left", + br(), + br(), + br(), + br(), + p( + HTML( + paste0( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 50px', 'To initiate allelic typing, a cgMLST scheme must be downloaded first.' + ) + ) + ) + ) + ) + } else {NULL} + } else {NULL} + }) + + ### Single Typing ---- + + #### Render UI Elements ---- + + # Render single typing naming issues + output$single_select_issues <- renderUI({ + req(input$assembly_id) + + if(nchar(trimws(input$assembly_id)) < 1) { + ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) + } else { + ass_id <- trimws(input$assembly_id) + } + + if(ass_id %in% unlist(DB$data["Assembly ID"])) { + HTML(paste( + '', + paste("", + "  Assembly ID already present in database."))) + } else if (ass_id == "") { + HTML(paste( + '', + paste("", + "  Empty Assembly ID."))) + } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { + HTML(paste( + '', + paste("", + "  Invalid Assembly ID. Avoid special characters."))) + } else if(grepl(" ", ass_id)) { + HTML(paste( + '', + paste("", + "  Invalid Assembly ID. Avoid empty spaces."))) + } else {HTML(paste( + '', + paste("", + "  Assembly ID compatible with local database.")))} + }) + + # Render Typing Results if finished + observe({ + if(Typing$progress_format_end == 999999) { + if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { + if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { + output$typing_result_table <- renderRHandsontable({ + Typing$typing_result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) + Typing$typing_result_table <- mutate_all(Typing$typing_result_table, as.character) + if(nrow(Typing$typing_result_table) > 0) { + if(nrow(Typing$typing_result_table) > 15) { + rhandsontable(Typing$typing_result_table, rowHeaders = NULL, + stretchH = "all", height = 500, readOnly = TRUE, + contextMenu = FALSE) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + } else { + rhandsontable(Typing$typing_result_table, rowHeaders = NULL, + stretchH = "all", readOnly = TRUE, + contextMenu = FALSE,) %>% + hot_cols(columnSorting = TRUE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:ncol(Typing$typing_result_table), valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + } + } + }) + + output$single_typing_results <- renderUI({ + result_table <- readRDS(paste0(getwd(), "/execute/event_df.rds")) + number_events <- nrow(result_table) + + n_new <- length(grep("New Variant", result_table$Event)) + + n_missing <- number_events - n_new + + # Show results table only if successful typing + if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { + if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { + if(number_events > 0) { + column( + width = 12, + HTML(paste("", + length(Typing$scheme_loci_f) - number_events, + "loci were assigned a variant from local scheme.")), + br(), + HTML(paste("", + n_missing, + if(n_missing == 1) " locus not assigned (NA)." else " loci not assigned (NA).")), + br(), + HTML(paste("", + n_new, + if(n_new == 1) " locus with new variant." else " loci with new variants.")), + br(), br(), + rHandsontableOutput("typing_result_table") + ) + } else { + column( + width = 12, + HTML(paste("", + length(Typing$scheme_loci_f), + "successfully assigned from local scheme.")) + ) + } + } + } + }) + + } else { + + output$single_typing_results <- NULL + + } + } else { + output$single_typing_results <- NULL + } + } + + }) + + # Render Initiate Typing UI + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + + # Render Declare Metadata UI + + observe({ + if (nrow(Typing$single_path) < 1) { + output$genome_path <- renderUI(HTML( + paste("", "No file selected.") + )) + + # dont show subsequent metadata declaration and typing start UI + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + } else if (nrow(Typing$single_path) > 0) { + + if (str_detect(str_sub(Typing$single_path$name, start = -6), ".fasta") | + str_detect(str_sub(Typing$single_path$name, start = -6), ".fna") | + str_detect(str_sub(Typing$single_path$name, start = -6), ".fa")) { + + # Render selected assembly path + output$genome_path <- renderUI({ + HTML( + paste( + "", + as.character(Typing$single_path$name) + ) + ) + }) + + # Render metadata declaration box + output$metadata_single_box <- renderUI({ + + # Render placeholder + updateTextInput(session, "assembly_id", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) + updateTextInput(session, "assembly_name", value = as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name)))) + + column( + width = 3, + align = "center", + br(), br(), + h3(p("Declare Metadata"), style = "color:white; margin-left:-40px"), + br(), br(), + div( + class = "multi_meta_box", + box( + solidHeader = TRUE, + status = "primary", + width = "90%", + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("assembly_id", + value = "", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 12, + uiOutput("single_select_issues") + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("assembly_name", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + dateInput("append_isodate", + label = "", + width = "80%", + max = Sys.Date()) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_host", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table_country", + pickerInput( + "append_country", + label = "", + choices = list("Common" = sel_countries, + "All Countries" = country_names), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "90%" + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput( + "append_city", + label = "", + width = "80%" + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + actionButton( + inputId = "conf_meta_single", + label = "Confirm" + ), + br() + ) + ), + br() + ) + ) + ) + }) + } else { + show_toast( + title = "Wrong file type (only fasta/fna/fa)", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + } + }) + + # Get genome datapath + + observe({ + # Get selected Genome in Single Mode + shinyFileChoose(input, + "genome_file", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + Typing$single_path <- parseFilePaths(roots = c(Home = path_home(), Root = "/"), input$genome_file) + + }) + + #### Run blat ---- + + observeEvent(input$typing_start, { + + log_print("Input typing_start") + + if(tail(readLogFile(), 1) != "0") { + show_toast( + title = "Pending Multi Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if (Screening$status == "started") { + show_toast( + title = "Pending Gene Screening", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + if(!is.null(DB$data)) { + if(sum(apply(DB$data, 1, anyNA)) >= 1) { + DB$no_na_switch <- TRUE + } else { + DB$no_na_switch <- FALSE + } + } + + # Activate entry detection + DB$check_new_entries <- TRUE + + Typing$single_end <- FALSE + + Typing$progress_format_start <- 0 + Typing$progress_format_end <- 0 + + # Remove Initiate Typing UI + output$initiate_typing_ui <- NULL + output$metadata_single_box <- NULL + output$start_typing_ui <- NULL + + # status feedback + Typing$status <- "Processing" + + # Locate folder containing cgMLST scheme + search_string <- paste0(gsub(" ", "_", DB$scheme), "_alleles") + + scheme_folders <- dir_ls(paste0(DB$database, "/", gsub(" ", "_", DB$scheme))) + + if (any(grepl(search_string, scheme_folders))) { + + # reset results file + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + } + + # blat initiate index + scheme_select <- as.character(scheme_folders[which(grepl(search_string, scheme_folders))]) + + show_toast( + title = "Typing Initiated", + type = "success", + position = "bottom-end", + timer = 6000 + ) + + log_print("Initiated single typing") + + ### Run blat Typing + + single_typing_df <- data.frame( + db_path = DB$database, + wd = getwd(), + save = input$save_assembly_st, + scheme = paste0(gsub(" ", "_", DB$scheme)), + genome = Typing$single_path$datapath, + alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", search_string) + ) + + saveRDS(single_typing_df, "execute/single_typing_df.rds") + + # Execute single typing script + system(paste("bash", paste0(getwd(), "/execute/single_typing.sh")), + wait = FALSE) + + scheme_loci <- list.files(path = scheme_select, full.names = TRUE) + + # Filter the files that have FASTA extensions + Typing$scheme_loci_f <- + scheme_loci[grep("\\.(fasta|fa|fna)$", scheme_loci, ignore.case = TRUE)] + + output$single_typing_progress <- renderUI({ + fluidRow( + br(), br(), + column(width = 1), + column( + width = 3, + h3(p("Pending Single Typing ..."), style = "color:white") + ), + br(), br(), br(), + fluidRow( + column(width = 1), + column( + width = 4, + br(), br(), br(), + fluidRow( + column( + width = 12, + uiOutput("reset_single_typing"), + HTML( + paste( + "", + as.character(Typing$single_path$name) + ) + ), + br(), br(), + progressBar( + "progress_bar", + value = 0, + display_pct = TRUE, + title = "" + ) + ) + ), + fluidRow( + column( + width = 12, + uiOutput("typing_formatting"), + uiOutput("typing_fin") + ) + ) + ), + column(1), + column( + width = 5, + br(), br(), br(), + uiOutput("single_typing_results") + ) + ) + ) + }) + } else { + log_print("Folder containing cgMLST alleles not in working directory") + + show_alert( + title = "Error", + text = paste0( + "Folder containing cgMLST alleles not in working directory.", + "\n", + "Download cgMLST Scheme for selected Organism first." + ), + type = "error" + ) + } + } + }) + + # Function to update Progress Bar + update <- reactive({ + invalidateLater(3000, session) + + # write progress in process tracker + cat( + c(length(list.files(paste0(getwd(), "/execute/blat_single/results"))), + readLines(paste0(getwd(), "/logs/progress.txt"))[-1]), + file = paste0(getwd(), "/logs/progress.txt"), + sep = "\n" + ) + + progress <- readLines(paste0(getwd(), "/logs/progress.txt")) + + # if typing with blat is finished -> "attaching" phase started + if(!is.na(progress[1])) { + if(!is.na(progress[2])) { + if(progress[2] == "888888") { + Typing$progress_format_start <- progress[2] + Typing$pending_format <- progress[2] + Typing$status <- "Attaching" + } + } + # "attaching" phase completed + if(!is.na(progress[3])) { + if(progress[3] == "999999") { + Typing$progress_format_end <- progress[3] + Typing$entry_added <- progress[3] + Typing$status <- "Finalized" + } + } + Typing$progress <- as.numeric(progress[1]) + floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) + } else { + floor((Typing$progress / length(Typing$scheme_loci_f)) * 100) + } + }) + + # Observe Typing Progress + observe({ + + if(readLogFile()[1] == "0") { + # Update Progress Bar + updateProgressBar( + session = session, + id = "progress_bar", + value = update(), + total = 100, + title = paste0(as.character(Typing$progress), "/", length(Typing$scheme_loci_f), " loci screened") + ) + } + + if (Typing$progress_format_start == 888888) { + output$typing_formatting <- renderUI({ + column( + width = 12, + align = "center", + br(), + fluidRow( + column( + width = 6, + HTML(paste("", "Transforming data ...")) + ), + column( + width = 3, + align = "left", + HTML(paste('')) + ) + ) + ) + }) + } else { + output$typing_formatting <- NULL + } + + # Render when finalized + if (Typing$progress_format_end == 999999) { + + output$typing_formatting <- NULL + + output$typing_fin <- renderUI({ + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + if(file.exists(paste0(getwd(),"/logs/single_typing_log.txt"))) { + if(str_detect(tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1), "Successful")) { + req(Typing$scheme_loci_f, Typing$typing_result_table) + if(sum(Typing$typing_result_table$Event != "New Variant") > (0.5 * length(Typing$scheme_loci_f))){ + HTML( + paste("", + sub(".*Successful", "Finished", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + paste("", "Warning: Isolate contains large number of failed allele assignments."), + paste("", "Reset to start another typing process."), + sep = '
\n')) + } else { + HTML(paste("", + sub(".*Successful", "Successful", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + "Reset to start another typing process.", sep = '
')) + } + } else { + HTML(paste("", + sub(".*typing", "Typing", tail(readLines(paste0(getwd(),"/logs/single_typing_log.txt")), 1)), + "Reset to start another typing process.", sep = '
')) + } + }, + br(), br(), + actionButton( + "reset_single_typing", + "Reset", + icon = icon("arrows-rotate") + ) + ) + ) + }) + } else { + output$typing_fin <- NULL + output$single_typing_results <- NULL + } + + }) + + #### Declare Metadata ---- + + observeEvent(input$conf_meta_single, { + + if(nchar(trimws(input$assembly_id)) < 1) { + ass_id <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) + } else { + ass_id <- trimws(input$assembly_id) + } + + if(nchar(trimws(input$assembly_name)) < 1) { + ass_name <- as.character(gsub("\\.fasta|\\.fna|\\.fa", "", basename(Typing$single_path$name))) + } else { + ass_name <- trimws(input$assembly_name) + } + + if(ass_id %in% unlist(DB$data["Assembly ID"])) { + show_toast( + title = "Assembly ID already present", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (isFALSE(Typing$reload)) { + show_toast( + title = "Reload Database first", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if (ass_id == "") { + show_toast( + title = "Empty Assembly ID", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (grepl("[()/\\:*?\"<>|]", ass_id)) { + show_toast( + title = "Invalid Assembly ID. No special characters allowed: ()/\\:*?\"<>|", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if(grepl(" ", ass_id)) { + show_toast( + title = "Empty spaces in Assembly ID not allowed", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + log_print("Single typing metadata confirmed") + + meta_info <- data.frame(assembly_id = ass_id, + assembly_name = ass_name, + cgmlst_typing = DB$scheme, + append_isodate = input$append_isodate, + append_host = trimws(input$append_host), + append_country = trimws(input$append_country), + append_city = trimws(input$append_city), + append_analysisdate = Sys.Date(), + db_directory = getwd()) + + saveRDS(meta_info, paste0( + getwd(), + "/execute/meta_info_single.rds" + )) + + show_toast( + title = "Metadata declared", + type = "success", + position = "bottom-end", + timer = 3000 + ) + + # Render Start Typing UI + output$start_typing_ui <- renderUI({ + div( + class = "multi_start_col", + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Start Typing"), style = "color:white"), + br(), + br(), + HTML( + paste( + "", + "Typing by ", + DB$scheme, + " scheme." + ) + ), + br(), br(), br(), br(), + div( + class = "save-assembly", + materialSwitch( + "save_assembly_st", + h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), + value = TRUE, + right = TRUE) + ), + HTML( + paste( + "", + "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." + ) + ), + br(), br(), br(), br(), + actionButton( + inputId = "typing_start", + label = "Start", + icon = icon("circle-play") + ) + ) + ) + }) + } + }) + + #### Events Single Typing ---- + + observeEvent(input$reset_single_typing, { + log_print("Reset single typing") + + Typing$status <- "Inactive" + + Typing$progress <- 0 + + Typing$progress_format <- 900000 + + output$single_typing_progress <- NULL + + output$typing_fin <- NULL + + output$single_typing_results <- NULL + + output$typing_formatting <- NULL + + Typing$single_path <- data.frame() + + # reset results file + if(dir_exists(paste0(getwd(), "/execute/blat_single/results"))) { + unlink(list.files(paste0(getwd(), "/execute/blat_single/results"), full.names = TRUE), recursive = TRUE) + # Resetting single typing progress logfile bar + con <- file(paste0(getwd(), "/logs/progress.txt"), open = "w") + + cat("0\n", file = con) + + close(con) + } + + output$initiate_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), + br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly File (FASTA)') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyFilesButton( + "genome_file", + "Browse" , + icon = icon("file"), + title = "Select the assembly in .fasta/.fna/.fa format:", + multiple = FALSE, + buttonType = "default", + class = NULL, + root = path_home() + ), + br(), + br(), + uiOutput("genome_path"), + br() + ) + ) + ) + }) + }) + + # Notification for finalized Single typing + Typing$single_end <- TRUE + Typing$progress_format_end <- 0 + + observe({ + if(Typing$single_end == FALSE) { + if (Typing$progress_format_end == 999999) { + show_toast( + title = "Single Typing finalized", + type = "success", + position = "bottom-end", + timer = 8000 + ) + Typing$single_end <- TRUE + } + } + }) + + ### Multi Typing ---- + + #### Render Multi Typing UI Elements ---- + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + # Render selection info + output$multi_select_info <- renderUI({ + + if(!is.null(Typing$multi_path)) { + if(length(Typing$multi_path) < 1) { + HTML(paste("", + "No files selected.")) + } else { + HTML(paste("", + sum(hot_to_r(input$multi_select_table)$Include == TRUE), + " files selected.")) + } + } + }) + + # Render multi selection table issues + output$multi_select_issues <- renderUI({ + req(Typing$multi_sel_table, input$multi_select_table) + if(any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & + any(duplicated(hot_to_r(input$multi_select_table)$Files))){ + HTML( + paste( + paste("", + "Some name(s) are already present in local database.
"), + paste("", + "Duplicated name(s).
") + ) + ) + } else if (any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & + !any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + HTML( + paste("", + "Some name(s) are already present in local database.
") + ) + } else if (!any(hot_to_r(input$multi_select_table)$Files %in% dupl_mult_id()) & + any(duplicated(hot_to_r(input$multi_select_table)$Files))) { + HTML( + paste("", + "Duplicated name(s).
") + ) + } + }) + + output$multi_select_issue_info <- renderUI({ + req(Typing$multi_sel_table, input$multi_select_table) + + multi_select_table <- hot_to_r(input$multi_select_table) + + if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | + any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)])) | + any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + + if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + + if(any(multi_select_table$Files[which(multi_select_table$Include == TRUE)] %in% dupl_mult_id()) | + any(duplicated(multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + HTML(paste( + paste( + '', + paste("", + " Rename highlighted isolates or deselect them.
")), + paste( + '', + paste("", + " Filename(s) contain(s) empty spaces.")) + )) + } else { + HTML(paste( + '', + paste("", + " Filename(s) contain(s) empty spaces."))) + } + } else { + HTML(paste( + '', + paste("", + " Rename highlighted isolates or deselect them."))) + } + } else { + HTML(paste( + '', + paste("", + " Files ready for allelic typing."))) + } + }) + + # Render Metadata Select Box after Folder selection + observe({ + if(!is.null(Typing$multi_sel_table)) { + if (nrow(Typing$multi_sel_table) > 0) { + + output$multi_select_tab_ctrls <- renderUI( + fluidRow( + column(1), + column( + width = 2, + align = "left", + actionButton( + "sel_all_mt", + "All", + icon = icon("check") + ) + ), + column( + width = 2, + align = "left", + actionButton( + "desel_all_mt", + "None", + icon = icon("xmark") + ) + ), + column(2), + column( + width = 5, + align = "right", + br(), + uiOutput("multi_select_issues") + ) + ) + ) + + output$metadata_multi_box <- renderUI({ + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Declare Metadata"), style = "color:white;margin-left:-40px"), + br(), br(), + div( + class = "multi_meta_box", + box( + solidHeader = TRUE, + status = "primary", + width = "90%", + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly ID", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Assembly Name", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5("Assembly filename", style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Isolation Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + dateInput("append_isodate_multi", + label = "", + width = "80%", + max = Sys.Date()) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Host", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_host_multi", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Country", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table_country", + pickerInput( + "append_country_multi", + label = "", + choices = list("Common" = sel_countries, + "All Countries" = country_names), + options = list( + `live-search` = TRUE, + `actions-box` = TRUE, + size = 10, + style = "background-color: white; border-radius: 5px;" + ), + width = "90%" + ) + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("City", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + div( + class = "append_table", + textInput("append_city_multi", + label = "", + width = "80%") + ) + ) + ), + fluidRow( + column( + width = 5, + align = "left", + h5("Typing Date", style = "color:white; margin-top: 30px; margin-left: 15px") + ), + column( + width = 7, + align = "left", + h5(paste0(" ", Sys.Date()), style = "color:white; margin-top: 30px; margin-left: 5px; font-style: italic") + ) + ), + fluidRow( + column( + width = 12, + align = "center", + br(), br(), + actionButton( + inputId = "conf_meta_multi", + label = "Confirm" + ), + br(), br(), + uiOutput("multi_select_issue_info") + ) + ) + ) + ) + ) + }) + } else { + output$metadata_multi_box <- NULL + } + } + }) + + # Check if ongoing Multi Typing - Render accordingly + observe({ + # Get selected Genome in Multi Mode + shinyDirChoose(input, + "genome_file_multi", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + + Typing$multi_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi) + + files_selected <- list.files(as.character(Typing$multi_path)) + Typing$files_filtered <- files_selected[which(!endsWith(files_selected, ".gz") & + grepl("\\.fasta|\\.fna|\\.fa", files_selected))] + + Typing$multi_sel_table <- data.frame( + Include = rep(TRUE, length(Typing$files_filtered)), + Files = gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", + Typing$files_filtered), + Type = sub(".*(\\.fasta|\\.fasta\\.gz|\\.fna|\\.fna\\.gz|\\.fa|\\.fa\\.gz)$", + "\\1", Typing$files_filtered, perl = F)) + + if(nrow(Typing$multi_sel_table) > 0) { + output$multi_select_tab_ctrls <- renderUI( + fluidRow( + column(1), + column( + width = 2, + align = "left", + actionButton( + "sel_all_mt", + "All", + icon = icon("check") + ) + ), + column( + width = 2, + align = "left", + actionButton( + "desel_all_mt", + "None", + icon = icon("xmark") + ) + ), + column(2), + column( + width = 5, + align = "right", + br(), + uiOutput("multi_select_issues") + ) + ) + ) + } else { + output$multi_select_tab_ctrls <- NULL + } + + if(between(nrow(Typing$multi_sel_table), 1, 15)) { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", contextMenu = FALSE + ) %>% + hot_cols(columnSorting = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()))) + }) + + } else if(nrow(Typing$multi_sel_table) > 15) { + output$multi_select_table <- renderRHandsontable({ + rht <- rhandsontable(Typing$multi_sel_table, rowHeaders = NULL, + stretchH = "all", height = 500, + contextMenu = FALSE + ) %>% + hot_cols(columnSorting = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(2, + readOnly = FALSE, + valign = "htBottom") %>% + hot_col(3, readOnly = TRUE) %>% + hot_col(1, + halign = "htCenter", + valign = "htTop", + colWidths = 60) + + htmlwidgets::onRender(rht, sprintf( + "function(el, x) { + var hot = this.hot; + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + var highlightInvalidAndDuplicates = function(invalidValues) { + + var columnData = hot.getDataAtCol(1); // Change column index if needed + var duplicates = {}; + + // Find all duplicate values + for (var i = 0; i < columnData.length; i++) { + var value = columnData[i]; + if (value !== null && value !== undefined) { + if (duplicates[value]) { + duplicates[value].push(i); + } else { + duplicates[value] = [i]; + } + } + } + + // Reset all cell backgrounds in the column + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + if (cell) { + cell.style.background = 'white'; + } + } + + // Highlight duplicates and invalid values + for (var i = 0; i < columnData.length; i++) { + var cell = hot.getCell(i, 1); // Change column index if needed + var value = columnData[i]; + if (cell) { + if (invalidValues.includes(value)) { + cell.style.background = 'rgb(224, 179, 0)'; // Highlight color for invalid values + } else if (duplicates[value] && duplicates[value].length > 1) { + cell.style.background = '#FF7334'; // Highlight color for duplicates + } + } + } + }; + + var changefn = function(changes, source) { + if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') { + highlightInvalidAndDuplicates(%s); + } + }; + + hot.addHook('afterChange', changefn); + hot.addHook('afterLoadData', function() { + highlightInvalidAndDuplicates(%s); + }); + hot.addHook('afterRender', function() { + highlightInvalidAndDuplicates(%s); + }); + + highlightInvalidAndDuplicates(%s); // Initial highlight on load + + Shiny.addCustomMessageHandler('setColumnValue', function(message) { + var colData = hot.getDataAtCol(0); + for (var i = 0; i < colData.length; i++) { + hot.setDataAtCell(i, 0, message.value); + } + hot.render(); // Re-render the table + }); + }", + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()), + jsonlite::toJSON(dupl_mult_id()))) + + }) + + } else { + output$multi_select_table <- NULL + } + }) + + observeEvent(input$conf_meta_multi, { + + multi_select_table <- hot_to_r(input$multi_select_table)[hot_to_r(input$multi_select_table)$Include == TRUE,] + + if(any(unlist(gsub(".fasta|.fna|.fa|.fasta.gz|.fna.gz|.fa.gz", "", multi_select_table$Files)) %in% unlist(DB$data["Assembly ID"]))) { + show_toast( + title = "Assembly ID(s) already present", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (any(duplicated(multi_select_table$Files))) { + show_toast( + title = "Duplicated filename(s)", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (any(multi_select_table$Files == "")) { + show_toast( + title = "Empty filename(s)", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (any(grepl("[()/\\:*?\"<>|]", multi_select_table$Files))) { + show_toast( + title = "Invalid filename(s). No special characters allowed: ()/\\:*?\"<>|", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (!any(multi_select_table$Include == TRUE)) { + show_toast( + title = "No files selected", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if(any(grepl(" ", multi_select_table$Files[which(multi_select_table$Include == TRUE)]))) { + show_toast( + title = "Empty spaces in filename(s) not allowed", + type = "error", + position = "bottom-end", + timer = 3000 + ) + } else if (isFALSE(Typing$reload)) { + show_toast( + title = "Reload Database first", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if(Screening$status == "started") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + + log_print("Multi typing metadata confirmed") + + meta_info <- data.frame(cgmlst_typing = DB$scheme, + append_isodate = trimws(input$append_isodate_multi), + append_host = trimws(input$append_host_multi), + append_country = trimws(input$append_country_multi), + append_city = trimws(input$append_city_multi), + append_analysisdate = Sys.Date(), + db_directory = getwd()) + + saveRDS(meta_info, paste0(getwd(), "/execute/meta_info.rds")) + + show_toast( + title = "Metadata declared", + type = "success", + position = "bottom-end", + timer = 3000 + ) + + output$start_multi_typing_ui <- renderUI({ + div( + class = "multi_start_col", + column( + width = 3, + align = "center", + br(), + br(), + h3(p("Start Typing"), style = "color:white"), + br(), + br(), + HTML( + paste( + "", + "Typing by ", + DB$scheme, + " scheme." + ) + ), + br(), br(), br(), br(), + div( + class = "save-assembly", + materialSwitch( + "save_assembly_mt", + h5(p("Save Assemblies in Local Database"), style = "color:white; padding-left: 0px; position: relative; top: -3px; right: -20px;"), + value = TRUE, + right = TRUE) + ), + HTML( + paste( + "", + "Isolates with unsaved assembly files can NOT be applied to screening for resistance genes." + ) + ), + br(), br(), br(), br(), + actionButton( + "start_typ_multi", + "Start", + icon = icon("circle-play") + ) + ) + ) + }) + } + }) + + #### Events Multi Typing ---- + + observeEvent(input$sel_all_mt, { + session$sendCustomMessage(type = "setColumnValue", message = list(value = TRUE)) + }) + + observeEvent(input$desel_all_mt, { + session$sendCustomMessage(type = "setColumnValue", message = list(value = FALSE)) + }) + + # Print Log + output$print_log <- downloadHandler( + filename = function() { + log_print(paste0("Save multi typing log ", paste("Multi_Typing_", Sys.Date(), ".txt", sep = ""))) + paste("Multi_Typing_", Sys.Date(), ".txt", sep = "") + }, + content = function(file) { + writeLines(readLines(paste0(getwd(), "/logs/script_log.txt")), file) + } + ) + + # Reset Multi Typing + observeEvent(input$reset_multi, { + if(!grepl("Multi Typing", tail(readLines(paste0(getwd(),"/logs/script_log.txt")), n = 1))) { + showModal( + modalDialog( + paste0( + "A Multi Typing process is still pending. Stopping this process will cancel the processing." + ), + title = "Reset Multi Typing", + fade = TRUE, + easyClose = TRUE, + footer = tagList( + modalButton("Cancel"), + actionButton("conf_multi_kill", "Stop", class = "btn btn-danger") + ) + ) + ) + } else { + + log_print("Reset multi typing") + + # Reset multi typing result list + saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) + multi_help <- FALSE + Typing$result_list <- NULL + + # Null logfile + writeLines("0", paste0(getwd(), "/logs/script_log.txt")) + + # Reset User Feedback variable + Typing$pending_format <- 0 + Typing$multi_started <- FALSE + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + output$pending_typing <- NULL + output$multi_typing_results <- NULL + } + }) + + # Confirm Reset after + observeEvent(input$conf_multi_kill, { + removeModal() + + log_print("Kill multi typing") + + # Kill multi typing and reset logfile + system(paste("bash", paste0(getwd(), "/execute/kill_multi.sh")), + wait = TRUE) + + show_toast( + title = "Execution cancelled", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + + # Kill multi typing and reset logfile + writeLines("0", paste0(getwd(), "/logs/script_log.txt")) + + #Reset multi typing result list + saveRDS(list(), paste0(getwd(), "/execute/event_list.rds")) + multi_help <- FALSE + Typing$result_list <- NULL + + # Reset User Feedback variable + Typing$pending_format <- 0 + output$pending_typing <- NULL + output$multi_typing_results <- NULL + Typing$failures <- 0 + Typing$successes <- 0 + Typing$multi_started <- FALSE + + output$initiate_multi_typing_ui <- renderUI({ + column( + width = 4, + align = "center", + br(), + br(), + h3(p("Initiate Typing"), style = "color:white; margin-left: 15px"), + br(), br(), + p( + HTML( + paste( + tags$span(style='color: white; font-size: 15px; margin-bottom: 0px; margin-left: 15px', 'Select Assembly Folder') + ) + ) + ), + fluidRow( + column(1), + column( + width = 11, + align = "center", + shinyDirButton( + "genome_file_multi", + "Browse", + icon = icon("folder-open"), + title = "Select the folder containing the genome assemblies (FASTA)", + buttonType = "default", + root = path_home() + ), + br(), + br(), + uiOutput("multi_select_info"), + br() + ) + ), + uiOutput("multi_select_tab_ctrls"), + br(), + fluidRow( + column(1), + column( + width = 11, + align = "left", + rHandsontableOutput("multi_select_table") + ) + ) + ) + }) + + }) + + observeEvent(input$start_typ_multi, { + log_print("Initiate multi typing") + + if(readLines(paste0(getwd(), "/logs/progress.txt"))[1] != "0") { + show_toast( + title = "Pending Single Typing", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else if (Screening$status == "started") { + show_toast( + title = "Pending Gene Screening", + type = "warning", + position = "bottom-end", + timer = 6000 + ) + } else { + removeModal() + + show_toast( + title = "Multi Typing started", + type = "success", + position = "bottom-end", + timer = 10000 + ) + + Typing$new_table <- NULL + + # Remove Allelic Typing Controls + output$initiate_multi_typing_ui <- NULL + output$metadata_multi_box <- NULL + output$start_multi_typing_ui <- NULL + + # Activate entry detection + DB$check_new_entries <- TRUE + + # Initiate Feedback variables + Typing$multi_started <- TRUE + Typing$pending <- TRUE + Typing$failures <- 0 + Typing$successes <- 0 + + # get selected file table + multi_select_table <- hot_to_r(input$multi_select_table) + + filenames <- paste(multi_select_table$Files[which(multi_select_table$Include == TRUE)], collapse = " ") + + files <- Typing$multi_sel_table$Files[which(multi_select_table$Include == TRUE)] + type <- Typing$multi_sel_table$Type[which(multi_select_table$Include == TRUE)] + genome_names <- paste(paste0(gsub(" ", "~", files), type), collapse = " ") + + # Start Multi Typing Script + multi_typing_df <- data.frame( + db_path = DB$database, + wd = getwd(), + save = input$save_assembly_mt, + scheme = paste0(gsub(" ", "_", DB$scheme)), + genome_folder = as.character(parseDirPath(roots = c(Home = path_home(), Root = "/"), input$genome_file_multi)), + filenames = paste0(filenames, collapse= " "), + genome_names = genome_names, + alleles = paste0(DB$database, "/", gsub(" ", "_", DB$scheme), "/", gsub(" ", "_", DB$scheme), "_alleles") + ) + + saveRDS(multi_typing_df, "execute/multi_typing_df.rds") + + # Execute multi blat script + system(paste("bash", paste0(getwd(), "/execute/multi_typing.sh")), wait = FALSE) + } + }) + + + #### User Feedback ---- + + observe({ + if(file.exists(paste0(getwd(), "/logs/script_log.txt"))) { + if(Typing$multi_started == TRUE) { + check_multi_status() + } else { + Typing$status <- "Inactive" + } + } + }) + + check_multi_status <- reactive({ + + invalidateLater(3000, session) + + log <- readLines(paste0(getwd(), "/logs/script_log.txt")) + + # Determine if Single or Multi Typing + if(str_detect(log[1], "Multi")) { + Typing$pending_mode <- "Multi" + } else { + Typing$pending_mode <- "Single" + } + + # Check typing status + if(str_detect(tail(log, 1), "Attaching")) { + Typing$status <- "Attaching" + } else if(str_detect(tail(log, 1), "Successful")) { + Typing$multi_help <- TRUE + Typing$status <- "Successful" + show_toast( + title = paste0("Successful", sub(".*Successful", "", tail(log, 1))), + type = "success", + position = "bottom-end", + timer = 8000 + ) + } else if(str_detect(tail(log, 1), "failed")) { + Typing$status <- "Failed" + show_toast( + title = sub(".* - ", "", tail(log, 1)), + type = "error", + position = "bottom-end", + timer = 8000 + ) + } else if(str_detect(tail(log, 1), "Processing")) { + Typing$status <- "Processing" + + if(any(str_detect(tail(log, 2), "Successful"))) { + + if(!identical(Typing$last_success, tail(log, 2)[1])) { + Typing$multi_help <- TRUE + show_toast( + title = paste0("Successful", sub(".*Successful", "", tail(log, 2)[1])), + type = "success", + position = "bottom-end", + timer = 8000 + ) + + Typing$last_success <- tail(log, 2)[1] + } + } else if(any(str_detect(tail(log, 2), "failed"))) { + + if(!identical(Typing$last_failure, tail(log, 2)[1])) { + + show_toast( + title = sub(".* - ", "", tail(log, 2)[1]), + type = "error", + position = "bottom-end", + timer = 8000 + ) + + Typing$last_failure <- tail(log, 2)[1] + } + } + } else if(str_detect(tail(log, 1), "finalized")) { + Typing$multi_help <- TRUE + Typing$status <- "Finalized" + + if(Typing$pending == TRUE) { + show_toast( + title = "Typing finalized", + type = "success", + position = "bottom-end", + timer = 8000 + ) + + Typing$pending <- FALSE + } + } + }) + + ##### Render Multi Typing UI Feedback ---- + + observe({ + if(!is.null(input$multi_results_picker)) { + Typing$multi_table_length <- nrow(Typing$result_list[[input$multi_results_picker]]) + } else { + Typing$multi_table_length <- NULL + } + }) + + observe({ + if(!is.null(Typing$result_list)) { + if(length(Typing$result_list) > 0) { + if(is.null(Typing$multi_table_length)) { + output$multi_typing_result_table <- renderRHandsontable({ + rhandsontable(Typing$result_list[[input$multi_results_picker]], + rowHeaders = NULL, stretchH = "all", + readOnly = TRUE, contextMenu = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + + } else { + if(Typing$multi_table_length > 15) { + output$multi_typing_result_table <- renderRHandsontable({ + rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, + stretchH = "all", height = 500, + readOnly = TRUE, contextMenu = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } else { + output$multi_typing_result_table <- renderRHandsontable({ + rhandsontable(Typing$result_list[[input$multi_results_picker]], rowHeaders = NULL, + stretchH = "all", readOnly = TRUE, + contextMenu = FALSE) %>% + hot_rows(rowHeights = 25) %>% + hot_col(1:3, valign = "htMiddle", halign = "htCenter", + cellWidths = list(100, 160, NULL)) %>% + hot_col("Value", renderer=htmlwidgets::JS( + "function(instance, td, row, col, prop, value, cellProperties) { + if (value.length > 8) { + value = value.slice(0, 4) + '...' + value.slice(value.length - 4); + } + td.innerHTML = value; + td.style.textAlign = 'center'; + return td; + }" + )) + }) + } + } + } else { + output$multi_typing_result_table <- NULL + } + } else { + output$multi_typing_result_table <- NULL + } + }) + + observe({ + if(!is.null(Typing$multi_result_status)) { + if(Typing$multi_result_status == "start" | Typing$multi_result_status == "finalized"){ + + if(Typing$multi_help == TRUE) { + Typing$result_list <- readRDS(paste0(getwd(), "/execute/event_list.rds")) + Typing$multi_help <- FALSE + } + } + } + }) + + + observe({ + #Render multi typing result feedback table + + if(!is.null(Typing$result_list)) { + if(length(Typing$result_list) > 0) { + output$multi_typing_results <- renderUI({ + column( + width = 12, + fluidRow( + column(1), + column( + width = 9, + br(), br(), + br(), br(), + br(), + div( + class = "mult_res_sel", + selectInput( + "multi_results_picker", + label = h5("Select Typing Results", style = "color:white"), + choices = names(Typing$result_list), + selected = names(Typing$result_list)[length(names(Typing$result_list))], + ) + ), + br(), br() + ) + ), + rHandsontableOutput("multi_typing_result_table") + ) + }) + } + } + }) + + observe({ + + # Render log content + output$logText <- renderPrint({ + cat(rev(paste0(tail(readLogFile(), 50), "\n"))) + }) + + output$logTextFull <- renderPrint({ + cat(rev(paste0(readLines(paste0(getwd(), "/logs/script_log.txt")), "\n"))) + }) + + # Render Pending UI + if(!grepl("Multi Typing", tail(readLogFile(), n = 1)) & grepl("Start Multi Typing", head(readLogFile(), n = 1))) { + + Typing$multi_result_status <- "start" + + output$initiate_multi_typing_ui <- NULL + + output$pending_typing <- renderUI({ + fluidRow( + fluidRow( + br(), br(), + column(width = 2), + column( + width = 4, + h3(p("Pending Typing ..."), style = "color:white"), + br(), br(), + fluidRow( + column( + width = 5, + HTML(paste('')) + ), + column( + width = 6, + align = "left", + actionButton( + "reset_multi", + "Terminate", + icon = icon("ban") + ) + ) + ), + ) + ), + br(), br(), + fluidRow( + column(width = 2), + column( + width = 10, + verbatimTextOutput("logText") + ) + ) + ) + }) + } else if(grepl("Multi Typing finalized", tail(readLogFile(), n = 1))) { + + Typing$multi_result_status <- "finalized" + + Typing$last_scheme <- NULL + + output$initiate_multi_typing_ui <- NULL + + output$pending_typing <- renderUI({ + + fluidRow( + fluidRow( + br(), br(), + column(width = 2), + column( + width = 4, + h3(p("Pending Multi Typing ..."), style = "color:white"), + br(), br(), + HTML(paste("", + paste("Typing of", sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Processing")), "assemblies finalized."), + paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "Successful")), "successes."), + paste(sum(str_detect(readLines(paste0(getwd(), "/logs/script_log.txt")), "failed")), "failures."), + "Reset to start another typing process.", + sep = '
')), + br(), br(), + fluidRow( + column( + width = 5, + actionButton( + "reset_multi", + "Reset", + icon = icon("arrows-rotate") + ) + ), + column( + width = 5, + downloadButton( + "print_log", + "Logfile", + icon = icon("floppy-disk") + ) + ) + ) + ) + ), + br(), br(), + fluidRow( + column(width = 2), + column( + width = 10, + verbatimTextOutput("logTextFull"), + ) + ) + ) + }) + } else if (!grepl("Start Multi Typing", head(readLogFile(), n = 1))){ + output$pending_typing <- NULL + Typing$multi_result_status <- "idle" + } + }) + + observe({ + # Get selected Genome in Multi Mode + shinyDirChoose(input, + "hash_dir", + roots = c(Home = path_home(), Root = "/"), + defaultRoot = "Home", + session = session, + filetypes = c('', 'fasta', 'fna', 'fa')) + }) + + observeEvent(input$hash_start, { + dir_path <- parseDirPath(roots = c(Home = path_home(), Root = "/"), input$hash_dir) + if (!is_empty(list.files(dir_path)) && all(endsWith(list.files(dir_path), ".fasta"))) { + log_print("Hashing directory using utilities") + shinyjs::hide("hash_start") + shinyjs::show("hash_loading") + show_toast( + title = "Hashing started!", + type = "success", + position = "bottom-end", + timer = 6000 + ) + hash_database(dir_path) + shinyjs::hide("hash_loading") + shinyjs::show("hash_start") + show_toast( + title = "Hashing completed!", + type = "success", + position = "bottom-end", + timer = 6000 + ) + } else { + show_toast( + title = "Incorrect folder selected!", + type = "error", + position = "bottom-end", + timer = 6000 + ) + } + }) + +} # end server + +# _______________________ #### + +# Shiny ---- + +shinyApp(ui = ui, server = server) From 131f476f77507926284d6077b65d80274b230323 Mon Sep 17 00:00:00 2001 From: fpaskali Date: Tue, 20 Aug 2024 19:17:08 +0200 Subject: [PATCH 73/75] Udpated type 2 clustering --- App.R | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/App.R b/App.R index 5a25259..4df9e98 100644 --- a/App.R +++ b/App.R @@ -1443,12 +1443,12 @@ ui <- dashboardPage( conditionalPanel( "input.mst_cluster_type=='Skeleton'", sliderInput( - "mst_cluster width", + "mst_cluster_width", label = h5("Skeleton Width", style = "color:white; margin-bottom: 0px;"), - value = 5, + value = 24, step = 1, min = 1, - max = 10, + max = 50, ticks = FALSE, width = "150px" ) @@ -18081,8 +18081,10 @@ server <- function(input, output, session) { if (input$mst_show_clusters) { if (input$mst_cluster_col_scale == "Viridis") { color_palette <- viridis(length(unique(data$nodes$group))) + color_edges <- viridis(length(unique(clusters$edges))) } else { color_palette <- rainbow(length(unique(data$nodes$group))) + color_edges <- rainbow(length(unique(clusters$edges))) } if (input$mst_cluster_type == "Area") { @@ -18092,18 +18094,16 @@ server <- function(input, output, session) { } } else { thin_edges <- data$edges - thin_edges$width <- 1 + thin_edges$width <- 2 thin_edges$color <- "black" thick_edges <- data$edges - thick_edges$width <- 24 - + thick_edges$width <- input$mst_cluster_width thick_edges$color <- rep("rgba(0, 0, 0, 0)", length(data$edges$from)) - color_palette <- rainbow(length(unique(clusters$edges))) + for (i in 1:length(unique(clusters$edges))) { - print(clusters$edges) if (unique(clusters$edges)[i] != "0") { - edge_color <- paste(col2rgb(color_palette[i]), collapse=", ") + edge_color <- paste(col2rgb(color_edges[i]), collapse=", ") thick_edges$color[clusters$edges == unique(clusters$edges)[i]] <- paste0("rgba(", edge_color, ", 0.5)") } } From 37359881931252b222b0fa74a21a2a70d488114c Mon Sep 17 00:00:00 2001 From: fpaskali Date: Wed, 21 Aug 2024 13:04:55 +0200 Subject: [PATCH 74/75] One-node cluster color assignment --- App.R | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/App.R b/App.R index 4df9e98..b3543c4 100644 --- a/App.R +++ b/App.R @@ -18089,8 +18089,13 @@ server <- function(input, output, session) { if (input$mst_cluster_type == "Area") { for (i in 1:length(unique(data$nodes$group))) { - visNetwork_graph <- visNetwork_graph %>% - visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) + if (sum(data$nodes$group == unique(data$nodes$group)[i]) > 1) { # Color only cluster with 2 or more nodes + visNetwork_graph <- visNetwork_graph %>% + visGroups(groupname = unique(data$nodes$group)[i], color = color_palette[i]) + } else { + visNetwork_graph <- visNetwork_graph %>% + visGroups(groupname = unique(data$nodes$group)[i], color = mst_color_node()) + } } } else { thin_edges <- data$edges From 6119b6baa42df9382e2a9b20c2bce467ad8accbb Mon Sep 17 00:00:00 2001 From: Marian Freisleben <115372379+infinity-a11y@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:36:42 +0200 Subject: [PATCH 75/75] Removed insertion --- App.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App.R b/App.R index 90d4c13..bddf512 100644 --- a/App.R +++ b/App.R @@ -1430,7 +1430,7 @@ ui <- dashboardPage( width = "150px" ) ) - )f + ) ) ) )