## ============================================================
##  PACKAGES
## ============================================================

# install.packages("dataRetrieval")   # run once if needed
# install.packages("trend")          # run once if needed

library(dataRetrieval)
library(trend)
library(knitr)
library(kableExtra)



## ============================================================
##  CONFIGURATION (EDIT THIS BLOCK FOR EACH NEW FIRE)
## ============================================================
## Use when:
##  - switch to a new fire
##  - use different USGS gages
##  - plug in a different precip CSV

## ------------------------------------------------------------

## --- USGS site numbers ---

# Fire-affected stream (downstream of burn)
site_stream <- "07103800"   # Eagle Creek (fire-affected)

# Control stream (not burned, similar region)
site_control <- "07104000"  # Rio Ruidoso (control)

## --- Basin Drainage Areas
basin_stream_area_km2  <- 38
basin_control_area_km2 <-526
# Only change the km2 areas section, the m2 will auto update below
stream_area_m2  <- basin_stream_area_km2  * 1e6
control_area_m2 <- basin_control_area_km2 * 1e6

## --- Names for plots and labels (for titles & legends) ---
fire_name          <- "WC Fire (2012)"
basin_stream_name  <- "West Monument Creek"
basin_control_name <- "Monument Creek"

## --- Analysis period (calendar dates) ---
start_date <- "2005-01-01"
end_date   <- "2018-12-31"

## --- Fire water year split ---
##   WY < fire_wy  as "pre-fire"
##   WY >= fire_wy as "post-fire"
fire_wy <- 2012

## --- Water-year analysis window .
wy_min <- 2006
wy_max <- 2018

## --- Precipitation data (Google Sheets CSV) ---
## This is a regional daily precipitation time series (one station), which we:
precip_url <- "https://docs.google.com/spreadsheets/d/e/2PACX-1vTUUfrM0KaKiFCMEIsD3e68Vsxo_GEno0dX0MbM7ahD0uUwvXJ87XIFbAR_hMySViHxS0T3lXiaM2Ik/pub?output=csv"



## ============================================================
##  CONVERSIONS – GLOBAL UNIT CONSTANTS
## ============================================================
## Purpose:
##   Centralize all unit conversions used anywhere in the script.
## ------------------------------------------------------------

## --- Discharge conversions ---
cfs_to_m3s      <- 0.0283168466          # cubic feet per second → m³/s
seconds_per_day <- 86400
cfs_to_m3day    <- cfs_to_m3s * seconds_per_day   # 1 cfs → m³/day (≈ 2446.576)

## --- Precipitation conversions ---
inch_to_m       <- 0.0254                # inches → meters
inch_to_mm      <- 25.4                  # inches → millimeters

## --- Area conversions ---
km2_to_m2       <- 1e6                   # km² → m²

## --- flow depth conversions ---
m3_to_mm        <- 1000                  # convert m³ per m² → mm depth
mm_to_m         <- 1e-3                  # mm → m (rarely needed)

## Now any section in the script can use:
##   discharge_m3day  <- Q_cfs * cfs_to_m3day
##   precip_m         <- precip_in * inch_to_m
##   area_m2          <- area_km2 * km2_to_m2
## etc.


## ============================================================
##  FUNCTIONS – GENERIC & REUSABLE
## ============================================================
## ------------------------------------------------------------
## water_year(date_vec)
## ------------------------------------------------------------
water_year <- function(date_vec) {
  yr <- as.integer(format(date_vec, "%Y"))
  mo <- as.integer(format(date_vec, "%m"))
  wy <- ifelse(mo >= 10, yr + 1, yr)
  return(wy)
}


## ------------------------------------------------------------
## add_wy_and_dQ(df)
##
## Input:
##   df: raw daily discharge from readNWISdv()
##
## Output:
##   df with added columns:
##     - date   : Date class
##     - Q_cfs  : discharge (cfs)
##     - wy     : water year
##     - dQ     : absolute daily change in discharge
##
## Significance:
##   dQ is the day-to-day change in flow. Summed over a water
##   year and normalized by total flow, this becomes the
##   Richards–Baker Index (RBI), a metric of "flashiness":
##      * high RBI  → more spiky, flashy hydrograph
##      * low RBI   → smoother, more baseflow-dominated behavior
## ------------------------------------------------------------
add_wy_and_dQ <- function(df) {
  
  # Convert to Date object and numeric discharge
  df$date  <- as.Date(df$Date)
  df$Q_cfs <- as.numeric(df$X_00060_00003)
  
  # Sort rows by date just in case
  df <- df[order(df$date), ]
  
  # Add water year
  df$wy <- water_year(df$date)
  
  # Lagged discharge (yesterday’s flow)
  Q_lag <- c(NA, head(df$Q_cfs, -1))
  
  # Daily change in discharge (absolute value)
  df$dQ <- abs(df$Q_cfs - Q_lag)
  
  return(df)
}


## ------------------------------------------------------------
## compute_flashiness(df, min_days = 300)
##
## Input:
##   df: data frame with columns wy, Q_cfs, dQ
##
## Output:
##   data.frame with one row per water year:
##     - wy      : water year
##     - flash   : Richards–Baker Flashiness Index
##     - meanQ   : mean daily discharge that WY
##     - n_days  : how many valid Q days in that WY
##
## Formula:
##   flashiness = sum(|dQ|) / sum(Q)
##
## Significance:
##   This compresses the entire annual hydrograph into a single
##   metric that tells you how "spiky" the flow regime is. Post-
##   fire
##     * higher flashiness (more event-driven flows)
##     * changes in mean Q (e.g., more runoff vs infiltration)
##
## Drop water years with < min_days of data to avoid
## interpreting incomplete records as a "real" change.
## ------------------------------------------------------------
compute_flashiness <- function(df, min_days = 300) {
  
  wy_list <- sort(unique(df$wy))
  
  out <- data.frame(
    wy     = wy_list,
    flash  = NA_real_,
    meanQ  = NA_real_,
    n_days = NA_integer_
  )
  
  for (i in seq_along(wy_list)) {
    w   <- wy_list[i]
    sub <- df[df$wy == w, ]
    
    n <- sum(!is.na(sub$Q_cfs))
    out$n_days[i] <- n
    
    if (n >= min_days) {
      out$flash[i] <- sum(sub$dQ, na.rm = TRUE) / sum(sub$Q_cfs, na.rm = TRUE)
      out$meanQ[i] <- mean(sub$Q_cfs, na.rm = TRUE)
    }
  }
  
  # Remove water years that didn't meet min_days requirement
  out <- out[!is.na(out$flash), ]
  
  return(out)
}

