]> nmode's Git Repositories - Rnaught/commitdiff
Update Shiny app
authorNaeem Model <me@nmode.ca>
Sun, 9 Jun 2024 16:01:51 +0000 (16:01 +0000)
committerNaeem Model <me@nmode.ca>
Sun, 9 Jun 2024 16:01:51 +0000 (16:01 +0000)
- Remove template/logic for single data entry
- Change 'Add estimators' to 'About estimators'; adding estimators and viewing estimates are now done in the same tab
- Swap rows and columns in estimates table (estimators as row names, datasets as column names)
- Add a separate column for the serial interval to the estimates table
- Add plots for daily and weekly data using the Plotly library
- Remove italics from the subscript in all occurences of 'R_0'
- Fix code/text formatting

50 files changed:
DESCRIPTION
R/app.R
inst/app/scripts/data.R
inst/app/scripts/estimators.R
inst/app/templates/content.html
inst/app/templates/content/about.html
inst/app/templates/content/data.html
inst/app/templates/content/data/enter-data.html
inst/app/templates/content/data/enter-data/bulk-entry.html [deleted file]
inst/app/templates/content/data/enter-data/entry.html [deleted file]
inst/app/templates/content/data/enter-data/load-samples.html
inst/app/templates/content/data/enter-data/manual-entry.html [new file with mode: 0644]
inst/app/templates/content/data/enter-data/required-format.html [new file with mode: 0644]
inst/app/templates/content/data/enter-data/single-entry.html [deleted file]
inst/app/templates/content/data/enter-data/upload-data.html [new file with mode: 0644]
inst/app/templates/content/data/view-data.html
inst/app/templates/content/data/view-data/data-plots.html [new file with mode: 0644]
inst/app/templates/content/data/view-data/data-table.html [new file with mode: 0644]
inst/app/templates/content/estimation.html [new file with mode: 0644]
inst/app/templates/content/estimation/about-estimators.html [new file with mode: 0644]
inst/app/templates/content/estimation/about-estimators/id.html [new file with mode: 0644]
inst/app/templates/content/estimation/about-estimators/idea.html [moved from inst/app/templates/content/estimators/add-estimators/descriptions/idea.html with 100% similarity]
inst/app/templates/content/estimation/about-estimators/panel.html [moved from inst/app/templates/content/estimators/add-estimators/components/panel.html with 51% similarity]
inst/app/templates/content/estimation/about-estimators/seq_bayes.html [moved from inst/app/templates/content/estimators/add-estimators/descriptions/seq_bayes.html with 100% similarity]
inst/app/templates/content/estimation/about-estimators/wp.html [moved from inst/app/templates/content/estimators/add-estimators/descriptions/wp.html with 100% similarity]
inst/app/templates/content/estimation/estimates.html [new file with mode: 0644]
inst/app/templates/content/estimation/estimates/add-estimators.html [new file with mode: 0644]
inst/app/templates/content/estimation/estimates/add-estimators/id.html [new file with mode: 0644]
inst/app/templates/content/estimation/estimates/add-estimators/idea.html [new file with mode: 0644]
inst/app/templates/content/estimation/estimates/add-estimators/mu.html [moved from inst/app/templates/content/estimators/add-estimators/components/mu.html with 86% similarity]
inst/app/templates/content/estimation/estimates/add-estimators/parameters.html [new file with mode: 0644]
inst/app/templates/content/estimation/estimates/add-estimators/seq_bayes.html [moved from inst/app/templates/content/estimators/add-estimators/parameters/seq_bayes.html with 70% similarity]
inst/app/templates/content/estimation/estimates/add-estimators/wp.html [moved from inst/app/templates/content/estimators/add-estimators/parameters/wp.html with 94% similarity]
inst/app/templates/content/estimation/estimates/estimates-table.html [new file with mode: 0644]
inst/app/templates/content/estimators.html [deleted file]
inst/app/templates/content/estimators/add-estimators.html [deleted file]
inst/app/templates/content/estimators/add-estimators/descriptions/id.html [deleted file]
inst/app/templates/content/estimators/add-estimators/descriptions/mu.html [deleted file]
inst/app/templates/content/estimators/add-estimators/parameters/id.html [deleted file]
inst/app/templates/content/estimators/add-estimators/parameters/idea.html [deleted file]
inst/app/templates/content/estimators/add-estimators/parameters/mu.html [deleted file]
inst/app/templates/content/estimators/view-estimates.html [deleted file]
inst/app/templates/content/help.html
inst/app/templates/content/help/example-help-1.html [deleted file]
inst/app/templates/content/help/example-help-2.html [deleted file]
inst/app/templates/content/help/serial-interval.html
inst/app/templates/navbar.html
inst/app/templates/tabs.html
inst/app/www/script.js
inst/app/www/styles.css

index 7a5b6e8c0b98923c6b39c815a937ece3a0b87c33..774891e5bddc7ddb37122f36f5e6ff91d5fc4751 100644 (file)
@@ -19,9 +19,10 @@ Imports:
 Suggests: 
     knitr,
     rmarkdown,
-    shiny,
     bslib,
-    DT
+    shiny,
+    DT,
+    plotly
 Encoding: UTF-8
 LazyData: true
 Roxygen: list(markdown = TRUE)
diff --git a/R/app.R b/R/app.R
index 01f35b470ff5e13726a2186756f1c06bf2c0fbae..23e32ab8674be017cf43500d9e8ed941172c6714 100644 (file)
--- a/R/app.R
+++ b/R/app.R
@@ -6,15 +6,18 @@
 app <- function() {
   missing_pkgs <- c()
   # Check for any missing, required packages.
-  if (!requireNamespace("shiny", quietly = TRUE)) {
-    missing_pkgs <- c(missing_pkgs, "shiny")
-  }
   if (!requireNamespace("bslib", quietly = TRUE)) {
     missing_pkgs <- c(missing_pkgs, "bslib")
   }
+  if (!requireNamespace("shiny", quietly = TRUE)) {
+    missing_pkgs <- c(missing_pkgs, "shiny")
+  }
   if (!requireNamespace("DT", quietly = TRUE)) {
     missing_pkgs <- c(missing_pkgs, "DT")
   }
+  if (!requireNamespace("plotly", quietly = TRUE)) {
+    missing_pkgs <- c(missing_pkgs, "plotly")
+  }
 
   # If any of the required packages are missing,
   # prompt the user to install them.
index 02b57c569700b4f797a72f9c9151baccd65a38bb..c85e27b057ed6fc2b6dd18d9ff4a065d1892ba27 100644 (file)
@@ -8,12 +8,12 @@ data_logic <- function(input, output, react_values) {
     check.names = FALSE
   )
 
-  render_plot(input, output)
-  single_entry(input, output, react_values)
-  manual_bulk_entry(input, output, react_values)
+  manual_entry(input, output, react_values)
   upload_data(input, output, react_values)
   load_samples(input, output, react_values)
-  render_data(output, react_values)
+  render_data_table(output, react_values)
+  render_plot(input, output, react_values, "Days")
+  render_plot(input, output, react_values, "Weeks")
   delete_data(input, react_values)
   export_data(output, react_values)
 }
@@ -23,91 +23,58 @@ tokenize_counts <- function(counts_str) {
   suppressWarnings(as.integer(unlist(strsplit(trimws(counts_str), ","))))
 }
 
