7  Population Projections

Purpose: Develop tools to understand effects of alternative water management and climate scenarios on future YCT productivity. Generate estimates/projections of future population productivity and redd density from the fitted Bayesian state-space hierarchical Ricker stock-recuitment model.

Code
library(manipulate)
library(tidyverse)
library(abind)
library(DT)
library(sf)
library(mapview)
library(wesanderson)

7.1 Load data

reddctsumm: summarized redd count data (coordinates, start and end years, number of years, and median redd density)

Code
reddctsumm <- read_csv("ReddCounts_DataSummary.csv")
datatable(reddctsumm %>% mutate(across(c(lat, long, med.redds), round, 3)))

Mcmcdat: Raw MCMC samples from the Bayesian model

Code
Mcmcdat <- read_csv("Model output/ReddCountsRicker_Phase1_Age01p_mcmcsamps.csv")
head(Mcmcdat)
# A tibble: 6 × 9,924
  `A[1]` `A[2]` `A[3]` `A[4]` `A[5]` `A[6]` `A[7]` `A[8]` `A[9]` `A[10]` `A[11]`
   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>
1  1.08   1.03    1.21  1.55    1.46   1.11  1.08    1.93   1.08    1.60   1.00 
2  0.753  1.44    1.93  1.54    1.59   1.21  1.33    1.87   1.31    1.59   0.816
3  0.694  1.13    1.40  0.778   1.08   1.76  1.17    2.04   1.10    1.25   1.54 
4  0.631  1.19    1.58  1.01    1.01   1.41  0.904   1.68   1.16    1.46   1.70 
5  0.804  1.10    1.38  0.930   1.22   1.18  1.46    1.49   1.40    1.14   1.03 
6  1.18   0.815   1.05  0.957   1.49   1.61  1.03    1.26   1.16    1.25   1.04 
# ℹ 9,913 more variables: `A[12]` <dbl>, `A[13]` <dbl>, `B[1]` <dbl>,
#   `B[2]` <dbl>, `B[3]` <dbl>, `B[4]` <dbl>, `B[5]` <dbl>, `B[6]` <dbl>,
#   `B[7]` <dbl>, `B[8]` <dbl>, `B[9]` <dbl>, `B[10]` <dbl>, `B[11]` <dbl>,
#   `B[12]` <dbl>, `B[13]` <dbl>, `K[1]` <dbl>, `K[2]` <dbl>, `K[3]` <dbl>,
#   `K[4]` <dbl>, `K[5]` <dbl>, `K[6]` <dbl>, `K[7]` <dbl>, `K[8]` <dbl>,
#   `K[9]` <dbl>, `K[10]` <dbl>, `K[11]` <dbl>, `K[12]` <dbl>, `K[13]` <dbl>,
#   `coef[1,1]` <dbl>, `coef[2,1]` <dbl>, `coef[3,1]` <dbl>, …

param.summary: Summarized MCMC output (means, standard deviations, and credible intervals)

Code
param.summary <- read.csv("Model output/ReddCountsRicker_Phase1_Age01p_ParameterSummary.csv", row.names = 1)
head(param.summary)
         mean        sd     X2.5.      X25.     X50.     X75.   X97.5.     Rhat
A[1] 1.077086 0.1867074 0.6939620 0.9589434 1.081459 1.195765 1.446672 1.001755
A[2] 1.107748 0.2288303 0.6697206 0.9637958 1.097771 1.238657 1.605090 1.001607
A[3] 1.272418 0.2387507 0.8866776 1.1004579 1.240625 1.419223 1.804258 1.004253
A[4] 1.110802 0.2018552 0.7100361 0.9846001 1.106778 1.232314 1.526012 1.002491
A[5] 1.118460 0.1979021 0.7468010 0.9928939 1.114735 1.236473 1.532194 1.000608
A[6] 1.176700 0.2125670 0.8041756 1.0377785 1.160428 1.300397 1.647619 1.000694
     n.eff
A[1]  3800
A[2]  4000
A[3]  2000
A[4]  3000
A[5]  5000
A[6]  5000

covsummary: Load covariate summaries: mean, standard deviation, min/max raw values, and min/max z-scored (standardized) values The model was fit with centered/scaled covariate data (i.e., z-scores, to make effect sizes comparable). Thus, environmental input data (to make predictions) needs to be standardized on the same scale. Also use min/max to get range for sliders/inputs.

