R/shinyAppServer.R

Defines functions shinyAppServer

#' @import RMySQL
#' @import shinydashboard
#' @importFrom DBI dbGetQuery
#' @importFrom DT dataTableOutput
#' @importFrom DT renderDataTable
#' @importFrom DT datatable
#' @import leaflet
#' @import leaflet.extras
#' @importFrom shinyWidgets pickerInput
#' @importFrom shinyWidgets updatePickerInput
#' @importFrom shinyjs reset
#' @importFrom shinyjs alert
#' @importFrom shinyjs useShinyjs
#' @import ggplot2
#' @import dplyr
#' @import readxl
#' @import reactable
#' @import writexl
#' @importFrom xfun file_ext
#' @importFrom berryFunctions is.error
#' @importFrom plotly plotlyOutput
#' @importFrom plotly style
#' @importFrom plotly layout
#' @importFrom plotly ggplotly
#' @importFrom plotly renderPlotly
#' @import htmltools
#' @importFrom shiny div
#' @importFrom shiny downloadHandler
#' @importFrom shiny icon
#' @importFrom shiny isolate
#' @importFrom shiny need
#' @importFrom shiny observe
#' @importFrom shiny observeEvent
#' @importFrom shiny reactive
#' @importFrom shiny reactiveVal
#' @importFrom shiny renderText
#' @importFrom shiny req
#' @importFrom shiny updateSelectInput
#' @importFrom shiny updateSliderInput
#' @importFrom shiny validate
#' @importFrom shiny a
#' @importFrom shiny actionButton
#' @importFrom shiny br
#' @importFrom shiny column
#' @importFrom shiny downloadLink
#' @importFrom shiny em
#' @importFrom shiny fileInput
#' @importFrom shiny fluidRow
#' @importFrom shiny h1
#' @importFrom shiny h3
#' @importFrom shiny h4
#' @importFrom shiny HTML
#' @importFrom shiny icon
#' @importFrom shiny numericInput
#' @importFrom shiny p
#' @importFrom shiny radioButtons
#' @importFrom shiny selectInput
#' @importFrom shiny sliderInput
#' @importFrom shiny strong
#' @importFrom shiny tabPanel
#' @importFrom shiny tabsetPanel
#' @importFrom shiny shinyApp
#' @importFrom shiny textOutput
#' @import methods
#' @importFrom utils read.csv
#' @importFrom utils str
#' @importFrom utils head
#' @importFrom utils tail
#' @importFrom utils zip
#' @importFrom stats family
#' @importFrom stats lm
#' @importFrom stats mad
#' @importFrom stats na.exclude
#' @importFrom stats na.omit
#' @importFrom stats quantile
#' @importFrom stats residuals
#' @importFrom bslib is_bs_theme
#' @import htmlwidgets


