From 2b3d775a0b0b504687c1a5373e9f7968c29623c8 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Thu, 5 Mar 2026 16:48:55 -0500 Subject: [PATCH 1/2] 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 04dec696..0b7dab56 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 816b4cff60a473f07b533c0b14cda1dfea0e2d2e Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Thu, 12 Mar 2026 13:26:36 -0400 Subject: [PATCH 2/2] 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 66469ece..3bc8baeb 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -47,6 +47,7 @@ Imports: naniar, prodlim, quarto, + rlang, scales, stats, stringr, diff --git a/R/plot_landings.R b/R/plot_landings.R index 0b7dab56..4b05fd81 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 dadddb23..b47d1727 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), #