Covariate definitions and units:

  • jld_rampdur: duration of ramp down (days)
  • jld_rampratemindoy: timing of ramp down (day of calendar year, i.e., days after Dec. 31)
  • jld_winvar: managed winter flow variation (units obscure)
  • jld_summean: managed summer mean flow (cubic feet per second)
  • jld_peakmag: magnitude of managed peak spring flows (cfs)
  • jld_peaktime: timing of managed peak spring flows (day of brood year, i.e., days after Aug. 31)
  • natq_peakmag: magnitude of natural peak spring flows (cfs)
  • natq_peaktime: timing of natural peak spring flows (day of brood year, i.e., days after Aug. 31)
  • temp_falmean: mean autumn air temperature, Sept-Nov (deg. C)
  • temp_winmean: mean winter air temperature, Dec-Feb (deg. C)
  • temp_sprmean: mean spring air temperature, Mar-Apr (deg. C)
  • temp_summean: mean summer air temperature, Jun-Aug (deg. C)
Code
# This does not get run...for JBaldock use only
covsrc_jldq_summary <- read_csv("Data/Derived/ManagedFlow_SummaryMeanSD_1967-2022.csv")
covsrc_natq_summary <- read_csv("Data/Derived/NaturalFlow_SummaryMeanSD_1975-2022.csv")
covsrc_expq_summary <- read_csv("Data/Derived/ExperiencedFlow_SummaryMeanSD_1975-2022.csv")
covsrc_temp_summary <- read_csv("Data/Derived/Temperature_SummaryMeanSD_1967-2022.csv")
covsummary <- rbind(covsrc_jldq_summary[c(1,2,6:9),], covsrc_natq_summary[c(6:7),], covsrc_temp_summary)
write_csv(covsummary, "Projections/Covariates_SummaryMeanSD_forProjections.csv")
Code
covsummary <- read_csv("Projections/Covariates_SummaryMeanSD_forProjections.csv")
datatable(covsummary %>% mutate(across(c(mean, sd, min_raw, max_raw, min_zscore, max_zscore), round, 3)))

airtemp: Future air temperature projections summarized from raw GCM data provided by Pramod Adhikari (University of Wyoming, WY-ACT)…to enable future projections under baseline warming trends.

Code
airtemp <- read_csv("Data/Derived/SeasonalMeanAirTemp_Summarized_1980-2099.csv")
head(airtemp)
# A tibble: 6 × 8
  type      season  year count temp_avg temp_sd temp_min temp_max
  <chr>     <chr>  <dbl> <dbl>    <dbl>   <dbl>    <dbl>    <dbl>
1 corrected fal     1980    15   -0.285   1.48    -2.12      2.80
2 corrected fal     1981    15    3.41    1.14     1.44      5.73
3 corrected fal     1982    15    2.50    0.871    0.968     4.51
4 corrected fal     1983    15    2.93    1.13     0.522     4.48
5 corrected fal     1984    15    2.92    0.987    1.48      4.76
6 corrected fal     1985    15    3.17    1.13     1.35      4.99

7.2 Map Sites

Map the approximate mid-points of WGFD redd counts monitoring reaches

Code
reddlocs_sp <- st_as_sf(reddctsumm, coords = c("long", "lat"), crs = "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84")
mapview(reddlocs_sp)

7.3 Control Panel

Do not change these parameters as they are specific to the fitted model and data

Code
n.pops <- 13 # number of populations
n.covars <- 14 # number of covariates in model
popshort <- c("THCH", "BLKT", "BLCR", "COCA", "FISH", "FLAT", "LTBC", "LOBC", "NOWL", "PRCE", "SRSC", "SPRG", "UPBC") # abbreviated population names
poplong <- c("Three Channel Spring", "Blacktail Spring", "Blue Crane Creek", "Cowboy Cabin Spring", "Fish Creek", "Flat Creek", "Little Bar BC Spring", "Lower Bar BC Spring", "Nowlin Creek", "Price Spring", "Snake River Side Channel", "Spring Creek", "Upper Bar BC Spring")

These can be changed depending on what you are interested in doing with future projections (for time series)

Code
n.years <- 50 # number of years to run projections
n.sims <- 100 # number of simulations/iterations (greater number of simulations will better account for uncertainty and predictions will be less biased, but more simulations takes longer to run. Ideally, you would use all the MCMC samples (n = 3000) but this would take forever)
startyear <- 2020 # first year of projections

7.4 Parameter Summaries

View parameter summary tables: mean, standard deviation, and quantiles of estimated parameter(s) of interest. To export any of the tables returned below, simply use the function write_csv(x, path = ““), replacing x with the table of interest specifying the file path as a character vector.

Global intrinsic rate of productivity (mu.A), population specific rates (A), and among-population standard deviation (sigma.A)

Code
datatable(param.summary[grepl("A", row.names(param.summary)),])

Population specific strength of density dependence (Ricker b)

Code
datatable(param.summary[grepl("B", row.names(param.summary)),])

Global covariate effects

Code
datatable(param.summary[grepl("mu.coef", row.names(param.summary)),])