# --- Helper: run Pettitt on a series ordered by WY and report the WY ---
run_pettitt <- function(wy_vec, value_vec, label = "series") {
  ord <- order(wy_vec)
  wy_ord <- wy_vec[ord]
  x_ord  <- value_vec[ord]
  
  pt <- pettitt.test(x_ord)
  
  # change-point index
  k  <- pt$estimate
  cp_wy <- wy_ord[k]
  
  cat("\nPettitt test for", label, "\n")
  cat("  Change-point WY:", cp_wy, "\n")
  cat("  K statistic    :", pt$statistic, "\n")
  cat("  p-value        :", pt$p.value, "\n\n")
  
  invisible(list(result = pt, cp_wy = cp_wy))
}

## ------------------------------------------------------------
## assign_prepost_colors(period_vec, pre_col, post_col)
##
## Simple helper to consistently map:
##   period == "pre"  → pre_col
##   period == "post" → post_col
## ------------------------------------------------------------
assign_prepost_colors <- function(period_vec, pre_col = "blue", post_col = "orange") {
  ifelse(period_vec == "pre", pre_col, post_col)
}

## ------------------------------------------------------------
## Helper for Wilcoxon Rank-Sum Tests (Mann-Whitney)
##
## Inputs:
##   df        : data frame with at least {response, period}
##   response  : string, name of column to test (e.g., "flash")
##   label     : string printed in output header
##
## Output:
##   A list containing the test object and the median diff
##
## Prints:
##   - variable tested
##   - group medians
##   - Hodges–Lehmann median difference
##   - 95% confidence interval
##   - p-value
## ------------------------------------------------------------
## Small helper to build a summary row-set for any MWW test
mww_stats <- function(df, response) {
  y   <- df[[response]]
  grp <- df$period
  
  med_pre  <- median(y[grp == "pre"],  na.rm = TRUE)
  med_post <- median(y[grp == "post"], na.rm = TRUE)
  
  wt <- wilcox.test(
    y ~ grp,
    exact     = FALSE,
    conf.int  = TRUE,
    conf.level = 0.95
  )
  
  data.frame(
    Statistic = c(
      "Pre-fire median",
      "Post-fire median",
      "Median difference (post - pre)",
      "95% CI lower",
      "95% CI upper",
      "p-value"
    ),
    Value = c(
      med_pre,
      med_post,
      unname(wt$estimate),
      wt$conf.int[1],
      wt$conf.int[2],
      wt$p.value
    )
  )
}

run_mww_pretty <- function(df, response, label = "Wilcoxon Test") {
  
  # Extract variables
  y   <- df[[response]]
  grp <- df$period
  
  # Compute group medians
  med_pre  <- median(y[grp == "pre"],  na.rm = TRUE)
  med_post <- median(y[grp == "post"], na.rm = TRUE)
  
  # Run test with CI + effect size
  wt <- wilcox.test(
    y ~ grp,
    exact    = FALSE,
    conf.int = TRUE,
    conf.level = 0.95
  )
  
  # Pretty printed output
  cat("\n------------------------------------------------------------\n")
  cat(label, "\n")
  cat("------------------------------------------------------------\n")
  cat("Pre-fire median:  ", round(med_pre,  4), "\n")
  cat("Post-fire median: ", round(med_post, 4), "\n")
  cat("Median difference (post - pre): ", round(wt$estimate, 4), "\n")
  cat("95% CI: [", round(wt$conf.int[1], 4), ", ", 
      round(wt$conf.int[2], 4), "]\n", sep = "")
  cat("p-value: ", format.pval(wt$p.value), "\n")
  
  invisible(wt)
}




## ============================================================
##  DATA RETRIEVAL & PROCESSING – DISCHARGE
## ============================================================
## Steps:
##   1) Download daily discharge for Eagle Creek (fire) and
##      Ruidoso (control) using USGS web services.
##   2) Add water year and daily |dQ|.
##   3) Aggregate by water year to get RBI and mean Q.
##   4) Restrict to water-year window of interest.
##
## Hydrologic significance:
##   * Comparing fire-affected vs control basins helps separate
##     climate-driven changes from fire-driven changes.
## ------------------------------------------------------------

## 1) Download daily discharge for FIRE (stream) and CONTROL

# Fire-affected site (Eagle Creek)
Q_stream_raw <- readNWISdv(
  siteNumbers = site_stream,
  parameterCd = "00060",     # discharge
  startDate   = start_date,
  endDate     = end_date
)
## Warning in readNWISdv(siteNumbers = site_stream, parameterCd = "00060", : NWIS
## servers are slated for decommission. Please begin to migrate to
## read_waterdata_daily.
## GET: https://waterservices.usgs.gov/nwis/dv/?site=07103800&format=waterml%2C1.1&ParameterCd=00060&StatCd=00003&startDT=2005-01-01&endDT=2018-12-31
# Control site (Ruidoso)
Q_control_raw <- readNWISdv(
  siteNumbers = site_control,
  parameterCd = "00060",
  startDate   = start_date,
  endDate     = end_date
)
## Warning in readNWISdv(siteNumbers = site_control, parameterCd = "00060", : NWIS
## servers are slated for decommission. Please begin to migrate to
## read_waterdata_daily.
## GET: https://waterservices.usgs.gov/nwis/dv/?site=07104000&format=waterml%2C1.1&ParameterCd=00060&StatCd=00003&startDT=2005-01-01&endDT=2018-12-31
# Add water year and daily dQ for both
Q_stream  <- add_wy_and_dQ(Q_stream_raw)
Q_control <- add_wy_and_dQ(Q_control_raw)

