R/tracer_selection_diagnostic_plot.R

Defines functions tracer_selection_diagnostic_plot

Documented in tracer_selection_diagnostic_plot

#' Tracer Selection Diagnostic plot
#'
#' Generates a generalized, faceted point plot to visualize tracer selection 
#' metrics across different datasets. Evaluates Classification Rate (CR), 
#' Concentration Indicator (CI), and Consistency Error (CONS) against user-defined thresholds.
#'
#' @param data Data frame. Must contain the columns: \code{dataset}, \code{tracer}, 
#'   \code{CR_score}, \code{CI_score}, and \code{consistency_error}. Optionally 
#'   include a \code{tracer_group} column to facet the plot.
#' @param cr_threshold Numeric. Minimum passing score for CR. Default 70.
#' @param ci_threshold Numeric. Minimum passing score for CI. Default 2.50.
#' @param cons_threshold Numeric. Maximum allowable consistency error. Default 0.025.
#' @param custom_theme A ggplot2 theme object. Defaults to \code{ggplot2::theme_minimal()}.
#'
#' @return A \code{ggplot} object visualizing tracer metric statuses.
#'
#' @import ggplot2
#' @import dplyr
#' 
#' @export
tracer_selection_diagnostic_plot <- function(data, 
                                             cr_threshold = 70, 
                                             ci_threshold = 2.50, 
                                             cons_threshold = 0.025, 
                                             custom_theme = ggplot2::theme_minimal()) {
  
  # ── 1. Validate Input Data ──────────────────────────────────────────────────
  req_cols <- c("dataset", "tracer", "CR_score", "CI_score", "consistency_error")
  missing_cols <- setdiff(req_cols, colnames(data))
  
  if (length(missing_cols) > 0) {
    stop(sprintf("Input data is missing required column(s): %s", paste(missing_cols, collapse = ", ")))
  }
  
  # Assign default grouping if not present
  if (!"tracer_group" %in% colnames(data)) {
    data$tracer_group <- "All Tracers"
  }
  
  # ── 2. Data Preparation ─────────────────────────────────────────────────────
  tracer_levels  <- unique(as.character(data$tracer))
  dataset_levels <- unique(as.character(data$dataset))
  
  plot_df <- data %>%
    mutate(
      tracer    = factor(tracer, levels = tracer_levels),
      dataset   = factor(dataset, levels = dataset_levels),
      tracer_id = as.numeric(tracer),
      CR_pass   = CR_score > cr_threshold,
      CI_pass   = CI_score > ci_threshold,
      CONS_pass = consistency_error < cons_threshold
    )
  
  # Build long format dataframe for dual-metric plotting
  cr_df <- plot_df %>%
    transmute(
      dataset, tracer, tracer_id, tracer_group,
      metric = "CR",
      pass = CR_pass,
      circle_flag = CR_pass & CI_pass & CONS_pass
    )
  
  ci_df <- plot_df %>%
    transmute(
      dataset, tracer, tracer_id, tracer_group,
      metric = "CI",
      pass = CI_pass,
      circle_flag = CR_pass & CI_pass & CONS_pass
    )
  
  long_df <- bind_rows(cr_df, ci_df) %>%
    mutate(
      x = ifelse(metric == "CR", tracer_id + 0.15, tracer_id - 0.15),
      color_group = case_when(
        metric == "CR" & pass  ~ "CR (Pass)",
        metric == "CR" & !pass ~ "CR (Fail)",
        metric == "CI" & pass  ~ "CI (Pass)",
        TRUE                   ~ "CI (Fail)"
      )
    )
  
  overall_pass_df <- long_df %>%
    distinct(dataset, tracer, tracer_group, circle_flag) %>%
    filter(circle_flag) %>%
    mutate(color_group = "Overall Pass")
  
  # ── 3. Build ggplot ─────────────────────────────────────────────────────────
  p <- ggplot(long_df, aes(x = x, y = dataset)) +
    
    # ---- Overall Pass Highlight Circle ----
  geom_point(
    data = overall_pass_df,
    aes(x = as.numeric(tracer), y = dataset, color = color_group),
    shape = 21, fill = NA, stroke = 1.2, size = 11
  ) +
    
    # ---- Individual Metric Status Dots ----
  geom_point(
    aes(color = color_group),
    size = 3.5
  ) +
    
    # ---- Scales & Aesthetic Definitions ----
  scale_x_continuous(
    breaks = seq_along(tracer_levels),
    labels = tracer_levels,
    expand = expansion(add = 0.6)
  ) +
    scale_color_manual(
      values = c(
        "CR (Pass)"    = "forestgreen",
        "CR (Fail)"    = "tomato",
        "CI (Pass)"    = "steelblue",
        "CI (Fail)"    = "orange",
        "Overall Pass" = "black"
      )
    ) +
    
    # ---- Native ggplot2 Faceting ----
  facet_grid(
    . ~ tracer_group,
    scales = "free_x",
    space = "free_x"
  ) +
    
    # ---- Theme Customization ----
  custom_theme +
    labs(
      x = "Tracer",
      y = "Dataset",
      color = "Metric Status"
    ) +
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1),
      legend.position = "bottom",
      strip.text.x = element_text(face = "bold", size = 10)
    )
  
  return(p)
}

Try the OceanTracer package in your browser

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

OceanTracer documentation built on Oct. 15, 2026, 5:09 p.m.