Population-specific covariate effects

Code
tmp <- param.summary[grepl("coef", row.names(param.summary)),]
datatable(tmp[!grepl(c("mu|sigma"), row.names(tmp)),])

Among population standard deviation in covariate effects

Code
datatable(param.summary[grepl("sigma.coef", row.names(param.summary)),])

Age-0/1 proportionality in covariate effects

Code
tmp <- param.summary[grepl("p", row.names(param.summary)),]
datatable(tmp[!grepl(c("logpred|phi|sigma"), row.names(tmp)),])

Observation and process error

Code
datatable(param.summary[c("sigma.oe"),])

Population specific process error

Code
datatable(param.summary[grepl("sigma.pe", row.names(param.summary)),])

Population specific autocorrelation term

Code
param.summary[grepl("phi", row.names(param.summary)),]
               mean        sd       X2.5.        X25.        X50.      X75.
phi[1]  -0.04797698 0.4531157 -0.86905872 -0.38476756 -0.05660092 0.2798009
phi[2]  -0.13127159 0.5030344 -0.93188113 -0.57322912 -0.13050265 0.2786591
phi[3]   0.15690270 0.4382906 -0.76270056 -0.14508684  0.17371598 0.4957205
phi[4]   0.72589287 0.3417269 -0.38736344  0.67721315  0.85056009 0.9312551
phi[5]   0.40458977 0.4858351 -0.71926860  0.08941981  0.55150244 0.8082427
phi[6]   0.77362121 0.2242098  0.16914557  0.70939791  0.82855758 0.9094922
phi[7]   0.42006398 0.2342579 -0.07873154  0.26196960  0.43342976 0.5873091
phi[8]   0.26832094 0.2773544 -0.30038367  0.08971290  0.27787523 0.4611586
phi[9]   0.44783813 0.3313165 -0.38721667  0.28525697  0.50428721 0.6834834
phi[10]  0.32857971 0.5517865 -0.81343647 -0.10315571  0.44460166 0.8391945
phi[11] -0.13607070 0.3678164 -0.83229079 -0.38667766 -0.14947804 0.1037305
phi[12]  0.19120098 0.5450643 -0.87631737 -0.23395405  0.27226964 0.6661601
phi[13]  0.66771034 0.2951146 -0.23424678  0.58312982  0.74592463 0.8558164
           X97.5.     Rhat n.eff
phi[1]  0.8235525 1.001597  4000
phi[2]  0.7897999 1.000838  5000
phi[3]  0.8970494 1.001994  3500
phi[4]  0.9851296 1.002214  3500
phi[5]  0.9698416 1.002538  3000
phi[6]  0.9813631 1.004090  2900
phi[7]  0.8518959 1.000746  5000
phi[8]  0.7917069 1.000701  5000
phi[9]  0.9224407 1.002022  3500
phi[10] 0.9836241 1.002679  2900
phi[11] 0.6253599 1.001419  4300
phi[12] 0.9619954 1.001221  4700
phi[13] 0.9730165 1.002299  3200

7.5 Scenarios

Set up scenarios for “static” scenario calculations, i.e., calculate productivity (Ricker a, ln recruits per spawner), recruitment, and Ricker stock-recruit curves under long-term average conditions and future discrete changes in select covariates

How many MCMC samples are there? (This sets the maximum number of simulations)

Code
dim(Mcmcdat)[1]
[1] 5000

Set the number of simulations

Code
n.simsss <- 1000

Get projected seasonal air temperature in 2050 and convert to z-scores based on covsummary (for static scenarios)

Code
at_fal_2050 <- (unlist(airtemp %>% filter(type == "corrected", season == "fal", year == 2050) %>% select(temp_avg)) - unlist(covsummary[9,"mean"])) / unlist(covsummary[9,"sd"])
at_win_2050 <- (unlist(airtemp %>% filter(type == "corrected", season == "win", year == 2050) %>% select(temp_avg)) - unlist(covsummary[10,"mean"])) / unlist(covsummary[10,"sd"])
at_spr_2050 <- (unlist(airtemp %>% filter(type == "corrected", season == "spr", year == 2050) %>% select(temp_avg)) - unlist(covsummary[11,"mean"])) / unlist(covsummary[11,"sd"])
at_sum_2050 <- (unlist(airtemp %>% filter(type == "corrected", season == "sum", year == 2050) %>% select(temp_avg)) - unlist(covsummary[12,"mean"])) / unlist(covsummary[12,"sd"])

c(at_win_2050, at_spr_2050, at_sum_2050)
 temp_avg  temp_avg  temp_avg 
0.9716682 1.7907533 2.3109484 

Calculate changes in natural and managed flow for static scenarios

Code
## Climate baseline