# Compute annual flashiness for each (using all available dates within start/end)
flash_stream_all  <- compute_flashiness(Q_stream)
flash_control_all <- compute_flashiness(Q_control)

# Restrict flashiness to chosen WY window (full water years only)
flash_stream <- flash_stream_all[
  flash_stream_all$wy >= wy_min & flash_stream_all$wy <= wy_max,
]

flash_control <- flash_control_all[
  flash_control_all$wy >= wy_min & flash_control_all$wy <= wy_max,
]

# Also create WY-limited daily discharge for plotting (nice to match precip)
Q_stream_plot  <- Q_stream[Q_stream$wy   >= wy_min & Q_stream$wy   <= wy_max, ]
Q_control_plot <- Q_control[Q_control$wy >= wy_min & Q_control$wy <= wy_max, ]



## ============================================================
##  DATA RETRIEVAL & PROCESSING – PRECIPITATION
## ============================================================
## Goal:
##   Convert a daily precip station time series into:
##     (1) Daily values aligned with WYs
##     (2) Water-year totals (precip_wy)
##
## Significance:
##   Need this to:
##     * Check if post-fire changes in flow could simply be due
##       to wetter/drier years.
##     * Build Q/P and RBI/P ratios that normalize out climate
##       forcing as best as possible.
## ------------------------------------------------------------

## 2) Read and process precipitation from Google Sheets URL

# ===== Load CSV directly from Google Sheets =====
precip_raw <- read.csv(precip_url, stringsAsFactors = FALSE)

# ===== Standardize column names (assumes 2 columns) =====
names(precip_raw) <- c("date_raw", "precip_raw")

# ===== Convert date to proper Date class =====
precip_raw$date <- as.Date(precip_raw$date_raw, format = "%m/%d/%y")

# ===== Clean precipitation values =====
precip_raw$precip_in <- as.character(precip_raw$precip_raw)

# M = missing → NA
precip_raw$precip_in[precip_raw$precip_in == "M"] <- NA

# T = trace → 0
precip_raw$precip_in[precip_raw$precip_in == "T"] <- "0"

# Convert to numeric
precip_raw$precip_in <- as.numeric(precip_raw$precip_in)

# ===== Add water year (Oct–Sep) =====
precip_raw$water_year <- water_year(precip_raw$date)

# ===== Final cleaned dataframe (keep only what you need) =====
precip_df <- precip_raw[, c("date", "precip_in", "water_year")]
names(precip_df)[names(precip_df) == "water_year"] <- "wy"

# Restrict precip to the same WY window (full water years only)
precip_df <- precip_df[precip_df$wy >= wy_min & precip_df$wy <= wy_max, ]

### precip_df now contains:
# date      (Date)
# precip_in (numeric, with T=0 and M=NA)
# wy        (numeric water year), from wy_min to wy_max


# ============================================================
#  ANNUAL (WATER-YEAR) PRECIP TOTALS
# ============================================================
## Significance:
##   precip_wy is your climate forcing series. If flashiness or
##   Q/P changes while precip_wy stays roughly similar, that’s
##   evidence for internal watershed change (e.g., wildfire
##   impacts) rather than just "it rained more."
# ------------------------------------------------------------

precip_wy <- aggregate(
  precip_in ~ wy,
  data = precip_df,
  FUN  = sum,
  na.rm = TRUE
)


## ============================================================
##  RUNOFF RATIO (RR) – ANNUAL WATER BALANCE METRIC
## ============================================================
## Purpose:
##   Compute the annual runoff ratio for each basin:
##
##       RR = (annual runoff depth) / (annual precipitation depth)
##
##   where:
##     - annual runoff depth = (sum of Q over WY) / basin area
##     - precipitation depth = WY total precipitation (converted to mm)
##
## Hydrologic meaning:
##   - RR expresses how efficiently precipitation becomes streamflow.
##   - RR close to 1 = most rainfall exits the basin as runoff
##   - RR << 1     = large losses to ET, infiltration, storage
##
## This provides a long-term water-balance perspective that
## complements:
##   * RBI (hydrograph shape)
##   * Q/P_peak (event-scale sensitivity)
## ============================================================

## --- 1) Compute annual discharge volume for each basin (m³ / WY)

Q_stream_wy_vol <- aggregate(
  Q_cfs ~ wy,
  data = Q_stream[!is.na(Q_stream$Q_cfs), ],
  FUN  = function(x) sum(x * cfs_to_m3day)
)
names(Q_stream_wy_vol)[2] <- "Q_vol_stream_m3"

Q_control_wy_vol <- aggregate(
  Q_cfs ~ wy,
  data = Q_control[!is.na(Q_control$Q_cfs), ],
  FUN  = function(x) sum(x * cfs_to_m3day)
)
names(Q_control_wy_vol)[2] <- "Q_vol_control_m3"


## --- 2) Convert discharge volume to runoff depth (mm)

Q_stream_wy_vol$runoff_mm  <- (Q_stream_wy_vol$Q_vol_stream_m3  / stream_area_m2)  * 1000
Q_control_wy_vol$runoff_mm <- (Q_control_wy_vol$Q_vol_control_m3 / control_area_m2) * 1000


## --- 3) Prepare annual precipitation depth (mm)