shinyAppServer <- function(input, output, session) {


  #MySQL Database connection and table querying ---------------------------

  #Running the MDMAPR 2.0 without a database connection: dbExists <- 'No'.
  #Running the MDMAPR 2.0 with a database connection: dbExists <- 'Yes'. (NOTE: Update the 'user', 'password', 'dbname', and 'host' variables in the dbConnect statement (line 44) to reference a specific database instance.)
  dbExists <-  db_int

  #MySQL connection to MDMAPR 2.0 Database
  if (dbExists == 'Yes') {

    #MySQL connection to MDMAPR Database
    con <- dbConnect(MySQL(), user = db_user, password = db_password, dbname = db_name, host = db_host)

    #Retrieving project table
    myQuery1 <- "select * from project_Table"
    project_data <- dbGetQuery(con, myQuery1)
    str(project_data)

    #Retrieving geographic region table
    myQuery2 <- "select * from geographicRegion_Table"
    geo_data <- dbGetQuery(con, myQuery2)
    str(geo_data)

    #Retrieving site table
    myQuery3 <- "select * from site_Table"
    site_data <- dbGetQuery(con, myQuery3)
    str(site_data)

    #Retrieving station table
    myQuery4 <- "select * from station_Table"
    station_data <- dbGetQuery(con, myQuery4)
    str(station_data)

    #Retrieving replicate table
    myQuery5 <- "select * from replicate_Table"
    replicate_data <- dbGetQuery(con, myQuery5)
    str(replicate_data)

    #Retrieving extract table
    myQuery6 <- "select * from extract_Table"
    extract_data <- dbGetQuery(con, myQuery6)
    str(extract_data)

    #Retrieving results table
    myQuery7 <- "select * from results_Table"
    result_data <- dbGetQuery(con, myQuery7)
    str(result_data)

    #Retrieving pcr chemistry table
    myQuery8 <- "select * from pcrChemistry_Table"
    pcrChemistry_data <- dbGetQuery(con, myQuery8)
    str(pcrChemistry_data)

    #Retrieving run information table
    myQuery9 <- "select * from runInformation_Table"
    runInformation_data <- dbGetQuery(con, myQuery9)
    str(runInformation_data)

    #Retrieving assay table
    myQuery10 <- "select * from assay_Table"
    assay_data <- dbGetQuery(con, myQuery10)
    str(assay_data)

    #Retrieving taxon table
    myQuery11 <- "select * from taxonomic_Table"
    taxon_data <- dbGetQuery(con, myQuery11)
    str(taxon_data)

    #Retrieving standard curve table
    myQuery12 <- "select * from standardCurve_Table"
    standardCurve_data <- dbGetQuery(con, myQuery12)
    str(standardCurve_data)

    #Retrieving standard curve results table
    myQuery13 <- "select * from standardCurveResults_Table"
    standardCurveResults_data <- dbGetQuery(con, myQuery13)
    str(standardCurveResults_data)

    #Disconnecting database after data has been read in.
    dbDisconnect(con)


    #Merge Experimental qPCR Data from MySQL tables ---------------------------
    my_sql_data <- left_join(result_data,  runInformation_data, by = "runID")
    my_sql_data <- left_join(my_sql_data,  pcrChemistry_data, by = "pcrChemistryID")
    my_sql_data <- left_join(my_sql_data,  assay_data, by = "assayID")
    my_sql_data <- left_join(my_sql_data,  taxon_data, by = "taxonID")
    my_sql_data <- left_join(my_sql_data,  extract_data, by = "extractID")
    my_sql_data <- left_join(my_sql_data, replicate_data, by = "replicateID")
    my_sql_data <- left_join(my_sql_data, station_data, by = "stationID")
    my_sql_data <- left_join(my_sql_data, site_data, by = "siteID" )
    my_sql_data <- left_join(my_sql_data, geo_data, by = "geographicRegionID")
    my_sql_data <- left_join(my_sql_data, project_data, by = "projectID")
    my_sql_data <- left_join(my_sql_data, standardCurve_data, by = "assayID")


    # Merge standardCurve Data from MySQL tables ---------------------------
    mysql_standardCurve_data <- left_join(standardCurveResults_data, runInformation_data, by = "runID")
    mysql_standardCurve_data  <- left_join(mysql_standardCurve_data , pcrChemistry_data, by = "pcrChemistryID")
    mysql_standardCurve_data  <- left_join(mysql_standardCurve_data , standardCurve_data, by = "standardCurveID")


    #The qPCR intensity can be categorized into five intensity levels including “none” (absence), “weak”, “moderate”, “strong”, “very strong”. In code below we are adding CqIntensity column to table based on user provided Cq values and adding another column called CqIntensitySystemCalculated based on system calculated Cq values. The intensity ranges include  0<=very strong <10, 10<= strong <20, "20 <= Moderate < 30", "30 <= Weak < 40",  and "None > 40".
    my_sql_data$CqIntensity <- cut(my_sql_data$userProvidedCqValue,
                                   breaks = c(0, 10, 20, 30, 40, 1000), right = FALSE,
                                   labels = c("0 < Very strong < 10",
                                              "10 <= Strong < 20",
                                              "20 <= Moderate < 30",
                                              "30 <= Weak < 40",
                                              "None > 40"))

    my_sql_data$CqIntensitySystemCalculated <- cut(my_sql_data$systemCalculatedCqValue,
                                                   breaks = c(0, 10, 20, 30, 40, 1000),
                                                   right = FALSE,
                                                   labels = c("0 < Very strong < 10",
                                                              "10 <= Strong < 20",
                                                              "20 <= Moderate < 30",
                                                              "30 <= Weak < 40",
                                                              "None > 40"))


    #Reformat date fields to be of the class type "Date"
    my_sql_data$runDate <- as.Date(my_sql_data$runDate, "%Y-%m-%d")
    my_sql_data$extractionDate <- as.Date(my_sql_data$extractionDate, "%Y-%m-%d")
    my_sql_data$assayDate <- as.Date(my_sql_data$assayDate, "%Y-%m-%d")
    my_sql_data$projectCreationDate <- as.Date(my_sql_data$projectCreationDate, "%Y-%m-%d")
    my_sql_data$collectionDate <- as.Date(my_sql_data$collectionDate, "%Y-%m-%d")
    my_sql_data$projectCreationDate <- as.Date(my_sql_data$projectCreationDate, "%Y-%m-%d")
    mysql_standardCurve_data$runDate <- as.Date(mysql_standardCurve_data$runDate, "%Y-%m-%d")

    #Remove LOD and LOQ variables from main table
    my_sql_data <- my_sql_data[ , -c(213, 214)]  }



  #Data Submission page functions  ---------------------------

  #Function takes in user uploaded data and parses it into Project table.
  create_project_table <- function(uploaded_data) {
    project_table <-
      distinct(uploaded_data[, c(
        "projectID",
        "projectCreationDate",
        "projectName",
        "projectRecordedBy",
        "projectOwner",
        "projectContactEmail",
        "projectDescription",
        "InstitutionID",
        "projectDataNotes"
      )])

    return(project_table)
  }



  #Function takes in user uploaded data and parses it into Geographic Region table.
  create_geographicRegion_Table <- function(uploaded_data) {
    geographicRegion_table <-
      distinct(uploaded_data[, c(
        "geographicRegionID",
        "projectID",
        "continent",
        "country",
        "stateProvince",
        "municipality"
      )])

    return(geographicRegion_table)
  }


  #Function takes in user uploaded data and parses it into Site table.
  create_site_Table <- function(uploaded_data) {
    site_table <-
      distinct(uploaded_data[, c(
        "siteID",
        "geographicRegionID",
        "locality",
        "estimatedPerimeter",
        "estimatedSurfaceArea(m2)",
        "siteType",
        "siteLength(m2)"
      )])

    return(site_table)
  }



  #Function takes in user uploaded data and parses it into Station table.
  create_station_Table <- function(uploaded_data) {
    station_Table <-
      distinct(uploaded_data[, c("stationID",
                                 "siteID",
                                 "stationName",
                                 "decimalLongitude",
                                 "decimalLatitude")])

    return(station_Table)
  }



  #Function takes in user uploaded data and parses it into Replicate table.
  create_replicate_Table <- function(uploaded_data) {
    replicate_Table <-
      distinct(uploaded_data[, c(
        "replicateID",
        "stationID",
        "collectorName",
        "replicateName",
        "collectionDate",
        "collectionTime",
        "storageID",
        "DateOfStorage",
        "methodOfStorage",
        "minimumElevationInMeters",
        "maximumElevationInMeters",
        "verbatimElevation",
        "minimumDepthInMeters",
        "maximumDepthInMeters",
        "verbatimDepth",
        "flowRate(m/s)",
        "filterType",
        "filtrationDuration(mins)",
        "volumeFiltered",
        "processLocation",
        "replicationNumber",
        "riparianVegetationPercentageCover",
        "dissolvedOxygen(mg/L)",
        "waterTemperature(C)",
        "pH",
        "TSS(mg/L)",
        "EC(uS/cm)",
        "turbidity(NTU)",
        "discharge",
        "tide",
        "chlorophyl",
        "salinity(ppt)",
        "contaminants(ng/g)",
        "traceMetals(mg/kg)",
        "organicContent(%)",
        "microbialActivity",
        "grainSize",
        "replicateDataNotes"
      )])

    return(replicate_Table)
  }



  #Function takes in user uploaded data and parses it into Extract table.
  create_extract_Table <- function(uploaded_data) {
    extract_Table <-
      distinct(uploaded_data[, c(
        "extractID",
        "replicateID",
        "extractName",
        "analyst",
        "extractionDate",
        "extractionTime",
        "location",
        "extractionMethod",
        "methodCitation",
        "extractionNotes",
        "tubePlateID",
        "frozen",
        "fixed",
        "dnaStorageLocation",
        "extractMethodOfStorage",
        "dnaVolume",
        "quantificationMethod",
        "concentration(ng/ul)"
      )])

    return(extract_Table)
  }


  ##Function takes in user uploaded data and parses it into Result table.
  create_results_Table <- function(uploaded_data) {
    results_Table <-
      uploaded_data[, c(
        "resultID",
        "runID",
        "assayID",
        "pcrChemistryID",
        "extractID",
        "wellLocation",
        "sampleName",
        "copyNumber",
        "control",
        "userProvidedThresholdValue",
        "userProvidedCqValue",
        "systemCalculatedThresholdValue",
        "systemCalculatedCqValue",
        "Cycle_Number1",
        "Cycle_Number2",
        "Cycle_Number3",
        "Cycle_Number4",
        "Cycle_Number5",
        "Cycle_Number6",
        "Cycle_Number7",
        "Cycle_Number8",
        "Cycle_Number9",
        "Cycle_Number10",
        "Cycle_Number11",
        "Cycle_Number12",
        "Cycle_Number13",
        "Cycle_Number14",
        "Cycle_Number15",
        "Cycle_Number16",
        "Cycle_Number17",
        "Cycle_Number18",
        "Cycle_Number19",
        "Cycle_Number20",
        "Cycle_Number21" ,
        "Cycle_Number22",
        "Cycle_Number23",
        "Cycle_Number24",
        "Cycle_Number25",
        "Cycle_Number26",
        "Cycle_Number27",
        "Cycle_Number28",
        "Cycle_Number29",
        "Cycle_Number30",
        "Cycle_Number31",
        "Cycle_Number32",
        "Cycle_Number33",
        "Cycle_Number34",
        "Cycle_Number35",
        "Cycle_Number36",
        "Cycle_Number37",
        "Cycle_Number38",
        "Cycle_Number39",
        "Cycle_Number40",
        "Cycle_Number41",
        "Cycle_Number42",
        "Cycle_Number43",
        "Cycle_Number44",
        "Cycle_Number45",
        "Cycle_Number46",
        "Cycle_Number47",
        "Cycle_Number48",
        "Cycle_Number49",
        "Cycle_Number50",
        "Cycle_Number51",
        "Cycle_Number52",
        "Cycle_Number53",
        "Cycle_Number54",
        "Cycle_Number55",
        "Cycle_Number56",
        "Cycle_Number57",
        "Cycle_Number58",
        "Cycle_Number59",
        "Cycle_Number60",
        "Cycle_Number61",
        "Cycle_Number62",
        "Cycle_Number63",
        "Cycle_Number64",
        "Cycle_Number65",
        "Cycle_Number66",
        "Cycle_Number67",
        "Cycle_Number68",
        "Cycle_Number69",
        "Cycle_Number70"
      )]

    return(results_Table)
  }



  #Function takes in user uploaded data and parses it into Assay table.
  create_assay_Table <- function(uploaded_data) {
    assay_table <-
      distinct(uploaded_data[, c(
        "assayID",
        "taxonID",
        "establishmentMeans",
        "assayName",
        "assayOwnership",
        "assayDescription",
        "assayCitation",
        "assayDate",
        "geneTarget",
        "geneSymbol",
        "dilutions",
        "replicates",
        "primerR",
        "primerF",
        "probe",
        "ampliconLength (bp)",
        "probeFluorescentTag",
        "dye(s)",
        "quencher",
        "probeModification"
      )])

    return(assay_table)

  }



  #Function takes in user uploaded data and parses it into Taxon table.
  create_taxon_Table <- function(uploaded_data) {
    taxon_table <-
      distinct(uploaded_data[, c(
        "taxonID",
        "kingdom",
        "phylum",
        "class",
        "order",
        "family",
        "genus",
        "subgenus",
        "species",
        "vernacularName",
        "organismScope"
      )])

    return(taxon_table)

  }



  ##Function takes in user uploaded data and parses it into PCR Chemsitry table.
  create_pcrChemistry_Table <- function(uploaded_data, SC_uploaded_data) {

    pcrChemistry_table <-
      distinct(uploaded_data[, c(
        "pcrChemistryID",
        "reactionConditions",
        "reactionVolume",
        "templateAmount",
        "forwardPrimerBatch",
        "reversePrimerBatch",
        "dNTPConcentration",
        "primerConcentration",
        "probeConcentration",
        "Mg2+Concentration",
        "polymeraseBatch",
        "polymeraseConcentrations",
        "thermocyclerParameters",
        "pcrDataNotes"
      )])


    SCpcrChemistry_table <-
      distinct(SC_uploaded_data[, c(
        "pcrChemistryID",
        "reactionConditions",
        "reactionVolume",
        "templateAmount",
        "forwardPrimerBatch",
        "reversePrimerBatch",
        "dNTPConcentration",
        "primerConcentration",
        "probeConcentration",
        "Mg2+Concentration",
        "polymeraseBatch",
        "polymeraseConcentrations",
        "thermocyclerParameters",
        "pcrDataNotes"
      )])


    pcrChemistry_table <-
      rbind(pcrChemistry_table, SCpcrChemistry_table)

    return(pcrChemistry_table)

  }



  #Function takes in user uploaded data and parses it into Standard Curve table.
  create_standardCurve_Table <- function(uploaded_data) {
    standardCurve_Table <-
      distinct(uploaded_data[, c(
        "standardCurveID",
        "assayID",
        "standardCurveName",
        "SCdate",
        "SCrecordedBy",
        "SCdataNotes",
        "LOD",
        "LOQ"
      )])

    return(standardCurve_Table)

  }



  #Function takes in user uploaded data and parses it into Standard Curve Result table.
  create_standardCurveResults_Table <- function(uploaded_data) {
    standardCurveResults_Table <-
      uploaded_data[, c(
        "SCresultID",
        "runID",
        "pcrChemistryID",
        "standardCurveID",
        "wellLocation",
        "sampleName",
        "copyNumber",
        "control",
        "standardConc",
        "userProvidedThresholdValue",
        "userProvidedCqValue",
        "systemCalculatedThresholdValue",
        "systemCalculatedCqValue",
        "Cycle_Number1",
        "Cycle_Number2",
        "Cycle_Number3",
        "Cycle_Number4",
        "Cycle_Number5",
        "Cycle_Number6",
        "Cycle_Number7",
        "Cycle_Number8",
        "Cycle_Number9",
        "Cycle_Number10",
        "Cycle_Number11",
        "Cycle_Number12",
        "Cycle_Number13",
        "Cycle_Number14",
        "Cycle_Number15",
        "Cycle_Number16",
        "Cycle_Number17",
        "Cycle_Number18",
        "Cycle_Number19",
        "Cycle_Number20",
        "Cycle_Number21",
        "Cycle_Number22",
        "Cycle_Number23",
        "Cycle_Number24",
        "Cycle_Number25",
        "Cycle_Number26",
        "Cycle_Number27",
        "Cycle_Number28",
        "Cycle_Number29",
        "Cycle_Number30",
        "Cycle_Number31",
        "Cycle_Number32",
        "Cycle_Number33",
        "Cycle_Number34",
        "Cycle_Number35",
        "Cycle_Number36",
        "Cycle_Number37",
        "Cycle_Number38",
        "Cycle_Number39",
        "Cycle_Number40",
        "Cycle_Number41",
        "Cycle_Number42",
        "Cycle_Number43",
        "Cycle_Number44",
        "Cycle_Number45",
        "Cycle_Number46",
        "Cycle_Number47",
        "Cycle_Number48",
        "Cycle_Number49",
        "Cycle_Number50",
        "Cycle_Number51",
        "Cycle_Number52",
        "Cycle_Number53",
        "Cycle_Number54",
        "Cycle_Number55",
        "Cycle_Number56",
        "Cycle_Number57",
        "Cycle_Number58",
        "Cycle_Number59",
        "Cycle_Number60",
        "Cycle_Number61",
        "Cycle_Number62",
        "Cycle_Number63",
        "Cycle_Number64",
        "Cycle_Number65",
        "Cycle_Number66",
        "Cycle_Number67",
        "Cycle_Number68" ,
        "Cycle_Number69",
        "Cycle_Number70"
      )]

    return(standardCurveResults_Table)

  }



  #Function takes in user uploaded data and parses it into Run Information table.
  create_runInformation_Table <-
    function(uploaded_data, SC_uploaded_data) {
      runInformation_Table <-
        distinct(uploaded_data[, c("runID",
                                   "runRecordedBy",
                                   "runDate",
                                   "runTime",
                                   "runPlatform",
                                   "machineID")])

      runInformation_Table2 <-
        distinct(SC_uploaded_data[, c("runID",
                                      "runRecordedBy",
                                      "runDate",
                                      "runTime",
                                      "runPlatform",
                                      "machineID")])


      runInformation_Table <-
        rbind(runInformation_Table, runInformation_Table2)

      return(runInformation_Table)

    }



  #Uploaded User File Validation functions ---------------------------

  #Funtion that is opposite on 'is in' function
  '%ni%' <- Negate('%in%')

  #Function runs validation tests on user uploaded fluorescence file and metadata file to see if they are the correct file types and if they are compatible with each other.
  user_uploaded_file_validate <- function(fluor_file, metadata_file, platform_type){

    if (is.null(fluor_file) | is.null(metadata_file))
    {return(TRUE)}

    else if (file_ext(fluor_file$datapath) %ni% c("csv", "xlsx", "xls"))
    {return(TRUE)}

    else if (platform_type == 'None')
    {return(TRUE)}

    #Both uploaded files must be csv format
    else if (file_ext(metadata_file$datapath) %ni% c("xlsx", "xls"))
    {return(TRUE)}


    else if (length(excel_sheets(metadata_file$datapath)) < 5)
    {return(TRUE)}


    #Checks to see if any of the sheets are empty (i.e: only contain field names)
    else if (nrow(read_excel(metadata_file$datapath, sheet = 1)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 2)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 3)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 4)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 5)) == 0)
    {return(TRUE)}


    #If files are MIC
    else if (platform_type == "MIC")
    {if (file_ext(fluor_file$datapath) != "csv")
    {return(TRUE)}


      #check if fluorescence file if biomeme file
      else if (read.csv(fluor_file$datapath)[1, 1] == 'Date & Time')
      {return(TRUE)}


      #Check is fluorescence file processing  function work
      else if (is.error(process_MIC_uploaded_file(read.csv(fluor_file$datapath))) == TRUE)
      {return(TRUE)}

      #Check is metadata parsing function works on file
      else if (is.error(format_qPCR_metadata(metadata_file$datapath)) == TRUE)
      {return(TRUE)}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_MIC_uploaded_file(read.csv(fluor_file$datapath))) != nrow(format_qPCR_metadata(metadata_file$datapath)))
      {return(TRUE)}


      else
      {return(FALSE)} }


    #If files are step one plus
    else if (platform_type == "StepOnePlus")
    {if (file_ext(fluor_file$datapath) %ni% c("xlsx", "xls"))
    {return(TRUE)}


      #Check is fluorescence file processing  function work
      else if (is.error(process_SOP_uploaded_file(read_excel(fluor_file$datapath, 4))) == TRUE)
      {return(TRUE)}


      #Check is metadata parsing function works on file
      else if (is.error(format_qPCR_metadata(metadata_file$datapath)) == TRUE)
      {return(TRUE)}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_SOP_uploaded_file(read_excel(fluor_file$datapath, 4))) != nrow(format_qPCR_metadata(metadata_file$datapath)))
      {return(TRUE)}


      else
      {return(FALSE)} }


    #If files are step one plus Biomeme two3/Franklin
    else if (platform_type ==  "Biomeme two3/Franklin")
    {if (file_ext(fluor_file$datapath) != "csv")
    {return(TRUE)}


      #Check is fluorescence file processing  function work
      else if (is.error(process_biomeme23_uploaded_file(read.csv(fluor_file$datapath))) == TRUE)
      {return(TRUE)}


      #Check is metadata parsing function works on file
      else if (is.error(format_qPCR_metadata(metadata_file$datapath)) == TRUE)
      {return(TRUE)}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_biomeme23_uploaded_file(read.csv(fluor_file$datapath))) != nrow(format_qPCR_metadata(metadata_file$datapath)))
      {return(TRUE)}


      else
      {return(FALSE)}
    }


    else {return(FALSE)}

  }



  #Function runs validation tests on user uploaded standard curve file.

  user_uploaded_standard_curve_file_validation <- function(fluor_file, metadata_file, platform_type){

    if (is.null(fluor_file) | is.null(metadata_file))
    {return(TRUE)}

    else if (file_ext(fluor_file$datapath) %ni% c("csv", "xlsx", "xls"))
    {return(TRUE)}

    else if (platform_type == 'None')
    {return(TRUE)}

    else if (file_ext(metadata_file$datapath) %ni% c("xlsx", "xls"))
    {return(TRUE)}

    else if (length(excel_sheets(metadata_file$datapath)) < 5)
    {return(TRUE)}


    #Checks to see if any of the sheets are empty (i.e: only contain field names)
    else if (nrow(read_excel(metadata_file$datapath, sheet = 1)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 2)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 3)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 4)) == 0 |
             nrow(read_excel(metadata_file$datapath, sheet = 5)) == 0)
    {return(TRUE)}


    #If files are MIC
    else if (platform_type == "MIC")
    {if (file_ext(fluor_file$datapath) != "csv")
    {return(TRUE)}


      #check if fluorescence file if biomeme file
      else if (read.csv(fluor_file$datapath)[1, 1] == 'Date & Time')
      {return(TRUE)}


      #Check is fluorescence file processingfunction work
      else if (is.error(process_MIC_uploaded_file(read.csv(fluor_file$datapath))) == TRUE)
      {return(TRUE)}


      #Check is metadata parsing function works on file
      else if (is.error(format_standardCurve_metadata(read_xlsx(metadata_file$datapath, sheet = 5))) == TRUE)
      {return(TRUE)}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_MIC_uploaded_file(read.csv(fluor_file$datapath))) != nrow(format_standardCurve_metadata(read_xlsx(metadata_file$datapath, sheet = 5))))
      {return(TRUE)}


      else
      {return(FALSE)}
    }


    #If files are step one plus
    else if (platform_type == "StepOnePlus")
    {if (file_ext(fluor_file$datapath) %ni% c("xlsx", "xls"))
    {return(TRUE)}


      #Check is fluorescence file processing  function work
      else if (is.error(process_SOP_uploaded_file(read_excel(fluor_file$datapath, 4))) == TRUE)
      {return(TRUE)}


      #Check is metadata parsing function works on file
      else if (is.error(format_standardCurve_metadata(read_xlsx(metadata_file$datapath, sheet = 5))) == TRUE)
      {return(TRUE)}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_SOP_uploaded_file(read_excel(fluor_file$datapath, 4))) != nrow(format_standardCurve_metadata(read_xlsx(metadata_file$datapath, sheet = 5))))
      {return(TRUE)}


      else
      {return(FALSE)}
    }


    #If files are step one plus Biomeme two3/Franklin
    else if (platform_type ==  "Biomeme two3/Franklin")
    {if (file_ext(fluor_file$datapath) != "csv")
    {return(TRUE)}


      #Check is fluorescence file processing  function work
      else if (is.error(process_biomeme23_uploaded_file(read.csv(fluor_file$datapath))) == TRUE)
      {return(TRUE)}


      #Check is metadata parsing function works on file
      else if (is.error(format_standardCurve_metadata(read_xlsx(metadata_file$datapath, sheet = 5))) == TRUE)
      {return(TRUE)}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_biomeme23_uploaded_file(read.csv(fluor_file$datapath))) != nrow(format_standardCurve_metadata(read_xlsx(metadata_file$datapath, sheet = 5))))
      {return(TRUE)}


      else
      {return(FALSE)} }


    else {return(FALSE)}

  }



  #Function to give pop-up validation messages for uploaded fluorescence file.
  fluorescence_file_validation_msgs <- function(flur_file) {

    if (file_ext(flur_file$datapath) %ni% c("csv", "xlsx", "xls"))
    {shinyjs::alert("ERROR: Fluorescence file is not an accepted file type.")}

    else {shinyjs::alert("Successful file upload.")}

  }


  #Function to give pop-up validation messages for uploaded metatdata file.
  metadata_file_validation_msgs <- function(meta_file){

    if (file_ext(meta_file$datapath) %ni% c("xlsx", "xls"))
    {shinyjs::alert("ERROR: Metadata file is not an accepted file type.")}

    #Check how many sheets are in uploaded metadata file
    else if (length(excel_sheets(meta_file$datapath)) < 5)
    {shinyjs::alert("ERROR: Incorrect Metadata template used.")}


    #Checks to see if any of the sheets are empty (i.e: only contain field names)
    else if (nrow(read_excel(meta_file$datapath, sheet = 1)) == 0 |
             nrow(read_excel(meta_file$datapath, sheet = 2)) == 0 |
             nrow(read_excel(meta_file$datapath, sheet = 3)) == 0 |
             nrow(read_excel(meta_file$datapath, sheet = 4)) == 0 |
             nrow(read_excel(meta_file$datapath, sheet = 5)) == 0)
    {shinyjs::alert("ERROR: One or more required sheets on Metadata file is empty.")}


    #Check is metadata parsing function works on file
    else if (is.error(format_qPCR_metadata(meta_file$datapath)) == TRUE)
    {shinyjs::alert("ERROR: Metadata file is missing one or more necessary columns.")}


    else {shinyjs::alert("Successful file upload.")}}


  #Function to give pop-up validation messages for fluorescence file and metadata file based on selected machine type.
  selected_platform_validation_msgs <- function(flur_file, meta_file, platform){

    #If files are MIC
    if (platform == "MIC")

    {if (file_ext(flur_file$datapath) != "csv")
    {shinyjs::alert("ERROR: MIC fluorescence file must be csv.")}


      #check if fluorescence file if biomeme file
      else if (read.csv(flur_file$datapath)[1, 1] == 'Date & Time')
      {shinyjs::alert("ERROR: Fluorescence file is not correct file type for MIC platform.")}


      #Check is fluorescence file processing  function work
      else if (is.error(process_MIC_uploaded_file(read.csv(flur_file$datapath))) == TRUE)
      {return(shinyjs::alert("ERROR: Fluorescence file is not correct file type for MIC platform."))}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_MIC_uploaded_file(read.csv(flur_file$datapath))) != nrow(format_qPCR_metadata(meta_file$datapath)))
      {shinyjs::alert("ERROR: Fluorescence file and metadata file have information for different number of wells.")}

      else {shinyjs::alert("Successful platform selected.")}}



    else if (platform == "StepOnePlus")

    {if (file_ext(flur_file$datapath) %ni% c("xlsx", "xls"))
    {shinyjs::alert("ERROR: Step One Plus fluorescence file must be xlsx/xls.")}

      #Check is fluorescence file processingfunction work
      else if (is.error(process_SOP_uploaded_file(read_excel(flur_file$datapath, 4))) == TRUE)
      {return(shinyjs::alert("ERROR: Fluorescence file is not correct file type for Step One Plus platform."))}

      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_SOP_uploaded_file(read_excel(flur_file$datapath, sheet = 4))) != nrow(format_qPCR_metadata(meta_file$datapath)))
      {shinyjs::alert("ERROR: Fluorescence file and metadata file have information for different number of wells.")}

      else {shinyjs::alert("Successful platform selected.")}}



    #If files are Biomeme two3/Franklin
    else if (platform == "Biomeme two3/Franklin")

    {if (file_ext(flur_file$datapath) != "csv")
    {shinyjs::alert("ERROR: Biomeme two3/Franklin fluorescence file must be csv.")}


      #Check is fluorescence file processing  function work
      else if (is.error(process_biomeme23_uploaded_file(read.csv(flur_file$datapath))) == TRUE)
      {return(shinyjs::alert("ERROR: Fluorescence file is not correct file type for Biomeme two3/Franklin platform."))}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_biomeme23_uploaded_file(read.csv(flur_file$datapath))) != nrow(format_qPCR_metadata(meta_file$datapath)))
      {shinyjs::alert("ERROR: Fluorescence file and metadata file have information for different number of wells.")}

      else {shinyjs::alert("Successful platform selected.")}}


    #qPCR platform not selected
    else {
      #shinyjs::alert("Please select qPCR platform type.")
    }

  }



  #Function to give pop-up validation messages for fluorescence file,standard curve fluorescence file, and metadata file based on selected machine type
  selected_platform_validation_msgs_SC_and_Experimental_flur <- function(flur_file, SC_flur_file, meta_file, platform) {

    #If files are MIC
    if (platform == "MIC") {


      if (file_ext(flur_file$datapath) != "csv")
      {shinyjs::alert("ERROR: MIC fluorescence file must be csv.")}


      else if (file_ext(SC_flur_file$datapath) != "csv")
      {shinyjs::alert("ERROR: MIC standard curve fluorescence file must be csv.")}


      #check if fluorescence file if biomeme file
      else if (read.csv(flur_file$datapath)[1, 1] == 'Date & Time')
      {shinyjs::alert("ERROR: Fluorescence file is not correct file type for MIC platform.")}


      #check if standard curve fluorescence file if biomeme file
      else if (read.csv(SC_flur_file$datapath)[1, 1] == 'Date & Time')
      {shinyjs::alert("ERROR: Standard curve fluorescence file is not correct file type for MIC platform.")}


      #Check if fluorescence file processing function work
      else if (is.error(process_MIC_uploaded_file(read.csv(flur_file$datapath))) == TRUE)
      {return(shinyjs::alert("ERROR: Fluorescence file is not correct file type for MIC platform."))}

      #Check if  fluorescence file processing function work on standard curve fluorescence
      else if (is.error(process_MIC_uploaded_file(read.csv(SC_flur_file$datapath))) == TRUE)
      {return(shinyjs::alert("ERROR: Standard curve fluorescence file is not correct file type for MIC platform."))}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_MIC_uploaded_file(read.csv(flur_file$datapath))) != nrow(format_qPCR_metadata(meta_file$datapath)))
      {shinyjs::alert("ERROR: Fluorescence file and metadata file have information for different number of wells.")}


      #Check that standard curve formatting function works on metadata
      else if(is.error(format_standardCurve_metadata(read_xlsx(meta_file$datapath, sheet = 5))) == TRUE)
      {shinyjs::alert("ERROR: Error in standardCurveResults_Table in Metadata file.")}


      #Check that standard curve fluorescence data and standard curve data have information for same number of wells
      else if(nrow(process_MIC_uploaded_file(read.csv(SC_flur_file$datapath))) != nrow(format_standardCurve_metadata(read_xlsx(meta_file$datapath, sheet = 5))))
      {shinyjs::alert("ERROR: Standard curve fluorescence file and metadata file have information for different number of wells.")}

      else {shinyjs::alert("Successful platform selected.")}}


    else if (platform == "StepOnePlus"){

      if (file_ext(flur_file$datapath) %ni% c("xlsx", "xls"))
      {shinyjs::alert("ERROR: Step One Plus fluorescence file must be xlsx/xls.")}


      else if (file_ext(SC_flur_file$datapath) %ni% c("xlsx", "xls"))
      {shinyjs::alert("ERROR:Step One Plus standard curve fluorescence file must be xlsx/xls.")}


      #Check is fluorescence file processing function works
      else if (is.error(process_SOP_uploaded_file(read_excel(flur_file$datapath, 4))) == TRUE)
      {return(shinyjs::alert("ERROR: Fluorescence file is not correct file type for Step One Plus platform."))}


      #Check if fluorescence file processing function works on standard curve fluorescence
      else if (is.error(process_SOP_uploaded_file(read_excel(SC_flur_file$datapath, 4))) == TRUE)
      {return(shinyjs::alert("ERROR: Fluorescence file is not correct file type for Step One Plus platform."))}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_SOP_uploaded_file(read_excel(flur_file$datapath, sheet = 4))) != nrow(format_qPCR_metadata(meta_file$datapath)))
      {shinyjs::alert("ERROR: Fluorescence file and metadata file have information for different number of wells")}


      #check standard curve formatting function works on metadata
      else if(is.error(format_standardCurve_metadata(read_xlsx(meta_file$datapath, sheet = 5))) == TRUE)
      {shinyjs::alert("ERROR: Error in standardCurveResults_Table in Metadata file.")}


      #check that formatted standard curve fluorescene data and formatted standard curve metadata have same number of rows
      else if(nrow(process_SOP_uploaded_file(read_excel(flur_file$datapath, sheet = 4))) != nrow(format_standardCurve_metadata(read_xlsx(meta_file$datapath, sheet = 5))))
      {shinyjs::alert("ERROR: Standard curve fluorescence file and metadata file have information for different number of wells.")}


      else {shinyjs::alert("Successful platform selected.")}}


    #If files are Biomeme two3/Franklin
    else if (platform == "Biomeme two3/Franklin") {
      if (file_ext(flur_file$datapath) != "csv")
      {shinyjs::alert("ERROR:Biomeme two3/Franklin fluorescence file must be csv.")}


      else if (file_ext(SC_flur_file$datapath) != "csv")
      {shinyjs::alert("ERROR:Biomeme two3/Franklin standard curve fluorescence file must be csv.")}


      #Check if fluorescence file processing function works
      else if (is.error(process_biomeme23_uploaded_file(read.csv(flur_file$datapath))) == TRUE)
      {return(shinyjs::alert("ERROR: Fluorescence file not correct file type for Biomeme two3/Franklin platform."))}


      #Check if fluorescence file processing  function work on standard curve fluorescence
      else if (is.error(process_biomeme23_uploaded_file(read.csv(SC_flur_file$datapath))) == TRUE)
      {return(shinyjs::alert("ERROR: Standard curve fluorescence file not correct file type for Biomeme two3/Franklin platform."))}


      #Check that formatted fluorescence file and formatted metadata file have the same number of rows
      else if (nrow(process_biomeme23_uploaded_file(read.csv(flur_file$datapath))) != nrow(format_qPCR_metadata(meta_file$datapath)))
      {shinyjs::alert("ERROR: Fluorescence file and metadata file have information for different number of wells.")}


      #Check that standard curve formatting function works on metadata
      else if(is.error(format_standardCurve_metadata(read_xlsx(meta_file$datapath, sheet = 5))) == TRUE)
      {shinyjs::alert("ERROR: Error in standardCurveResults_Table in Metadata file.")}


      #Check that standard curve fluorescence data and standard curve data have information for same number of wells
      else if(nrow(process_biomeme23_uploaded_file(read.csv(SC_flur_file$datapath))) != nrow(format_standardCurve_metadata(read_xlsx(meta_file$datapath, sheet = 5))))
      {shinyjs::alert("ERROR: Standard curve fluorescence file and metadata file have information for different number of wells.")}


      else {shinyjs::alert("Successful platform selected.")}}


    #qPCR platform not selected
    else {
      #shinyjs::alert("Please select qPCR platform type")
    }}


  #Data Analysis Functions for Mapping Dashboard and Fata Overview page  ---------------------------


  #Function removes null records (controls or empty runs) from associated fluorescence file based on if sample name contains 'null' in metadata file.
  null_records_to_remove_flur <- function(meta_data, fluor_file) {
    if (length(which(grepl("null", tolower(meta_data$sampleName)))) != 0)
    {return (fluor_file[-c(which(grepl("null", tolower(meta_data$sampleName)))), ])}

    else
    {return(fluor_file)}

  }


  #Function removes null records (controls or empty runs) from metadata file if sample name contains 'null'.
  null_records_to_remove_meta <- function(meta_data) {
    if (length(which(grepl("null", tolower(meta_data$sampleName)))) != 0)
    {return (meta_data[-c(which(grepl("null", tolower(meta_data$sampleName)))), ])}

    else
    {return(meta_data)}

  }


  #Removing non template control records from standard curve fluorescene table
  control_records_to_remove <-
    function(meta_data) {
      if (length(which(grepl("Y", toupper(meta_data$control)))) != 0)
      {return (meta_data[-c(which(grepl("Y", toupper(meta_data$control)))), ])}

      else
      {return(meta_data)}
    }



  #Script to read in metadata file and format for qPCR experimental data
  format_qPCR_metadata <- function(metadataFile) {

    #Read in sheets
    project_Table <- read_xlsx(metadataFile,sheet = 1)
    replicate_Table <- read_xlsx(metadataFile,sheet = 2)
    assay_Table <-  read_xlsx(metadataFile, sheet = 3)
    results_Table <- read_xlsx(metadataFile, sheet = 4)
    standardCurve_Table <- read_xlsx(metadataFile, sheet = 5)


    #Creating metadata table
    metadata_table <-
      distinct(left_join(assay_Table, standardCurve_Table[, c("standardCurveID", "assayID", "standardCurveName", "SCdate", "SCrecordedBy", "SCdataNotes")], by = "assayID"))

    metadata_table <-  left_join(results_Table, metadata_table, by = "assayID")

    metadata_table <- left_join(metadata_table, replicate_Table, by = "extractID")

    metadata_table <- left_join(metadata_table, project_Table, by = "stationID")


    #Organize columns
    metadata_table <- as.data.frame(metadata_table[, c(
      "resultID","runID", "assayID","pcrChemistryID","extractID","wellLocation","sampleName", "copyNumber","control","userProvidedThresholdValue", "userProvidedCqValue","runRecordedBy", "runDate","runTime","runPlatform","machineID","reactionConditions","reactionVolume","templateAmount","forwardPrimerBatch","reversePrimerBatch","dNTPConcentration", "primerConcentration","probeConcentration","Mg2+Concentration","polymeraseBatch","polymeraseConcentrations","thermocyclerParameters","pcrDataNotes","taxonID","establishmentMeans","assayName","assayOwnership","assayDescription","assayCitation","assayDate","geneTarget","geneSymbol","dilutions","replicates","primerR","primerF","probe","ampliconLength (bp)","probeFluorescentTag","dye(s)","quencher","probeModification","kingdom","phylum","class","order","family","genus","subgenus","species","vernacularName","organismScope","replicateID","extractName","analyst", "extractionDate", "extractionTime", "location", "extractionMethod", "methodCitation", "extractionNotes","tubePlateID","frozen", "fixed","dnaStorageLocation","extractMethodOfStorage","dnaVolume","quantificationMethod", "concentration(ng/ul)","stationID","collectorName","replicateName","collectionDate","collectionTime","storageID","DateOfStorage","methodOfStorage","minimumElevationInMeters","maximumElevationInMeters","verbatimElevation","minimumDepthInMeters","maximumDepthInMeters","verbatimDepth", "flowRate(m/s)", "filterType","filtrationDuration(mins)","volumeFiltered","processLocation","replicationNumber","riparianVegetationPercentageCover","dissolvedOxygen(mg/L)","waterTemperature(C)","pH","TSS(mg/L)","EC(uS/cm)","turbidity(NTU)","discharge","tide","chlorophyl","salinity(ppt)","contaminants(ng/g)","traceMetals(mg/kg)","organicContent(%)","microbialActivity","grainSize","replicateDataNotes","siteID","stationName","decimalLongitude","decimalLatitude","geographicRegionID","locality","estimatedPerimeter","estimatedSurfaceArea(m2)","siteType","siteLength(m2)","projectID","continent","country","stateProvince","municipality","projectCreationDate","projectName", "projectRecordedBy","projectOwner","projectContactEmail","projectDescription","InstitutionID","projectDataNotes","standardCurveID","standardCurveName","SCdate","SCrecordedBy","SCdataNotes")])

    return(metadata_table)

  }



  #Combing data from formatted fluorescence file and formatted metdata file (Same for MIC, Biomeme two3/Franklin, and StepOnePlus)
  merge_metadata_fluorescence_file <-  function(fluorescence_File, metadata) {

    #Remove null records (controls or empty runs) and associated fluorescence
    fluorescence_File <- null_records_to_remove_flur(metadata, fluorescence_File)
    metadata <- null_records_to_remove_meta(metadata)


    #Add CqValue row to dataframe. If user does not provided Cq value with assoicated threshold value then the function will calculate it.
    user_Cq <- function (flur, meta) {

      if (any(is.na(meta$userProvidedCqValue)) == TRUE) {
        flur$userProvidedCqValue <- ""

        flur <- add_CqValue(flur, meta)

        return(flur)}

      else {

        flur$userProvidedCqValue <- meta$userProvidedCqValue

        return(flur)
      }
    }


    fluorescence_File <- user_Cq(fluorescence_File, metadata)


    #Handeling extreme values
    fluorescence_File$userProvidedCqValue <- as.numeric(fluorescence_File$userProvidedCqValue)
    fluorescence_File$userProvidedCqValue[fluorescence_File$userProvidedCqValue < 0] <- 40
    fluorescence_File$userProvidedCqValue[fluorescence_File$userProvidedCqValue > 40] <- 40


    #Making dataframe with empty fluorescence data
    total_runs <- ncol(fluorescence_File) - 1  #substract one for Cq value column
    flur_col <- as.data.frame(matrix(NA ,
                                     nrow =  nrow(fluorescence_File),
                                     ncol = (70 - total_runs)))

    colnames(flur_col) <- c(paste0("Cycle_Number", c(((total_runs + 1):70))))


    #Calculate threshold
    fluorescence_data_for_threshold <- fluorescence_File[1:(ncol(fluorescence_File) - 1)]
    systemCalculatedThreshold <- calculate_threshold_value(fluorescence_data_for_threshold)
    colnames(systemCalculatedThreshold) <-"userProvidedThresholdValue"

    #Calculated Cq value with calulcated threshold
    calculated_system_cq <- add_CqValue(fluorescence_File, systemCalculatedThreshold)
    names(calculated_system_cq)[ncol(calculated_system_cq)] <- "systemCalculatedCqValue"
    colnames(systemCalculatedThreshold) <-"systemCalculatedThresholdValue"

    #Ensure threshold value and Cq value are numeric
    calculated_system_cq$systemCalculatedCqValue <- as.numeric(calculated_system_cq$systemCalculatedCqValue)


    #Merging fluorescence and metadata files
    merged_file <- cbind(metadata[1:10],
                         fluorescence_File[ncol(fluorescence_File)], #user provided Cq value
                         systemCalculatedThreshold[1],
                         calculated_system_cq[ncol(calculated_system_cq)],
                         fluorescence_File[1:(ncol(fluorescence_File) - 1)],
                         flur_col,
                         metadata[12:140])


    merged_file$CqIntensity <-cut(merged_file$userProvidedCqValue,
                                  breaks = c(0, 10, 20, 30, 40, 1000),
                                  right = FALSE,
                                  labels = c("0 < Very strong < 10",
                                             "10 <= Strong < 20",
                                             "20 <= Moderate < 30",
                                             "30 <= Weak < 40",
                                             "None > 40"))


    merged_file$CqIntensitySystemCalculated <- cut(merged_file$systemCalculatedCqValue,
                                                   breaks = c(0, 10, 20, 30, 40, 1000),
                                                   right = FALSE,
                                                   labels = c("0 < Very strong < 10",
                                                              "10 <= Strong < 20",
                                                              "20 <= Moderate < 30",
                                                              "30 <= Weak < 40",
                                                              "None > 40"))


    #Changing wellLocation column class to character
    merged_file$wellLocation <- as.character(merged_file$wellLocation)

    merged_file$projectCreationDate <- as.Date(as.character(merged_file$projectCreationDate), "%Y-%m-%d")
    merged_file$collectionDate <- as.Date(as.character(merged_file$collectionDate ), "%Y-%m-%d")
    merged_file$extractionDate <- as.Date(as.character(merged_file$extractionDate), "%Y-%m-%d")
    merged_file$runDate <- as.Date(as.character(merged_file$runDate), "%Y-%m-%d")

    merged_file$assayDate <- as.Date(as.character(merged_file$assayDate), "%Y-%m-%d")

    #Return merged dataframe
    return(merged_file)
  }



  #format standard curve metadata
  format_standardCurve_metadata <- function (standardCurve_metadata) {
    standardCurve_Table <- as.data.frame(standardCurve_metadata[, c("SCresultID",
                                                                    "runID",
                                                                    "pcrChemistryID",
                                                                    "standardCurveID",
                                                                    "wellLocation",
                                                                    "sampleName",
                                                                    "copyNumber",
                                                                    "control",
                                                                    "standardConc",
                                                                    "userProvidedThresholdValue",
                                                                    "userProvidedCqValue",
                                                                    "runRecordedBy",
                                                                    "runDate",
                                                                    "runTime",
                                                                    "runPlatform",
                                                                    "machineID",
                                                                    "reactionConditions",
                                                                    "reactionVolume",
                                                                    "templateAmount",
                                                                    "forwardPrimerBatch",
                                                                    "reversePrimerBatch",
                                                                    "dNTPConcentration",
                                                                    "primerConcentration",
                                                                    "probeConcentration",
                                                                    "Mg2+Concentration",
                                                                    "polymeraseBatch",
                                                                    "polymeraseConcentrations",
                                                                    "thermocyclerParameters",
                                                                    "pcrDataNotes",
                                                                    "assayID",
                                                                    "standardCurveName",
                                                                    "SCdate",
                                                                    "SCrecordedBy",
                                                                    "SCdataNotes",
                                                                    "LOD",
                                                                    "LOQ")])
    return (standardCurve_Table)
  }



  #Combing data from formatted fluorescence file and formatted standard curve metdata file (Same for MIC, biomeme23, and SOP)
  merge_standardCurve_metadata_fluorescence_file <- function(fluorescence_File, metadata) {

    #Remove null records (controls or empty runs) and associated fluorescence
    fluorescence_File <- null_records_to_remove_flur(metadata, fluorescence_File)
    metadata <- null_records_to_remove_meta(metadata)


    #Add CqValue row to dataframe
    user_Cq <- function (flur, meta) {

      if (any(is.na(meta$userProvidedCqValue)) == TRUE)

      {flur$userProvidedCqValue <- ""
      flur <- add_CqValue(flur, meta)

      return(flur)}

      else {
        flur$userProvidedCqValue <- meta$userProvidedCqValue
        # flur <- add_CqValue(flur, meta)

        return(flur)
      }
    }


    fluorescence_File <- user_Cq(fluorescence_File, metadata)

    #Handeling extreme values
    fluorescence_File$userProvidedCqValue <- as.numeric(fluorescence_File$userProvidedCqValue)
    fluorescence_File$userProvidedCqValue[fluorescence_File$userProvidedCqValue < 0] <-40
    fluorescence_File$userProvidedCqValue[fluorescence_File$userProvidedCqValue > 40] <- 40


    #Making dataframe with empty fluorescence data
    total_runs <- ncol(fluorescence_File) - 1  #substract one for Cq value column
    flur_col <- as.data.frame(matrix(NA, nrow =  nrow(fluorescence_File),ncol = (70 - total_runs)))
    colnames(flur_col) <- c(paste0("Cycle_Number", c(((total_runs + 1):70))))


    #System calculated threshold and CqValue
    #Calculate threshold
    fluorescence_data_for_threshold <- fluorescence_File[1:(ncol(fluorescence_File) - 1)]
    systemCalculatedThreshold <- calculate_threshold_value(fluorescence_data_for_threshold)
    colnames(systemCalculatedThreshold) <-"userProvidedThresholdValue"

    #Calculated Cq value with calulcated threshold
    calculated_system_cq <- add_CqValue(fluorescence_File, systemCalculatedThreshold)
    names(calculated_system_cq)[ncol(calculated_system_cq)] <- "systemCalculatedCqValue"
    colnames(systemCalculatedThreshold) <-"systemCalculatedThresholdValue"

    #Ensure threshold value and cq value are numeric
    calculated_system_cq$systemCalculatedCqValue <- as.numeric(calculated_system_cq$systemCalculatedCqValue)

    #Change class to date
    metadata$runDate <- as.Date(as.character(metadata$runDate), "%Y-%m-%d")
    metadata$SCdate <- as.Date(as.character(metadata$SCdate), "%Y-%m-%d")


    #Mreging fluorescence and metadata files
    merged_file <-
      cbind(
        metadata[1:10],
        fluorescence_File[ncol(fluorescence_File)],
        systemCalculatedThreshold[1],
        calculated_system_cq[ncol(calculated_system_cq)],
        fluorescence_File[1:(ncol(fluorescence_File) - 1)],
        flur_col,
        metadata[12:36]
      )


    #Changing wellLocation column class to character
    merged_file$wellLocation <- as.character(merged_file$wellLocation)

    #Ensure columns are numeric
    merged_file$userProvidedThresholdValue <- as.numeric(merged_file$userProvidedThresholdValue)
    merged_file$userProvidedCqValue <- as.numeric(merged_file$userProvidedCqValue)
    merged_file$standardConc <- as.numeric(merged_file$standardConc)

    #Return merged dataframe
    return(merged_file)

  }




  #Mapping Dashboard page ---------------------------

  #Code for ValueBoxes
  #Icons from https://fontawesome.com/icons?from=io

  sample_number <- reactive({

    if (!is.null(uploaded_data())| dbExists == "Yes") {
      filt_data <- as.data.frame(filtered())
      return(length(unique(filt_data$extractID)))}

    else { return (0)}
  })




  output$sampleBox <- renderValueBox({

    val <- as.numeric(sample_number())

    valueBox(
      paste0(sample_number()),
      "Samples",
      icon = icon("vials"),
      color = "yellow"
    )})




  platform_number <- reactive({
    if (!is.null(uploaded_data()) | dbExists == "Yes") {
      filt_data <- as.data.frame(filtered())
      return(length(unique(filt_data$runPlatform)))}

    else { return (0)}
  })


  output$platformBox <- renderValueBox({

    valueBox(
      paste0(platform_number()),
      "Unique qPCR Platforms",
      icon = icon("hdd"),
      color = "yellow"
    )})




  taxon_number <- reactive({
    if (!is.null(uploaded_data()) | dbExists == "Yes") {
      filt_data <- as.data.frame(filtered())
      return(length(unique(filt_data$taxonID)))}

    else { return (0)}
  })



  output$taxonBox <- renderValueBox({

    valueBox(
      paste0(taxon_number()),
      "Taxon",
      icon = icon("frog"),
      color = "yellow"
    )})



  assay_number <- reactive({
    if (!is.null(uploaded_data()) | dbExists == "Yes") {
      filt_data <- as.data.frame(filtered())
      return(length(unique(filt_data$assayID)))}

    else { return (0)}
  })




  output$assayBox <- renderValueBox({

    valueBox(
      paste0(assay_number()),
      "Unique Assays",
      icon = icon("flask"),
      color = "yellow"
    )})



  #File validate errors messages.
  error_message <- reactive({
    validate(need(input$qpcr_file, 'No fluorescence file uploaded'),
             need(input$metadata_file, 'No metadata file uploaded'),
             need(try(file_ext(input$qpcr_file) == "csv" | file_ext(input$qpcr_file) == "xlsx" | file_ext(input$qpcr_file) == "xls") ,
                  "fluorescence file must be csv or xlsx/xls"),
             need(try(file_ext(input$metadata_file) == "xlsx" | file_ext(input$metadata_file) == "xls") , "Metadata file must be xlsx/xls"))
  })


  output$error_msg <- renderText({
    error_message()})




  #Pop-up validation messages for uploaded fluorescence file.
  observeEvent(input$qpcr_file,fluorescence_file_validation_msgs(input$qpcr_file))


  #Pop-up validation messages for uploaded metadata file,
  observeEvent(input$metadata_file, metadata_file_validation_msgs(input$metadata_file))


  #Pop-up validation messages for uploaded uploaded fluorescence and metadata file, based on machine type.
  observeEvent(req(input$qpcr_file, input$metadata_file,input$platform),
               selected_platform_validation_msgs(input$qpcr_file,
                                                 input$metadata_file,
                                                 input$platform))


  #Function process the user uploaded fluorescence file and metadata file to be analyzed on the mapping dashboard. The MDMAPR currently accepts fluorescence files from the following qPCR platforms: MIC, StepOnePlus and Biomeme23/Franklin.

  #initalize uploaded_data reactive variable
  uploaded_data <- reactiveVal(value = NULL)

  observeEvent(input$submit, {


    #Validate content of user uploaded files
    if (user_uploaded_file_validate(input$qpcr_file, input$metadata_file, input$platform) == TRUE)
    {return(uploaded_data(NULL))}


    else{

      if (input$platform == "Biomeme two3/Franklin") {

        #Read in raw qPCR data
        qpcr_biomem23_raw <- process_biomeme23_uploaded_file(read.csv(input$qpcr_file$datapath))
        #Read in metadata
        metadata_biomem23 <- format_qPCR_metadata(input$metadata_file$datapath)

        #Function to process and merge files
        merged_biomem23_file <- merge_metadata_fluorescence_file(qpcr_biomem23_raw,metadata_biomem23)

        #This merged datatable that will be used to populate map
        return(uploaded_data(merged_biomem23_file))

      }


      ### Machine Option 2: MIC ###
      else if (input$platform == "MIC") {

        #Read in raw qPCR data
        qpcr_MIC_raw  <- process_MIC_uploaded_file(read.csv(input$qpcr_file$datapath))

        #Read in metadata
        metadata_MIC <- format_qPCR_metadata(input$metadata_file$datapath)

        #Function to process and merge files
        merged_mic_file <- merge_metadata_fluorescence_file(qpcr_MIC_raw, metadata_MIC)

        #This merged datatable that will be used to populate map
        return(uploaded_data(merged_mic_file))
      }


      ### Machine Option 3: StepOnePlus ###
      else if (input$platform == "StepOnePlus") {

        #Read in raw qPCR data
        qpcr_StepOnePlus_raw <- process_SOP_uploaded_file(read_excel(input$qpcr_file$datapath, 4))

        #Read in metadata
        metadata_StepOnePlus <- format_qPCR_metadata(input$metadata_file$datapath)

        #Function to process and merge files
        merged_StepOnePlus_file <-  merge_metadata_fluorescence_file(qpcr_StepOnePlus_raw, metadata_StepOnePlus)
        #This merged datatable that will be used to populate map
        return(uploaded_data(merged_StepOnePlus_file))

      }
    }})




  #Update filtering option values if user uploads compatible fluorescence file and metadata file.

  #Updated Family list
  family_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes' ) {
      data <- as.data.frame(mergedData())
      family_data <- as.character(unique(data$family))
      return(family_data)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "family_input",
                      choices = family_list(),
                      selected = family_list())
  })



  #Updated Genus list
  genus_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      genus_data <- as.character(unique(data$genus))
      return(genus_data)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "genus_input",
                      choices = genus_list(),
                      selected = genus_list())
  })



  #Updated Species list
  species_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      species_data <- as.character(unique(data$species))
      return(species_data)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "species_input",
                      choices = species_list(),
                      selected = species_list())
  })




  #Update qPCR machine list
  machine_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      run_platform_add <- as.character(unique(data$runPlatform))
      return(run_platform_add)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "machine_input",
                      choices = machine_list(),
                      selected = machine_list() )
  })




  #Update target gene list
  targetGene_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      targetGene_add <- as.character(unique(data$geneSymbol))
      return(targetGene_add)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "targetGene_input",
                      choices = targetGene_list(),
                      selected = targetGene_list() )
  })




  #Update project list
  project_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      project_add <- as.character(unique(data$projectName))
      return(project_add)} else {
        return(NULL)}
  })


  observe({
    updatePickerInput(session, "projectID_input",
                      choices = project_list(),
                      selected = project_list() )
  })



  #Update assay list
  assay_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      assay_add <- as.character(unique(data$assayName))
      return(assay_add)} else {
        return(NULL)}
  })


  observe({
    updatePickerInput(session, "assay_input",
                      choices = assay_list(),
                      selected = assay_list())
  })




  #Update continent list
  continent_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      continent_add <- as.character(unique(data$continent))
      return(continent_add)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "continent_input",
                      choices = continent_list(),
                      selected = continent_list() )
  })


  #Update country list
  country_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      country_add <- as.character(unique(data$country))
      return(country_add)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "country_input",
                      choices = country_list(),
                      selected = country_list() )
  })




  #Update state/province list
  stateProvince_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      stateProvince_add <- as.character(unique(data$stateProvince))
      return(stateProvince_add)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "stateProvince_input",
                      choices = stateProvince_list(),
                      selected = stateProvince_list() )
  })



  #Update locality list
  locality_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      locality_add <- as.character(unique(data$locality))
      return(locality_add)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "locality_input",
                      choices = locality_list(),
                      selected = locality_list())
  })




  #Update establishment means list
  establishmentMeans_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      establishmentMeans_add <- as.character(unique(data$establishmentMeans))
      return(establishmentMeans_add)} else {
        return(NULL)}
  })

  observe({
    updatePickerInput(session, "establishmentMeans_input",
                      choices = establishmentMeans_list(),
                      selected = establishmentMeans_list() )
  })


  #Update Cq intensity list
  ctIntensity_list <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      ctintensity_updated <- as.character(unique(c(as.character(unique(data$CqIntensity)),
                               as.character(unique(data$CqIntensitySystemCalculated)))))
      return(ctintensity_updated)}


    else {
      return(NULL)}
  })


  observe({
    updatePickerInput(session, "CqIntensity_input",
                      choices = ctIntensity_list(),
                      selected = ctIntensity_list() )
  })



  #Update minimum date on date range slider
  #Update Cq intensity list
  min_date <- reactive({
    if (!is.null(uploaded_data()) | dbExists == 'Yes') {
      data <- as.data.frame(mergedData())
      min_date_updated <- min(as.Date(data$collectionDate, "%Y-%m-%d"))
      return(as.character(min_date_updated))}

    else {
      return(NULL)}
  })



  observe({

    updateSliderInput(session, "date_input",
                      min = as.Date(min_date(),"%Y-%m-%d"),
                      max = as.Date(Sys.Date(), "%Y-%m-%d"),
                      value = range(c(as.Date(min_date(),"%Y-%m-%d"),
                                      as.Date(Sys.Date(), "%Y-%m-%d"))),
                      step=1)
  })




  #merge uploaded data with data from MySQL connection
  mergedData <- reactive({

    if(dbExists == 'No' && is.null(uploaded_data())) {

      return("No_Data")}


    else if (dbExists == 'Yes' && is.null(uploaded_data())){

      my_sql_data <-  control_records_to_remove(my_sql_data)

      return(my_sql_data)
    }


    else if (dbExists == 'No' && !is.null(uploaded_data())) {

      return (mysql_and_uploaddata <- control_records_to_remove(as.data.frame(uploaded_data())))
    }

    else {

      mysql_and_uploaddata <- as.data.frame(rbind(my_sql_data, uploaded_data()))

      mysql_and_uploaddata <-  control_records_to_remove(mysql_and_uploaddata)

      return(mysql_and_uploaddata)

    }

  })



  #Mapped markers filtered by widgets on dashboard page.
  filtered <- reactive({

    data_final <- mergedData()

    if (!is.null(uploaded_data()) | dbExists == 'Yes') {

      data_final <- data_final[data_final[ , cq_column()] >= input$range[1] &
                                 data_final[ , cq_column()] <= input$range[2] &
                                 data_final$collectionDate >= input$date_input[1] &
                                 data_final$collectionDate <= input$date_input[2], ] %>%
        filter(family %in% input$family_input)  %>%
        filter(species %in% input$species_input)  %>%
        filter(genus %in% input$genus_input)  %>%
        filter(runPlatform %in% input$machine_input) %>%
        filter(geneSymbol %in% input$targetGene_input) %>%
        filter(projectName%in% input$projectID_input) %>%
        filter(assayName %in% input$assay_input) %>%
        filter(country %in% input$country_input) %>%
        filter(continent %in% input$continent_input) %>%
        filter(stateProvince %in% input$stateProvince_input) %>%
        filter(locality %in% input$locality_input) %>%
        filter(establishmentMeans %in% input$establishmentMeans_input)


      if (input$thresholdValueButton == 10)
      {data_final <- data_final %>%  filter(CqIntensity %in% input$CqIntensity_input)

      return(data_final)}

      else  { data_final <- data_final %>%  filter(CqIntensitySystemCalculated %in% input$CqIntensity_input)

      return(data_final)}
    }
  })


  #Download button for downloading CSV of filtered mapping data
  output$downloadFilteredData <- downloadHandler(

    filename = 'MDMAP_Mapping_data.csv',

    content = function(file) {

      write.csv(filtered(), file,  row.names=FALSE)
    })


  #Dynamic data table with Mapping marker information
  output$mapping_data <- renderDataTable({

    mapping_data <- as.data.frame(filtered()[, c(
      "projectName","projectDescription",	"InstitutionID", "sampleName", "wellLocation", "copyNumber",	"control","runRecordedBy", "runDate",	"runTime",	"runPlatform", "machineID",	"reactionConditions",	"reactionVolume", "templateAmount",	"forwardPrimerBatch",	"reversePrimerBatch", "dNTPConcentration",	"primerConcentration",	"probeConcentration","Mg2+Concentration",	"polymeraseBatch",	"polymeraseConcentrations", "thermocyclerParameters",	"pcrDataNotes",	"taxonID","establishmentMeans",	"assayName",	"assayOwnership","assayDescription",	"assayCitation", "assayDate",	"geneTarget", "geneSymbol",	"dilutions",	"replicates","primerR",	"primerF",	"probe","ampliconLength (bp)",	"probeFluorescentTag",	"dye(s)","quencher",	"probeModification", "kingdom",	"phylum",	"class","order",	"family",	"genus","subgenus",	"species",	"vernacularName","organismScope",	"replicateID",	"extractName", "analyst",	"extractionDate",	"extractionTime","location",	"extractionMethod",	"methodCitation","extractionNotes",	"tubePlateID",	"frozen","fixed",	"dnaStorageLocation",	"extractMethodOfStorage", "dnaVolume",	"quantificationMethod",	"concentration(ng/ul)","stationID",	"collectorName",	"replicateName", "collectionDate",	"collectionTime",	"storageID","DateOfStorage",	"methodOfStorage",	"minimumElevationInMeters","maximumElevationInMeters",	"verbatimElevation",	"minimumDepthInMeters","maximumDepthInMeters",	"verbatimDepth", "flowRate(m/s)",	"filterType",	"filtrationDuration(mins)", "volumeFiltered",	"processLocation",	"replicationNumber","riparianVegetationPercentageCover",	"dissolvedOxygen(mg/L)",	"waterTemperature(C)","pH",	"TSS(mg/L)",	"EC(uS/cm)", "turbidity(NTU)",	"discharge",	"tide", "chlorophyl",	"salinity(ppt)",	"contaminants(ng/g)","traceMetals(mg/kg)",	"organicContent(%)",	"microbialActivity", "grainSize",	"replicateDataNotes",	"siteID", "stationName",	"decimalLongitude",	"decimalLatitude", "geographicRegionID",	"locality",	"estimatedPerimeter","estimatedSurfaceArea(m2)",	"siteType",	"siteLength(m2)","projectID",	"continent",	"country","stateProvince",	"municipality",	"standardCurveID",	"standardCurveName","SCdate",	"SCrecordedBy",	"SCdataNotes", "CqIntensity",	"CqIntensitySystemCalculated", "userProvidedThresholdValue",	"userProvidedCqValue",	"systemCalculatedThresholdValue","systemCalculatedCqValue", "Cycle_Number1",	"Cycle_Number2", "Cycle_Number3",	"Cycle_Number4",	"Cycle_Number5", "Cycle_Number6",	"Cycle_Number7",	"Cycle_Number8", "Cycle_Number9",	"Cycle_Number10",	"Cycle_Number11","Cycle_Number12",	"Cycle_Number13",	"Cycle_Number14","Cycle_Number15",	"Cycle_Number16",	"Cycle_Number17","Cycle_Number18",	"Cycle_Number19",	"Cycle_Number20","Cycle_Number21",	"Cycle_Number22",	"Cycle_Number23","Cycle_Number24",	"Cycle_Number25",	"Cycle_Number26","Cycle_Number27",	"Cycle_Number28",	"Cycle_Number29", "Cycle_Number30",	"Cycle_Number31",	"Cycle_Number32","Cycle_Number33",	"Cycle_Number34",	"Cycle_Number35","Cycle_Number36",	"Cycle_Number37",	"Cycle_Number38","Cycle_Number39",	"Cycle_Number40",	"Cycle_Number41", "Cycle_Number42",	"Cycle_Number43",	"Cycle_Number44","Cycle_Number45",	"Cycle_Number46",	"Cycle_Number47","Cycle_Number48",	"Cycle_Number49",	"Cycle_Number50","Cycle_Number51",	"Cycle_Number52",	"Cycle_Number53","Cycle_Number54",	"Cycle_Number55",	"Cycle_Number56", "Cycle_Number57",	"Cycle_Number58",	"Cycle_Number59",  "Cycle_Number60",	"Cycle_Number61",	"Cycle_Number62", "Cycle_Number63",	"Cycle_Number64",	"Cycle_Number65", "Cycle_Number66",	"Cycle_Number67",	"Cycle_Number68", "Cycle_Number69",	"Cycle_Number70" )])

    datatable(mapping_data,
              options = list(
                scrollX = TRUE
              ))
  })



  #What Cq value to use based on user select threshold value on Mapping Dashboard.
  cq_column <- reactive({if (input$thresholdValueButton == 10)
  {return(11)}
    else{return(13)}
  })


  #Data that will appear in each popup window for the mapped markers.
  popup_data <- reactive({

    data <- as.data.frame(filtered())


    content.output <- paste("<strong><h5>Species:", data$species, "</strong>",
                            "<strong><h5> NCBI Taxon ID:", "<a href='https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id=",
                            data$taxonID, "'>", data$taxonID, "</a>", "</strong>",
                            "<strong><h5>Cq Value:", data[ , cq_column()], "</strong>",
                            "<strong><h5>Threshold Value:", data[ , as.numeric(input$thresholdValueButton)], "</strong>",
                            "<br><h6>Sample Name:", data$extractName,
                            "<br><h6>Well Location:", data$wellLocation,
                            "<br><h6>qPCR Device:", data$runPlatform,
                            "<br><h6>Common Name:", data$vernacularName,
                            "<br><h6>Event Date:", data$collectionDate,
                            "<h6>Event Coordinate(Lat, Lon):", data$decimalLatitude,",", data$decimalLongitude,
                            "<h6>Event Identifer(s):", data$analyst)
    return(content.output)
  })


  #Updated marker colour based on what threshold value was selected
  cq_intensity_column <- reactive({ if (input$thresholdValueButton == 10)
  {return(as.data.frame(filtered())$CqIntensity)}
    else  {return(as.data.frame(filtered())$CqIntensitySystemCalculated)}
  })



  #Define the colour Palette for leaflet map
  palette_map_ct <- colorFactor( palette = c("#fbd300",
                                             "#ff8600",
                                             "#ea5f94",
                                             "#9d02d7",
                                             "#0000ff"),
                                 levels = c("0 < Very strong < 10",
                                            "10 <= Strong < 20",
                                            "20 <= Moderate < 30",
                                            "30 <= Weak < 40",
                                            "None > 40"))


  #Default static leaflet map before filtering parameters are applied.
  output$mymap <- renderLeaflet({
    leaflet() %>%
      addTiles() %>%

      addLegend(position = "bottomright",
                pal = palette_map_ct,
                values =  c("0 < Very strong < 10",
                            "10 <= Strong < 20",
                            "20 <= Moderate < 30",
                            "30 <= Weak < 40",
                            "None > 40"),
                title = 'qPCR Cq Signal Intensity',
                opacity = 0.6) %>%

      #View map full screen (note: only works in web broswer)
      addFullscreenControl() %>%


      #Default map view --> Change to Guelph
      setView(lng = -80.2262, lat = 43.5327, zoom = 3) %>%

      #Change leaflet map tiles
      addProviderTiles(providers$Esri.WorldStreetMap)

  })


  # Observe will track if any filtering widgets are used. If any filters are implemented the   # Leaflet map will clear the existing markers and update the markers to relflect the
  # current filtering conditions.
  observe({

    #when leaflet map is not on first page you need to use req in order for marker points to appear on map
    req(input$tab_being_displayed == "dashboard")

    if (!is.null(uploaded_data()) | dbExists == 'Yes') {

      leafletProxy("mymap", data = as.data.frame(filtered())) %>%
        clearMarkers() %>%
        clearMarkerClusters() %>%
        clearPopups() %>%
        #Adding labels to markers on map
        addCircleMarkers(lng = ~decimalLongitude,
                         lat = ~decimalLatitude,
                         color = ~palette_map_ct(cq_intensity_column()),
                         clusterOptions = markerClusterOptions(),
                         popup= popup_data()) }


  })






  #Reset uploaded file input and fitler widget selections to return map to its default view.
  observeEvent(input$reset, {

    if (dbExists == "Yes") {
      shinyjs::reset("platform")
      updateSelectInput(session,
                        inputId = "platform",
                        label = "qPCR Platform",
                        choices = c("None",
                                    "StepOnePlus",
                                    "Biomeme two3/Franklin",
                                    "MIC"),
                        selected = "None")

      shinyjs::reset("qpcr_file")
      shinyjs::reset("metadata_file")
      shinyjs::reset("range") #ct range slider

      #Reset date range slider
      updateSliderInput(session, "date_input",
                        value = range(c(min(as.Date("2010-01-01", "%Y-%m-%d")), as.Date(Sys.Date(), "%Y-%m-%d"))))

      #update value of upload_data
      uploaded_data(NULL)}

    else {

      shinyjs::reset("platform")
      updateSelectInput(session,
                        inputId = "platform",
                        label = "qPCR Platform",
                        choices = c("None",
                                    "StepOnePlus",
                                    "Biomeme two3/Franklin",
                                    "MIC"),
                        selected = "None")

      shinyjs::reset("qpcr_file")
      shinyjs::reset("metadata_file")
      shinyjs::reset("range") #ct range slider
      shinyjs::reset("family_input") #family dropdown box
      shinyjs::reset("genus_input") #genus dropdown box
      shinyjs::reset("species_input") #species dropdown box
      shinyjs::reset("CqIntensity_input") #ct intensity dropdown box
      shinyjs::reset("machine_input") #machine input
      shinyjs::reset("targetGene_input") #target gene (gene symbol) input
      shinyjs::reset("projectID_input") #project ID input
      shinyjs::reset("assay_input") #assay input
      shinyjs::reset("continent_input") #continent input
      shinyjs::reset("country_input") #country input
      shinyjs::reset("stateProvince_input") #state/province input
      shinyjs::reset("locality_input") #locality input
      shinyjs::reset("establishmentMeans_input") #establishment means input

      #Reset date range slider
      updateSliderInput(session, "date_input",
                        value = range(c(min(as.Date("2010-01-01", "%Y-%m-%d")), as.Date(Sys.Date(), "%Y-%m-%d"))))

      #Clear markers from leaflet map
      leafletProxy("mymap") %>%
        clearMarkers() %>%
        clearMarkerClusters() %>%
        clearPopups() }

  })


  #qPCR Data Overview page ---------------------------

  #Uploaded file validation
  #Return popup message regarding uploaded fluorescence file.
  observeEvent(input$qPCR_fluorescence_file,
               fluorescence_file_validation_msgs(input$qPCR_fluorescence_file))

  #Return popup message regarding uploaded standard curve fluorescence file.
  observeEvent(input$SC_fluorescence_file,
               fluorescence_file_validation_msgs(input$SC_fluorescence_file))

  #Return popup messaged regarding uploaded metadata file.
  observeEvent(input$qPCR_metadata_file,
               metadata_file_validation_msgs(input$qPCR_metadata_file))

  #Return popup messaged regarding uploaded fluorescence and metadata file, based on machine type.
  observeEvent(req(input$qPCR_fluorescence_file,
                   input$SC_fluorescence_file,
                   input$qPCR_metadata_file,
                   input$DA_platform),

               selected_platform_validation_msgs_SC_and_Experimental_flur(input$qPCR_fluorescence_file,
                                                                          input$SC_fluorescence_file,
                                                                          input$qPCR_metadata_file,
                                                                          input$DA_platform))


  #Process user uploaded standard curve data
  user_uploaded_standard_curve_data <-  reactive({
    input$Uploaded_DA_submit

    isolate(

      #Validate content of user uploaded files
      if (user_uploaded_standard_curve_file_validation(input$SC_fluorescence_file,
                                                       input$qPCR_metadata_file,
                                                       input$DA_platform) == TRUE)

      {return(NULL)}


      else{

        if (input$DA_platform == "Biomeme two3/Franklin") {

          #Read in raw qPCR data
          qpcr_biomem23_raw <- process_biomeme23_uploaded_file(read.csv(input$SC_fluorescence_file$datapath))

          #Read in metadata
          metadata_biomem23 <-  format_standardCurve_metadata(read_xlsx(input$qPCR_metadata_file$datapath, sheet = 5))

          #Function to process and merge files
          merged_biomem23_file <- merge_standardCurve_metadata_fluorescence_file(qpcr_biomem23_raw, metadata_biomem23)


          #This merged datatable that will be used to populate map
          return(merged_biomem23_file)

        }


        ### Machine Option 2: MIC ###
        else if (input$DA_platform == "MIC") {

          #Read in raw qPCR data
          qpcr_MIC_raw  <- process_MIC_uploaded_file(read.csv(input$SC_fluorescence_file$datapath))

          #Read in metadata
          metadata_MIC <- format_standardCurve_metadata(read_xlsx(input$qPCR_metadata_file$datapath, sheet = 5))

          #Function to process and merge files
          merged_mic_file <- merge_standardCurve_metadata_fluorescence_file(qpcr_MIC_raw,
                                                                            metadata_MIC)

          #This merged datatable that will be used to populate map
          return(merged_mic_file)

        }

        ### Machine Option 3: StepOnePlus ###
        else if (input$DA_platform == "StepOnePlus") {

          #Read in standard curve fluorescence file
          standardCurve_StepOnePlus_raw <- process_SOP_uploaded_file(read_excel(input$SC_fluorescence_file$datapath, sheet = 4))

          #Read in standard curve metadata
          standardCurve_metadata_StepOnePlus <- format_standardCurve_metadata(read_xlsx(input$qPCR_metadata_file$datapath, sheet = 5))

          #Function to process and merge files
          merged_StepOnePlus_file <- merge_standardCurve_metadata_fluorescence_file(standardCurve_StepOnePlus_raw, standardCurve_metadata_StepOnePlus)


          return(merged_StepOnePlus_file)
        }
      })
  })


  #merge uploaded data with data from MySQL connection
  standardCurve_mergedData <- reactive({
    input$Uploaded_DA_submit


    if(dbExists == 'No' && is.null(user_uploaded_standard_curve_data()))
      return(NULL)

    else if (dbExists == 'Yes' && is.null(user_uploaded_standard_curve_data()))
    {return (mysql_standardCurve_data)}

    else if (dbExists == 'No' && !is.null(user_uploaded_standard_curve_data()))
    { mysql_and_uploaddata <- user_uploaded_standard_curve_data()
    mysql_and_uploaddata$userProvidedCqValue <- as.numeric(mysql_and_uploaddata$userProvidedCqValue)
    mysql_and_uploaddata$standardConc <-as.numeric(mysql_and_uploaddata$standardConc)

    return (mysql_and_uploaddata)}

    else {
      mysql_and_uploaddata <- rbind(mysql_standardCurve_data, user_uploaded_standard_curve_data())
      mysql_and_uploaddata$userProvidedCqValue <- as.numeric(mysql_and_uploaddata$userProvidedCqValue)
      mysql_and_uploaddata$standardConc <-as.numeric(mysql_and_uploaddata$standardConc)

      return(mysql_and_uploaddata)

    }
  })


  #Process user uploaded qPCR fluorescence data.

  user_uploaded_qPCR_data <-  reactive({

    input$Uploaded_DA_submit

    isolate(

      #Validate content of user uploaded files
      if (user_uploaded_file_validate(input$qPCR_fluorescence_file,
                                      input$qPCR_metadata_file,
                                      input$DA_platform) == TRUE)

      {return(NULL)}


      else{

        if (input$DA_platform == "Biomeme two3/Franklin") {

          #Read in raw qPCR data
          qpcr_biomem23_raw <- process_biomeme23_uploaded_file(read.csv(input$qPCR_fluorescence_file$datapath))

          #Read in metadata
          metadata_biomem23 <- format_qPCR_metadata(input$qPCR_metadata_file$datapath)

          #Function to process and merge files
          merged_biomem23_file <- merge_metadata_fluorescence_file(qpcr_biomem23_raw, metadata_biomem23)
          #This merged datatable that will be used to populate map
          return(merged_biomem23_file)
        }

        ### Machine Option 2: MIC ###
        else if (input$DA_platform == "MIC") {

          #Read in raw qPCR data
          qpcr_MIC_raw  <- process_MIC_uploaded_file(read.csv(input$qPCR_fluorescence_file$datapath))

          #Read in metadata
          metadata_MIC <- format_qPCR_metadata(input$qPCR_metadata_file$datapath)


          #Function to process and merge files
          merged_mic_file <- merge_metadata_fluorescence_file(qpcr_MIC_raw, metadata_MIC)


          #This merged datatable that will be used to populate map
          return(merged_mic_file)
        }

        ### Machine Option 3: StepOnePlus ###
        else if (input$DA_platform == "StepOnePlus") {

          #Read in standard curve fluorescence file
          standardCurve_StepOnePlus_raw <- process_SOP_uploaded_file(read_excel(input$qPCR_fluorescence_file$datapath, 4))


          #Read in standard curve metadata
          standardCurve_metadata_StepOnePlus <- format_qPCR_metadata(input$qPCR_metadata_file$datapath)

          #Function to process and merge files
          merged_StepOnePlus_file <- merge_metadata_fluorescence_file(standardCurve_StepOnePlus_raw, standardCurve_metadata_StepOnePlus)


          return(merged_StepOnePlus_file)
        }
      }
    )
  })


  #merge uploaded data with data from MySQL connection
  MySQL_mergedData <- reactive({

    if(dbExists == 'No' && is.null(user_uploaded_qPCR_data()))
      return(NULL)

    else if (dbExists == "Yes" && is.null(user_uploaded_qPCR_data()))
    { return(my_sql_data)
    }

    else if (dbExists == "No" && !is.null(user_uploaded_qPCR_data()))
    {return (user_uploaded_qPCR_data())}

    else {mysql_and_uploaddata <- rbind(my_sql_data, user_uploaded_qPCR_data())

    return(mysql_and_uploaddata)
    }
  })


  #Update dropdown menus based on selection in previous dropdown menu

  #Update assay list on page when additional file is uploaded
  SC_assay_list <- reactive({

    if (!is.null(MySQL_mergedData())) {

      data <- as.data.frame(MySQL_mergedData())

      assay_data <- append('None', as.character(unique(data$assayName)))

      return(assay_data)}

    else {return(NULL)}
  })

  observe({updatePickerInput(session,
                             "SC_assay_input",
                             choices = SC_assay_list(),
                             selected = 'None')})


  #Update machine based on assay selection
  SC_runPlatform_list <- reactive({

    if (input$SC_assay_input != 'None') {

      data <- as.data.frame(MySQL_mergedData())

      updated_list <- data[data$assayName == input$SC_assay_input, ]

      runPlatform_list <-  as.character(unique(updated_list$runPlatform))

      return(runPlatform_list)}

    else {return(NULL)}
  })

  observe({updatePickerInput(session,
                             "SC_machine_input",
                             choices = append('None', SC_runPlatform_list()),
                             selected = 'None')})


  #Update project list based on assay selection
  SC_project_list <- reactive({

    if (input$SC_machine_input != 'None') {

      data <- as.data.frame(MySQL_mergedData())

      updated_list <- data[data$assayName == input$SC_assay_input, ]
      updated_list <- updated_list[updated_list$runPlatform == input$SC_machine_input, ]
      project_list <-  as.character(unique(updated_list$projectName))

      return(project_list)}

    else {return(NULL)}
  })


  observe({updatePickerInput(session,
                             "SC_project_input",
                             choices = append('None', SC_project_list()),
                             selected = 'None') })


  #Update standard curve list based on selected project
  SC_version_list <- reactive({

    if (input$SC_project_input != 'None') {

      data <- as.data.frame(MySQL_mergedData())
      SC_data <- standardCurve_mergedData()

      updated_list <- data[data$assayName == input$SC_assay_input, ]
      updated_list <- updated_list[updated_list$runPlatform == input$SC_machine_input, ]
      updated_list <- updated_list[updated_list$projectName == input$SC_project_input, ]

      unique_standardCurveID <-  as.character(unique(updated_list$standardCurveID))

      return(unique_standardCurveID)}

    else {return(NULL)}
  })


  observe({updatePickerInput(session, "SC_input",
                             choices = append('None', SC_version_list()),
                             selected = 'None')})







  ## Standard curve plot

  #Transform dataframe for plot based on assay filters
  standard_curve_data_for_plot <- reactive({

    if (dbExists == "Yes" | !is.null(user_uploaded_qPCR_data())) {

      data <- MySQL_mergedData()

      SC_data <- standardCurve_mergedData()

      SC_filtered_data <- data[data$assayName == input$SC_assay_input, ]
      SC_filtered_data <- SC_filtered_data[SC_filtered_data$runPlatform == input$SC_machine_input, ]
      SC_filtered_data <- SC_filtered_data[SC_filtered_data$projectName == input$SC_project_input, ]
      SC_filtered_data <-  SC_data[SC_data$standardCurveID  == input$SC_input, ]
      SC_filtered_data <-  SC_filtered_data %>% filter(SC_filtered_data$userProvidedCqValue != 0)

      return(SC_filtered_data)
    }

  })


  #Standard curve plot only appears when submit button is pressed
  observeEvent(input$DA_submit, isolate({

    output$standardCurve_plot <- renderPlotly({

      #Add data to plot
      SC_plot_data <- standard_curve_data_for_plot()

      #Remove control records
      SC_plot_data <- control_records_to_remove(SC_plot_data)

      #Change standard concentration value to numeric and then take log value
      SC_plot_data$standardConc <- as.numeric(SC_plot_data$standardConc)
      SC_plot_data$standardConc <- log(SC_plot_data$standardConc)

      #Change user provided Cq to numeric value to numeric
      SC_plot_data$userProvidedCqValue <- as.numeric(SC_plot_data$userProvidedCqValue)
      SC_plot_data$LOQ<- as.numeric(SC_plot_data$LOQ)
      SC_plot_data$LOD<- as.numeric(SC_plot_data$LOD)

      #Add column with residual values to data set
      regression_line <- lm(as.numeric(userProvidedCqValue) ~ as.numeric(standardConc), SC_plot_data)
      SC_plot_data$Residual <- abs(residuals(regression_line))

      #Code to get R squared
      #Adapted from: https://stackoverflow.com/questions/7549694/add-regression-line-equation-and-r2-on-graph
      # Code to get equation of the line and R-squared
      # Adapted from: https://groups.google.com/forum/#!topic/ggplot2/1TgH-kG5XMA

      lm_eq <- function(df){

        model1 <- lm(userProvidedCqValue ~ standardConc, df, na.action=na.exclude)

        b = format(unname(coef(model1)[1]), digits = 2)

        mx = paste("(", format(unname(coef(model1)[2]), digits = 2), "x", ")",  sep = "")

        r2 = format(summary(model1)$r.squared, digits = 3)

        equation_of_line <- paste("y", " = ", mx, " + ", b, ",   ", "R-squared", " = ", r2,  sep = "")

        return (equation_of_line)

      }



      print(

        ggplotly(height = 700,

                 ggplot(data = SC_plot_data, aes(x = standardConc,
                                                 y = userProvidedCqValue,
                                                 color = Residual)) +

                   geom_point(size = 10, alpha = .3) +

                   geom_smooth(method = "lm",
                               se = FALSE,
                               alpha = .15,
                               color = 'black',
                               formula = y ~ x) +

                   geom_vline(xintercept = log(SC_plot_data$LOD),
                              color = "#ea5f94",
                              linetype="dashed") +

                   geom_vline(xintercept = log(SC_plot_data$LOQ),
                              color = "#0178A1",
                              linetype="dotted") +

                   geom_text(aes(x= log(LOD),
                                 label="LOD",
                                 y= mean(userProvidedCqValue)),
                             colour="#ea5f94",
                             angle=90,
                             vjust = 1.2,
                             size=5) +

                   geom_text(aes(x= log(LOQ),
                                 label="LOQ",
                                 y= mean(userProvidedCqValue)*1.2),
                             colour="#0178A1",
                             angle=90,
                             vjust = 1.2,
                             size=5) +


                   xlab("log DNA Copy Number") +

                   ylab("Cq") +

                   theme_minimal() +

                   scale_color_gradient(low = "#fbd300", high = "#0000ff") +

                   theme( axis.title.x = element_text( size=13),
                          axis.title.y = element_text( size=13),
                          axis.text.x = element_text(size=12),
                          axis.text.y = element_text(size=12),
                          plot.title = element_text(hjust = 0.5, size=18)) +

                   ggtitle(paste0("Standard Curve for ", input$SC_project_input,  "\n",
                                  lm_eq(SC_plot_data)))

        ) %>%

          layout(margin = list(l=50, r=50, b=100, t=100, pad=4),
                 annotations = list(x = 1.1, y = -0.17,
                                    text = "Source: MDMAPR-CC-BY",
                                    showarrow = F,
                                    xref='paper',
                                    yref='paper',
                                    font=list(size=12, color="darkblue"))))
    })
  })
  )


  ##Presence Absence table

  #Colour cell value by Cqvalue to indicate if species is present or absent
  what_clr <- function(value) {
    if (value >= input$cqValueCutoff)
    {return ("#8FBACB")}

    else
    {return("#ffb14e")}
  }


  available_threshold <- function(value) {
    if (value == "Unable to Determine Threshold")
    {return ("#ffd700")}
  }


  #Transform dataframe for presence/absence table based on filtered
  presence_absence_table_data <- reactive({

    if (dbExists == "Yes" | !is.null(user_uploaded_qPCR_data())) {

      data <- MySQL_mergedData()

      PA_filtered_data <- data[data$assayName == input$SC_assay_input, ]
      PA_filtered_data <- PA_filtered_data[PA_filtered_data$runPlatform == input$SC_machine_input, ]
      PA_filtered_data <- PA_filtered_data[PA_filtered_data$projectName == input$SC_project_input, ]

    }
  })


  #Presence/absence table
  observeEvent(input$DA_submit, isolate ({

    output$presence_absence_table <- renderReactable({
      data <- as.data.frame(presence_absence_table_data())

      prescence_abscence_table <- data[ , c("projectName", "runID", "extractName", "control", "geneSymbol", "runPlatform", "wellLocation", "userProvidedThresholdValue", "userProvidedCqValue", "systemCalculatedThresholdValue", "systemCalculatedCqValue" )]

      reactable(prescence_abscence_table,

                #Table columns
                columns = list(

                  projectName = colDef(name = "Project Name",align = "center", width = 300),
                  runID = colDef(name = "Plate ID", align = "center"),
                  extractName = colDef(name = "Sample Name", align = "center", width = 200),
                  control = colDef(name = "Control", align = "center"),
                  geneSymbol = colDef(name = "Gene", align = "center"),
                  runPlatform = colDef(name = "Machine", align = "center"),
                  wellLocation = colDef(name = "Well Location", align = "center", width = 200),

                  userProvidedThresholdValue = colDef(name = "User Provided Threshold",
                                                      align = "center",
                                                      width = 300),

                  userProvidedCqValue = colDef(name = "User Provided Cq Value",
                                               width = 250,
                                               style = function(value) {
                                                 color  <- what_clr(value)
                                                 list(background = color)}),

                  systemCalculatedThresholdValue = colDef(name = "System Calculated Threshold",
                                                          width = 300,
                                                          align = "center",
                                                          style = function(value) {
                                                            color  <- available_threshold(value)
                                                            list(background = color)}),

                  systemCalculatedCqValue = colDef(name = "System Calculated Cq Value",
                                                   width = 250,
                                                   style = function(value) {
                                                     color  <- what_clr(value)
                                                     list(background = color)})),

                #Filter each column by text
                filterable = TRUE,

                #Type in page number to jump to a page
                paginationType = "jump",

                #Minimum rows shown on page
                minRows = 20,

                #Number of rows to show
                defaultPageSize = 20,

                #Adding outline around cells
                outlined = TRUE,

                #Color every other row
                striped = TRUE,

                #Hover above row to highlight it
                highlight = TRUE,

                #Default record selected from table
                defaultSelected = 1,

                #Check box
                selection = "single",

                #Wrap text in column
                wrap = FALSE,

                theme = reactableTheme(rowSelectedStyle = list(backgroundColor = "#eee",
                                                               boxShadow = "inset 2px 0 0 0 #ffa62d"))
      )
    })
  }))


  ## Amplification plot

  #Get selected row for amplification plot
  selected <- reactive(getReactableState("presence_absence_table", "selected"))

  #Created amplifcation plot based on selected well sample

  observeEvent(input$DA_submit, isolate({

    output$selected <-  renderPlotly({

      #Created dataframe of filtered presence/absence data
      data <- as.data.frame(presence_absence_table_data())[selected(), ]


      #Create data frame for amplification curve
      amp_curve_data <- na.omit(as.data.frame(t(data[ , c(14:83)])))
      colnames(amp_curve_data) <- "Fluorescence"
      amp_curve_data$cycles <- c(1:nrow(amp_curve_data))


      #Created plot
      print(
        ggplotly(height = 700,

                 ggplot(amp_curve_data, aes(x = cycles, y = as.numeric(Fluorescence))) +

                   geom_point(aes(colour = "Absorbances") , size = 2) +

                   geom_hline(aes(yintercept = as.numeric(data$userProvidedThresholdValue),
                                  color = "User Provided Threshold"),
                              linetype="dashed", size = 1) +

                   geom_hline(aes(yintercept = as.numeric(data$systemCalculatedThresholdValue),
                                  color = "System Calculated Threshold"),
                              linetype="dotted", size = 1) +


                   ggtitle(paste0( "Well ", data$wellLocation, " Amplification Curve")) +

                   labs(x = " Cycle", y = "Absorbance") +

                   theme_gray() +

                   scale_colour_manual("",
                                       breaks = c("Absorbances",
                                                  "User Provided Threshold",
                                                  "System Calculated Threshold"),
                                       values = c("User Provided Threshold"="#ea5f94",
                                                  "Absorbances"="#0000ff",
                                                  "System Calculated Threshold"="#ff8600")) +

                   theme(plot.title = element_text(hjust = 0.5, size=18),
                         axis.title.x = element_text( size=13),
                         axis.title.y = element_text( size=13),
                         axis.text.x = element_text(size=12),
                         axis.text.y = element_text(size=12),
                         legend.text = element_text(size = 10),
                         legend.background = element_rect(fill="lightblue")))  %>%

          layout(legend = list(orientation = "h", x = 0.02, y = -0.16), #legend position
                 margin = list(l=50, r=60, b=140, t=100, pad=4),
                 annotations = list(x = 1, y = -0.31,
                                    text = "Source: MDMAPR-CC-BY",
                                    showarrow = F,
                                    xref='paper',
                                    yref='paper',
                                    font=list(size=12,
                                              color="darkblue"))))})
  }))


  #Reset dropdown menu selections for standard curve plot
  observeEvent(input$DA_reset,
               {shinyjs::reset("SC_assay_input") #assay selected
                 shinyjs::reset("SC_machine_input") #machine selected
                 shinyjs::reset("SC_project_input") #project selected
                 shinyjs::reset("SC_input") #standard curve selected
               })


  #Reset Uploaded files
  observeEvent(input$Uploaded_DA_reset,


               {shinyjs::reset("SC_fluorescence_file") #standard curve fluorescence file
                 shinyjs::reset("SC_metadata_file") #reset uploaded standard curve metadata file
                 shinyjs::reset("qPCR_fluorescence_file") #reset uploaded qPCR fluorescene file
                 shinyjs::reset("qPCR_metadata_file") #reset uploaded qPCR metadata file
                 updateSelectInput(session,
                                   "DA_platform",
                                   label = "qPCR Platform",
                                   choices = c("None",
                                               "StepOnePlus",
                                               "Biomeme two3/Franklin",
                                               "MIC"),
                                   selected = "None") #reset selected platform
               })


  #Standarc Curve Data table
  output$SC_overview_table  <- renderDataTable({

    data <- standard_curve_data_for_plot()[ , -c(1, 2, 3, 4, 102)]

    datatable(data,
              options = list(scrollX = TRUE,
                             autoWidth = TRUE,
                             columnDefs = list(list(width = '500px', targets = c(84)))))})



  #Data Submission Page   ---------------------------

  #Return popup messaged regarding uploaded fluorescence file
  observeEvent(input$DS_qpcr_file,
               fluorescence_file_validation_msgs(input$DS_qpcr_file))


  #Return popup messaged regarding uploaded standard curve fluorescence file
  observeEvent(input$DS_standardCurve_fluorescence_file,
               fluorescence_file_validation_msgs(input$DS_standardCurve_fluorescence_file))


  #Return popup messaged regarding uploaded metadata file file
  observeEvent(input$DS_metadata_file,
               metadata_file_validation_msgs(input$DS_metadata_file))


  #Return popup messaged regarding uploaded fluorescence and metadata file, based on machine type.
  observeEvent(req(input$DS_qpcr_file,
                   input$DS_standardCurve_fluorescence_file,
                   input$DS_metadata_file,
                   input$DS_platform),

               selected_platform_validation_msgs_SC_and_Experimental_flur(input$DS_qpcr_file,
                                                                          input$DS_standardCurve_fluorescence_file,
                                                                          input$DS_metadata_file,
                                                                          input$DS_platform))

  #Validate messaged based on uploaded data on Data Submission page.
  DS_error_message <- reactive({
    validate(
      need(input$DS_qpcr_file, 'No fluorescence file uploaded'),
      need(input$DS_metadata_file, 'No metadata file uploaded'),
      need(try(file_ext(input$DS_qpcr_file) == "csv" |
                 file_ext(input$DS_qpcr_file) == "xlsx" |
                 file_ext(input$DS_qpcr_file) == "xls")
           ,
           "fluorescence file must be csv or xlsx/xls"),
      need(try(file_ext(input$DS_metadata_file) == "xlsx" |
                 file_ext(input$DS_metadata_file) == "xls")
           , "Metadata file must be xlsx/xls")
    )
  })

  output$DS_error_msg <- renderText({DS_error_message()})


  #Function to process uploaded qPCR fluorescence and metadata on data submission page
  uploaded_data_dataSubmissionPage <-  reactive({

    #No qPCR file input
    if (user_uploaded_file_validate(input$DS_qpcr_file,
                                    input$DS_metadata_file,
                                    input$DS_platform) == TRUE)
    {return(NULL)}


    else{
      if (input$DS_platform == "Biomeme two3/Franklin") {

        #Read in raw qPCR data
        qpcr_biomem23_raw <- process_biomeme23_uploaded_file(read.csv(input$DS_qpcr_file$datapath))

        #Read in metadata
        metadata_biomem23 <- format_qPCR_metadata(input$DS_metadata_file$datapath)


        #Function to process and merge files
        merged_biomem23_file <- merge_metadata_fluorescence_file(qpcr_biomem23_raw, metadata_biomem23)

        #This merged datatable that will be used to populate map
        return(merged_biomem23_file)
      }


      ### Machine Option 2: MIC ###
      else if (input$DS_platform == "MIC") {

        #Read in raw qPCR data
        qpcr_MIC_raw  <- process_MIC_uploaded_file(read.csv(input$DS_qpcr_file$datapath))


        #Read in metadata
        metadata_MIC <- format_qPCR_metadata(input$DS_metadata_file$datapath)


        #Function to process and merge files
        merged_mic_file <- merge_metadata_fluorescence_file(qpcr_MIC_raw, metadata_MIC)


        #This merged datatable that will be used to populate map
        return(merged_mic_file)
      }


      ### Machine Option 3: StepOnePlus ###
      else if (input$DS_platform == "StepOnePlus") {


        #Read in raw qPCR data
        qpcr_StepOnePlus_raw <- process_SOP_uploaded_file(read_excel(input$DS_qpcr_file$datapath,
                                                                     4))

        #Read in metadata
        metadata_StepOnePlus <-format_qPCR_metadata(input$DS_metadata_file$datapath)


        #Function to process and merge files
        merged_StepOnePlus_file <- merge_metadata_fluorescence_file(qpcr_StepOnePlus_raw,
                                                                    metadata_StepOnePlus)

        return(merged_StepOnePlus_file)

      }
    }})


  #Function to process uploaded standard curve fluorescence and metadata on data submission page

  uploaded_standard_curve_data_dataSubmissionPage <-  reactive({

    #No qPCR file input
    if (user_uploaded_standard_curve_file_validation(input$DS_standardCurve_fluorescence_file,
                                                     input$DS_metadata_file, input$DS_platform) == TRUE)
    {return(NULL)}


    else{

      if (input$DS_platform == "Biomeme two3/Franklin") {

        #Read in raw qPCR data
        qpcr_biomem23_raw <- process_biomeme23_uploaded_file(read.csv(input$DS_standardCurve_fluorescence_file$datapath))

        #Read in metadata
        metadata_biomem23 <- format_standardCurve_metadata(read_xlsx(input$DS_metadata_file$datapath, sheet = 5))

        #Function to process and merge files
        merged_biomem23_file <- merge_standardCurve_metadata_fluorescence_file(qpcr_biomem23_raw, metadata_biomem23)

        #This merged datatable that will be used to populate map
        return(merged_biomem23_file)

      }


      ### Machine Option 2: MIC ###
      else if (input$DS_platform == "MIC") {

        #Read in raw qPCR data
        qpcr_MIC_raw  <- process_MIC_uploaded_file(read.csv(input$DS_standardCurve_fluorescence_file$datapath))

        #Read in metadata
        metadata_MIC <- format_standardCurve_metadata(read_xlsx(input$DS_metadata_file$datapath, sheet = 5))

        #Function to process and merge files
        merged_mic_file <- merge_standardCurve_metadata_fluorescence_file(qpcr_MIC_raw, metadata_MIC)


        #This merged datatable that will be used to populate map
        return(merged_mic_file)
      }

      ### Machine Option 3: StepOnePlus ###
      else if (input$DS_platform == "StepOnePlus") {

        #Read in raw qPCR data
        qpcr_StepOnePlus_raw <- process_SOP_uploaded_file(read_excel(input$DS_standardCurve_fluorescence_file$datapath, 4))

        #Read in metadata
        metadata_StepOnePlus <- format_standardCurve_metadata(read_xlsx(input$DS_metadata_file$datapath, sheet = 5))

        #Function to process and merge files
        merged_StepOnePlus_file <- merge_standardCurve_metadata_fluorescence_file(qpcr_StepOnePlus_raw,
                                                                                  metadata_StepOnePlus)


        return(merged_StepOnePlus_file)

      }

    }})



  #Show tables of uploaded data on data Submission Page ************************

  #project information Table
  project_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    project_table <- create_project_table(uploaded_merged_data)

  })


  output$projectTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(project_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })



  #Geographic Region Table
  geographicRegion_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    geographicRegion_table <- create_geographicRegion_Table(uploaded_merged_data)

  })


  output$geographicRegionTable <- renderDataTable({
    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(geographicRegion_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #Site Table
  site_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    site_table <- create_site_Table(uploaded_merged_data)

  })


  output$siteTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(site_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #Station Table
  station_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    station_table <- create_station_Table(uploaded_merged_data)

  })


  output$stationTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(station_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })



  #Replicate Table
  replicate_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    replicate_table <- create_replicate_Table(uploaded_merged_data)

  })


  output$replicateTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(replicate_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #Extract Table
  extract_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    extract_table <- create_extract_Table(uploaded_merged_data)
  })


  output$extractTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(extract_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })



  #Run Information Table
  runInformation_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    uploaded_SC_merged_data <- as.data.frame(uploaded_standard_curve_data_dataSubmissionPage())

    runInformation_table <- create_runInformation_Table(uploaded_merged_data, uploaded_SC_merged_data)
  })


  output$runInformationTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)
    req(input$DS_standardCurve_fluorescence_file)

    datatable(runInformation_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })



  #Results Table
  results_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    results_table <- create_results_Table(uploaded_merged_data)

  })


  output$resultsTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(results_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #Assay Table
  assay_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    assay_table <- create_assay_Table(uploaded_merged_data)

  })


  output$assayTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(assay_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #taxonomic Table
  taxon_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    taxon_table <- create_taxon_Table(uploaded_merged_data)

  })


  output$taxonomicTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)

    datatable(taxon_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #PCR Chemistry Table
  pcrChemistry_data <- reactive({

    uploaded_merged_data <- as.data.frame(uploaded_data_dataSubmissionPage())
    uploaded_SC_merged_data <- as.data.frame(uploaded_standard_curve_data_dataSubmissionPage())
    pcrChemistry_table <- create_pcrChemistry_Table(uploaded_merged_data, uploaded_SC_merged_data)

  })


  output$pcrChemistryTable <- renderDataTable({

    req(input$DS_qpcr_file)
    req(input$DS_metadata_file)
    req(input$DS_standardCurve_fluorescence_file)

    datatable(pcrChemistry_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #Standard Curve Table
  standardCurve_data <- reactive({

    uploaded_SC_merged_data <- as.data.frame(uploaded_standard_curve_data_dataSubmissionPage())
    standardCurve_table <- create_standardCurve_Table(uploaded_SC_merged_data)

  })


  output$standardCurveTable <- renderDataTable({

    req(input$DS_standardCurve_fluorescence_file)
    req(input$DS_metadata_file)

    datatable(standardCurve_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  #Standard Curve Results Table
  standardCurveResults_data <- reactive({

    uploaded_SC_merged_data <- as.data.frame(uploaded_standard_curve_data_dataSubmissionPage())
    standardCurveResults_table <- create_standardCurveResults_Table(uploaded_SC_merged_data)
  })


  output$standardCurveResultsTable <- renderDataTable({

    req(input$DS_standardCurve_fluorescence_file)
    req(input$DS_metadata_file)

    datatable(standardCurveResults_data(),
              rownames = FALSE,
              options = list(scrollX = TRUE))
  })


  # Download Data Submission files
  #Adapted from: https://groups.google.com/forum/#!topic/shiny-discuss/zATYJCdSTwk
  output$downloadData <- downloadHandler(
    filename = 'MySQL_Upload_data.zip',
    content = function(fname) {
      fs <- c("projectDataTable.csv",
              "geographicRegionTable.csv",
              "siteTable.csv",
              "stationTable.csv",
              "replicateTable.csv",
              "extractTable.csv",
              "runInformationTable.csv",
              "resultsTable.csv",
              "assayTable.csv",
              "taxonTable.csv",
              "pcrChemistryTable.csv",
              "standardCurveTable.csv",
              "standardCurveResultsTable.csv")

      write.csv(
        project_data(),
        file = "projectDataTable.csv",
        sep = ",",
        row.names = FALSE,
        na = "NULL")

      write.csv(
        geographicRegion_data(),
        file = "geographicRegionTable.csv",
        sep = ",",
        row.names = FALSE,
        na = "NULL")

      write.csv(site_data(),
                file = "siteTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(station_data(),
                file = "stationTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(replicate_data(),
                file = "replicateTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(extract_data(),
                file = "extractTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(runInformation_data(),
                file = "runInformationTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(results_data(),
                file = "resultsTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(assay_data(),
                file = "assayTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(taxon_data(),
                file = "taxonTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(pcrChemistry_data(),
                file = "pcrChemistryTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(standardCurve_data(),
                file = "standardCurveTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      write.csv(standardCurveResults_data(),
                file = "standardCurveResultsTable.csv",
                sep = ",",
                row.names = FALSE,
                na="NULL")

      zip(zipfile=fname, files=fs)
    },

    contentType = "application/zip")


  #Reset uploaded file input and selected machine type on data submission page
  observeEvent(input$DS_reset, {
    updateSelectInput(session, "DS_platform",
                      label = "qPCR Platform",
                      choices = c("None",
                                  "StepOnePlus",
                                  "Biomeme two3/Franklin",
                                  "MIC"),
                      selected = "None")

    shinyjs::reset("DS_qpcr_file")
    shinyjs::reset("DS_metadata_file")
    shinyjs::reset("DS_standardCurve_fluorescence_file")})


  ## Get Started Page (Creat downloadable metadata template) -----

  #Created  metadata template for users to download
  project_sheet <- data.frame(matrix(ncol = 24, nrow = 1))

  colnames(project_sheet) <- c("projectID", "projectCreationDate","projectName","projectRecordedBy","projectOwner","projectContactEmail","projectDescription","InstitutionID","projectDataNotes","geographicRegionID", "continent","country", "stateProvince","municipality","siteID", "locality","estimatedPerimeter","estimatedSurfaceArea(m2)","siteType","siteLength(m2)", "stationID","stationName", "decimalLongitude", "decimalLatitude")


  replicate_sheet <- data.frame(matrix(ncol = 55, nrow = 1))
  colnames(replicate_sheet) <- c("replicateID", "stationID", "collectorName","replicateName","collectionDate","collectionTime","storageID","DateOfStorage","methodOfStorage","minimumElevationInMeters","maximumElevationInMeters","verbatimElevation","minimumDepthInMeters","maximumDepthInMeters","verbatimDepth","flowRate(m/s)", "filterType","filtrationDuration(mins)","volumeFiltered","processLocation","replicationNumber","riparianVegetationPercentageCover","dissolvedOxygen(mg/L)","waterTemperature(C)","pH","TSS(mg/L)","EC(uS/cm)","turbidity(NTU)","discharge","tide","chlorophyl","salinity(ppt)","contaminants(ng/g)","traceMetals(mg/kg)","organicContent(%)","microbialActivity","grainSize","replicateDataNotes", "extractID", "extractName","analyst", "extractionDate", "extractionTime", "location", "extractionMethod", "methodCitation", "extractionNotes","tubePlateID","frozen", "fixed","dnaStorageLocation","extractMethodOfStorage","dnaVolume","quantificationMethod", "concentration(ng/ul)")


  assay_sheet <- data.frame(matrix(ncol = 30, nrow = 1))
  colnames(assay_sheet) <- c( "assayID", "establishmentMeans","assayName","assayOwnership","assayDescription", "assayCitation", "assayDate", "geneTarget", "geneSymbol","dilutions", "replicates", "primerR", "primerF", "probe","ampliconLength (bp)", "probeFluorescentTag", "dye(s)","quencher","probeModification", "taxonID", "kingdom","phylum","class","order","family", "genus", "subgenus", "species", "vernacularName","organismScope")

  results_sheet <- data.frame(matrix(ncol = 29, nrow = 1))
  colnames(results_sheet) <- c("resultID","assayID", "extractID", "wellLocation","sampleName", "copyNumber", "control", "userProvidedThresholdValue", "userProvidedCqValue", "runID", "runRecordedBy", "runDate", "runTime","runPlatform","machineID", "pcrChemistryID","reactionConditions","reactionVolume","templateAmount","forwardPrimerBatch", "reversePrimerBatch", "dNTPConcentration", "primerConcentration","probeConcentration", "Mg2+Concentration", "polymeraseBatch","polymeraseConcentrations","thermocyclerParameters", "pcrDataNotes")

  standardCurveResults_sheet <- data.frame(matrix(ncol = 36, nrow = 1))
  colnames(standardCurveResults_sheet ) <- c("SCresultID","wellLocation","sampleName", "copyNumber", "control","standardConc",   "userProvidedThresholdValue", "userProvidedCqValue","runID", "runRecordedBy", "runDate", "runTime", "runPlatform","machineID", "standardCurveID","assayID", "standardCurveName", "SCdate", "SCrecordedBy", "SCdataNotes", "LOD","LOQ", "pcrChemistryID","reactionConditions","reactionVolume","templateAmount","forwardPrimerBatch", "reversePrimerBatch", "dNTPConcentration", "primerConcentration","probeConcentration", "Mg2+Concentration", "polymeraseBatch","polymeraseConcentrations","thermocyclerParameters", "pcrDataNotes")


  data_list <- (list( project_Table = project_sheet,
                      replicate_Table = replicate_sheet,
                      assay_Table = assay_sheet,
                      results_Table = results_sheet,
                      standardCurveResults_Table = standardCurveResults_sheet ))

  output$downloadTemplate <- downloadHandler(
    filename = 'MDMap_metadata_template.xlsx',
    content = function(file) {write_xlsx(data_list, file)})



  #Available Data page ---------------------------

  output$availableDataTable <- renderReactable({

    if (dbExists == "Yes") {

      availableAssays <- my_sql_data[ , c("taxonID", "assayID", "assayName", "assayOwnership", "assayDescription", "assayCitation", "assayDate", "establishmentMeans", "geneTarget", "geneSymbol", "dilutions", "replicates", "primerR", "primerF", "probe", "ampliconLength (bp)", "probeFluorescentTag", "dye(s)", "quencher",  "probeModification")]

      availableAssays  <- distinct(availableAssays)

      taxonData <- as.data.frame(unique(my_sql_data[, c("taxonID", "kingdom", "phylum", "class", "order", "family", "genus", "subgenus", "species", "vernacularName", "organismScope")]))


      reactable(taxonData,
                details = function(index) {
                  assay_data <- availableAssays[availableAssays$taxonID == taxonData$taxonID[index], ]
                  htmltools::div(style = "padding: 16px",
                                 reactable(assay_data[ , -c(1)],

                                           columns = list(
                                             assayID = colDef(name = "Assay ID", align = "left"),
                                             assayName = colDef(name = "Name", align = "left"),
                                             assayOwnership = colDef(name = "Ownership",
                                                                     align = "left"),

                                             assayDescription = colDef(name = "Description",
                                                                       align = "left"),

                                             assayCitation = colDef(name = "Citation",
                                                                    align = "left"),

                                             assayDate = colDef(name = "Date", align = "left"),

                                             establishmentMeans = colDef(name = "Establishment Means",
                                                                         align = "left",
                                                                         minWidth = 500),

                                             geneTarget = colDef(name = "Gene Target",
                                                                 align = "left",
                                                                 minWidth = 500),

                                             geneSymbol = colDef(name = "Gene Symbol",
                                                                 align = "left"),

                                             dilutions = colDef(name = "Dilutions",
                                                                align = "left"),

                                             replicates = colDef(name = "Replicates",
                                                                 align = "left"),

                                             primerR = colDef(name = "Reverse Primer",
                                                              align = "left"),

                                             primerF = colDef(name = "Forward Primer",
                                                              align = "left"),

                                             probe = colDef(name = "Probe", align = "left"),

                                             `ampliconLength (bp)` = colDef(name = "Amplicon Length (bp)",
                                                                            align = "left",
                                                                            minWidth = 500),

                                             probeFluorescentTag = colDef(name = "Probe Fluorescent Tag",
                                                                          align = "left",
                                                                          minWidth = 500),


                                             quencher = colDef(name = "Quencher", align = "left"),

                                             probeModification = colDef(name = "Probe Modification",
                                                                        align = "left",
                                                                        minWidth = 500)),

                                           outlined = TRUE,

                                           wrap =  FALSE,

                                           defaultColDef = colDef(minWidth = 300),
                                           theme = reactableTheme(
                                             rowSelectedStyle = list(backgroundColor = "#eee", boxShadow = "inset 2px 0 0 0 #ffa62d"))))},

                columns = list(
                  taxonID = colDef(name = "Taxon ID", align = "left"),
                  kingdom = colDef(name = "Kingdom", align = "left"),
                  phylum = colDef(name = "Phylum", align = "left"),
                  class = colDef(name = "Class", align = "left"),
                  order = colDef(name = "Order", align = "left"),
                  family = colDef(name = "Family", align = "left"),
                  genus = colDef(name = "Genus", align = "left"),
                  subgenus = colDef(name = "Subgenus", align = "left"),
                  species = colDef(name = "Species", align = "left", minWidth = 500),
                  vernacularName = colDef(name = "Vernacular Name",
                                          align = "left",
                                          minWidth = 500),
                  organismScope = colDef(name = "Organism Scope",
                                         align = "left",
                                         minWidth = 500)),

                theme = reactableTheme(
                  rowSelectedStyle = list(backgroundColor = "#eee",
                                          boxShadow = "inset 2px 0 0 0 #ffa62d")),

                #Wrap column text
                wrap = FALSE,

                #Default column width
                defaultColDef = colDef(minWidth = 300),

                #Type in page number to jump to a page
                paginationType = "jump",

                #Minimum rows shown on page
                minRows = 10,

                #Number of rows to show
                defaultPageSize = 10,

                #Adding outline around cells
                outlined = TRUE,

                striped = TRUE,

                highlight = TRUE)} })




}

Try the MDMAPR package in your browser

Any scripts or data that you put into this service are public.

MDMAPR documentation built on June 23, 2021, 9:08 a.m.