# 12 days early: May 23, 12 days before avg (-1 SD)
early_runoff <- ((unlist(covsummary[8,"mean"]) - 12) - unlist(covsummary[8,"mean"])) / unlist(covsummary[8,"sd"])
# natural drought: 7334 cfs (-1 SD)
drought <- -1  #(-1*unlist(covsummary[7,"sd"])) + unlist(covsummary[7,"mean"])


## Mgmt. Scenarios

# Early peak release: May 23, matched to natural early runoff (-1.28 SDs)
early_release <- ((unlist(covsummary[8,"mean"]) - 12) - unlist(covsummary[6,"mean"])) / unlist(covsummary[6,"sd"])
# Late peak release: June 29, 14 days after long-term average (+1 SD)
late_release <- 1 #(1*unlist(covsummary[6,"sd"])) + unlist(covsummary[6,"mean"])
#((unlist(covsummary[6,"mean"]) + 14) - unlist(covsummary[6,"mean"])) / unlist(covsummary[6,"sd"])

# early ramp down: Sept 19, 8 days before long term average (-1 standard deviations)
early_rampdown <- -1  #(-1*unlist(covsummary[2,"sd"])) + unlist(covsummary[2,"mean"])
#((unlist(covsummary[2,"mean"]) - 8) - unlist(covsummary[2,"mean"])) / unlist(covsummary[2,"sd"])
# late ramp down: Oct 5, 8 days after long term average (+1 standard deviations)
late_rampdown <- 1  #(1*unlist(covsummary[2,"sd"])) + unlist(covsummary[2,"mean"])
#((unlist(covsummary[2,"mean"]) + 8) - unlist(covsummary[2,"mean"])) / unlist(covsummary[2,"sd"])

# low mgd summer flow: 1863 cfs, -1 SD
low_summerq <- -1  #(-1*unlist(covsummary[4,"sd"])) + unlist(covsummary[4,"mean"])
# high mgd summer flow: 3538 cfs, +1 SD
high_summerq <- 1  #(1*unlist(covsummary[4,"sd"])) + unlist(covsummary[4,"mean"])

Calculate seasonal warming rates between 2020 and 2050 using linear models: warming is fastest in spring and summer, followed by autumn, and slowest in winter.

Code
mod1 <- summary(lm(temp_avg ~ year, airtemp %>% filter(type == "corrected", season == "fal", year %in% c(2020:2050))))
mod2 <- summary(lm(temp_avg ~ year, airtemp %>% filter(type == "corrected", season == "win", year %in% c(2020:2050))))
mod3 <- summary(lm(temp_avg ~ year, airtemp %>% filter(type == "corrected", season == "spr", year %in% c(2020:2050))))
mod4 <- summary(lm(temp_avg ~ year, airtemp %>% filter(type == "corrected", season == "sum", year %in% c(2020:2050))))

tibble(season = c("autumn", "winter", "spring", "summer"),
       warmingrate = c(round(coefficients(mod1)[2,1], digits = 4),
                       round(coefficients(mod2)[2,1], digits = 4),
                       round(coefficients(mod3)[2,1], digits = 4),
                       round(coefficients(mod4)[2,1], digits = 4)))
# A tibble: 4 × 2
  season warmingrate
  <chr>        <dbl>
1 autumn      0.0545
2 winter      0.0332
3 spring      0.0564
4 summer      0.0564

Define scenarios:

Code
covarvec0 <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               0,  # 8. nat peak flow magnitude
               0,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               0,  # 11. winter temp
               0,  # 12. spring temp
               0,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# 1. Baseline warming (through 2050)
covarvec1 <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               0,  # 8. nat peak flow magnitude
               0,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# 2. warming + early peak runoff 
covarvec2 <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               0,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# 3.Warming + early runoff + drought
covarvec3 <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               drought,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# 4a. Scen 3 + early release
covarvec4a <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               early_release,  # 7. mgd peak flow timing
               drought,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               early_release*early_runoff)  # 14. mgd x nat peak flow timing (interaction)

# 4b. Scen 3 + late release
covarvec4b <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               late_release,  # 7. mgd peak flow timing
               drought,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               late_release*early_runoff)  # 14. mgd x nat peak flow timing (interaction)