precip_wy$P_mm <- precip_wy$precip_in * inch_to_mm


## --- 4) Merge Q_depth and P_depth for RR calculation

RR_stream <- merge(Q_stream_wy_vol[, c("wy", "runoff_mm")],
                   precip_wy[, c("wy", "P_mm")],
                   by = "wy")

RR_control <- merge(Q_control_wy_vol[, c("wy", "runoff_mm")],
                    precip_wy[, c("wy", "P_mm")],
                    by = "wy")


## --- 5) Compute runoff ratio

RR_stream$RR  <- RR_stream$runoff_mm  / RR_stream$P_mm
RR_control$RR <- RR_control$runoff_mm / RR_control$P_mm


## --- 6) Restrict to complete water years + WY window

# Use the WYs already accepted as complete in the flashiness section
valid_wy_stream  <- flash_stream$wy
valid_wy_control <- flash_control$wy

RR_stream  <- RR_stream[RR_stream$wy   %in% valid_wy_stream  , ]
RR_control <- RR_control[RR_control$wy %in% valid_wy_control , ]

## ============================================================
## Data proceessing: PEAK-FLOW SENSITIVITY (Q_peak / P_peak)
## ============================================================
## Goal:
##   Relate the annual maximum daily discharge (Q_peak) to the
##   annual maximum daily precipitation (P_peak) in each WY.
##
## Metric:
##   Q_peak / P_peak  (units: cfs per inch)
## ------------------------------------------------------------

## ---- Annual peak discharge (per WY) ----
Q_stream_peak <- aggregate(
  Q_cfs ~ wy,
  data = Q_stream[!is.na(Q_stream$Q_cfs), ],
  FUN  = max
)
names(Q_stream_peak)[2] <- "Q_peak_stream"

Q_control_peak <- aggregate(
  Q_cfs ~ wy,
  data = Q_control[!is.na(Q_control$Q_cfs), ],
  FUN  = max
)
names(Q_control_peak)[2] <- "Q_peak_control"

## ---- Annual peak daily precip (per WY) ----
precip_peak <- aggregate(
  precip_in ~ wy,
  data = precip_df[!is.na(precip_df$precip_in), ],
  FUN  = max
)
names(precip_peak)[2] <- "P_peak"

## ---- Merge peaks by WY ----
peak_stream  <- merge(Q_stream_peak,  precip_peak, by = "wy", all = FALSE)
peak_control <- merge(Q_control_peak, precip_peak, by = "wy", all = FALSE)

## ---- Restrict to analysis WY window ----
peak_stream  <- peak_stream[peak_stream$wy  >= wy_min & peak_stream$wy  <= wy_max, ]
peak_control <- peak_control[peak_control$wy >= wy_min & peak_control$wy <= wy_max, ]

## ---- Compute Q/P ratios (cfs per inch) ----
peak_stream$ratio_QP  <- peak_stream$Q_peak_stream   / peak_stream$P_peak
peak_control$ratio_QP <- peak_control$Q_peak_control / peak_control$P_peak

## ---- Tag pre vs post fire ----
peak_stream$period  <- ifelse(peak_stream$wy  < fire_wy, "pre", "post")
peak_control$period <- ifelse(peak_control$wy < fire_wy, "pre", "post")

## ---- Drop any WY with missing ratio ----
peak_stream  <- peak_stream[!is.na(peak_stream$ratio_QP), ]
peak_control <- peak_control[!is.na(peak_control$ratio_QP), ]

## ============================================================
##  PRE / POST FIRE TAGGING (WATER YEAR–BASED)
## ============================================================
## We split all WY-based series into:
##   period = "pre"  for WY < fire_wy
##   period = "post" for WY >= fire_wy
##
## This is the basic grouping used for:
##   * Mann–Whitney tests
##   * plotting color schemes
## ------------------------------------------------------------

# Tag pre vs post for flashiness at stream (fire site)
flash_stream$period <- ifelse(flash_stream$wy < fire_wy, "pre", "post")

# Same split for control site to keep comparison aligned
flash_control$period <- ifelse(flash_control$wy < fire_wy, "pre", "post")

# Tag pre vs post in precip WY totals
precip_wy$period <- ifelse(precip_wy$wy < fire_wy, "pre", "post")

## --- 7) Tag pre/post fire for RR

RR_stream$period  <- ifelse(RR_stream$wy   < fire_wy, "pre", "post")
RR_control$period <- ifelse(RR_control$wy < fire_wy, "pre", "post")

## ============================================================
##  PLOTTING – BASIC DIAGNOSTIC PLOTS
## ============================================================
## Purpose:
##   Visual inspection of:
##     * How flashiness evolves through time
##     * Whether daily Q patterns look different post-fire
##     * How precip behaves through the same window
## ------------------------------------------------------------

## Pre/post color vectors (using helper)
cols_stream  <- assign_prepost_colors(flash_stream$period)
cols_control <- assign_prepost_colors(flash_control$period)
cols_precip  <- assign_prepost_colors(precip_wy$period)

## For vertical line in time-series plots:
fire_start_date <- as.Date(paste0(fire_wy - 1, "-10-01"))  # 1 Oct of fire WY

## 1) Flashiness – stream (fire basin)
plot(
  flash_stream$wy, flash_stream$flash,
  type = "b", pch = 16, col = cols_stream,
  xlab = "Water Year",
  ylab = "Flashiness (RBI)",
  main = paste("Flashiness –", basin_stream_name,
               "(", site_stream, ")", sep = " ")
)
abline(v = fire_wy, lty = 2, col = "red")
legend(
  "topleft",
  legend = c("Pre-fire", "Post-fire", fire_name),
  col    = c("blue", "orange", "red"),
  pch    = c(16, 16, NA),
  lty    = c(NA, NA, 2),
  bty    = "n"
)

