From c907fa360d3edf753257ff473c34adf1275ea8e5 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Thu, 5 Mar 2026 16:48:55 -0500 Subject: [PATCH 1/8] Create first draft of key quantities template csv; start drafting pipeline to add kqs to it in landings plot --- R/plot_landings.R | 81 ++++++++++++++--- inst/resources/key_quantity_template.csv | 109 +++++++++++++++++++++++ 2 files changed, 180 insertions(+), 10 deletions(-) create mode 100644 inst/resources/key_quantity_template.csv diff --git a/R/plot_landings.R b/R/plot_landings.R index 7fc9041e..047ca5d0 100644 --- a/R/plot_landings.R +++ b/R/plot_landings.R @@ -99,16 +99,77 @@ plot_landings <- function( ### Make RDA ---- if (make_rda) { - create_rda( - object = plt, - # get name of function and remove "plot_" from it - topic_label = gsub("plot_", "", as.character(sys.call()[[1]])), - fig_or_table = "figure", - dat = dat, - dir = figures_dir, - scale_amount = scale_amount, - unit_label = unit_label - ) + + if (file.exists(fs::path(dir, "key_quantities.csv"))) { + cli::cli_alert_info("Key quantities text file (key_quantities.csv) exists. Newly calculated key quantities will be added to it.", wrap = TRUE) + caps_alttext <- utils::read.csv( + file.path(dir, "key_quantities.csv") + ) + } else { + caps_alttext <- utils::read.csv( + system.file("resources", "key_quantity_template.csv", package = "stockplotr") + ) + } + + # Obtain relevant key quantities for captions/alt text + landings.end.year <- max(prepared_data$year) + landings.max <- max(prepared_data$estimate) + landings.min <- min(prepared_data$estimate) + landings.start.year <- min(prepared_data$year) + landings.units <- unit_label + + fill_in_kqs <- function(df, ...) { + + arg_names <- sapply(substitute(list(...))[-1], deparse) + arg_values <- list(...) + + lookup_df <- tibble::tibble( + key_quantity = arg_names, + value_new = purrr::map_chr(arg_values, as.character) + ) + + # TODO: Add message when certain values aren't overwritten (already present) + df <- df |> + dplyr::mutate(across(everything(), as.character)) |> + dplyr::left_join(lookup_df, by = "key_quantity") |> + dplyr::mutate(value = dplyr::if_else( + (is.na(value) | value == "" & !is.na(value_new)), + value_new, + value)) |> + dplyr::select(-value_new) + } + } + + caps_alttext_filled <- fill_in_kqs(caps_alttext, + landings.max, + landings.min, + landings.start.year, + landings.end.year, + landings.units) + + # next step: export caps_alttext_filled + + # export df with updated captions and alt text to csv + # utils::write.csv( + # x = caps_alttext, + # file = fs::path( + # dir, + # "key_quantities.csv" + # ), + # row.names = FALSE + # ) + + + # create_rda( + # object = plt, + # # get name of function and remove "plot_" from it + # topic_label = gsub("plot_", "", as.character(sys.call()[[1]])), + # fig_or_table = "figure", + # dat = dat, + # dir = figures_dir, + # scale_amount = scale_amount, + # unit_label = unit_label + # ) } # Output final plot plt diff --git a/inst/resources/key_quantity_template.csv b/inst/resources/key_quantity_template.csv new file mode 100644 index 00000000..f6a637a6 --- /dev/null +++ b/inst/resources/key_quantity_template.csv @@ -0,0 +1,109 @@ +key_quantity,value,meaning,dependent_on_other_kq,dependent_kq,dependent_on_other_fxn_args,fxn_with_other_args +B.BMSY.end.yr,,,,,, +B.start.year,,,,,, +Bend,,,,,, +Bmsy,,,,,, +Btarg,,,,,, +caa.age.max,,,,,, +caa.age.min,,,,,, +caa.end.year,,,,,, +caa.start.year,,,,,, +cal.length.max,,,,,, +cal.length.min,,,,,, +cpue.end.year,,,,,, +cpue.max,,,,,, +cpue.min,,,,,, +cpue.start.year,,,,,, +F.FMSY.end.yr,,,,,, +F.max,,,,,, +F.min,,,,,, +F.ref.pt,,,,,, +F.start.year,,,,,, +fecundity.length.max,,,,,, +fecundity.length.min,,,,,, +fecundity.length.units,,,,,, +fecundity.max,,,,,, +fecundity.min,,,,,, +fecundity.units,,,,,, +fork.length.max,,,,,, +fork.length.min,,,,,, +fork.length.units,,,,,, +Ftarg,,,,,, +kobe.end.year,,,,,, +landings.end.year,,,,,, +landings.max,,,,,, +landings.min,,,,,, +landings.start.year,,,,,, +landings.units,,,,,, +M.age.max,,,,,, +M.age.min,,,,,, +M.rate.max,,,,,, +M.rate.min,,,,,, +mod.fit.abun.end.year,,,,,, +mod.fit.abun.start.year,,,,,, +mod.fit.catch.end.year,,,,,, +mod.fit.catch.max,,,,,, +mod.fit.catch.min,,,,,, +mod.fit.catch.start.year,,,,,, +mod.fit.catch.units,,,,,, +mod.fit.discards.end.year,,,,,, +mod.fit.discards.max,,,,,, +mod.fit.discards.min,,,,,, +mod.fit.discards.start.year,,,,,, +mod.fit.discards.units,,,,,, +overfished.status.is.isnot,,,,,, +overfishing.status.is.isnot,,,,,, +pop.baa.age.max,,,,,, +pop.baa.age.min,,,,,, +pop.baa.end.year,,,,,, +pop.baa.fish.max,,,,,, +pop.baa.fish.min,,,,,, +pop.baa.start.year,,,,,, +pop.naa.age.max,,,,,, +pop.naa.age.min,,,,,, +pop.naa.end.year,,,,,, +pop.naa.fish.max,,,,,, +pop.naa.fish.min,,,,,, +pop.naa.start.year,,,,,, +proj.catch.end.year,,,,,, +proj.catch.min,,,,,, +proj.catch.start.year,,,,,, +proj.catch.units,,,,,, +prop.mat.length.max,,,,,, +prop.mat.length.min,,,,,, +prop.mat.length.units,,,,,, +R0,,,,,, +recruit.dev.max,,,,,, +recruit.dev.min,,,,,, +recruit.dev.start.year,,,,,, +recruitment.start.year,,,,,, +rel.B.max,,,,,, +rel.B.min,,,,,, +rel.recruitment.max,,,,,, +rel.recruitment.min,,,,,, +selectivity.end.year,,,,,, +selectivity.length.max,,,,,, +selectivity.length.min,,,,,, +selectivity.length.units,,,,,, +selectivity.start.year,,,,,, +spr.max,,,,,, +spr.min,,,,,, +spr.ref.pt,,,,,, +sr.age.min,,,,,, +ssb.start.year,,,,,, +tot.catch.max,,,,,, +tot.catch.min,,,,,, +total.length.max,,,,,, +total.length.min,,,,,, +total.length.units,,,,,, +vonb.age.max,,,,,, +vonb.age.min,,,,,, +vonb.length.max,,,,,, +vonb.length.min,,,,,, +vonb.length.units,,,,,, +wl.length.max,,,,,, +wl.length.min,,,,,, +wl.length.units,,,,,, +wl.weight.max,,,,,, +wl.weight.min,,,,,, +wl.weight.units,,,,,, \ No newline at end of file From 97965cb3c5ed231ad83d4d695d2dbfa3ac05b25d Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Thu, 12 Mar 2026 13:26:36 -0400 Subject: [PATCH 2/8] Finished draft of key quantities pipeline for landings plot --- DESCRIPTION | 1 + R/plot_landings.R | 95 ++++++-------------- R/utils_rda.R | 219 +++++++++++++++++++++++++--------------------- 3 files changed, 147 insertions(+), 168 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 3f5e946f..99d97f9d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,6 +48,7 @@ Imports: naniar, prodlim, quarto, + rlang, scales, stats, stringr, diff --git a/R/plot_landings.R b/R/plot_landings.R index 047ca5d0..bf7bdb64 100644 --- a/R/plot_landings.R +++ b/R/plot_landings.R @@ -100,76 +100,37 @@ plot_landings <- function( ### Make RDA ---- if (make_rda) { - if (file.exists(fs::path(dir, "key_quantities.csv"))) { - cli::cli_alert_info("Key quantities text file (key_quantities.csv) exists. Newly calculated key quantities will be added to it.", wrap = TRUE) - caps_alttext <- utils::read.csv( - file.path(dir, "key_quantities.csv") - ) - } else { - caps_alttext <- utils::read.csv( - system.file("resources", "key_quantity_template.csv", package = "stockplotr") - ) - } + # Obtain relevant key quantities for captions/alt text + landings.end.year <- max(prepared_data$year) + landings.max <- max(prepared_data$estimate) + landings.min <- min(prepared_data$estimate) + landings.start.year <- min(prepared_data$year) + landings.units <- unit_label - # Obtain relevant key quantities for captions/alt text - landings.end.year <- max(prepared_data$year) - landings.max <- max(prepared_data$estimate) - landings.min <- min(prepared_data$estimate) - landings.start.year <- min(prepared_data$year) - landings.units <- unit_label - - fill_in_kqs <- function(df, ...) { - - arg_names <- sapply(substitute(list(...))[-1], deparse) - arg_values <- list(...) - - lookup_df <- tibble::tibble( - key_quantity = arg_names, - value_new = purrr::map_chr(arg_values, as.character) - ) - - # TODO: Add message when certain values aren't overwritten (already present) - df <- df |> - dplyr::mutate(across(everything(), as.character)) |> - dplyr::left_join(lookup_df, by = "key_quantity") |> - dplyr::mutate(value = dplyr::if_else( - (is.na(value) | value == "" & !is.na(value_new)), - value_new, - value)) |> - dplyr::select(-value_new) - } - } - - caps_alttext_filled <- fill_in_kqs(caps_alttext, - landings.max, - landings.min, - landings.start.year, - landings.end.year, - landings.units) - - # next step: export caps_alttext_filled - - # export df with updated captions and alt text to csv - # utils::write.csv( - # x = caps_alttext, - # file = fs::path( - # dir, - # "key_quantities.csv" - # ), - # row.names = FALSE - # ) + # calculate & export key quantities + export_kqs(landings.end.year, + landings.max, + landings.min, + landings.start.year, + landings.units) + # Add key quantities to captions/alt text + insert_kqs(landings.end.year, + landings.max, + landings.min, + landings.start.year, + landings.units) - # create_rda( - # object = plt, - # # get name of function and remove "plot_" from it - # topic_label = gsub("plot_", "", as.character(sys.call()[[1]])), - # fig_or_table = "figure", - # dat = dat, - # dir = figures_dir, - # scale_amount = scale_amount, - # unit_label = unit_label - # ) + create_rda( + object = plt, + # get name of function and remove "plot_" from it + topic_label = gsub("plot_", "", as.character(sys.call()[[1]])), + fig_or_table = "figure", + dat = dat, + dir = figures_dir, + scale_amount = scale_amount, + unit_label = unit_label + ) } # Output final plot plt diff --git a/R/utils_rda.R b/R/utils_rda.R index 6d513427..453221ce 100644 --- a/R/utils_rda.R +++ b/R/utils_rda.R @@ -2,6 +2,123 @@ # RDA utility functions # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# TODO: update new fxns to work with a specified 'dir' instead of default 'getwd()'? + +# Fill in key quantities in template +fill_in_kqs <- function(df, ...) { + + arg_names <- sapply(substitute(list(...))[-1], deparse) + arg_values <- list(...) + + lookup_df <- tibble::tibble( + key_quantity = arg_names, + value_new = purrr::map_chr(arg_values, as.character) + ) + + # TODO: Add message when certain values aren't overwritten (already present) + df <- df |> + dplyr::mutate(across(everything(), as.character)) |> + dplyr::left_join(lookup_df, by = "key_quantity") |> + dplyr::mutate(value = dplyr::if_else( + (is.na(value) | value == "" & !is.na(value_new)), + value_new, + value)) |> + dplyr::select(-value_new) +} + +# Calculate and export key quantities +## kqs (e.g., landings.end.year) are the ellipsis args +export_kqs <- function(...) { + + # Open new or existing key quantities csv + if (file.exists(fs::path(getwd(), "key_quantities.csv"))) { + cli::cli_alert_info("Key quantities text file (key_quantities.csv) exists. Newly calculated key quantities will be added to it.", wrap = TRUE) + kqs <- utils::read.csv(file.path(getwd(), "key_quantities.csv")) + } else { + kqs <- utils::read.csv( + system.file("resources", "key_quantity_template.csv", package = "stockplotr") + ) + } + + # kqs (e.g., landings.end.year) are the ellipsis args + kqs_filled <- fill_in_kqs(kqs, + ...) + + utils::write.csv( + x = kqs_filled, + file = fs::path(getwd(), "key_quantities.csv"), + row.names = FALSE + ) + +} + +# Add key quantities to captions/alt text csv +## kqs (e.g., landings.end.year) are the ellipsis args +insert_kqs <- function(...) { + if (file.exists(fs::path(getwd(), "captions_alt_text.csv"))) { + cli::cli_alert_info("Captions/alternative text file (captions_alt_text.csv) exists. Newly calculated key quantities will be added to it.", wrap = TRUE) + caps_alttext <- utils::read.csv(fs::path(getwd(), "captions_alt_text.csv")) + } else { + caps_alttext <- utils::read.csv( + system.file("resources", "captions_alt_text_template.csv", package = "stockplotr") + ) + } + + create_patterns <- function(...) { + # Capture the names from the dots without evaluating them yet + arg_names <- sapply(rlang::enexprs(...), as.character) + + # Get the actual values + vals <- list(...) + + # Combine them into a named character vector + stats::setNames(as.character(vals), arg_names) + } + + # insert new kqs into alt text/caps csv, where applicable + patterns_replacements <- create_patterns(...) |> + # If a value = NA, then make it "NA" to avoid errors + tidyr::replace_na("NA") + + # replace values in caption column + caps_alttext$caption <- stringr::str_replace_all( + caps_alttext$caption, + patterns_replacements + ) + + # replace values in alt text column + caps_alttext$alt_text <- stringr::str_replace_all( + caps_alttext$alt_text, + patterns_replacements + ) + + # export df with updated captions and alt text to csv + utils::write.csv( + x = caps_alttext, + file = fs::path(getwd(), "captions_alt_text.csv"), + row.names = FALSE + ) + + # message explaining the extracted and inserted key quantities + replaced_vals <- patterns_replacements |> + as.data.frame() |> + tibble::rownames_to_column() |> + dplyr::rename( + "name" = 1, + "key_quantity" = 2 + ) + + cli::cli_h3("The following key quantities were extracted and inserted into 'captions_alt_text.csv' and 'key_quantities.csv':") + for (i in 1:dim(replaced_vals)[1]) { + cli::cli_li(paste0( + replaced_vals[i, 1], + ": ", + replaced_vals[i, 2] + )) + } +} + + #' Create the rda package for a plot or table #' #' @param object Table or plot object @@ -46,38 +163,6 @@ create_rda <- function( unit_label = "mt", table_df = NULL ) { - # run write_captions.R if its output doesn't exist - if (!file.exists( - fs::path(getwd(), "captions_alt_text.csv") - ) - ) { - write_captions( - dat = dat, - dir = dir, - year = max(dat$year, na.rm = TRUE) # this is not right I think - ) - } - - # Remove non-numeric strings from year - year <- dat |> - dplyr::filter( - year %notin% c("Virg", "S/Rcurve", "Init", "selex"), - era == "time" - ) |> - dplyr::mutate(year = as.numeric(year)) - - # add more key quantities included as arguments in this fxn - add_more_key_quants( - dat, - topic = topic_label, - fig_or_table = fig_or_table, - dir = dir, - end_year = max(year$year, na.rm = TRUE), - units = unit_label, - ref_pt = ref_point, - ref_line = ref_line, - scaling = scale_amount - ) # extract this plot's caption and alt text caps_alttext <- extract_caps_alttext( @@ -96,7 +181,7 @@ create_rda <- function( export_rda( object = object, - caps_alttext = caps_alttext, # Load in of this is missing I think + caps_alttext = caps_alttext, figures_tables_dir = dir, topic_label = topic_label, fig_or_table = fig_or_table, @@ -880,62 +965,6 @@ write_captions <- function(dat, # converted model output object # F.Ftarg : added with add_more_key_quants - ## landings plot - - # start year of landings plot - landings.start.year <- dat |> - dplyr::filter( - c(module_name == "t.series" & grepl("landings_observed", label)) | c(module_name == "CATCH" & grepl("ret_bio", label)), - # t.series is associated with a conversion from BAM output and CATCH with SS3 converted output - !is.na(fleet) - ) |> - dplyr::slice(which.min(year)) |> - dplyr::select(year) |> - as.numeric() - - # end year of landings plot - landings.end.year <- dat |> - dplyr::filter( - c(module_name == "t.series" & grepl("landings_observed", label)) | c(module_name == "CATCH" & grepl("ret_bio", label)), - # t.series is associated with a conversion from BAM output and CATCH with SS3 converted output - !is.na(fleet) - ) |> - dplyr::slice(which.max(year)) |> - dplyr::select(year) |> - as.numeric() - - # units of landings (plural) - # landings.units : added with add_more_key_quants - - # minimum landings - landings.min <- dat |> - dplyr::filter( - c(module_name == "t.series" & grepl("landings_observed", label)) | c(module_name == "CATCH" & grepl("ret_bio", label)), - # t.series is associated with a conversion from BAM output and CATCH with SS3 converted output - !is.na(fleet) - ) |> - dplyr::slice(which.min(estimate)) |> - dplyr::select(estimate) |> - as.numeric() |> - round(digits = 2) - - # maximum landings - landings.max <- dat |> - dplyr::filter( - c(module_name == "t.series" & grepl("landings_observed", label)) | c(module_name == "CATCH" & grepl("ret_bio", label)), - # t.series is associated with a conversion from BAM output and CATCH with SS3 converted output - !is.na(fleet) - ) |> - dplyr::group_by(fleet, year) |> - dplyr::summarise(max_est = max(estimate)) |> - dplyr::filter(!is.na(max_est)) |> - dplyr::group_by(year) |> - dplyr::summarise(max_est_yr = sum(max_est)) |> - dplyr::slice(which.max(max_est_yr)) |> - dplyr::select(max_est_yr) |> - as.numeric() |> - round(digits = 2) - ## natural mortality (M)- bam examples have label as natural_mortality ## but other formats don't (in input) # minimum age of M @@ -1492,9 +1521,6 @@ write_captions <- function(dat, # converted model output object ## catch # catch.fleet <- # fleet - ## landings - # landings.tbl.units <- # landings units; remove if units already in table - ## discards # discards.tbl.units <- # discards units @@ -1539,12 +1565,6 @@ write_captions <- function(dat, # converted model output object "F.max" = as.character(F.max), # 'Ftarg' = as.character(Ftarg), - ## landings plot - "landings.start.year" = as.character(landings.start.year), - "landings.end.year" = as.character(landings.end.year), - "landings.min" = as.character(landings.min), - "landings.max" = as.character(landings.max), - ## natural mortality (M) "M.age.min" = as.character(M.age.min), "M.age.max" = as.character(M.age.max), @@ -1687,9 +1707,6 @@ write_captions <- function(dat, # converted model output object # ## catch # 'catch.fleet' = as.character(catch.fleet), # - # ## landings - # 'landings.tbl.units' = as.character(landings.tbl.units), - # # ## discards # 'discards.tbl.units' = as.character(discards.tbl.units), # From f749fce018f8e0d0728c05f75cbe2abe886c97f2 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Tue, 17 Mar 2026 09:53:06 -0400 Subject: [PATCH 3/8] Reorder KQs in plot_landings() by logical grouping; update plot_recruitment_deviations() to work with new KQ extraction/insertion design --- R/plot_landings.R | 16 +++---- R/plot_recruitment_deviations.R | 19 ++++++++ R/utils_rda.R | 60 ------------------------ inst/resources/key_quantity_template.csv | 1 + 4 files changed, 28 insertions(+), 68 deletions(-) diff --git a/R/plot_landings.R b/R/plot_landings.R index bf7bdb64..8f7e32a4 100644 --- a/R/plot_landings.R +++ b/R/plot_landings.R @@ -101,24 +101,24 @@ plot_landings <- function( if (make_rda) { # Obtain relevant key quantities for captions/alt text + landings.start.year <- min(prepared_data$year) landings.end.year <- max(prepared_data$year) - landings.max <- max(prepared_data$estimate) landings.min <- min(prepared_data$estimate) - landings.start.year <- min(prepared_data$year) + landings.max <- max(prepared_data$estimate) landings.units <- unit_label # calculate & export key quantities - export_kqs(landings.end.year, - landings.max, + export_kqs(landings.start.year, + landings.end.year, landings.min, - landings.start.year, + landings.max, landings.units) # Add key quantities to captions/alt text - insert_kqs(landings.end.year, - landings.max, + insert_kqs(landings.start.year, + landings.end.year, landings.min, - landings.start.year, + landings.max, landings.units) create_rda( diff --git a/R/plot_recruitment_deviations.R b/R/plot_recruitment_deviations.R index ca84f27b..e757cd68 100644 --- a/R/plot_recruitment_deviations.R +++ b/R/plot_recruitment_deviations.R @@ -100,6 +100,25 @@ plot_recruitment_deviations <- function( } else { selected_dat <- dat } + + # Obtain relevant key quantities for captions/alt text + recruit.dev.start.year <- min(filter_data$year) + recruit.dev.end.year <- max(filter_data$year) + recruit.dev.min <- min(filter_data$estimate) + recruit.dev.max <- max(filter_data$estimate) + + # calculate & export key quantities + export_kqs(recruit.dev.start.year, + recruit.dev.end.year, + recruit.dev.min, + recruit.dev.max) + + # Add key quantities to captions/alt text + insert_kqs(recruit.dev.start.year, + recruit.dev.end.year, + recruit.dev.min, + recruit.dev.max) + create_rda( object = final, # get name of function and remove "plot_" from it diff --git a/R/utils_rda.R b/R/utils_rda.R index 453221ce..7a31112c 100644 --- a/R/utils_rda.R +++ b/R/utils_rda.R @@ -1299,61 +1299,6 @@ write_captions <- function(dat, # converted model output object # rel.recruitment.max <- (sr.max / R0) |> # round(digits = 2) - - ## recruitment deviations - # start year of recruitment deviations plot - recruit.dev.start.year <- dat |> - dplyr::filter( - label == "recruitment_deviations" | label == "log_recruitment_deviations", - module_name == "SPAWN_RECRUIT" | module_name == "t.series", - !is.na(year), - is.na(fleet) | length(unique(fleet)) <= 1, - is.na(sex) | length(unique(sex)) <= 1, - is.na(area) | length(unique(area)) <= 1, - is.na(growth_pattern) | length(unique(growth_pattern)) <= 1, - !year %in% year_exclusions - ) |> # SS3 and BAM target module names - dplyr::slice(which.min(year)) |> - dplyr::select(year) |> - as.numeric() - - # end year of recruitment deviations plot - # recruit.dev.end.year : added with add_more_key_quants - - # minimum recruitment deviation - recruit.dev.min <- dat |> - dplyr::filter( - label == "recruitment_deviations" | label == "log_recruitment_deviations", - module_name == "SPAWN_RECRUIT" | module_name == "t.series", - !is.na(year), - is.na(fleet) | length(unique(fleet)) <= 1, - is.na(sex) | length(unique(sex)) <= 1, - is.na(area) | length(unique(area)) <= 1, - is.na(growth_pattern) | length(unique(growth_pattern)) <= 1, - !year %in% year_exclusions - ) |> # SS3 and BAM target module names - dplyr::slice(which.min(estimate)) |> - dplyr::select(estimate) |> - as.numeric() |> - round(digits = 2) - - # maximum recruitment deviation - recruit.dev.max <- dat |> - dplyr::filter( - label == "recruitment_deviations" | label == "log_recruitment_deviations", - module_name == "SPAWN_RECRUIT" | module_name == "t.series", - !is.na(year), - is.na(fleet) | length(unique(fleet)) <= 1, - is.na(sex) | length(unique(sex)) <= 1, - is.na(area) | length(unique(area)) <= 1, - is.na(growth_pattern) | length(unique(growth_pattern)) <= 1, - !year %in% year_exclusions - ) |> # SS3 and BAM target module names - dplyr::slice(which.max(estimate)) |> - dplyr::select(estimate) |> - as.numeric() |> - round(digits = 2) - ## tot_b (total biomass): same as B plot above ## spawning_biomass (ssb) @@ -1673,11 +1618,6 @@ write_captions <- function(dat, # converted model output object ## recruitment ts "recruitment.start.year" = as.character(recruitment.start.year), - ## recruitment deviations - "recruit.dev.start.year" = as.character(recruit.dev.start.year), - "recruit.dev.min" = as.character(recruit.dev.min), - "recruit.dev.max" = as.character(recruit.dev.max), - ## spawning.biomass (ssb) "ssb.start.year" = as.character(ssb.start.year), diff --git a/inst/resources/key_quantity_template.csv b/inst/resources/key_quantity_template.csv index f6a637a6..b9a04e21 100644 --- a/inst/resources/key_quantity_template.csv +++ b/inst/resources/key_quantity_template.csv @@ -73,6 +73,7 @@ prop.mat.length.max,,,,,, prop.mat.length.min,,,,,, prop.mat.length.units,,,,,, R0,,,,,, +recruit.dev.end.year,,,,,, recruit.dev.max,,,,,, recruit.dev.min,,,,,, recruit.dev.start.year,,,,,, From 73597344c4f419a58ab831e18a76f4af2cdb1300 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Tue, 17 Mar 2026 14:07:15 -0400 Subject: [PATCH 4/8] update plot_fishing_mortality() to work with new KQ extraction/insertion design --- R/plot_fishing_mortality.R | 22 +++ R/utils_rda.R | 132 ------------------ inst/resources/captions_alt_text_template.csv | 2 +- inst/resources/key_quantity_template.csv | 1 + 4 files changed, 24 insertions(+), 133 deletions(-) diff --git a/R/plot_fishing_mortality.R b/R/plot_fishing_mortality.R index 3a48dd54..4ffa7542 100644 --- a/R/plot_fishing_mortality.R +++ b/R/plot_fishing_mortality.R @@ -95,6 +95,28 @@ plot_fishing_mortality <- function( ### Make RDA ---- if (make_rda) { + + # Obtain relevant key quantities for captions/alt text + F.ref.pt <- as.character(ref_line) + F.start.year <- min(prepared_data$year) + F.end.year <- max(prepared_data$year) + F.min <- min(prepared_data$estimate) + F.max <- max(prepared_data$estimate) + + # calculate & export key quantities + export_kqs(F.ref.pt, + F.start.year, + F.end.year, + F.min, + F.max) + + # Add key quantities to captions/alt text + insert_kqs(F.ref.pt, + F.start.year, + F.end.year, + F.min, + F.max) + create_rda( object = final, topic_label = ifelse(relative, "relative_fishing_mortality", "fishing_mortality"), diff --git a/R/utils_rda.R b/R/utils_rda.R index 7a31112c..6582553a 100644 --- a/R/utils_rda.R +++ b/R/utils_rda.R @@ -234,47 +234,6 @@ add_more_key_quants <- function( cli::cli_h3("Key quantities extracted and inserted from add_more_key_quants():") - # calculate key quantities that rely on end_year for calculation - ## terminal fishing mortality - # if (topic_cap_alt$label == "fishing_mortality") { - # if (is.null(dat)) { - # cli::cli_alert_warning("Some key quantities associated with fishing mortality were not extracted and added to captions_alt_text.csv due to missing data file (i.e., 'dat' argument).", wrap = TRUE) - # } else { - # F.end.year <- dat |> - # dplyr::filter( - # c(label == "fishing_mortality" & - # year == end_year) | - # c(label == "terminal_fishing_mortality" & is.na(year)) - # ) |> - # dplyr::pull(estimate) |> - # as.numeric() |> - # round(digits = 2) - # - # # COMMENTING OUT THESE LINES because the current alt text/captions csv - # # doesn't include Ftarg or F.Ftarg. If we alter them to include them, - # # then uncomment these lines and add code that would substitute the key - # # quantities into the df, like at the bottom of write_captions. - # # - # # # recalculate Ftarg for F.Ftarg, below - # # Ftarg <- dat |> - # # dplyr::filter(grepl('f_target', label) | - # # grepl('f_msy', label) | - # # c(grepl('fishing_mortality_msy', label) & - # # is.na(year))) |> - # # dplyr::pull(estimate) |> - # # as.numeric() |> - # # round(digits = 2) - # # - # # # Terminal year F respective to F target - # # F.Ftarg <- F.end.year / Ftarg - # - # if (!is.null(F.end.year)) { - # end_year <- as.character(F.end.year) - # } - # } - # } - - # calculate key quantities that rely on scaling for calculation # TODO: pull the relative forms of these three KQs (B, R, SSB) from write_captions, # write analogous code for each in this section, and remove placeholders from @@ -876,94 +835,6 @@ write_captions <- function(dat, # converted model output object # rel.B.max <- (B.max / Btarg) |> # round(digits = 2) - # TODO: uncomment and recode once we get clarity about how to extract this value properly - ## mortality (F) plot - # F reference point - # F.ref.pt <- dat |> - # dplyr::filter( - # label == stringr::str_to_lower("F_targ") | - # label == stringr::str_to_lower("F_proxy") | - # label == stringr::str_to_lower("F_msy") | - # label == "F_target" - # # label == "F40" - # # label == "F30" - # # label == "F50" - # # label == "F_initial" - # # label == "Fmsy" - # ) |> - # dplyr::filter(module_name == "DERIVED_QUANTITIES" | module_name == "parms") |> - # dplyr::pull(estimate) |> - # as.numeric() |> - # round(digits = 2) - - # start year of F plot - F.start.year <- dat |> - dplyr::filter(label == "fishing_mortality") |> - dplyr::slice(which.min(year)) |> - dplyr::select(year) |> - as.numeric() - - # terminal fishing mortality - # F.end.year : added with add_more_key_quants - - # minimum F - F.min <- dat |> - dplyr::filter(label == "fishing_mortality") - - if (length(unique(F.min$age)) == 1) { - if (is.na(unique(F.min$age))) { - F.min <- F.min |> - dplyr::filter(module_name %in% c("TIME_SERIES", "t.series")) |> - dplyr::slice(which.min(estimate)) |> - as.numeric() |> - round(digits = 2) - } - } else { - F.min <- F.min |> - dplyr::group_by(age) |> - dplyr::summarize(val = max(estimate)) |> - dplyr::slice(which.min(val)) |> - dplyr::select(val) |> - as.numeric() |> - round(digits = 2) - } - - - # maximum F - F.max <- dat |> - dplyr::filter(label == "fishing_mortality") - - if (length(unique(F.max$age)) == 1) { - if (is.na(unique(F.max$age))) { - F.min <- F.min |> - dplyr::filter(module_name %in% c("TIME_SERIES", "t.series")) |> - dplyr::slice(which.max(estimate)) |> - as.numeric() |> - round(digits = 2) - } - } else { - F.max <- F.max |> - dplyr::group_by(age) |> - dplyr::summarize(val = max(estimate)) |> - dplyr::slice(which.max(val)) |> - dplyr::select(val) |> - as.numeric() |> - round(digits = 2) - } - - # TODO: uncomment and recode once we get clarity about how to extract this value properly - # fishing mortality at msy - # Ftarg <- dat |> - # dplyr::filter(grepl('f_target', label) | - # grepl('f_msy', label) | - # c(grepl('fishing_mortality_msy', label) & is.na(year))) |> - # dplyr::pull(estimate) |> - # as.numeric() |> - # round(digits = 2) - - # Terminal year F respective to F target - # F.Ftarg : added with add_more_key_quants - ## natural mortality (M)- bam examples have label as natural_mortality ## but other formats don't (in input) @@ -1505,9 +1376,6 @@ write_captions <- function(dat, # converted model output object ## mortality (F) plot # 'F.ref.pt' = as.character(F.ref.pt), - "F.start.year" = as.character(F.start.year), - "F.min" = as.character(F.min), - "F.max" = as.character(F.max), # 'Ftarg' = as.character(Ftarg), ## natural mortality (M) diff --git a/inst/resources/captions_alt_text_template.csv b/inst/resources/captions_alt_text_template.csv index d5ea858c..a2b5c135 100644 --- a/inst/resources/captions_alt_text_template.csv +++ b/inst/resources/captions_alt_text_template.csv @@ -2,7 +2,7 @@ label,type,caption,alt_text kobe,figure,"Kobe plot showing stock status. Triangles delineate start and end years. Horizontal and vertical dashed lines delineate the proportion of F/F~MSY~ where F~MSY~ = B.ref.pt, and B/B~MSY~ where B~MSY~ = B.ref.pt. Overfishing is occurring when F/F~MSY~ > 1 and an overfished status is indicated where B/B~MSY~ > 1.","A Kobe plot showing stock status. The x axis shows overfished status (i.e., B/B~MSY~) and the y axis shows overfishing (i.e., F/F~MSY~). The B/B~MSY~ and F/F~MSY~ for kobe.end.year were B.BMSY.end.yr and F.FMSY.end.yr, respectively, indicating that the stock overfished.status.is.isnot overfished and overfishing.status.is.is.not experiencing overfishing." biomass,figure,Biomass (B) time series. The horizontal dashed line represents the limit reference point (B.ref.pt B.units).,"Line graph showing biomass time series. The x axis shows the year, which spans from B.start.year to B.end.year . The y axis shows biomass in B.units, which spans from B.min to B.max." relative_biomass,figure,Relative biomass (B) time series. The horizontal dashed line represents the limit reference point calculated as B/B(reference point) (B.ref.point B.units).,"Line graph showing relative biomass time series. The x axis shows the year, which spans from B.start.year to B.end.year . The y axis shows relative biomass (B/B~target~), which spans from rel.B.min to rel.B.max B.units ." -fishing_mortality,figure,Fishing mortality (F) over time. The horizontal dashed line represents the target reference point (F.ref.pt).,"Line graph showing fishing mortality over time . The x axis shows the year, which spans from F.start.year to F.end.year . The y axis shows fishing mortality in F.units, which spans from F.min to F.max." +fishing_mortality,figure,Fishing mortality (F) over time. The horizontal dashed line represents the target reference point (F.ref.pt).,"Line graph showing fishing mortality over time . The x axis shows the year, which spans from F.start.year to F.end.year . The y axis shows fishing mortality, which spans from F.min to F.max." relative_fishing_mortality,figure,Relative fishing mortality (F) over time. The horizontal dashed line represents the target reference point (F.ref.pt).,"Line graph showing fishing mortality over time . The x axis shows the year, which spans from F.start.year to F.end.year . The y axis shows relative fishing mortality (F/F~target~), which spans from rel.F.min to rel.F.max." landings,figure,Historical landings by fleet.,"Cumulative area plot showing historical landings. The x axis shows the year, which spans from landings.start.year to landings.end.year . The y axis shows landings in landings.units, which spans from landings.min to landings.max." natural_mortality,figure,Natural mortality (M) for each age. ,"Line graph showing natural mortality. The x axis shows age in years, which spans from M.age.min to M.age.max. The y axis shows the natural mortality rate per year, which spans from M.rate.min to M.rate.max." diff --git a/inst/resources/key_quantity_template.csv b/inst/resources/key_quantity_template.csv index b9a04e21..b40f8f62 100644 --- a/inst/resources/key_quantity_template.csv +++ b/inst/resources/key_quantity_template.csv @@ -15,6 +15,7 @@ cpue.max,,,,,, cpue.min,,,,,, cpue.start.year,,,,,, F.FMSY.end.yr,,,,,, +F.end.year,,,,,, F.max,,,,,, F.min,,,,,, F.ref.pt,,,,,, From 5f2412becff4e4258c68661a837d5c251aec95f8 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Tue, 17 Mar 2026 14:30:26 -0400 Subject: [PATCH 5/8] update plot_stock_recruitment() to work with new KQ extraction/insertion design --- R/plot_stock_recruitment.R | 32 ++++++++ R/utils_rda.R | 81 ------------------- inst/resources/captions_alt_text_template.csv | 2 +- inst/resources/key_quantity_template.csv | 6 ++ 4 files changed, 39 insertions(+), 82 deletions(-) diff --git a/R/plot_stock_recruitment.R b/R/plot_stock_recruitment.R index 65732a51..ca7eea6d 100644 --- a/R/plot_stock_recruitment.R +++ b/R/plot_stock_recruitment.R @@ -127,6 +127,38 @@ plot_stock_recruitment <- function( # Make RDA if (make_rda) { + + # Obtain relevant key quantities for captions/alt text + sr.age.min <- dat |> + dplyr::filter(!is.na(year) & !is.na(age)) |> + dplyr::slice(which.min(age)) |> + dplyr::select(age) |> + as.numeric() + sr.ssb.units <- spawning_biomass_label + sr.ssb.min <- min(sr$spawning_biomass, na.rm = TRUE) + sr.ssb.max <- max(sr$spawning_biomass, na.rm = TRUE) + sr.min <- min(sr$predicted_recruitment, na.rm = TRUE) + sr.max <- max(sr$predicted_recruitment, na.rm = TRUE) + sr.units <- recruitment_label + + # calculate & export key quantities + export_kqs(sr.age.min, + sr.ssb.units, + sr.ssb.min, + sr.ssb.max, + sr.min, + sr.max, + sr.units) + + # Add key quantities to captions/alt text + insert_kqs(sr.age.min, + sr.ssb.units, + sr.ssb.min, + sr.ssb.max, + sr.min, + sr.max, + sr.units) + create_rda( object = final, # get name of function and remove "plot_" from it diff --git a/R/utils_rda.R b/R/utils_rda.R index 6582553a..95c53cec 100644 --- a/R/utils_rda.R +++ b/R/utils_rda.R @@ -470,65 +470,6 @@ add_more_key_quants <- function( } } - ## recruitment - if (topic_cap_alt$label == "recruitment" | topic_cap_alt$label == "stock_recruitment") { - if (is.null(dat)) { - cli::cli_alert_warning("Some key quantities associated with recruitment were not extracted and added to captions_alt_text.csv due to missing data file (i.e., 'dat' argument).", wrap = TRUE) - } else { - # minimum recruitment - sr.min <- dat |> - dplyr::filter( - label == "recruitment", - module_name == "TIME_SERIES" | module_name == "t.series", - !is.na(year), - is.na(fleet) | length(unique(fleet)) <= 1, - is.na(sex) | length(unique(sex)) <= 1, - is.na(area) | length(unique(area)) <= 1, - is.na(growth_pattern) | length(unique(growth_pattern)) <= 1, - !year %in% year_exclusions - ) |> # SS3 and BAM target module names - dplyr::slice(which.min(estimate)) |> - dplyr::select(estimate) |> - dplyr::mutate(estimate = estimate / scaling) |> - as.numeric() |> - round(digits = 2) - - # maximum recruitment - sr.max <- dat |> - dplyr::filter( - label == "recruitment", - module_name == "TIME_SERIES" | module_name == "t.series", - !is.na(year), - is.na(fleet) | length(unique(fleet)) <= 1, - is.na(sex) | length(unique(sex)) <= 1, - is.na(area) | length(unique(area)) <= 1, - is.na(growth_pattern) | length(unique(growth_pattern)) <= 1, - !year %in% year_exclusions - ) |> # SS3 and BAM target module names - dplyr::slice(which.max(estimate)) |> - dplyr::select(estimate) |> - dplyr::mutate(estimate = estimate / scaling) |> - as.numeric() |> - round(digits = 2) - - # replace sr.min and sr.max placeholders within topic_cap_alt - topic_cap_alt <- topic_cap_alt |> - dplyr::mutate(alt_text = stringr::str_replace_all( - alt_text, - "sr.min", - as.character(sr.min) - )) |> - dplyr::mutate(alt_text = stringr::str_replace_all( - alt_text, - "sr.max", - as.character(sr.max) - )) - - cli::cli_li("sr.min: {as.character(sr.min)}") - cli::cli_li("sr.max: {as.character(sr.max)}") - } - } - # replace placeholders (e.g., if "end.year" is found in topic_alt, replace it with end_year) ## end_year----- if (!is.null(end_year)) { @@ -1114,25 +1055,6 @@ write_captions <- function(dat, # converted model output object # selectivity.length.min <- # minimum length # selectivity.length.max <- # maximum length - - ## estimated stock recruitment - # youngest-age recruited fish (instead of age-0) - sr.age.min <- dat |> - dplyr::filter(!is.na(year) & !is.na(age)) |> - dplyr::slice(which.min(age)) |> - dplyr::select(age) |> - as.numeric() - - # ssb units (plural) - # sr.ssb.units : added with add_more_key_quants - - # minimum ssb : added with add_more_key_quants - - # maximum ssb : added with add_more_key_quants - - # recruitment units (plural) - # sr.units : added with add_more_key_quants - # minimum recruitment : added with add_more_key_quants # maximum recruitment: added with add_more_key_quants @@ -1474,9 +1396,6 @@ write_captions <- function(dat, # converted model output object # 'selectivity.length.min' = as.character(selectivity.length.min), # 'selectivity.length.max' = as.character(selectivity.length.max), - ## estimated stock recruitment (aka spawning stock biomass) - # 'sr.age.min' = as.character(sr.age.min), - # relative recruitment ts # NOTE: moving this above recruitment so rel.recruitment.min isn't changed # to "rel." + recruitment.min (etc.) diff --git a/inst/resources/captions_alt_text_template.csv b/inst/resources/captions_alt_text_template.csv index a2b5c135..717c1eed 100644 --- a/inst/resources/captions_alt_text_template.csv +++ b/inst/resources/captions_alt_text_template.csv @@ -19,7 +19,7 @@ mod.fit.catch,figure,Observed catch from the data input file (points) and model mod.fit.abun,figure,Assessment model fits to input catch per unit of effort index values over time calculated from fleet.or.survey.name.,"Point and line graph showing the assessment model fit, displayed as a line, to input catch per unit effort index values, displayed as points over time, for fleet.or.survey.name. The x axis shows years, which spans from mod.fit.abun.start.year to mod.fit.abun.end.year . The y axis shows catch per unit effort in cpue.units, which spans from cpue.min to cpue.max." mod.fit.discards,figure,Observed discards (points) and estimated discards (line).,"Point and line graph showing the assessment model fit to observed discards. Observed discards are represented as points while the model fitted estimates are represented as a line over time for fleet.or.survey.name. The x axis shows the year, which spans from mod.fit.discards.start.year to mod.fit.discards.end.year . The y axis shows discards in mod.fit.discards.units, which spans from mod.fit.discards.min to mod.fit.discards.max." selectivity,figure,Length-based selectivity for each fleet and survey estimated by the assessment model.,"Line graph showing length-based selectivity for fleet.or.survey.name from selectivity.start.year to selectivity.end.year . The x axis shows length in selectivity.length.units, which spans from selectivity.length.min to selectivity.length.max. The y axis shows the proportion of the stock that the gear selects for, which spans from 0--1." -stock_recruitment,figure,Stock recruitment relationship estimated by the assessment model. ,"Point and line graph showing the relationship between stock biomass and newly recruited sr.age.min fish as estimated by the assessment model. Points represent model estimates of recruitment each year as a function of stock biomass, after adjusted by annual recruitment deviations. The line represents the best fit through the points for the stock relationship selected for use in the assessment model. The x axis shows spawning stock biomass in sr.ssb.units, which spans from sr.ssb.min to sr.ssb.max. The y axis shows recruitment in sr.units, which spans from sr.min to sr.max." +stock_recruitment,figure,Stock recruitment relationship estimated by the assessment model. ,"Point and line graph showing the relationship between stock biomass and newly recruited age sr.age.min fish as estimated by the assessment model. Points represent model estimates of recruitment each year as a function of stock biomass, after adjusted by annual recruitment deviations. The line represents the best fit through the points for the stock relationship selected for use in the assessment model. The x axis shows spawning stock biomass in sr.ssb.units, which spans from sr.ssb.min to sr.ssb.max. The y axis shows recruitment in sr.units, which spans from sr.min to sr.max." recruitment,figure,Estimated recruitment by the assessment model each year in recruitment.units.,"Line graph showing the assessment model estimated recruitment in sr.units for each year. The x axis shows years, which spans from recruitment.start.year to recruitment.end.year . The y axis shows recruitment in recruitment.units, which spans from sr.min to sr.max." recruitment.comp,figure,Predicted (black points) and expected (red line) recruitment by the assessment model each year in recruitment.units.,"Scatter plot showing the assessment model estimated recruitment in sr.units for each year with a red line showing the predicted recruitment in sr.units for each year. The x axis shows years, which spans from recruitment.start.year to recruitment.end.year . The y axis shows recruitment in recruitment.units, which spans from sr.min to sr.max." relative.recruitment,figure,"Estimated relative recruitment by the assessment model each year in recruitment.units, calculated as R/R~0~ where R~0~ is R0.","Line graph showing the assessment model estimated relative recruitment in sr.units for each year. The x axis shows year, which spans from recruitment.start.year to recruitment.end.year . The y axis shows relative recruitment (R/R~0~), which spans from rel.recruitment.min to rel.recruitment.max recruitment.units ." diff --git a/inst/resources/key_quantity_template.csv b/inst/resources/key_quantity_template.csv index b40f8f62..67de2291 100644 --- a/inst/resources/key_quantity_template.csv +++ b/inst/resources/key_quantity_template.csv @@ -92,6 +92,12 @@ spr.max,,,,,, spr.min,,,,,, spr.ref.pt,,,,,, sr.age.min,,,,,, +sr.max,,,,,, +sr.min,,,,,, +sr.ssb.max,,,,,, +sr.ssb.min,,,,,, +sr.ssb.units,,,,,, +sr.units,,,,,, ssb.start.year,,,,,, tot.catch.max,,,,,, tot.catch.min,,,,,, From a231fbe2025c5f4af492d82f7cfbdffb8c569bd7 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Wed, 18 Mar 2026 10:35:01 -0400 Subject: [PATCH 6/8] update plot_abundance_at_age() to work with new KQ extraction/insertion design --- R/plot_abundance_at_age.R | 27 ++++++++++++++++- R/utils_rda.R | 63 --------------------------------------- 2 files changed, 26 insertions(+), 64 deletions(-) diff --git a/R/plot_abundance_at_age.R b/R/plot_abundance_at_age.R index fffd2c63..62c88e50 100644 --- a/R/plot_abundance_at_age.R +++ b/R/plot_abundance_at_age.R @@ -53,7 +53,7 @@ plot_abundance_at_age <- function( ) { # Create label for abundance units in legend abundance_label <- label_magnitude( - label = "Abudance", + label = "Abundance", unit_label = unit_label, scale_amount = scale_amount ) @@ -111,6 +111,31 @@ plot_abundance_at_age <- function( ) # export figure to rda if argument = T if (make_rda == TRUE) { + + # Obtain relevant key quantities for captions/alt text + pop.naa.start.year <- min(data$year) + pop.naa.end.year <- max(data$year) + pop.naa.age.min <- min(data$age) + pop.naa.age.max <- max(data$age) + pop.naa.fish.min <- min(data$estimate) + pop.naa.fish.max <- max(data$estimate) + + # calculate & export key quantities + export_kqs(pop.naa.start.year, + pop.naa.end.year, + pop.naa.age.min, + pop.naa.age.max, + pop.naa.fish.min, + pop.naa.fish.max) + + # Add key quantities to captions/alt text + insert_kqs(pop.naa.start.year, + pop.naa.end.year, + pop.naa.age.min, + pop.naa.age.max, + pop.naa.fish.min, + pop.naa.fish.max) + create_rda( object = plot, # get name of function and remove "plot_" from it diff --git a/R/utils_rda.R b/R/utils_rda.R index 95c53cec..d032b4c7 100644 --- a/R/utils_rda.R +++ b/R/utils_rda.R @@ -963,61 +963,6 @@ write_captions <- function(dat, # converted model output object # cpue.min <- # minimum CPUE (SHARED with mod_fit_abun, below) # cpue.max <- # maximum CPUE (SHARED with mod_fit_abun, below) - - ## NAA (numbers at age) - # start year of NAA plot - pop.naa.start.year <- dat |> - dplyr::filter(label == "abundance" & !is.na(year)) |> - dplyr::slice(which.min(year)) |> - dplyr::select(year) |> - as.numeric() - - # end year of NAA plot - pop.naa.end.year <- dat |> - dplyr::filter( - label == "abundance" & !is.na(year), - era == "time" - ) |> - dplyr::slice(which.max(year)) |> - dplyr::select(year) |> - as.numeric() - - # minimum age - pop.naa.age.min <- dat |> - dplyr::filter(label == "abundance" & !is.na(year)) |> - dplyr::slice(which.min(age)) |> - dplyr::select(age) |> - as.numeric() - - # maximum age - pop.naa.age.max <- dat |> - dplyr::filter(label == "abundance" & !is.na(year)) |> - dplyr::slice(which.max(age)) |> - dplyr::select(age) |> - as.numeric() - - # minimum abundance (number) of fish - pop.naa.fish.min <- dat |> - dplyr::filter( - grepl("abundance", label) & !is.na(year), - era == "time" - ) |> - dplyr::slice(which.min(estimate)) |> - dplyr::select(estimate) |> - as.numeric() |> - round(digits = 2) - - # maximum abundance (number) of fish - pop.naa.fish.max <- dat |> - dplyr::filter( - grepl("abundance", label) & !is.na(year), - era == "time" - ) |> - dplyr::slice(which.max(estimate)) |> - dplyr::select(estimate) |> - as.numeric() |> - round(digits = 2) - ## mod_fit_catch (model fit to catch ts)- don't code quantities yet # mod.fit.catch.start.year <- # start year of model fit to catch ts plot # mod.fit.catch.end.year <- # end year of model fit to catch ts plot @@ -1363,14 +1308,6 @@ write_captions <- function(dat, # converted model output object # 'cpue.min' = as.character(cpue.min), # 'cpue.max' = as.character(cpue.max), - ## NAA (numbers at age) - "pop.naa.start.year" = as.character(pop.naa.start.year), - "pop.naa.end.year" = as.character(pop.naa.end.year), - "pop.naa.age.min" = as.character(pop.naa.age.min), - "pop.naa.age.max" = as.character(pop.naa.age.max), - "pop.naa.fish.min" = as.character(pop.naa.fish.min), - "pop.naa.fish.max" = as.character(pop.naa.fish.max), - ## mod_fit_catch (model fit to catch ts) # 'mod.fit.catch.start.year' = as.character(mod.fit.catch.start.year), # 'mod.fit.catch.end.year' = as.character(mod.fit.catch.end.year), From 2a828cc9cff9dce56ea64d5027bf82c235b8ec1c Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Wed, 18 Mar 2026 10:38:55 -0400 Subject: [PATCH 7/8] update plot_biomass_at_age() to work with new KQ extraction/insertion design --- R/plot_biomass_at_age.R | 25 ++++++++++++++ R/utils_rda.R | 72 ----------------------------------------- 2 files changed, 25 insertions(+), 72 deletions(-) diff --git a/R/plot_biomass_at_age.R b/R/plot_biomass_at_age.R index 041dfac7..c6d74112 100644 --- a/R/plot_biomass_at_age.R +++ b/R/plot_biomass_at_age.R @@ -95,6 +95,31 @@ plot_biomass_at_age <- function( ) # export figure to rda if argument = T if (make_rda == TRUE) { + + # Obtain relevant key quantities for captions/alt text + pop.baa.start.year <- min(data$year) + pop.baa.end.year <- max(data$year) + pop.baa.age.min <- min(data$age) + pop.baa.age.max <- max(data$age) + pop.baa.fish.min <- min(data$estimate) + pop.baa.fish.max <- max(data$estimate) + + # calculate & export key quantities + export_kqs(pop.baa.start.year, + pop.baa.end.year, + pop.baa.age.min, + pop.baa.age.max, + pop.baa.fish.min, + pop.baa.fish.max) + + # Add key quantities to captions/alt text + insert_kqs(pop.baa.start.year, + pop.baa.end.year, + pop.baa.age.min, + pop.baa.age.max, + pop.baa.fish.min, + pop.baa.fish.max) + create_rda( object = plot, # get name of function and remove "plot_" from it diff --git a/R/utils_rda.R b/R/utils_rda.R index d032b4c7..de9cf377 100644 --- a/R/utils_rda.R +++ b/R/utils_rda.R @@ -1106,69 +1106,6 @@ write_captions <- function(dat, # converted model output object # round(digits = 2) - ## pop.baa (population biomass at age) - # start year of pop.baa plot - pop.baa.start.year <- dat |> - dplyr::filter(grepl("^biomass", label)) |> - dplyr::slice(which.min(year)) |> - dplyr::select(year) |> - as.numeric() - - # end year of pop.baa plot - pop.baa.end.year <- dat |> - dplyr::filter( - grepl("^biomass", label), - era == "time" - ) |> - dplyr::slice(which.max(year)) |> - dplyr::select(year) |> - as.numeric() - - # minimum biomass of fish - pop.baa.fish.min <- dat |> - dplyr::filter( - grepl("^biomass", label) & !is.na(year), - era == "time" - ) |> - dplyr::slice(which.min(estimate)) |> - dplyr::select(estimate) |> - as.numeric() |> - round(digits = 2) - - # maximum biomass of fish - pop.baa.fish.max <- dat |> - dplyr::filter( - grepl("^biomass", label) & !is.na(year), - era == "time" - ) |> - dplyr::slice(which.max(estimate)) |> - dplyr::select(estimate) |> - as.numeric() |> - round(digits = 2) - - # minimum age - pop.baa.age.min <- dat |> - dplyr::filter( - label == "biomass", - module_name == "BIOMASS_AT_AGE" | module_name == "B.age", # SS3 and BAM target module names - !is.na(age) - ) |> - dplyr::slice(which.min(age)) |> - dplyr::select(age) |> - as.numeric() - - # maximum age - pop.baa.age.max <- dat |> - dplyr::filter( - label == "biomass", - module_name == "BIOMASS_AT_AGE" | module_name == "B.age", # SS3 and BAM target module names - !is.na(age) - ) |> - dplyr::slice(which.max(age)) |> - dplyr::select(age) |> - as.numeric() - - ## proj_catch (projected catch) # projected catch units (plural) # proj.catch.units <- # probably mt, but wait until figure coded @@ -1350,15 +1287,6 @@ write_captions <- function(dat, # converted model output object "spr.max" = as.character(spr.max), # 'spr.ref.pt' = as.character(spr.ref.pt), - # ## pop.baa (population biomass at age) - "pop.baa.start.year" = as.character(pop.baa.start.year), - "pop.baa.end.year" = as.character(pop.baa.end.year), - "pop.baa.fish.min" = as.character(pop.baa.fish.min), - "pop.baa.fish.max" = as.character(pop.baa.fish.max), - "pop.baa.age.min" = as.character(pop.baa.age.min), - "pop.baa.age.max" = as.character(pop.baa.age.max), - - ## proj_catch (projected catch) # 'proj.catch.units' = as.character(proj.catch.units), "proj.catch.start.year" = as.character(proj.catch.start.year), From 03bf02b0b944d41fe77871440ab2c87ae49acc88 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Wed, 18 Mar 2026 11:17:10 -0400 Subject: [PATCH 8/8] update plot_indices() to work with new KQ extraction/insertion design --- R/plot_indices.R | 26 +++++++++++++++++++++++- R/utils_rda.R | 16 --------------- inst/resources/key_quantity_template.csv | 1 + 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/R/plot_indices.R b/R/plot_indices.R index e0ff78e7..bda2ab1d 100644 --- a/R/plot_indices.R +++ b/R/plot_indices.R @@ -28,7 +28,7 @@ plot_indices <- function( module = NULL, focus = NULL, make_rda = FALSE, - figures_dir = NULL, + figures_dir = getwd(), ... ) { # Set cpue unit label for plot @@ -114,6 +114,30 @@ plot_indices <- function( ### Make RDA ---- if (make_rda) { + + # Obtain relevant key quantities for captions/alt text + cpue.start.year <- min(prepared_data$year) + cpue.end.year <- max(prepared_data$year) + cpue.min <- min(prepared_data$estimate) + cpue.max <- max(prepared_data$estimate) + cpue.units <- ifelse(unit_label == "", + "an estimated index ratio", # default if empty + unit_label) + + # calculate & export key quantities + export_kqs(cpue.start.year, + cpue.end.year, + cpue.min, + cpue.max, + cpue.units) + + # Add key quantities to captions/alt text + insert_kqs(cpue.start.year, + cpue.end.year, + cpue.min, + cpue.max, + cpue.units) + create_rda( object = plt, # get name of function and remove "plot_" from it diff --git a/R/utils_rda.R b/R/utils_rda.R index de9cf377..ede5f931 100644 --- a/R/utils_rda.R +++ b/R/utils_rda.R @@ -953,16 +953,6 @@ write_captions <- function(dat, # converted model output object # cal.length.max <- # maximum length group # fleet.or.survey.name <- # fleet or survey name - ## CPUE indices plot- don't code quantities yet - # cpue.start.year <- # start year of CPUE indices plot - # cpue.end.year <- # end year of CPUE indices plot - - # CPUE units (plural) (SHARED with mod.fit.abun, below) - # cpue.units : added with add_more_key_quants - - # cpue.min <- # minimum CPUE (SHARED with mod_fit_abun, below) - # cpue.max <- # maximum CPUE (SHARED with mod_fit_abun, below) - ## mod_fit_catch (model fit to catch ts)- don't code quantities yet # mod.fit.catch.start.year <- # start year of model fit to catch ts plot # mod.fit.catch.end.year <- # end year of model fit to catch ts plot @@ -1239,12 +1229,6 @@ write_captions <- function(dat, # converted model output object # 'cal.length.min' = as.character(cal.length.min), # 'cal.length.max' = as.character(cal.length.max), - ## CPUE indices plot - # 'cpue.start.year' = as.character(cpue.start.year), - # 'cpue.end.year' = as.character(cpue.end.year), - # 'cpue.min' = as.character(cpue.min), - # 'cpue.max' = as.character(cpue.max), - ## mod_fit_catch (model fit to catch ts) # 'mod.fit.catch.start.year' = as.character(mod.fit.catch.start.year), # 'mod.fit.catch.end.year' = as.character(mod.fit.catch.end.year), diff --git a/inst/resources/key_quantity_template.csv b/inst/resources/key_quantity_template.csv index 67de2291..9f261da3 100644 --- a/inst/resources/key_quantity_template.csv +++ b/inst/resources/key_quantity_template.csv @@ -14,6 +14,7 @@ cpue.end.year,,,,,, cpue.max,,,,,, cpue.min,,,,,, cpue.start.year,,,,,, +cpue.units,,,,,, F.FMSY.end.yr,,,,,, F.end.year,,,,,, F.max,,,,,,