# 5a. Scen3 + early ramp down
covarvec5a <- c(0,  # 1. duration of ramp down
               early_rampdown,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               drought,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# 5b. Scen3 + late ramp down
covarvec5b <- c(0,  # 1. duration of ramp down
               late_rampdown,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               0,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               drought,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# 6a. Scen3 + low summer flow
covarvec6a <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               low_summerq,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               drought,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# 6b. Scen3 + high summer flow
covarvec6b <- c(0,  # 1. duration of ramp down
               0,  # 2. timing of ramp down
               0,  # 3. mgd winter flow variation
               high_summerq,  # 4. mgd summer mean flow
               0,  # 5. mgd peak flow magnitude (age-0)
               0,  # 6. mgd peak flow magnitude (age-1)
               0,  # 7. mgd peak flow timing
               drought,  # 8. nat peak flow magnitude
               early_runoff,  # 9. nat peak flow timing
               0,  # 10. autumn temp
               at_win_2050,  # 11. winter temp
               at_spr_2050,  # 12. spring temp
               at_sum_2050,  # 13. summer temp
               0)  # 14. mgd x nat peak flow timing (interaction)

# combine scenarios into list
scenario_list <- list(covarvec1, covarvec2, covarvec3, covarvec4a, covarvec4b, covarvec5a, covarvec5b, covarvec6a, covarvec6b)

7.6 Productivity

“Simple” projections show change in productivity, ln(R/S) or “Ricker a”, given a specified change in environmental variables relative to baseline (long-term average) conditions.

7.6.1 Interactive

For simplicity, only allow users to toggle covariates with “weak” (75% credible interval does not include 0) or “strong” (95% credible interval does not include 0) effects on productivity.

This doesn’t evaluate, as interactivity is not supported in Quarto/Rmarkdown, but you can download this script and run in RStudio to get a sense of how this would function.

Code
ChangeProdBP <- function(z_jld_rampratemindoy, z_jld_peaktime, z_natq_peaktime, z_temp_winmean, z_temp_sprmean, z_temp_summean) {
  # mean global and population-specific Ricker a under average conditions
  #A.mu <- param.summary["mu.A",1]
  #A.pop <- c()
  #for (i in 1:n.pops) {
  #  A.pop[i] <- param.summary[paste("A[", i, "]", sep = ""),1]
  #}
  # carrying capacity with covariate effects and model uncertainty
  A.mu.change <- unlist(Mcmcdat[,"mu.coef[2]"]*z_jld_rampratemindoy + Mcmcdat[,"mu.coef[6]"]*z_jld_peaktime + Mcmcdat[,"mu.coef[8]"]*z_natq_peaktime + Mcmcdat[,"mu.coef[10]"]*z_temp_winmean + Mcmcdat[,"mu.coef[11]"]*z_temp_sprmean + Mcmcdat[,"mu.coef[12]"]*z_temp_summean + Mcmcdat[,"mu.coef[14]"]*z_jld_peaktime*z_natq_peaktime)
  A.pop.change <- list()
  for (i in 1:n.pops) {
    A.pop.change[[i]] <- unlist(Mcmcdat[,paste("coef[",i,",2]", sep = "")]*z_jld_rampratemindoy + Mcmcdat[,paste("coef[",i,",6]", sep = "")]*z_jld_peaktime + Mcmcdat[,paste("coef[",i,",8]", sep = "")]*z_natq_peaktime + Mcmcdat[,paste("coef[",i,",10]", sep = "")]*z_temp_winmean + Mcmcdat[,paste("coef[",i,",11]", sep = "")]*z_temp_sprmean + Mcmcdat[,paste("coef[",i,",12]", sep = "")]*z_temp_summean + Mcmcdat[,paste("coef[",i,",14]", sep = "")]*z_jld_peaktime*z_natq_peaktime)
  }
  simtib <- tibble(population = c(rep("Global", times = dim(Mcmcdat)[1]), rep(popshort, each = dim(Mcmcdat)[1])),
                   outcome = c(A.mu.change, unlist(A.pop.change))) %>% mutate(population = factor(population, levels = c("Global", popshort)))
  # plot boxplot with line for reference
  boxplot(outcome ~ population, data = simtib, xlab = "Population", ylab = "Change in productivity, ln(R/S)", las = 2, ylim = c(-5,5), col = c("red", rep("grey", times = n.pops)))
  abline(h = 0, lty = 2)
}
manipulate(ChangeProdBP(z_jld_rampratemindoy, z_jld_peaktime, z_natq_peaktime, z_temp_winmean, z_temp_sprmean, z_temp_summean), 
           z_jld_rampratemindoy = slider(min = covsummary$min_zscore[2], covsummary$max_zscore[2], initial = 0, step = 0.1), 
           z_jld_peaktime = slider(min = covsummary$min_zscore[6], covsummary$max_zscore[6], initial = 0, step = 0.1), 
           z_natq_peaktime = slider(min = covsummary$min_zscore[8], covsummary$max_zscore[8], initial = 0, step = 0.1), 
           z_temp_winmean = slider(min = covsummary$min_zscore[10], covsummary$max_zscore[10], initial = 0, step = 0.1), 
           z_temp_sprmean = slider(min = covsummary$min_zscore[11], covsummary$max_zscore[11], initial = 0, step = 0.1), 
           z_temp_summean = slider(min = covsummary$min_zscore[12], covsummary$max_zscore[12], initial = 0, step = 0.1))

7.6.2 Static

Vector to store estimated productivity

Code
productivity_list <- list()

Run “simple” projections, just showing change in A

Code
for (i in 1:length(scenario_list)) {
  covarvec <- scenario_list[[i]]
  prodvec <- c()
  for (j in 1:n.simsss) {
    anncoveff <- c()
    for (c in 1:n.covars) { anncoveff[c] <- unlist(Mcmcdat[j,paste("mu.coef[", c, "]", sep = "")]) * covarvec[c] }
    prodvec[j] <- sum(anncoveff) 
  }
  productivity_list[[i]] <- prodvec
  print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
Code
prodtib <- tibble(scenario = rep(c("sc1", "sc2", "sc3", "sc4a", "sc4b", "sc5a", "sc5b", "sc6a", "sc6b"), each = n.simsss),
                  productivity = unlist(productivity_list))

Plot

Code
mypal <- c("grey60", wes_palette("GrandBudapest2", n = 3))

par(mar = c(4,4,1,1), mgp = c(2.5,1,0))
boxplot(productivity ~ scenario, prodtib, xlab = "Scenario", ylab = "Change in productivity", lty = 1, axes = FALSE, 
        col = c("grey85", "grey85", mypal[1], 
                mypal[2], mypal[2], 
                mypal[3], mypal[3], 
                mypal[4], mypal[4]))
abline(h = 0, lwd = 1, lty = 2)
axis(1, at = c(1:9), labels = c("1", "2", "3", "4a", "4b", "5a", "5b", "6a", "6b"))
axis(2)

Code
# par(mgp = c(2.5,4.75,0))
# axis(1, at = c(1:6), labels = c("(1)\nProjected\nwarming\n(2050)\n ", 
#                                 "(2)\nWarming (2050)\nEarly runoff (2 wks)\n ", 
#                                 "(3)\nWarming (2050)\nEarly runoff (2 wks)\nEarly release (matched)",
#                                 "(4)\nWarming (2050)\nEarly runoff (2 wks)\nLate release (2 wks)",
#                                 "(5)\nWarming (2050)\nEarly runoff (2 wks)\nEarly ramp-down (1 wk)",
#                                 "(6)\nWarming (2050)\nEarly runoff (2 wks)\nLate ramp-down (1 wk)"))
# par(mgp = c(2.5,1,0))
# axis(2)
Code
jpeg("Figures/Projections/ScenarioPlanning_ChangeProductivity.jpg", units = "in", width = 4.5, height = 4.5, res = 1000)
par(mar = c(4,4,0.1,0.1), mgp = c(2.5,1,0))
boxplot(productivity ~ scenario, prodtib, xlab = "Scenario", ylab = "Change in productivity", lty = 1, axes = FALSE, 
        col = c("grey85", "grey85", mypal[1], 
                mypal[2], mypal[2], 
                mypal[3], mypal[3], 
                mypal[4], mypal[4]))
abline(h = 0, lwd = 1, lty = 2)
axis(1, at = c(1:9), labels = c("1", "2", "3", "4a", "4b", "5a", "5b", "6a", "6b"))
axis(2)
dev.off()

7.7 Recruitment

The “simple” projections of change in productivity (above) fail to capture dramatic differences in redd densities among streams, which range from 14.9 redds/km in Blue Crane Creek to 254.7 redds per km in Blacktail Spring. Management actions based on projections of among-population mean productivity would act to benefit all populations equally, implicitly valuing population diversity (i.e., preserving as many populations as possible). However, managers may also wish to understand how alternative management actions affect total recruitment (redd density summed across populations), which effectively values populations according to their size (i.e., management actions may be favored if they disproportionately benefit a large population, even if it comes at a cost to a smaller population). In this section, I calculate changes in recruitment for each population and summed across all populations under alternative scenarios of climate change and water management (sensu Murdoch et al. 2024). This approach also accounts for population-level variation in the effect of environmental variables on productivity.

As above, only vary environmental variables that were found to have either weak or strong effects on productivity

7.7.0.1 Interactive

This does not evaluate in Quarto, but can be run in RStudio

Code
ChangeRecBP <- function(z_jld_rampratemindoy, z_jld_peaktime, z_natq_peaktime, z_temp_winmean, z_temp_sprmean, z_temp_summean) {
  # empty matrix to store recruitment predictions
  R.pop.change <- matrix(data = NA, nrow = dim(Mcmcdat)[1], ncol = n.pops)
  # fill matrix
  for (i in 1:n.pops) {
    # calculate effect of covariates
    coveff <- Mcmcdat[,paste("coef[",i,",2]", sep = "")]*z_jld_rampratemindoy + Mcmcdat[,paste("coef[",i,",6]", sep = "")]*z_jld_peaktime + Mcmcdat[,paste("coef[",i,",8]", sep = "")]*z_natq_peaktime + Mcmcdat[,paste("coef[",i,",10]", sep = "")]*z_temp_winmean + Mcmcdat[,paste("coef[",i,",11]", sep = "")]*z_temp_sprmean + Mcmcdat[,paste("coef[",i,",12]", sep = "")]*z_temp_summean + Mcmcdat[,paste("coef[",i,",14]", sep = "")]*z_jld_peaktime*z_natq_peaktime
    # Calculate change in recruitment (relative to long-term median redd density)
    R.pop.change[,i] <- unlist(reddctsumm$med.redds[i] * exp(Mcmcdat[,paste("A[",i,"]", sep = "")] - (Mcmcdat[,paste("B[",i,"]", sep = "")] * reddctsumm$med.redds[i]) + coveff)) - reddctsumm$med.redds[i]
  }
  # sum changes in recruitment across populations
  R.pop.change <- cbind(rowSums(R.pop.change), R.pop.change)
  colnames(R.pop.change) <- c("Total", popshort)
  # plot
  boxplot(R.pop.change, las = 2, ylim = c(-1000,1000), col = c("red", rep("grey", times = n.pops)))
  abline(h = 0, lty = 2)
}


manipulate(ChangeRecBP(z_jld_rampratemindoy, z_jld_peaktime, z_natq_peaktime, z_temp_winmean, z_temp_sprmean, z_temp_summean), 
           z_jld_rampratemindoy = slider(min = covsummary$min_zscore[2], covsummary$max_zscore[2], initial = 0, step = 0.1), 
           z_jld_peaktime = slider(min = covsummary$min_zscore[6], covsummary$max_zscore[6], initial = 0, step = 0.1), 
           z_natq_peaktime = slider(min = covsummary$min_zscore[8], covsummary$max_zscore[8], initial = 0, step = 0.1), 
           z_temp_winmean = slider(min = covsummary$min_zscore[10], covsummary$max_zscore[10], initial = 0, step = 0.1), 
           z_temp_sprmean = slider(min = covsummary$min_zscore[11], covsummary$max_zscore[11], initial = 0, step = 0.1), 
           z_temp_summean = slider(min = covsummary$min_zscore[12], covsummary$max_zscore[12], initial = 0, step = 0.1))

7.7.1 Static

Vector to store estimated recruitment

Code
recruitment_array <- array(data = NA, dim = c(n.simsss, n.pops, length(scenario_list)))
recruitment_summed <- matrix(data = NA, nrow = n.simsss, ncol = length(scenario_list))

Run recruitment projections

Code
# calculation change in recruitment for each population
for (i in 1:length(scenario_list)) {
  covarvec <- scenario_list[[i]]
  for (j in 1:n.pops) {
    coveff <- 
      Mcmcdat[1:n.simsss,paste("coef[",i,",1]", sep = "")]*covarvec[1] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",2]", sep = "")]*covarvec[2] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",3]", sep = "")]*covarvec[3] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",4]", sep = "")]*covarvec[4] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",5]", sep = "")]*covarvec[5] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",6]", sep = "")]*covarvec[6] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",7]", sep = "")]*covarvec[7] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",8]", sep = "")]*covarvec[8] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",9]", sep = "")]*covarvec[9] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",10]", sep = "")]*covarvec[10] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",11]", sep = "")]*covarvec[11] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",12]", sep = "")]*covarvec[12] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",13]", sep = "")]*covarvec[13] + 
      Mcmcdat[1:n.simsss,paste("coef[",i,",14]", sep = "")]*covarvec[14]
    recruitment_array[,j,i] <- unlist(reddctsumm$med.redds[j] * exp(Mcmcdat[1:n.simsss,paste("A[",j,"]", sep = "")] - (Mcmcdat[1:n.simsss,paste("B[",j,"]", sep = "")] * reddctsumm$med.redds[j]) + coveff)) - reddctsumm$med.redds[j]
  }
}
# sum over populations
for (i in 1:dim(recruitment_array)[3]) {
  recruitment_summed[,i] <- rowSums(recruitment_array[,,i])
}
rectib <- tibble(scenario = rep(c("sc1", "sc2", "sc3", "sc4a", "sc4b", "sc5a", "sc5b", "sc6a", "sc6b"), each = n.simsss),
                 recruitment = c(recruitment_summed))