## 2) Flashiness – control basin
plot(
  flash_control$wy, flash_control$flash,
  type = "b", pch = 16, col = cols_control,
  xlab = "Water Year",
  ylab = "Flashiness (RBI)",
  main = paste("Flashiness –", basin_control_name,
               "(", site_control, ")", sep = " ")
)
abline(v = fire_wy, lty = 2, col = "red")
legend(
  "topleft",
  legend = c("Pre-fire", "Post-fire", fire_name),
  col    = c("blue", "orange", "red"),
  pch    = c(16, 16, NA),
  lty    = c(NA, NA, 2),
  bty    = "n"
)

## 3) Daily discharge – stream (limited to WY window)
plot(
  Q_stream_plot$date, Q_stream_plot$Q_cfs,
  type = "l",
  col  = "steelblue",
  xlab = "Date",
  ylab = "Discharge (cfs)",
  main = paste("Daily Discharge –", basin_stream_name,
               "(", site_stream, ")", sep = " ")
)
abline(v = fire_start_date, col = "red", lty = 2)

legend(
  "topleft",
  legend = c("Discharge", fire_name),
  col    = c("steelblue", "red"),
  lty    = c(1, 2),
  bty    = "n"
)

## 4) Daily discharge – control (limited to WY window)
plot(
  Q_control_plot$date, Q_control_plot$Q_cfs,
  type = "l",
  col  = "darkgreen",
  xlab = "Date",
  ylab = "Discharge (cfs)",
  main = paste("Daily Discharge –", basin_control_name,
               "(", site_control, ")", sep = " ")
)
abline(v = fire_start_date, col = "red", lty = 2)

legend(
  "topleft",
  legend = c("Discharge", fire_name),
  col    = c("darkgreen", "red"),
  lty    = c(1, 2),
  bty    = "n"
)

## 5) Daily precipitation time series (WY window)
plot(
  precip_df$date, precip_df$precip_in,
  type = "h",
  col  = "gray40",
  xlab = "Date",
  ylab = "Precipitation (in/day)",
  main = "Daily Precipitation (Regional Station)"
)
abline(v = fire_start_date, col = "red", lty = 2)
legend(
  "topleft",
  legend = c("Daily precip", paste("Start of WY", fire_wy)),
  col    = c("gray40", "red"),
  lty    = c(1, 2),
  bty    = "n"
)

## 6) Annual (water-year) precipitation totals
plot(
  precip_wy$wy, precip_wy$precip_in,
  type = "b", pch = 16, col = cols_precip,
  xlab = "Water Year",
  ylab = "Total Precipitation (in / WY)",
  main = "Annual (Water-Year) Precipitation"
)
abline(v = fire_wy, col = "red", lty = 2)
legend(
  "topleft",
  legend = c("Pre-fire WY", "Post-fire WY", fire_name),
  col    = c("blue", "orange", "red"),
  pch    = c(16, 16, NA),
  lty    = c(NA, NA, 2),
  bty    = "n"
)

## --- 7) RR (runoff Ratio)


plot(
  RR_stream$wy, RR_stream$RR,
  type = "b", pch = 16,
  col  = ifelse(RR_stream$period == "pre", "blue", "orange"),
  xlab = "Water Year",
  ylab = "Runoff Ratio (RR)",
  main = paste("Runoff Ratio –", basin_stream_name)
)
abline(v = fire_wy, col = "red", lty = 2)
legend(
  "topleft",
  legend = c("Pre-fire WY", "Post-fire WY", fire_name),
  col    = c("blue", "orange", "red"),
  pch    = c(16, 16, NA),
  lty    = c(NA, NA, 2),
  bty    = "n"
)

plot(
  RR_control$wy, RR_control$RR,
  type = "b", pch = 16,
  col  = ifelse(RR_control$period == "pre", "blue", "orange"),
  xlab = "Water Year",
  ylab = "Runoff Ratio (RR)",
  main = paste("Runoff Ratio –", basin_control_name)
)
abline(v = fire_wy, col = "red", lty = 2)
legend(
  "bottomright",
  legend = c("Pre-fire WY", "Post-fire WY", fire_name),
  col    = c("blue", "orange", "red"),
  pch    = c(16, 16, NA),
  lty    = c(NA, NA, 2),
  bty    = "n"
)

## ============================================================
##  Plot: Peak-flow sensitivity (Q_peak / P_peak)
## ============================================================


## ---- FIRE site ----
cols_QP_stream <- ifelse(peak_stream$period == "pre", "blue", "orange")

plot(
  peak_stream$wy, peak_stream$ratio_QP,
  type = "b", pch = 16,
  col  = cols_QP_stream,
  xlab = "Water Year",
  ylab = "Q_peak / P_peak (cfs per inch)",
  main = paste("Peak Flow Sensitivity –", basin_stream_name)
)
abline(v = fire_wy, col = "red", lty = 2)
legend(
  "topleft",
  legend = c("Pre-fire WY", "Post-fire WY", fire_name),
  col    = c("blue", "orange", "red"),
  pch    = c(16, 16, NA),
  lty    = c(NA, NA, 2),
  bty    = "n"
)

## ---- CONTROL site ----
cols_QP_control <- ifelse(peak_control$period == "pre", "blue", "orange")

plot(
  peak_control$wy, peak_control$ratio_QP,
  type = "b", pch = 16,
  col  = cols_QP_control,
  xlab = "Water Year",
  ylab = "Q_peak / P_peak (cfs per inch)",
  main = paste("Peak Flow Sensitivity –", basin_control_name)
)
abline(v = fire_wy, col = "red", lty = 2)
legend(
  "topleft",
  legend = c("Pre-fire WY", "Post-fire WY", fire_name),
  col    = c("blue", "orange", "red"),
  pch    = c(16, 16, NA),
  lty    = c(NA, NA, 2),
  bty    = "n"
)