-# Render the preview plot for single entry data.
-render_plot <- function(input, output) {
+# Render the plots for daily and weekly data when the data table is updated.
+render_plot <- function(input, output, react_values, time_units) {
   observe({
-    counts <- tokenize_counts(input$data_counts)
-    if (length(counts) > 0 && !anyNA(counts) && all(counts >= 0)) {
-      output$data_plot <- renderPlot(
-        plot(seq_along(counts) - 1, counts, type = "o", pch = 16, col = "black",
-          xlab = input$data_units, ylab = "Cases", cex.lab = 1.5,
-          xlim = c(0, max(length(counts) - 1, 1)), ylim = c(0, max(counts, 1))
+    datasets <- react_values$data_table[
+      which(react_values$data_table[["Time units"]] == time_units),
+    ]
+
+    data_plot <- plotly::plot_ly(type = "scatter", mode = "lines")
+    if (nrow(datasets) > 0) {
+      for (i in seq_len(nrow(datasets))) {
+        counts <- tokenize_counts(datasets[i, 3])
+        data_plot <- plotly::add_trace(data_plot,
+          x = seq_along(counts) - 1, y = counts, name = datasets[i, 1]
         )
-      )
-    } else {
-      output$data_plot <- renderPlot(
-        plot(NULL, xlim = c(0, 10), ylim = c(0, 10),
-          xlab = input$data_units, ylab = "Cases", cex.lab = 1.5
-        )
-      )
-    }
-  })
-}
-
-# Add a single dataset to the existing table.
-single_entry <- function(input, output, react_values) {
-  observeEvent(input$data_single, {
-    valid <- TRUE
-
-    # Ensure the dataset name is neither blank nor a duplicate.
-    name <- trimws(input$data_name)
-    if (name == "") {
-      output$data_name_warn <- renderText("The dataset name cannot be blank.")
-      valid <- FALSE
-    } else if (name %in% react_values$data_table[, 1]) {
-      output$data_name_warn <- renderText(
-        "There is already a dataset with the specified name."
-      )
-      valid <- FALSE
-    } else {
-      output$data_name_warn <- renderText("")
-    }
-
-    # Ensure the case counts are specified as a comma-separated of one or more
-    # non-negative integers.
-    counts <- tokenize_counts(input$data_counts)
-    if (length(counts) == 0) {
-      output$data_counts_warn <- renderText("Case counts cannot be blank.")
-      valid <- FALSE
-    } else if (anyNA(counts) || any(counts < 0)) {
-      output$data_counts_warn <- renderText(
-        "Case counts can only contain non-negative integers."
-      )
-      valid <- FALSE
-    } else {
-      output$data_counts_warn <- renderText("")
+      }
     }
 
-    if (valid) {
-      # Add the new dataset to the data table.
-      new_row <- data.frame(name, input$data_units, toString(counts))
-      colnames(new_row) <- c("Name", "Time units", "Case counts")
-      react_values$data_table <- rbind(react_values$data_table, new_row)
+    plot_title <- paste(
+      if (time_units == "Days") "Daily" else "Weekly", "case counts"
+    )
 
-      # Evaluate all existing estimators on the new dataset and update the
-      # corresponding row in the estimates table.
-      update_estimates_rows(new_row, react_values)
+    data_plot <- plotly::layout(data_plot, title = plot_title,
+      xaxis = list(title = time_units), yaxis = list(title = "Cases")
+    )
 
-      showNotification("Dataset added successfully.",
-        duration = 3, id = "notify-success"
+    data_plot <- plotly::config(data_plot, displaylogo = FALSE,
+      toImageButtonOptions = list(
+        filename = paste0("Rnaught_data_", tolower(time_units), "_plot")
       )
-    }
+    )
+
+    output[[paste0("data_plot_", tolower(time_units))]] <-
+      plotly::renderPlotly(data_plot)
   })
 }
 
-manual_bulk_entry <- function(input, output, react_values) {
+# Validate and add manually-entered datasets.
+manual_entry <- function(input, output, react_values) {
   observeEvent(input$data_bulk, {
-    validate_bulk_data(input, output, react_values, "data_area")
+    validate_data(input, output, react_values, "data_area")
   })
 }
 
+# Validate and add datasets from a CSV file.
 upload_data <- function(input, output, react_values) {
   observeEvent(input$data_upload, {
-    validate_bulk_data(input, output, react_values, "data_upload")
+    validate_data(input, output, react_values, "data_upload")
   })
 }
 
-validate_bulk_data <- function(input, output, react_values, data_source) {
+# Validate datasets and update the data table.
+validate_data <- function(input, output, react_values, data_source) {
   tryCatch(
     {
       if (data_source == "data_area") {
@@ -171,8 +138,8 @@ validate_bulk_data <- function(input, output, react_values, data_source) {
         react_values$data_table <- rbind(react_values$data_table, new_rows)
 
         # Evaluate all existing estimators on the new datasets and update the
-        # corresponding rows in the estimates table.
-        update_estimates_rows(new_rows, react_values)
+        # corresponding columns in the estimates table.
+        update_estimates_cols(new_rows, react_values)
 
         showNotification("Datasets added successfully.",
           duration = 3, id = "notify-success"
@@ -225,8 +192,8 @@ load_samples <- function(input, output, react_values) {
       react_values$data_table <- rbind(react_values$data_table, new_rows)
 
       # Evaluate all existing estimators on the sample datasets and update the
-      # corresponding rows in the estimates table.
-      update_estimates_rows(new_rows, react_values)
+      # corresponding columns in the estimates table.
+      update_estimates_cols(new_rows, react_values)
 
       showNotification("Datasets added successfully.",
         duration = 3, id = "notify-success"
@@ -236,30 +203,22 @@ load_samples <- function(input, output, react_values) {
 }
 
 # Render the data table when new datasets are added.
-render_data <- function(output, react_values) {
+render_data_table <- function(output, react_values) {
   observe({
-    output$data_table <- DT::renderDataTable(react_values$data_table)
+    output$data_table <- DT::renderDataTable(
+      react_values$data_table, rownames = FALSE
+    )
   })
 }
 
-# Delete rows in the data table,
-# and the corresponding rows in the estimates table.
+# Delete rows in the data table and the corresponding columns in the estimates
+# table.
 delete_data <- function(input, react_values) {
   observeEvent(input$data_delete, {
-    new_table <- react_values$data_table[-input$data_table_rows_selected, ]
-    if (nrow(new_table) > 0) {
-      rownames(new_table) <- seq_len(nrow(new_table))
-    }
-    react_values$data_table <- new_table
-
-    if (ncol(react_values$estimates_table) == 1) {
-      react_values$estimates_table <- data.frame(
-        Datasets = react_values$data_table[, 1]
-      )
-    } else {
-      react_values$estimates_table <-
-        react_values$estimates_table[-input$data_table_rows_selected, ]
-    }
+    rows_selected <- input$data_table_rows_selected
+    react_values$data_table <- react_values$data_table[-rows_selected, ]
+    react_values$estimates_table <-
+      react_values$estimates_table[, -(rows_selected + 2)]
   })
 }
 
@@ -276,26 +235,23 @@ export_data <- function(output, react_values) {
 }
 
 # When new datasets are added, evaluate all existing estimators on them and
-# add new rows to the estimates table.
-update_estimates_rows <- function(datasets, react_values) {
-  new_rows <- data.frame(
-    matrix(nrow = nrow(datasets), ncol = ncol(react_values$estimates_table))
+# add new columns to the estimates table.
+update_estimates_cols <- function(datasets, react_values) {
+  new_cols <- data.frame(
+    matrix(nrow = nrow(react_values$estimates_table), ncol = nrow(datasets))
   )
-  colnames(new_rows) <- colnames(react_values$estimates_table)
-
-  for (row in seq_len(nrow(datasets))) {
-    new_rows[row, 1] <- datasets[row, 1]
+  colnames(new_cols) <- datasets[, 1]
 
-    if (length(react_values$estimators) > 0) {
-      for (col in 2:ncol(react_values$estimates_table)) {
-        new_rows[row, col] <- eval_estimator(
-          react_values$estimators[[col - 1]], datasets[row, ]
-        )
+  if (nrow(new_cols) > 0) {
+    for (row in seq_len(nrow(new_cols))) {
+      estimator <- react_values$estimators[[row]]
+      for (col in seq_len(ncol(new_cols))) {
+        new_cols[row, col] <- eval_estimator(estimator, datasets[col, ])
       }
     }
   }
 
-  react_values$estimates_table <- rbind(
-    react_values$estimates_table, new_rows
+  react_values$estimates_table <- cbind(
+    react_values$estimates_table, new_cols
   )
 }
index 171d197535473441db522dbf96c555e4c18b9f81..b61f4d4e7331684a2f2de0805be64f2435b7c3eb 100644 (file)
@@ -1,6 +1,12 @@
+# Main logic block for estimator-related interactions.
 estimators_logic <- function(input, output, react_values) {
   # Initialize a data frame to hold estimates.
-  react_values$estimates_table <- data.frame(Dataset = character(0))
+  react_values$estimates_table <- data.frame(
+    Estimator = character(0),
+    `Serial interval` = character(0),
+    check.names = FALSE
+
+  )
   # Initialize a list to hold added estimators.
   react_values$estimators <- list()
 
@@ -37,9 +43,9 @@ add_estimator <- function(method, new_estimator, output, react_values) {
     duration = 3, id = "notify-success"
   )
 
-  # Evaluate all the new estimator on all existing datasets and create a new
-  # column in the estimates table.
-  update_estimates_col(new_estimator, react_values)
+  # Evaluate the new estimator on all existing datasets and create a new row in
+  # the estimates table.
+  update_estimates_row(new_estimator, react_values)
 }
 
 # Ensure serial intervals are specified as positive numbers.
@@ -176,21 +182,26 @@ convert_mu_units <- function(data_units, estimator_units, mu) {
   mu
 }
 
-# Add a column to the estimates table when a new estimator is added.
-update_estimates_col <- function(estimator, react_values) {
+# Add a row to the estimates table when a new estimator is added.
+update_estimates_row <- function(estimator, react_values) {
   dataset_rows <- seq_len(nrow(react_values$data_table))
-  estimates <- dataset_rows
+  estimates <- c()
 
-  for (row in dataset_rows) {
-    estimate <- eval_estimator(estimator, react_values$data_table[row, ])
-    estimates[row] <- estimate
+  if (nrow(react_values$data_table) > 0) {
+    estimates <- dataset_rows
+    for (row in dataset_rows) {
+      estimate <- eval_estimator(estimator, react_values$data_table[row, ])
+      estimates[row] <- estimate
+    }
   }
 
-  estimates <- data.frame(estimates)
-  colnames(estimates) <- estimates_col_name(estimates, estimator)
+  new_row <- data.frame(
+    t(c(estimator_name(estimator), estimator_mu_text(estimator), estimates))
+  )
+  colnames(new_row) <- colnames(react_values$estimates_table)
 
-  react_values$estimates_table <- cbind(
-    react_values$estimates_table, estimates
+  react_values$estimates_table <- rbind(
+    react_values$estimates_table, new_row
   )
 }
 
@@ -214,7 +225,7 @@ eval_estimator <- function(estimator, dataset) {
         max_shape = estimator$max_shape, max_scale = estimator$max_scale
       )
       estimated_mu <- round(sum(estimate$supp * estimate$pmf), 2)
-      estimate <- paste0(round(estimate$r0, 2), " (&#956; = ", estimated_mu,
+      estimate <- paste0(round(estimate$r0, 2), " (SI = ", estimated_mu,
         " ", tolower(dataset[, 2]), ")"
       )
     } else {
@@ -226,39 +237,39 @@ eval_estimator <- function(estimator, dataset) {
   return(estimate)
 }
 
-# Create the column name of an estimator when it is
-# added to the estimates table.
-estimates_col_name <- function(estimates, estimator) {
+# Create the name of an estimator to be added to the first column of the
+# estimates table.
+estimator_name <- function(estimator) {
   if (estimator$method == "id") {
-    return(paste0("ID", " (&#956; = ", estimator$mu, " ",
-      tolower(estimator$mu_units), ")"
-    ))
+    return("ID")
   } else if (estimator$method == "idea") {
-    return(paste0("IDEA", " (&#956; = ", estimator$mu, " ",
-      tolower(estimator$mu_units), ")"
-    ))
+    return("IDEA")
   } else if (estimator$method == "seq_bayes") {
-    return(paste0("seqB", " (&#956; = ", estimator$mu, " ",
-      tolower(estimator$mu_units), ", &#954; = ", estimator$kappa, ")"
-    ))
+    return(paste0("seqB", " (&#954; = ", estimator$kappa, ")"))
   } else if (estimator$method == "wp") {
     if (is.na(estimator$mu)) {
       return(paste0("WP (", estimator$grid_length, ", ",
         round(estimator$max_shape, 3), ", ", round(estimator$max_scale, 3), ")"
       ))
     } else {
-      return(paste0("WP", " (&#956; = ", estimator$mu, " ",
-        tolower(estimator$mu_units), ")"
-      ))
+      return("WP")
     }
   }
 }
 
+# Create the text to be displayed for the serial interval in the second column
+# of the estimates table.
+estimator_mu_text <- function(estimator) {
+  if (is.na(estimator$mu)) {
+    return("—")
+  }
+  paste(estimator$mu, tolower(estimator$mu_units))
+}
+
 # Render the estimates table whenever it is updated.
 render_estimates <- function(output, react_values) {
   observe({
     output$estimates_table <- DT::renderDataTable(react_values$estimates_table,
-      selection = list(target = "column", selectable = c(0)),
       escape = FALSE, rownames = FALSE,
       options = list(
         columnDefs = list(list(className = "dt-left", targets = "_all"))
@@ -267,13 +278,13 @@ render_estimates <- function(output, react_values) {
   })
 }
 
-# Delete columns from the estimates table,
-# as well as the corresponding estimators.
+# Delete rows from the estimates table and the corresponding estimators.
 delete_estimators <- function(input, react_values) {
   observeEvent(input$estimators_delete, {
-    cols_selected <- input$estimates_table_columns_selected
-    react_values$estimators <- react_values$estimators[-cols_selected]
-    react_values$estimates_table[, cols_selected + 1] <- NULL
+    rows_selected <- input$estimates_table_rows_selected
+    react_values$estimators <- react_values$estimators[-rows_selected]
+    react_values$estimates_table <-
+      react_values$estimates_table[-rows_selected, ]
   })
 }
 
@@ -299,7 +310,6 @@ export_estimates <- function(output, react_values) {
 
 # Substitute HTML entity codes with natural names.
 sub_entity <- function(obj) {
-  obj <- gsub("&#956;", "mu", obj)
   obj <- gsub("&#954;", "kappa", obj)
   obj
 }
index 8147c073ba787805986f796196d9fded96e68dd9..da69f085bf1b597f642b4d12b250801f6d60a7d0 100644 (file)
@@ -5,8 +5,8 @@
   <div id="data" class="tab-pane fade">
     {{ htmlTemplate("templates/content/data.html") }}
   </div>
-  <div id="estimators" class="tab-pane fade">
-    {{ htmlTemplate("templates/content/estimators.html") }}
+  <div id="estimation" class="tab-pane fade">
+    {{ htmlTemplate("templates/content/estimation.html") }}
   </div>
    <div id="help" class="tab-pane fade">
     {{ htmlTemplate("templates/content/help.html") }}
index d88738f0d3703816643cd7f31c9ff448d336283c..73b75ea8987120a6fa0b6ca21454307afcf550cc 100644 (file)
   Technical details about the estimators featured in this project can be found in the reference
   <a href="https://doi.org/10.1371/journal.pone.0269306" target="_blank">article</a>.
 </p>
-
 <h4>What is the basic reproduction number?</h4>
 <p>
-  The basic reproduction number, denoted <em>R<sub>0</sub></em>, is defined as the expected number of infections caused by a
-  single infectious individual when introduced into a totally susceptible population. It assumes that all individuals in a given population are susceptible to the disease,
-  and that no preventive measures (such as lockdowns or vaccinations) have been enforced. It is a useful
-  indicator of the transmissibility of an infectious disease during the early stages of its spread and detection.
+  The basic reproduction number, denoted <em>R</em><sub>0</sub>, is defined as the expected number of infections caused
+  by a single infectious individual when introduced into a totally susceptible population. It assumes that all
+  individuals in a given population are susceptible to the disease, and that no preventive measures (such as lockdowns
+  or vaccinations) have been enforced. It is a useful indicator of the transmissibility of an infectious disease during
+  the early stages of its spread and detection.
 </p>
 <p>
-  If <em>R<sub>0</sub></em> &lt; 1, the disease will eventually die out. On the other hand, if
-  <em>R<sub>0</sub></em> &gt; 1, the disease will spread (the higher the <em>R<sub>0</sub></em>, the faster this will happen). Due to uncertainty of known data about the disease, it is difficult to
-  determine <em>R<sub>0</sub></em> precisely.
-  Therefore, many estimation methods exist, each based on different assumptions and yielding different estimates. It is the
-  responsibility of users to employ the most appropriate estimator (or suite of estimators) given the situation at hand.
+  If <em>R</em><sub>0</sub> &lt; 1, the disease will eventually die out. On the other hand, if
+  <em>R</em><sub>0</sub> &gt; 1, the disease will spread (the higher the <em>R</em><sub>0</sub>, the faster this will
+  happen). Due to uncertainty of known data about the disease, it is difficult to determine <em>R</em><sub>0</sub>
+  precisely. Therefore, many estimation methods exist, each based on different assumptions and yielding different
+  estimates. It is the responsibility of users to employ the most appropriate estimator (or suite of estimators) given
+  the situation at hand.
 </p>
index eaae5711a99fbdd8eb6acf0b3712e03dd1e243d6..574f0035cc224691d900cc706659181ce77c4e0e 100644 (file)
@@ -2,7 +2,6 @@
   <a class="nav-link active" data-bs-toggle="tab" href="#enter-data">Enter data</a>
   <a class="nav-link" data-bs-toggle="tab" href="#view-data">View data</a>
 </nav>
-
 <div class="container-fluid tab-content">
   <div id="enter-data" class="pt-3 tab-pane fade show active">
     {{ htmlTemplate("templates/content/data/enter-data.html") }}
index 77846faebcd0241b0041721c52fe943203267ed1..254f1d785339626f39e416df7372d1386bf684bb 100644 (file)
@@ -1,8 +1,9 @@
-\r
-<form class="mb-5">\r
-  {{ htmlTemplate("templates/content/data/enter-data/entry.html") }}\r
-</form>\r
-<hr>\r
-<form>\r
-  {{ htmlTemplate("templates/content/data/enter-data/load-samples.html") }}\r
-</form>\r
+<form class="mb-5">
+  {{ htmlTemplate("templates/content/data/enter-data/required-format.html") }}
+  {{ htmlTemplate("templates/content/data/enter-data/manual-entry.html") }}
+  {{ htmlTemplate("templates/content/data/enter-data/upload-data.html") }}
+</form>
+<hr>
+<form>
+  {{ htmlTemplate("templates/content/data/enter-data/load-samples.html") }}
+</form>
diff --git a/inst/app/templates/content/data/enter-data/bulk-entry.html b/inst/app/templates/content/data/enter-data/bulk-entry.html
deleted file mode 100644 (file)
index 30fab06..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<h4 class="mb-3">Bulk entry</h4>
-<!-- Button to toggle help text. -->
-<button type="button" class="btn btn-outline-primary btn-sm" id="bulk-help-toggle"
-        data-bs-toggle="collapse" data-bs-target="#bulk-help">Show required format</button>
-<!-- Help text for bulk input format. -->
-<div class="collapse mt-2" id="bulk-help">
-  <div class="card card-body border-primary">
-    <p>Manually enter rows or upload a CSV file in the following format:</p>
-    <p class="overflow-x-scroll text-nowrap font-monospace">
-      <u>Dataset name</u>,<u>Time units</u>,<u>Case counts</u>
-    </p>
-    <p>
-      <u class="font-monospace">Time units</u> must be one of
-      <u class="font-monospace">Days</u> or 
-      <u class="font-monospace">Weeks</u>, and
-      <u class="font-monospace">Case counts</u>
-      must be a comma-separated list of one or more non-negative integers.
-    </p>
-    <p>Example:</p>
-    <p class="overflow-x-scroll text-nowrap font-monospace lh-sm">
-      Montreal,Days,1,2,3,4,5,6,7,8,9,19<br>
-      Ottawa,Weeks,1,2,3,4,5,6,7,8,9,19<br>
-      Toronto,Days,1,2,3,4,5,6,7,8,9,19
-    </p>
-  </div>
-</div>
-<!-- Data input area. -->
-<div class="my-4">
-  <label class="form-label" for="data_area">Enter manually</label>
-  <textarea id="data_area" class="form-control" rows="3" wrap="off"></textarea>
-  <div>
-    <small id="data_area_warn" class="form-text text-primary shiny-html-output"></small>
-  </div>
-  <button id="data_bulk" type="button" class="btn btn-outline-primary btn-sm action-button mt-3">
-    <span class="glyphicon glyphicon-plus"></span> Add
-  </button>
-</div>
-<!-- File input for data upload (hidden). -->
-<input class="form-control" type="file" id="data_upload" accept="text/csv,text/comma-separated-values,text/plain,.csv">
-<!-- Custom button to trigger file selector for data upload (visible). -->
-<label class="form-label" for="data-upload-select">Upload a CSV file</label>
-<div class="input-group">
-  <button id="data-upload-select" type="button" class="btn btn-outline-primary btn-sm">
-    <span class="glyphicon glyphicon-file"></span> Select file
-  </button>
-  <input type="text" id="data-upload-name" class="form-control" placeholder="No file selected" disabled>
-</div>
-<small id="data_upload_warn" class="form-text text-primary shiny-html-output"></small>
diff --git a/inst/app/templates/content/data/enter-data/entry.html b/inst/app/templates/content/data/enter-data/entry.html
deleted file mode 100644 (file)
index be43625..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-\r
-<!-- Button to toggle help text. -->\r
-<button type="button" class="btn btn-outline-primary btn-sm" id="bulk-help-toggle"\r
-        data-bs-toggle="collapse" data-bs-target="#bulk-help">Show required format</button>\r
-<!-- Help text for bulk input format. -->\r
-<div class="collapse mt-2" id="bulk-help">\r
-  <div class="card card-body border-primary">\r
-    <p>Manually enter rows or upload a CSV file in the following format:</p>\r
-    <p class="overflow-x-scroll text-nowrap font-monospace">\r
-      <u>Dataset name</u>,<u>Time units</u>,<u>Case counts</u>\r
-    </p>\r
-    <p>\r
-      <u class="font-monospace">Time units</u> must be one of\r
-      <u class="font-monospace">Days</u> or \r
-      <u class="font-monospace">Weeks</u>, and\r
-      <u class="font-monospace">Case counts</u>\r
-      must be a comma-separated list of one or more non-negative integers.\r
-    </p>\r
-    <p>Example:</p>\r
-    <p class="overflow-x-scroll text-nowrap font-monospace lh-sm">\r
-      Montreal,Days,1,2,3,4,5,6,7,8,9,19<br>\r
-      Ottawa,Weeks,1,2,3,4,5,6,7,8,9,19<br>\r
-      Toronto,Days,1,2,3,4,5,6,7,8,9,19\r
-    </p>\r
-  </div>\r
-</div>\r
-<!-- Data input area. -->\r
-<div class="my-4">\r
-  <label class="form-label" for="data_area">Enter manually</label>\r
-  <textarea id="data_area" class="form-control" rows="3" wrap="off"></textarea>\r
-  <div>\r
-    <small id="data_area_warn" class="form-text text-primary shiny-html-output"></small>\r
-  </div>\r
-  <button id="data_bulk" type="button" class="btn btn-outline-primary btn-sm action-button mt-3">\r
-    <span class="glyphicon glyphicon-plus"></span> Add\r
-  </button>\r
-</div>\r
-<!-- File input for data upload (hidden). -->\r
-<input class="form-control" type="file" id="data_upload" accept="text/csv,text/comma-separated-values,text/plain,.csv">\r
-<!-- Custom button to trigger file selector for data upload (visible). -->\r
-<label class="form-label" for="data-upload-select">Upload a CSV file</label>\r
-<div class="input-group">\r
-  <button id="data-upload-select" type="button" class="btn btn-outline-primary btn-sm">\r
-    <span class="glyphicon glyphicon-file"></span> Select file\r
-  </button>\r
-  <input type="text" id="data-upload-name" class="form-control" placeholder="No file selected" disabled>\r
-</div>\r
-<small id="data_upload_warn" class="form-text text-primary shiny-html-output"></small>\r
index a42a8c8545647793f48f87edc3e8a07054ae6aac..2a4f01313ac6092efe9046804c5030a97caa9d05 100644 (file)
@@ -1,4 +1,5 @@
 <h4 class="mb-3">Load samples</h4>
+<!-- Checkboxes for sample data. -->
 {{
   checkboxInput(inputId = "covid_canada", label = "COVID-19 Canada, 2020/03/03 - 2020/03/31 (Weekly)",
     value = FALSE, width = "100%"
@@ -9,6 +10,7 @@
     value = FALSE, width = "100%"
   )
 }}
+<!-- Warning text. -->
 <div>
   <small id="data_samples_warn" class="form-text text-primary shiny-text-output"></small>
 </div>
diff --git a/inst/app/templates/content/data/enter-data/manual-entry.html b/inst/app/templates/content/data/enter-data/manual-entry.html
new file mode 100644 (file)
index 0000000..a6319d9
--- /dev/null
@@ -0,0 +1,11 @@
+<!-- Data input area (manual entry). -->
+<div class="my-4">
+  <label class="form-label" for="data_area">Enter manually</label>
+  <textarea id="data_area" class="form-control" rows="3" wrap="off"></textarea>
+  <div>
+    <small id="data_area_warn" class="form-text text-primary shiny-html-output"></small>
+  </div>
+  <button id="data_bulk" type="button" class="btn btn-outline-primary btn-sm action-button mt-3">
+    <span class="glyphicon glyphicon-plus"></span> Add
+  </button>
+</div>
diff --git a/inst/app/templates/content/data/enter-data/required-format.html b/inst/app/templates/content/data/enter-data/required-format.html
new file mode 100644 (file)
index 0000000..724dd83
--- /dev/null
@@ -0,0 +1,25 @@
+<!-- Button to toggle help text. -->
+<button type="button" class="btn btn-outline-primary btn-sm" id="data-format-toggle"
+        data-bs-toggle="collapse" data-bs-target="#data-format">Show required format</button>
+<!-- Help text for data input format. -->
+<div class="collapse mt-2" id="data-format">
+  <div class="card card-body border-primary">
+    <p>Manually enter rows or upload a CSV file in the following format:</p>
+    <p class="overflow-x-scroll text-nowrap font-monospace">
+      <u>Dataset name</u>,<u>Time units</u>,<u>Case counts</u>
+    </p>
+    <p>
+      <u class="font-monospace">Time units</u> must be one of
+      <u class="font-monospace">Days</u> or 
+      <u class="font-monospace">Weeks</u>, and
+      <u class="font-monospace">Case counts</u>
+      must be a comma-separated list of one or more non-negative integers.
+    </p>
+    <p>Example:</p>
+    <p class="overflow-x-scroll text-nowrap font-monospace lh-sm">
+      Disease A,Days,1,2,3,4,5,6,7,8,9<br>
+      Disease B,Weeks,3,1,4,1,5,2,9<br>
+      Disease C,Days,2,3,5,7,11,13,17,19
+    </p>
+  </div>
+</div>
diff --git a/inst/app/templates/content/data/enter-data/single-entry.html b/inst/app/templates/content/data/enter-data/single-entry.html
deleted file mode 100644 (file)
index 9f249d9..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<h4>Single entry</h4>
-<!-- Dataset name. -->
-<div class="my-3">
-  <label class="form-label" for="data_name">Dataset name</label>
-  <input name="data_name" class="form-control" type="text">
-  <small id="data_name_warn" class="form-text text-primary shiny-text-output"></small>
-</div>
-<!-- Case counts. -->
-<div class="mb-3">
-  <label class="form-label" for="data_counts">
-    Case counts
-    <sup data-bs-toggle="tooltip" data-bs-placement="right"
-         data-bs-title="Enter as a comma-separated list of non-negative integers (example: 0,1,1,2,3,5,8,13).">
-      [?]
-    </sup>
-  </label>
-  <input name="data_counts" class="form-control" type="text">
-  <small id="data_counts_warn" class="form-text text-primary shiny-text-output"></small>
-</div>
-<!-- Time units. -->
-<div class="mb-3">
-  <label class="form-label" for="data_units">Time units</label>
-  <div class="shiny-input-radiogroup" id="data_units">
-    <div class="form-check form-check-inline">
-      <label class="form-check-label">
-        <input type="radio" class="form-check-input me-2" name="data_units" value="Days">Days
-      </label>
-    </div>
-    <div class="form-check form-check-inline">
-      <label class="form-check-label">
-        <input type="radio" class="form-check-input me-2" name="data_units" value="Weeks" checked>Weeks
-      </label>
-    </div>
-  </div>
-</div>
-<!-- Submit data. -->
-<button id="data_single" type="button" class="btn btn-outline-primary btn-sm action-button">
-  <span class="glyphicon glyphicon-plus"></span> Add
-</button>
diff --git a/inst/app/templates/content/data/enter-data/upload-data.html b/inst/app/templates/content/data/enter-data/upload-data.html
new file mode 100644 (file)
index 0000000..740047b
--- /dev/null
@@ -0,0 +1,12 @@
+<!-- File input for data upload (hidden). -->
+<input class="form-control" type="file" id="data_upload" accept="text/csv,text/comma-separated-values,text/plain,.csv">
+<!-- Custom button to trigger file selector for data upload (visible). -->
+<label class="form-label" for="data-upload-select">Upload a CSV file</label>
+<div class="input-group">
+  <button id="data-upload-select" type="button" class="btn btn-outline-primary btn-sm">
+    <span class="glyphicon glyphicon-file"></span> Select file
+  </button>
+  <input type="text" id="data-upload-name" class="form-control" placeholder="No file selected" disabled>
+</div>
+<!-- Warning text. -->
+<small id="data_upload_warn" class="form-text text-primary shiny-html-output"></small>
index 52f1e855fb0caf16c6c71cbeb81f5a46019c76ca..880cf7f62cd56dc5a913bb094a291e11f00b37c1 100644 (file)
@@ -1,19 +1,3 @@
-<h4>Data table</h4>
-<!-- Data table. -->
-<div class="my-3">
-  {{ DT::dataTableOutput(outputId = "data_table") }}
-</div>
-<!-- Display inactive delete button when no rows are selected. -->
-<button type="button" class="btn btn-primary btn-sm text-white" disabled
-        data-display-if="'data_table_rows_selected' in input && input.data_table_rows_selected.length == 0">
-  <span class="glyphicon glyphicon-remove"></span> Delete row(s)
-</button>
-<!-- Display active delete button when at least one row is selected. -->
-<button id="data_delete" type="button" class="btn btn-primary btn-sm action-button text-white"
-        data-display-if="'data_table_rows_selected' in input && input.data_table_rows_selected.length != 0">
-  <span class="glyphicon glyphicon-remove"></span> Delete row(s)
-</button>
-<!-- Button to export data table as a CSV file. -->
-<a id="data_export" type="button" class="btn btn-outline-primary btn-sm shiny-download-link">
-  <span class="glyphicon glyphicon-download-alt"></span> Export table
-</a>
+{{ htmlTemplate("templates/content/data/view-data/data-table.html") }}
+<hr>
+{{ htmlTemplate("templates/content/data/view-data/data-plots.html") }}
diff --git a/inst/app/templates/content/data/view-data/data-plots.html b/inst/app/templates/content/data/view-data/data-plots.html
new file mode 100644 (file)
index 0000000..5019088
--- /dev/null
@@ -0,0 +1,7 @@
+<h4>Data plots</h4>
+<div class="container my-5">
+  {{ plotly::plotlyOutput(outputId = "data_plot_days") }}
+</div>
+<div class="container">
+  {{ plotly::plotlyOutput(outputId = "data_plot_weeks") }}
+</div>
diff --git a/inst/app/templates/content/data/view-data/data-table.html b/inst/app/templates/content/data/view-data/data-table.html
new file mode 100644 (file)
index 0000000..590a5b9
--- /dev/null
@@ -0,0 +1,18 @@
+<h4>Data table</h4>
+<div class="my-3">
+  {{ DT::dataTableOutput(outputId = "data_table") }}
+</div>
+<!-- Display inactive delete button when no rows are selected. -->
+<button type="button" class="btn btn-primary btn-sm text-white" disabled
+        data-display-if="'data_table_rows_selected' in input && input.data_table_rows_selected.length == 0">
+  <span class="glyphicon glyphicon-remove"></span> Delete row(s)
+</button>
+<!-- Display active delete button when at least one row is selected. -->
+<button id="data_delete" type="button" class="btn btn-primary btn-sm action-button text-white"
+        data-display-if="'data_table_rows_selected' in input && input.data_table_rows_selected.length != 0">
+  <span class="glyphicon glyphicon-remove"></span> Delete row(s)
+</button>
+<!-- Button to export data table as a CSV file. -->
+<a id="data_export" type="button" class="btn btn-outline-primary btn-sm shiny-download-link">
+  <span class="glyphicon glyphicon-download-alt"></span> Export table
+</a>
diff --git a/inst/app/templates/content/estimation.html b/inst/app/templates/content/estimation.html
new file mode 100644 (file)
index 0000000..5764057
--- /dev/null
@@ -0,0 +1,13 @@
+<nav class="nav nav-tabs">
+  <a class="nav-link active" data-bs-toggle="tab" href="#about-estimators">About the estimators</a>
+  <a class="nav-link" data-bs-toggle="tab" href="#estimates">Compute and view estimates</a>
+</nav>
+
+<div class="container-fluid tab-content">
+  <div id="about-estimators" class="pt-3 tab-pane fade show active">
+    {{ htmlTemplate("templates/content/estimation/about-estimators.html") }}
+  </div>
+  <div id="estimates" class="pt-3 tab-pane fade">
+    {{ htmlTemplate("templates/content/estimation/estimates.html") }}
+  </div>
+</div>
diff --git a/inst/app/templates/content/estimation/about-estimators.html b/inst/app/templates/content/estimation/about-estimators.html
new file mode 100644 (file)
index 0000000..db2898b
--- /dev/null
@@ -0,0 +1,31 @@
+<div class="accordion accordion-flush" id="estimation-accordion">
+  {{
+    htmlTemplate("templates/content/estimation/about-estimators/panel.html",
+      id = "id",
+      header = "Incidence Decay (ID)",
+      reference_label = "Fisman et al. (PloS One, 2013)",
+      reference_url = "https://doi.org/10.1371/journal.pone.0083622"
+    )
+  }}
+  {{
+    htmlTemplate("templates/content/estimation/about-estimators/panel.html",
+      id = "idea", header = "Incidence Decay and Exponential Adjustment (IDEA)",
+      reference_label = "Fisman et al. (PloS One, 2013)",
+      reference_url = "https://doi.org/10.1371/journal.pone.0083622"
+    )
+  }}
+  {{
+    htmlTemplate("templates/content/estimation/about-estimators/panel.html",
+      id = "seq_bayes", header = "Sequential Bayes (seqB)",
+      reference_label = "Bettencourt and Riberio (PloS One, 2008)",
+      reference_url = "https://doi.org/10.1371/journal.pone.0002185"
+    )
+  }}
+  {{
+    htmlTemplate("templates/content/estimation/about-estimators/panel.html",
+      id = "wp", header = "White and Pagano (WP)",
+      reference_label = "White and Pagano (Statistics in Medicine, 2008)",
+      reference_url = "https://doi.org/10.1002/sim.3136"
+    )
+  }}
+</div>
diff --git a/inst/app/templates/content/estimation/about-estimators/id.html b/inst/app/templates/content/estimation/about-estimators/id.html
new file mode 100644 (file)
index 0000000..3200c00
--- /dev/null
@@ -0,0 +1,5 @@
+The incidence decay (ID) estimator assumes an exponential model and finds the parameters by minimizing the sum of the
+squared differences between the observed cases counts and the case counts expected based on the assumed model.
+The method assumes that the serial interval is known. This means that the user needs to input the value of the serial
+interval. The serial interval is the average time between the first infection and the time the first infected individual
+exhibits disease symptoms.  
similarity index 51%
rename from inst/app/templates/content/estimators/add-estimators/components/panel.html
rename to inst/app/templates/content/estimation/about-estimators/panel.html
index b1e037868f8d8bc05b7dd22b3cca44dc5ec4300d..98fe1557b2435bbee36d6da82733b6422fe0a70a 100644 (file)
@@ -8,14 +8,7 @@
   <div id="{{ id }}" class="accordion-collapse collapse" data-bs-parent="#estimators-accordion">
     <div class="accordion-body">
       <p>Reference: <a href="{{ reference_url }}" target="_blank"><em>{{ reference_label }}</em></a></p>
-      <p>{{ htmlTemplate(paste0("templates/content/estimators/add-estimators/descriptions/", id, ".html")) }}</p>
-      <h5>Parameters</h5>
-      <form class="my-3">
-        {{ htmlTemplate(paste0("templates/content/estimators/add-estimators/parameters/", id, ".html")) }}
-      </form>
-      <button id="add_{{ id }}" type="button" class="btn btn-outline-primary btn-sm action-button">
-        <span class="glyphicon glyphicon-plus"></span> Add
-      </button>
+      <p>{{ htmlTemplate(paste0("templates/content/estimation/about-estimators/", id, ".html")) }}</p>
     </div>
   </div>
 </div>
diff --git a/inst/app/templates/content/estimation/estimates.html b/inst/app/templates/content/estimation/estimates.html
new file mode 100644 (file)
index 0000000..bc9124e
--- /dev/null
@@ -0,0 +1,3 @@
+{{ htmlTemplate("templates/content/estimation/estimates/estimates-table.html") }}
+<hr>
+{{ htmlTemplate("templates/content/estimation/estimates/add-estimators.html") }}
diff --git a/inst/app/templates/content/estimation/estimates/add-estimators.html b/inst/app/templates/content/estimation/estimates/add-estimators.html
new file mode 100644 (file)
index 0000000..60111c7
--- /dev/null
@@ -0,0 +1,16 @@
+<h4>Add estimators</h4>
+<form class="my-3">
+  <!-- Dropdown to select estimator. -->
+  <label class="form-label" for="estimator_select">Select estimator:</label>
+  <select name="estimator_select" class="form-select">
+    <option value="id" selected>Incidence Decay (ID)</option>
+    <option value="idea">Incidence Decay and Exponential Adjustment (IDEA)</option>
+    <option value="seq_bayes">Sequential Bayes (seqB)</option>
+    <option value="wp">White and Pagano (WP)</option>
+  </select>
+  <!-- Parameters. -->
+  {{ htmlTemplate("templates/content/estimation/estimates/add-estimators/parameters.html", id = "id") }}
+  {{ htmlTemplate("templates/content/estimation/estimates/add-estimators/parameters.html", id = "idea") }}
+  {{ htmlTemplate("templates/content/estimation/estimates/add-estimators/parameters.html", id = "seq_bayes") }}
+  {{ htmlTemplate("templates/content/estimation/estimates/add-estimators/parameters.html", id = "wp") }}
+</form>
diff --git a/inst/app/templates/content/estimation/estimates/add-estimators/id.html b/inst/app/templates/content/estimation/estimates/add-estimators/id.html
new file mode 100644 (file)
index 0000000..7c35e55
--- /dev/null
@@ -0,0 +1 @@
+{{ htmlTemplate("templates/content/estimation/estimates/add-estimators/mu.html", id = "id") }}
diff --git a/inst/app/templates/content/estimation/estimates/add-estimators/idea.html b/inst/app/templates/content/estimation/estimates/add-estimators/idea.html
new file mode 100644 (file)
index 0000000..781349f
--- /dev/null
@@ -0,0 +1 @@
+{{ htmlTemplate("templates/content/estimation/estimates/add-estimators/mu.html", id = "idea") }}
similarity index 86%
rename from inst/app/templates/content/estimators/add-estimators/components/mu.html
rename to inst/app/templates/content/estimation/estimates/add-estimators/mu.html
index f25a1c854a70fafe07300343092f2b3d8880f34f..878157482c191acd351e0e3dca233ef5c7f19c83 100644 (file)
@@ -1,6 +1,6 @@
 <!-- Serial interval label and help tooltip. -->
 <label class="form-label" for="mu_{{ id }}">
-  Serial interval (&#956;)
+  Serial interval
   <sup data-bs-toggle="tooltip" data-bs-placement="right"
        data-bs-title="The serial interval is the time between when an infected individual (the infector) becomes
                       symptomatic, to when another individual (who is infected by the infector) becomes symptomatic.">
@@ -17,4 +17,6 @@
   </select>
 </div>
 <!-- Warning text for incorrect values. -->
-<small id="mu_{{ id }}_warn" class="form-text text-primary shiny-text-output"></small>
+<div>
+  <small id="mu_{{ id }}_warn" class="form-text text-primary shiny-text-output"></small>
+</div>
diff --git a/inst/app/templates/content/estimation/estimates/add-estimators/parameters.html b/inst/app/templates/content/estimation/estimates/add-estimators/parameters.html
new file mode 100644 (file)
index 0000000..5250e31
--- /dev/null
@@ -0,0 +1,7 @@
+<div class="my-4" data-display-if="input.estimator_select === '{{ id }}'">
+  <h5>Parameters</h5>
+  {{ htmlTemplate(paste0("templates/content/estimation/estimates/add-estimators/", id, ".html")) }}
+  <button id="add_{{ id }}" type="button" class="btn btn-outline-primary btn-sm action-button mt-3">
+    <span class="glyphicon glyphicon-plus"></span> Add
+  </button>
+</div>
similarity index 70%
rename from inst/app/templates/content/estimators/add-estimators/parameters/seq_bayes.html
rename to inst/app/templates/content/estimation/estimates/add-estimators/seq_bayes.html
index bcc82b750fb46bd0a5ec767f18849d3bb44d7733..028fabc577f47d8e4e907288f160534e8c079e16 100644 (file)
@@ -1,7 +1,7 @@
 <div class="row">
   <!-- Serial interval (mu). -->
   <div class="col-md">
-    {{ htmlTemplate("templates/content/estimators/add-estimators/components/mu.html", id = "seq_bayes") }}
+    {{ htmlTemplate("templates/content/estimation/estimates/add-estimators/mu.html", id = "seq_bayes") }}
   </div>
   <!-- Maximum value of the uniform prior (kappa). -->
   <div class="col-md mt-2 mt-md-0">
@@ -9,8 +9,8 @@
     <label class="form-label" for="kappa">
       Maximum prior (&#954;)
       <sup data-bs-toggle="tooltip" data-bs-placement="right" data-bs-html="true"
-           data-bs-title="The initial maximum belief of <em>R<sub>0</sub></em>. The higher this value, the higher
-                          <em>R<sub>0</sub></em> is believed to be prior to the estimation.">
+           data-bs-title="The initial maximum belief of <em>R</em><sub>0</sub>. The higher this value, the higher
+                          <em>R</em><sub>0</sub> is believed to be prior to the estimation.">
         [?]
       </sup>
     </label>
similarity index 94%
rename from inst/app/templates/content/estimators/add-estimators/parameters/wp.html
rename to inst/app/templates/content/estimation/estimates/add-estimators/wp.html
index b789a23ddd0d3fe4c88fe3ba6ea14a17d332c8c2..511170f7e687cab1f7a58a9af85dab80df366f2b 100644 (file)
@@ -14,7 +14,7 @@
 </div>
 <!-- Show the input field for the serial interval if it is known. -->
 <div data-display-if="input.wp_mu_known == 'Yes'" class="mt-2 mt-md-0">
-    {{ htmlTemplate("templates/content/estimators/add-estimators/components/mu.html", id = "wp") }}
+  {{ htmlTemplate("templates/content/estimation/estimates/add-estimators/mu.html", id = "wp") }}
 </div>
 <!-- Show the input fields for the grid search parameters if the serial interval is unknown. -->
 <div data-display-if="input.wp_mu_known == 'No'" class="row">
diff --git a/inst/app/templates/content/estimation/estimates/estimates-table.html b/inst/app/templates/content/estimation/estimates/estimates-table.html
new file mode 100644 (file)
index 0000000..4704d03
--- /dev/null
@@ -0,0 +1,19 @@
+<h4>Estimates table</h4>
+<!-- Estimates table. -->
+<div class="my-3">
+  {{ DT::dataTableOutput(outputId = "estimates_table") }}
+</div>
+<!-- Display inactive delete button when no rows are selected. -->
+<button type="button" class="btn btn-primary btn-sm text-white" disabled
+        data-display-if="'estimates_table_rows_selected' in input && input.estimates_table_rows_selected.length == 0">
+  <span class="glyphicon glyphicon-remove"></span> Delete row(s)
+</button>
+<!-- Display active delete button when at least one row is selected. -->
+<button id="estimators_delete" type="button" class="btn btn-primary btn-sm action-button text-white"
+        data-display-if="'estimates_table_rows_selected' in input && input.estimates_table_rows_selected.length != 0">
+  <span class="glyphicon glyphicon-remove"></span> Delete row(s)
+</button>
+<!-- Button to export estimates table as a CSV file. -->
+<a id="estimates_export" type="button" class="btn btn-outline-primary btn-sm shiny-download-link">
+  <span class="glyphicon glyphicon-download-alt"></span> Export table
+</a>
diff --git a/inst/app/templates/content/estimators.html b/inst/app/templates/content/estimators.html
deleted file mode 100644 (file)
index 133241a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<nav class="nav nav-tabs">
-  <a class="nav-link active" data-bs-toggle="tab" href="#add-estimators">About the estimators</a>
-  <a class="nav-link" data-bs-toggle="tab" href="#view-estimates">Select and compute estimates</a>
-</nav>
-
-<div class="container-fluid tab-content">
-  <div id="add-estimators" class="pt-3 tab-pane fade show active">
-    {{ htmlTemplate("templates/content/estimators/add-estimators.html") }}
-  </div>
-  <div id="view-estimates" class="pt-3 tab-pane fade">
-    {{ htmlTemplate("templates/content/estimators/view-estimates.html") }}
-  </div>
-</div>
diff --git a/inst/app/templates/content/estimators/add-estimators.html b/inst/app/templates/content/estimators/add-estimators.html
deleted file mode 100644 (file)
index 0d7562e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<div class="accordion accordion-flush" id="estimators-accordion">
-  {{
-  htmlTemplate("templates/content/estimators/add-estimators/components/panel.html",
-  id = "id", header = "Incidence Decay (ID)", reference_label = "Fisman et al.
-  (PloS One, 2013)", reference_url =
-  "https://doi.org/10.1371/journal.pone.0083622" ) }} {{
-  htmlTemplate("templates/content/estimators/add-estimators/components/panel.html",
-  id = "idea", header = "Incidence Decay and Exponential Adjustment (IDEA)",
-  reference_label = "Fisman et al. (PloS One, 2013)", reference_url =
-  "https://doi.org/10.1371/journal.pone.0083622" ) }} {{
-  htmlTemplate("templates/content/estimators/add-estimators/components/panel.html",
-  id = "seq_bayes", header = "Sequential Bayes (seqB)", reference_label =
-  "Bettencourt and Riberio (PloS One, 2008)", reference_url =
-  "https://doi.org/10.1371/journal.pone.0002185" ) }} {{
-  htmlTemplate("templates/content/estimators/add-estimators/components/panel.html",
-  id = "wp", header = "White and Pagano (WP)", reference_label = "White and
-  Pagano (Statistics in Medicine, 2008)", reference_url =
-  "https://doi.org/10.1002/sim.3136" ) }}
-</div>
diff --git a/inst/app/templates/content/estimators/add-estimators/descriptions/id.html b/inst/app/templates/content/estimators/add-estimators/descriptions/id.html
deleted file mode 100644 (file)
index b47850f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-The incidence decay (ID) estimator assumes an exponential model and finds the parameters by minimizing the sum of the squared differences between the observed cases counts and the case counts  expected based on the assumed model.  The method assumes that the serial interval is known.   This means that the user needs to input the value of the serial interval.   The serial interval is the average time between the first infection and the time the first infected individual exhibits disease symptoms.  
diff --git a/inst/app/templates/content/estimators/add-estimators/descriptions/mu.html b/inst/app/templates/content/estimators/add-estimators/descriptions/mu.html
deleted file mode 100644 (file)
index 6e7bfe9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-The serial interval (SI) is NOT one of the estimators.   
-
-<p>The SI is a parameter required by all of the estimators, and can also be estimated by the WP method.</p>
-
-<p>The SI is defined as the average time between successive infections in a chain of transmission i.e., the time between the infection of an infected and their subsequent transmissions. </p>
-
-<P> Make the tab a different shade (light gray) and then this won't have parameters.   It will let us not have to explain SI every single time.  We'll expand the description later.</p>
diff --git a/inst/app/templates/content/estimators/add-estimators/parameters/id.html b/inst/app/templates/content/estimators/add-estimators/parameters/id.html
deleted file mode 100644 (file)
index a3159ca..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{{ htmlTemplate("templates/content/estimators/add-estimators/components/mu.html", id = "id") }}
diff --git a/inst/app/templates/content/estimators/add-estimators/parameters/idea.html b/inst/app/templates/content/estimators/add-estimators/parameters/idea.html
deleted file mode 100644 (file)
index 379be84..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{{ htmlTemplate("templates/content/estimators/add-estimators/components/mu.html", id = "idea") }}
diff --git a/inst/app/templates/content/estimators/add-estimators/parameters/mu.html b/inst/app/templates/content/estimators/add-estimators/parameters/mu.html
deleted file mode 100644 (file)
index a3159ca..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{{ htmlTemplate("templates/content/estimators/add-estimators/components/mu.html", id = "id") }}
diff --git a/inst/app/templates/content/estimators/view-estimates.html b/inst/app/templates/content/estimators/view-estimates.html
deleted file mode 100644 (file)
index e81fff6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<h4>Estimates table</h4>
-<!-- Estimates table. -->
-<div class="my-3">
-  {{ DT::dataTableOutput(outputId = "estimates_table") }}
-</div>
-<!-- Display inactive delete button when no columns are selected. -->
-<button type="button" class="btn btn-primary btn-sm text-white" disabled
-        data-display-if="'estimates_table_columns_selected' in input &&
-                         input.estimates_table_columns_selected.length == 0">
-  <span class="glyphicon glyphicon-remove"></span> Delete column(s)
-</button>
-<!-- Display active delete button when at least one column is selected. -->
-<button id="estimators_delete" type="button" class="btn btn-primary btn-sm action-button text-white"
-        data-display-if="'estimates_table_columns_selected' in input &&
-                         input.estimates_table_columns_selected.length != 0">
-  <span class="glyphicon glyphicon-remove"></span> Delete column(s)
-</button>
-<!-- Button to export estimates table as a CSV file. -->
-<a id="estimates_export" type="button" class="btn btn-outline-primary btn-sm shiny-download-link">
-  <span class="glyphicon glyphicon-download-alt"></span> Export table
-</a>
index 51192fc610961d5fbb06720e77b0b78cf7f491ef..df4e887e2152dce53206820e1adbefab83710975 100644 (file)
@@ -1,6 +1,8 @@
 <div class="accordion accordion-flush" id="help-accordion">
-  {{ htmlTemplate("templates/content/help/panel.html", id = "serial-interval",
-  header = "What is a Serial Interval(mu) ?" ) }} {{
-  htmlTemplate("templates/content/help/panel.html", id = "example-help-2",
-  header = "Example help 2" ) }}
+  {{
+    htmlTemplate("templates/content/help/panel.html",
+      id = "serial-interval",
+      header = "What is the serial interval?"
+    )
+  }}
 </div>
diff --git a/inst/app/templates/content/help/example-help-1.html b/inst/app/templates/content/help/example-help-1.html
deleted file mode 100644 (file)
index 245b9b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Example help 1
diff --git a/inst/app/templates/content/help/example-help-2.html b/inst/app/templates/content/help/example-help-2.html
deleted file mode 100644 (file)
index a4817b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Example help 2
index 88bf82c59da362d6e72a94d2ad5785a7c7cf749b..e0611154e14c6d5b156d2260ebf74025d30a6ef7 100644 (file)
@@ -1,18 +1,9 @@
-Reference
-<a href="https://en.wikipedia.org/wiki/Serial_interval" target="_blank"
-  ><i>Wikipedia</i></a
->
-<br />
-<br />
-
-<p>The serial interval (SI) is NOT one of the estimators.</p>
+<p>Reference: <a href="https://en.wikipedia.org/wiki/Serial_interval" target="_blank"><em>Wikipedia</em></a>
 <p>
-  The SI is a parameter required by all of the estimators, and can also be
-  estimated by the WP method.
+  The serial interval (SI) is not one of the estimators. It is a parameter required by most of the estimators, and can
+  also be estimated by some of them (if not specified).
 </p>
-
 <p>
-  The SI is defined as the average time between successive infections in a chain
-  of transmission i.e., the time between the infection of an infected and their
-  subsequent transmissions.
+  The SI is defined as the average time between successive infections in a chain of transmission (i.e., the time between
+  the infection of an infected individual and their subsequent transmissions).
 </p>
index 1f86953a5601786ad87a306fa04930384378dfdd..d447fba7b38a5dc28481643f44607b6ea8564543 100644 (file)
@@ -3,7 +3,7 @@
     <!-- Project name and description. -->
     <a class="navbar-brand text-primary" href="/">Rnaught Web</a>
     <span class="navbar-text d-none d-md-block">
-      An estimation suite for <em>R<sub>0</sub></em>
+      An estimation suite for <em>R</em><sub>0</sub>
     </span>
     <!-- Navigation toggler for smaller screens. -->
     <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#nav-toggle">
index 22985f917920d1b38e6c298c83166872d484c54a..351b48076504222a4a524c03e7e65c3ff32002a4 100644 (file)
@@ -3,10 +3,10 @@
     About <span class="glyphicon glyphicon-info-sign"></span>
   </a>
   <a class="nav-link rounded-0" data-bs-toggle="pill" href="#data">
-    Upload Data <span class="glyphicon glyphicon-list-alt"></span>
+    Data <span class="glyphicon glyphicon-list-alt"></span>
   </a>
-  <a class="nav-link rounded-0" data-bs-toggle="pill" href="#estimators">
-    Select and Compute Estimators <span class="glyphicon glyphicon-random"></span>
+  <a class="nav-link rounded-0" data-bs-toggle="pill" href="#estimation">
+    Estimation <span class="glyphicon glyphicon-random"></span>
   </a>
   <a class="nav-link rounded-0" data-bs-toggle="pill" href="#help">
     Help <span class="glyphicon glyphicon-question-sign"></span>
index c31584fce53d89960bff62c09919103ba7e00151..30066d1fa15958304be32e760ce444655a2f3d88 100644 (file)
@@ -3,7 +3,7 @@ $(document).ready(() => {
   $('[data-bs-toggle="tooltip"]').tooltip();
 
   // Toggle the text in the bulk data help button.
-  $('#bulk-help-toggle').on('click', event => {
+  $('#data-format-toggle').on('click', event => {
     btn = $(event.target);
     show_format = 'Show required format';
     btn.text(btn.text() === show_format ? 'Hide required format' : show_format);
index d53a38745b291588e9cc9a0d0d49608dde6a3661..a6fc3cd177cc35f9ac86d67cebaf68aa05d6dc34 100644 (file)
@@ -8,23 +8,16 @@ noscript {
   text-align: center;
 }
 
-.nav-pills .active {
-  color: white !important;
+.shiny-notification {
+  background-color: black;
+  color: white;
 }
 
-.action-button:hover, #bulk-help-toggle:hover, #data_export:hover {
+.plotly-notifier .notifier-note {
+  background-color: black !important;
   color: white !important;
 }
 
-#data_plot {
-  margin-top: -0.5rem;
-}
-
-td.selected, .shiny-notification {
-  background-color: black;
-  color: white;
-}
-
 #data_upload {
   display: none;
 }