Plot

Code
mypal <- c("grey60", wes_palette("GrandBudapest2", n = 3))
par(mar = c(4,4,1,1), mgp = c(2.5,1,0))
boxplot(recruitment ~ scenario, rectib, xlab = "Scenario", ylab = "Change in recruitment (redds/km)", lty = 1, axes = FALSE, col = c("grey85", "grey85", mypal[1], 
                mypal[2], mypal[2], 
                mypal[3], mypal[3], 
                mypal[4], mypal[4]))
abline(h = 0, lwd = 1, lty = 2)
axis(1, at = c(1:9), labels = c("1", "2", "3", "4a", "4b", "5a", "5b", "6a", "6b"))
axis(2)

7.8 Rule Curves

Calculate population-specific Ricker stock-recruit curves and show how these change under alternative climate and water management scenarios.

7.8.1 Interactive

As above, this does not evaluate in Quarto

Code
Ricker <- function(z_jld_rampratemindoy, z_jld_peaktime, z_natq_peaktime, z_temp_winmean, z_temp_sprmean, z_temp_summean, population) {
  j <- population
  # necessary vectors
  npoints <- 500
  maxsp <- 400
  spawners <- seq(from = 0, to = maxsp, length.out = npoints)
  recruits <- vector(length = npoints)
  # calculate recruitment with covariate effects
  for (i in 1:npoints) { recruits[i] <- exp(log(spawners[i]) + param.summary[paste("A[", j, "]", sep = ""),1] - param.summary[paste("B[", j, "]", sep = ""),1]*exp(log(spawners[i])) + param.summary[paste("coef[", j, ",2]", sep = ""),1]*z_jld_rampratemindoy + param.summary[paste("coef[", j, ",6]", sep = ""),1]*z_jld_peaktime + param.summary[paste("coef[", j, ",8]", sep = ""),1]*z_natq_peaktime + param.summary[paste("coef[", j, ",10]", sep = ""),1]*z_temp_winmean + param.summary[paste("coef[", j, ",11]", sep = ""),1]*z_temp_sprmean + param.summary[paste("coef[", j, ",12]", sep = ""),1]*z_temp_summean) }
  # carrying capacity under average conditions
  # K.mu <- (param.summary["mu.A",1]) / param.summary["mu.B",1]
  # carrying capacity with covariate effects
  # K <- (param.summary["mu.A",1] + param.summary["mu.coef[1]",1]*x1 + param.summary["mu.coef[2]",1]*x2 + param.summary["mu.coef[3]",1]*x1*x2) / param.summary["mu.B",1]
  # plot stock-recruitment Ricker curve with lines and text denoting change in carrying capacity
  plot(x = spawners, y = recruits, type = "l", xaxs = "i", yaxs = "i", xlim = c(0,maxsp), ylim = c(0,maxsp), lwd = 2, col = "blue", xlab = "Spawners (redds/km)", ylab ="Recruits (redds/km)", main = poplong[j])
  # arrows(x0 = K, y0 = -50, x1 = K, y1 = K, col = "blue", length = 0, lwd = 0.75)
  # text(x = K+1, y = 5, labels = paste(round((K/K.mu)*100), "%", sep = ""), col = "blue", srt = 90)
  abline(a = 0, b = 1, lty = 2)
}