## ============================================================
##  RBI vs. PRECIPITATION – BASE CASE
## ============================================================
## Here we relate annual flashiness (RBI) to annual precip.
##
## Questions:
##   - Do wetter years tend to be flashier?
##   - Does the slope or intercept change post-fire?
##
## We first fit regression lines to:
##   * all pre-fire years
##   * all post-fire years
## ------------------------------------------------------------

# Merge WY flashiness with WY precipitation
flash_precip <- merge(
  flash_stream_all,
  precip_wy[, c("wy", "precip_in")],
  by = "wy"
)

# Tag pre vs post fire
flash_precip$period <- ifelse(flash_precip$wy < fire_wy, "pre", "post")

# Colors
colvec <- ifelse(flash_precip$period == "pre", "blue", "orange")

# RBI vs Precipitation Plot
plot(
  flash_precip$precip_in,
  flash_precip$flash,
  pch = 19,
  col = colvec,
  xlab = "Annual Precipitation (inches)",
  ylab = "Flashiness (RBI)",
  main = "RBI vs Precipitation (Pre vs Post Fire)"
)

# Regression lines
pre_mod  <- lm(flash ~ precip_in, data = flash_precip[flash_precip$period == "pre", ])
post_mod <- lm(flash ~ precip_in, data = flash_precip[flash_precip$period == "post", ])

#comment out to remove trendline
#abline(pre_mod,  col = "blue",   lwd = 2)
#abline(post_mod, col = "orange", lwd = 2, lty = 2)

legend(
  "topright",
  legend = c("Pre-fire", "Post-fire"),
  col    = c("blue", "orange"),
  pch    = 19,
  lty    = c(1, 2),
  bty    = "n"
)

## ============================================================
##  Statistcal Analysis Section
## ============================================================


## ============================================================
##  1) MANN–WHITNEY (WILCOXON) TESTS – PRE vs POST
## ============================================================
## Compare distributions of flashiness, mean Q, and RR
## before vs after fire.
## ------------------------------------------------------------

# Flashiness – stream (fire site)
w_flash_stream <- run_mww_pretty(
  flash_stream, "flash",
  label = "Flashiness – FIRE Site (Stream)"
)
## 
## ------------------------------------------------------------
## Flashiness – FIRE Site (Stream) 
## ------------------------------------------------------------
## Pre-fire median:   0.0844 
## Post-fire median:  0.11 
## Median difference (post - pre):  0.0253 
## 95% CI: [-0.0535, 0.0918]
## p-value:  0.61708
# Flashiness – control site
w_flash_control <- run_mww_pretty(
  flash_control, "flash",
  label = "Flashiness – CONTROL Site"
)
## 
## ------------------------------------------------------------
## Flashiness – CONTROL Site 
## ------------------------------------------------------------
## Pre-fire median:   0.2516 
## Post-fire median:  0.3132 
## Median difference (post - pre):  0.0606 
## 95% CI: [-0.0119, 0.1626]
## p-value:  0.074146
# Summary table for flashiness (stream vs control)
flash_fire_stats  <- mww_stats(flash_stream,  "flash")
flash_ctrl_stats  <- mww_stats(flash_control, "flash")

mww_flash_table <- data.frame(
  Statistic      = flash_fire_stats$Statistic,
  FIRE_Flash     = flash_fire_stats$Value,
  CONTROL_Flash  = flash_ctrl_stats$Value
)

knitr::kable(
  mww_flash_table,
  digits  = 4,
  caption = "Mann–Whitney tests for flashiness (RBI): FIRE vs CONTROL"
)
Mann–Whitney tests for flashiness (RBI): FIRE vs CONTROL
Statistic FIRE_Flash CONTROL_Flash
Pre-fire median 0.0844 0.2516
Post-fire median 0.1100 0.3132
Median difference (post - pre) 0.0253 0.0606
95% CI lower -0.0535 -0.0119
95% CI upper 0.0918 0.1626
p-value 0.6171 0.0741
# Mean Q – stream (fire site)
w_meanQ_stream <- run_mww_pretty(
  flash_stream, "meanQ",
  label = "Mean Q – FIRE Site (Stream)"
)
## 
## ------------------------------------------------------------
## Mean Q – FIRE Site (Stream) 
## ------------------------------------------------------------
## Pre-fire median:   0.9628 
## Post-fire median:  4.4491 
## Median difference (post - pre):  3.4971 
## 95% CI: [1.5812, 5.5092]
## p-value:  0.018416
# Mean Q – control site
w_meanQ_control <- run_mww_pretty(
  flash_control, "meanQ",
  label = "Mean Q – CONTROL Site"
)
## 
## ------------------------------------------------------------
## Mean Q – CONTROL Site 
## ------------------------------------------------------------
## Pre-fire median:   32.7533 
## Post-fire median:  29.2479 
## Median difference (post - pre):  2.7666 
## 95% CI: [-11.7614, 36.2593]
## p-value:  0.72098
# Summary table for mean Q (stream vs control)
meanQ_fire_stats  <- mww_stats(flash_stream,  "meanQ")
meanQ_ctrl_stats  <- mww_stats(flash_control, "meanQ")

mww_meanQ_table <- data.frame(
  Statistic      = meanQ_fire_stats$Statistic,
  FIRE_MeanQ     = meanQ_fire_stats$Value,
  CONTROL_MeanQ  = meanQ_ctrl_stats$Value
)