manipulate(Ricker(z_jld_rampratemindoy, z_jld_peaktime, z_natq_peaktime, z_temp_winmean, z_temp_sprmean, z_temp_summean, population), 
           population = picker("Three Channel Spring" = 1, 
                               "Blacktail Spring" = 2,
                               "Blue Crane Creek" = 3,
                               "Cowboy Cabin Spring" = 4,
                               "Fish Creek" = 5,
                               "Flat Creek" = 6,
                               "Little Bar BC Spring" = 7,
                               "Lower Bar BC Spring" = 8,
                               "Nowlin Creek" = 9,
                               "Price Spring" = 10,
                               "Snake River Side Channel" = 11,
                               "Spring Creek" = 12,
                               "Upper Bar BC Spring" = 13),
           z_jld_rampratemindoy = slider(min = covsummary$min_zscore[2], covsummary$max_zscore[2], initial = 0, step = 0.1), 
           z_jld_peaktime = slider(min = covsummary$min_zscore[6], covsummary$max_zscore[6], initial = 0, step = 0.1), 
           z_natq_peaktime = slider(min = covsummary$min_zscore[8], covsummary$max_zscore[8], initial = 0, step = 0.1), 
           z_temp_winmean = slider(min = covsummary$min_zscore[10], covsummary$max_zscore[10], initial = 0, step = 0.1), 
           z_temp_sprmean = slider(min = covsummary$min_zscore[11], covsummary$max_zscore[11], initial = 0, step = 0.1), 
           z_temp_summean = slider(min = covsummary$min_zscore[12], covsummary$max_zscore[12], initial = 0, step = 0.1))