knitr::kable(
  mww_meanQ_table,
  digits  = 4,
  caption = "Mann–Whitney tests for mean daily discharge: FIRE vs CONTROL"
)
Mann–Whitney tests for mean daily discharge: FIRE vs CONTROL
Statistic FIRE_MeanQ CONTROL_MeanQ
Pre-fire median 0.9628 32.7533
Post-fire median 4.4491 29.2479
Median difference (post - pre) 3.4971 2.7666
95% CI lower 1.5812 -11.7614
95% CI upper 5.5092 36.2593
p-value 0.0184 0.7210
# Runoff Ratio – stream (fire site)
w_RR_stream <- run_mww_pretty(
  RR_stream, "RR",
  label = "Runoff Ratio (RR) – FIRE Site (Stream)"
)
## 
## ------------------------------------------------------------
## Runoff Ratio (RR) – FIRE Site (Stream) 
## ------------------------------------------------------------
## Pre-fire median:   0.0638 
## Post-fire median:  0.2377 
## Median difference (post - pre):  0.1765 
## 95% CI: [0.0936, 0.2365]
## p-value:  0.008221
# Runoff Ratio – control site
w_RR_control <- run_mww_pretty(
  RR_control, "RR",
  label = "Runoff Ratio (RR) – CONTROL Site"
)
## 
## ------------------------------------------------------------
## Runoff Ratio (RR) – CONTROL Site 
## ------------------------------------------------------------
## Pre-fire median:   0.1402 
## Post-fire median:  0.1401 
## Median difference (post - pre):  0.0045 
## 95% CI: [-0.065, 0.0649]
## p-value:  0.83032
# Summary table for RR (stream vs control)
RR_fire_stats  <- mww_stats(RR_stream,  "RR")
RR_ctrl_stats  <- mww_stats(RR_control, "RR")

mww_RR_table <- data.frame(
  Statistic      = RR_fire_stats$Statistic,
  FIRE_RR        = RR_fire_stats$Value,
  CONTROL_RR     = RR_ctrl_stats$Value
)

knitr::kable(
  mww_RR_table,
  digits  = 4,
  caption = "Mann–Whitney tests for runoff ratio (RR): FIRE vs CONTROL"
)
Mann–Whitney tests for runoff ratio (RR): FIRE vs CONTROL
Statistic FIRE_RR CONTROL_RR
Pre-fire median 0.0638 0.1402
Post-fire median 0.2377 0.1401
Median difference (post - pre) 0.1765 0.0045
95% CI lower 0.0936 -0.0650
95% CI upper 0.2365 0.0649
p-value 0.0082 0.8303
## ============================================================
##  2) PEAK-FLOW SENSITIVITY (Q_peak / P_peak)
## ============================================================
## Goal:
##   Relate the annual maximum daily discharge (Q_peak) to the
##   annual maximum daily precipitation (P_peak) in each WY.
##
## Metric:
##   Q_peak / P_peak  (units: cfs per inch)
## ------------------------------------------------------------

## ---- Wilcoxon tests on Q/P ratio (pretty output) ----
w_ratio_stream <- run_mww_pretty(
  peak_stream,
  response = "ratio_QP",
  label    = "Q_peak / P_peak – FIRE Site (Stream)"
)
## 
## ------------------------------------------------------------
## Q_peak / P_peak – FIRE Site (Stream) 
## ------------------------------------------------------------
## Pre-fire median:   5.1589 
## Post-fire median:  12.5217 
## Median difference (post - pre):  8.7056 
## 95% CI: [1.9247, 25.0331]
## p-value:  0.018416
w_ratio_control <- run_mww_pretty(
  peak_control,
  response = "ratio_QP",
  label    = "Q_peak / P_peak – CONTROL Site"
)
## 
## ------------------------------------------------------------
## Q_peak / P_peak – CONTROL Site 
## ------------------------------------------------------------
## Pre-fire median:   260.0089 
## Post-fire median:  294.0789 
## Median difference (post - pre):  36.1176 
## 95% CI: [-122.0362, 268.6274]
## p-value:  0.61708
## ---- Summary table for Q_peak / P_peak (stream vs control) ----
QP_fire_stats  <- mww_stats(peak_stream,  "ratio_QP")
QP_ctrl_stats  <- mww_stats(peak_control, "ratio_QP")

mww_QP_table <- data.frame(
  Statistic      = QP_fire_stats$Statistic,
  FIRE_QP        = QP_fire_stats$Value,
  CONTROL_QP     = QP_ctrl_stats$Value
)

knitr::kable(
  mww_QP_table,
  digits  = 4,
  caption = "Mann–Whitney tests for Q_peak / P_peak: FIRE vs CONTROL"
)
Mann–Whitney tests for Q_peak / P_peak: FIRE vs CONTROL
Statistic FIRE_QP CONTROL_QP
Pre-fire median 5.1589 260.0089
Post-fire median 12.5217 294.0789
Median difference (post - pre) 8.7056 36.1176
95% CI lower 1.9247 -122.0362
95% CI upper 25.0331 268.6274
p-value 0.0184 0.6171
## ============================================================
##  3) CHANGE-POINT TESTS (PETTITT) – FLASHINESS, Q/P, RR
## ============================================================

## 3a) Flashiness – FIRE site
pettitt_flash_stream <- run_pettitt(
  wy_vec    = flash_stream$wy,
  value_vec = flash_stream$flash,
  label     = "Flashiness – FIRE site (stream)"
)
## 
## Pettitt test for Flashiness – FIRE site (stream) 
##   Change-point WY: 2015 
##   K statistic    : 26 
##   p-value        : 0.3601846
kable(
  data.frame(
    Series          = "Flashiness – FIRE",
    Change_point_WY = pettitt_flash_stream$cp_wy,
    p_value         = pettitt_flash_stream$result$p.value
  ),
  caption = "Pettitt Test – Flashiness (FIRE site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Flashiness (FIRE site)
Series Change_point_WY p_value
Flashiness – FIRE 2015 0.3601846
## 3b) Flashiness – CONTROL site
pettitt_flash_control <- run_pettitt(
  wy_vec    = flash_control$wy,
  value_vec = flash_control$flash,
  label     = "Flashiness – CONTROL site"
)
## 
## Pettitt test for Flashiness – CONTROL site 
##   Change-point WY: 2010 2011 
##   K statistic    : 26 
##   p-value        : 0.3601846
kable(
  data.frame(
    Series          = "Flashiness – CONTROL",
    Change_point_WY = pettitt_flash_control$cp_wy,
    p_value         = pettitt_flash_control$result$p.value
  ),
  caption = "Pettitt Test – Flashiness (CONTROL site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Flashiness (CONTROL site)
Series Change_point_WY p_value
Flashiness – CONTROL 2010 0.3601846
Flashiness – CONTROL 2011 0.3601846
## 3c) Q_peak / P_peak – FIRE site
pettitt_ratio_stream <- run_pettitt(
  wy_vec    = peak_stream$wy,
  value_vec = peak_stream$ratio_QP,
  label     = "Q_peak / P_peak – FIRE site (stream)"
)
## 
## Pettitt test for Q_peak / P_peak – FIRE site (stream) 
##   Change-point WY: 2011 
##   K statistic    : 34 
##   p-value        : 0.1066308
kable(
  data.frame(
    Series          = "Q_peak / P_peak – FIRE",
    Change_point_WY = pettitt_ratio_stream$cp_wy,
    p_value         = pettitt_ratio_stream$result$p.value
  ),
  caption = "Pettitt Test – Q/P Ratio (FIRE site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Q/P Ratio (FIRE site)
Series Change_point_WY p_value
Q_peak / P_peak – FIRE 2011 0.1066308
## 3d) Q_peak / P_peak – CONTROL site
pettitt_ratio_control <- run_pettitt(
  wy_vec    = peak_control$wy,
  value_vec = peak_control$ratio_QP,
  label     = "Q_peak / P_peak – CONTROL site"
)
## 
## Pettitt test for Q_peak / P_peak – CONTROL site 
##   Change-point WY: 2012 
##   K statistic    : 16 
##   p-value        : 1
kable(
  data.frame(
    Series          = "Q_peak / P_peak – CONTROL",
    Change_point_WY = pettitt_ratio_control$cp_wy,
    p_value         = pettitt_ratio_control$result$p.value
  ),
  caption = "Pettitt Test – Q/P Ratio (CONTROL site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Q/P Ratio (CONTROL site)
Series Change_point_WY p_value
Q_peak / P_peak – CONTROL 2012 1
## 3e) Runoff Ratio – FIRE site
pettitt_RR_stream <- run_pettitt(
  wy_vec    = RR_stream$wy,
  value_vec = RR_stream$RR,
  label     = "Runoff Ratio – FIRE site (stream)"
)
## 
## Pettitt test for Runoff Ratio – FIRE site (stream) 
##   Change-point WY: 2012 
##   K statistic    : 42 
##   p-value        : 0.02281754
kable(
  data.frame(
    Series          = "Runoff Ratio – FIRE",
    Change_point_WY = pettitt_RR_stream$cp_wy,
    p_value         = pettitt_RR_stream$result$p.value
  ),
  caption = "Pettitt Test – Runoff Ratio (FIRE site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Runoff Ratio (FIRE site)
Series Change_point_WY p_value
Runoff Ratio – FIRE 2012 0.0228175
## 3f) Runoff Ratio – CONTROL site
pettitt_RR_control <- run_pettitt(
  wy_vec    = RR_control$wy,
  value_vec = RR_control$RR,
  label     = "Runoff Ratio – CONTROL site"
)
## 
## Pettitt test for Runoff Ratio – CONTROL site 
##   Change-point WY: 2014 
##   K statistic    : 22 
##   p-value        : 0.5861141
kable(
  data.frame(
    Series          = "Runoff Ratio – CONTROL",
    Change_point_WY = pettitt_RR_control$cp_wy,
    p_value         = pettitt_RR_control$result$p.value
  ),
  caption = "Pettitt Test – Runoff Ratio (CONTROL site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Runoff Ratio (CONTROL site)
Series Change_point_WY p_value
Runoff Ratio – CONTROL 2014 0.5861141
## 3g) Mean daily discharge – FIRE site (stream)
pettitt_meanQ_stream <- run_pettitt(
  wy_vec    = flash_stream$wy,
  value_vec = flash_stream$meanQ,
  label     = "Mean Q – FIRE site (stream)"
)
## 
## Pettitt test for Mean Q – FIRE site (stream) 
##   Change-point WY: 2012 
##   K statistic    : 42 
##   p-value        : 0.02281754
kable(
  data.frame(
    Series          = "Mean Q – FIRE",
    Change_point_WY = pettitt_meanQ_stream$cp_wy,
    p_value         = pettitt_meanQ_stream$result$p.value
  ),
  caption = "Pettitt Test – Mean Daily Discharge (FIRE site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Mean Daily Discharge (FIRE site)
Series Change_point_WY p_value
Mean Q – FIRE 2012 0.0228175
## 3h) Mean daily discharge – CONTROL site
pettitt_meanQ_control <- run_pettitt(
  wy_vec    = flash_control$wy,
  value_vec = flash_control$meanQ,
  label     = "Mean Q – CONTROL site"
)
## 
## Pettitt test for Mean Q – CONTROL site 
##   Change-point WY: 2013 2014 
##   K statistic    : 20 
##   p-value        : 0.7252615
kable(
  data.frame(
    Series          = "Mean Q – CONTROL",
    Change_point_WY = pettitt_meanQ_control$cp_wy,
    p_value         = pettitt_meanQ_control$result$p.value
  ),
  caption = "Pettitt Test – Mean Daily Discharge (CONTROL site)"
) |>
  kable_styling(full_width = FALSE, bootstrap_options = "striped")
Pettitt Test – Mean Daily Discharge (CONTROL site)
Series Change_point_WY p_value
Mean Q – CONTROL 2013 0.7252615
Mean Q – CONTROL 2014 0.7252615