From 6e7495104a975b16e6079ed8db4beb63ad64e7be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 19:50:26 +0000 Subject: [PATCH 1/9] Add figure and table workflow guide --- pkgdown/_pkgdown.yml | 2 + vignettes/figure-table-workflow.Rmd | 125 ++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 vignettes/figure-table-workflow.Rmd diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 6ad964d2..339c320b 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -23,6 +23,8 @@ navbar: menu: - text: FAQs href: articles/faqs.html + - text: Figure and Table Workflow Guide + href: articles/figure-table-workflow.html - text: How captions and alternative text are generated href: articles/how-caps-alttext-are-made.html - text: Standardizing Assessment Model Output diff --git a/vignettes/figure-table-workflow.Rmd b/vignettes/figure-table-workflow.Rmd new file mode 100644 index 00000000..9f8b1a2e --- /dev/null +++ b/vignettes/figure-table-workflow.Rmd @@ -0,0 +1,125 @@ +--- +title: "Figure and Table Workflow Guide" +output: + html_document: + toc: true +vignette: > + %\VignetteIndexEntry{Figure and Table Workflow Guide} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r setup, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +# Purpose + +This guide summarizes the workflow used by the `plot_x` and `table_x` functions in `R/`. +Use it as a template when building a new figure or table function from the existing package patterns. + +# The common starting point + +Most functions begin with standardized output from `convert_output()`. +That data is then narrowed to one label or related labels, reshaped if needed, and finally rendered as a plot or table. + +The recurring helpers are: + +- `filter_data()` to isolate the target label(s) and apply module, era, grouping, faceting, and scaling choices. +- `process_data()` to detect indexing variables, set `group_var`, and decide whether additional variables should become grouping or facetting variables. +- `process_table()` for table-specific label handling and row/column organization. +- `create_rda()` when `make_rda = TRUE`. + +# How the figure functions are built + +The figure functions in `R/` follow the same basic sequence: + +1. **Filter the data.** + Pick the relevant label with `filter_data()`. + This is where each figure decides whether it needs `year`, `age`, `fleet`, `area`, `sex`, a specific module, or a specific era. + +2. **Process the filtered data.** + Run `process_data()` to identify the index structure and to decide how the data should be grouped or faceted. + +3. **Choose the plot builder.** + - `plot_timeseries()` for standard time-series figures + - `plot_obsvpred()` for observed-vs-predicted index figures + - `plot_aa()` for age-composition bubble plots + - `plot_error()` for point/error summaries + +4. **Add figure-specific layers.** + Examples from the existing functions include: + - `reference_line()` and `calculate_reference_point()` for biomass and fishing mortality plots + - `average_age_line()` for abundance/biomass-at-age plots + - `cohort_line()` for catch-composition plots + - extra overlays for expected recruitment or stock-recruit curves + +5. **Apply the final theme.** + Most figures end with `theme_noaa()`. + +6. **Optionally export the accessibility package.** + If `make_rda = TRUE`, the figure function usually: + - calculates key quantities, + - writes them with `export_kqs()`, + - inserts them into captions and alt text with `insert_kqs()`, + - and saves the final object with `create_rda()`. + +## Figure families in this package + +- **Time-series plots:** `plot_biomass()`, `plot_spawning_biomass()`, `plot_recruitment()`, `plot_landings()`, `plot_fishing_mortality()`, `plot_natural_mortality()` +- **Observation/comparison plots:** `plot_index()`, `plot_stock_recruitment()`, `plot_recruitment_deviations()` +- **Age-composition plots:** `plot_abundance_at_age()`, `plot_biomass_at_age()`, `plot_catch_comp()` + +# How the table functions are built + +The data-driven table functions use a shorter version of the same workflow: + +1. **Filter the data.** + Use `filter_data()` to isolate the label or labels needed for the table. + +2. **Clean and round values.** + The existing tables round `estimate` and `uncertainty` before formatting. + +3. **Process the table structure.** + `process_table()` determines which variables are indexing the data, handles multiple labels, and prepares the data for table formatting. + +4. **Merge estimates and uncertainty.** + `merge_error()` combines the value and error columns into a single presentation-ready column where needed. + +5. **Render the table.** + - `table_index()` and `table_landings()` convert the prepared data to `gt` tables and apply `add_theme()` + - the static reference tables (`table_afsc_tier()` and `table_harvest_projection()`) are built directly with `flextable` + +6. **Optionally export the accessibility package.** + As with plots, `make_rda = TRUE` triggers `export_kqs()`, `insert_kqs()`, and `create_rda()`. + +## Table families in this package + +- **Data-driven tables:** `table_index()`, `table_landings()` +- **Static reference tables:** `table_afsc_tier()`, `table_harvest_projection()` +- **Legacy/incomplete table workflow:** `table_bnc()` is present but commented out + +# A simple recipe for a new function + +When adding a new `plot_x` or `table_x` function, follow this order: + +1. Identify the source label(s) in the standardized output. +2. Filter with `filter_data()`. +3. Process with `process_data()` or `process_table()`. +4. Build the figure or table with the helper that matches the display type. +5. Add domain-specific layers or table formatting. +6. Apply the package theme. +7. Export key quantities and the `.rda` package if the function supports accessibility output. +8. Document the workflow in the function's roxygen file and add an example. + +# Existing functions to use as models + +- `plot_biomass()` and `plot_spawning_biomass()` for reference-line time series +- `plot_index()` for observed vs predicted comparisons +- `plot_catch_comp()` for age-composition plotting +- `table_landings()` for a standard data-driven table +- `table_index()` for label selection and uncertainty formatting + From 21df98feeb1fe82ae805bd7502ed345ae92d6f83 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 19:53:40 +0000 Subject: [PATCH 2/9] Remove unused static table references --- R/save_all_plots.R | 7 --- R/table_afsc_tier.R | 66 ----------------------------- R/table_harvest_projection.R | 52 ----------------------- vignettes/figure-table-workflow.Rmd | 3 -- 4 files changed, 128 deletions(-) delete mode 100644 R/table_afsc_tier.R delete mode 100644 R/table_harvest_projection.R diff --git a/R/save_all_plots.R b/R/save_all_plots.R index a7433344..a420d812 100644 --- a/R/save_all_plots.R +++ b/R/save_all_plots.R @@ -152,12 +152,10 @@ save_all_plots <- function( biomass_at_age_unit_label = "mt", # imported from plot_index index_unit_label = "", - # imported from table_afsc_tier- add potential unique arguments after dev # imported from table_bnc biomass_unit_label = "mt", catch_unit_label = "mt", catch_scale_amount = 1 - # imported from table_harvest_projection- add potential unique arguments after dev # imported from table_index- zero unique arguments # imported from table_landings- zero unique arguments ) { @@ -499,10 +497,5 @@ save_all_plots <- function( } ) - # uncomment when finished - # - # undeveloped tables - add arguments after more development - # table_afsc_tier() #|> suppressWarnings() |> invisible() - # table_harvest_projection() #|> suppressWarnings() |> invisible() cli::cli_h1("Finished export of figures and tables.") } diff --git a/R/table_afsc_tier.R b/R/table_afsc_tier.R deleted file mode 100644 index abb24da8..00000000 --- a/R/table_afsc_tier.R +++ /dev/null @@ -1,66 +0,0 @@ -# AFSC Tier Table -table_afsc_tier <- function() { - # REMINDERS: add in code that - # -adds make_rda and tables_dir as arguments - # -defines topic_label, fig_or_table; and - # -makes an rda if make_rda = TRUE - # (see table_index.R for reference) - # for the rda-related fxns to work, the final table has to be called tab - - # identify output - fig_or_table <- "table" - - # run write_captions.R if its output doesn't exist - # if (!file.exists( - # fs::path(getwd(), "captions_alt_text.csv") - # ) - # ) { - # stockplotr::write_captions( - # dat = dat, - # dir = tables_dir, - # year = NULL - # ) - # } - level <- c( - "Level 1: Normal", - "Level 2: Substantially Increased Concerns", - "Level 3: Major Concern", - "Level 4: Extreme COncern" - ) - ass_considerations <- c( - "Typical to moderately increased uncertainty/minor unresolved issues in assessment.", - "Substantially increased assessment uncertainty/ unresolved issues.", - "Major problems with the stock assessment; very poor fits to data; high level of uncertainty; strong retrospective bias.", - "Severe problems with the stock assessment; severe retrospective bias. Assessment considered unreliable." - ) - popdy_considerations <- c( - "Stock trends are typical for the stock; recent recruitment is within normal range.", - "Stock trends are unusual; abundance increasing or decreasing faster than has been seen recently, or recruitment pattern is atypical.", - "Stock trends are highly unusual; very rapid changes in stock abundance, or highly atypical recruitment patterns.", - "Stock trends are unprecedented; More rapid changes in stock abundance than have ever been seen previously, or a very long stretch o poor recruitment compared to previous patterns." - ) - eco_considerations <- c( - "No apparent environmental/ecosystem concerns", - "Some indicators showing adverse signals relevant to the stock but the pattern is not consistent across all indicators.", - "Multiple indicators showing consistent adverse signals a) across the same trophic level as the stock, and/or b) up or down trophic levels (i.e., predators and prey of the stock)", - "Extreme anomalies in multiple ecosystem indicators that are highly likely to impact the stock; Potential for cascading effects on other ecosystem components" - ) - fish_performance <- c( - "No apparent fishery/resourceuse performance and/or behavior concerns", - "Some indicators showing adverse signals but the pattern is not consistent across all indicators", - "Multiple indicators showing consistent adverse signals a) across different sectors, and/or b) different gear types", - "Extreme anomaliesin multiple performance indicators that are highly likely to impact the stock" - ) - tier_df <- data.frame(level, ass_considerations, popdy_considerations, eco_considerations, fish_performance) - flextable::flextable(tier_df) |> - flextable::set_header_labels( - level = "", - ass_considerations = "Assessment-related considerations", - popdy_considerations = "Population dynamics considerations", - eco_considerations = "Environmental/ecosystems considerations", - fish_performance = "Fishery Performance" - ) |> - flextable::italic(part = "header") |> - flextable::bold(part = "header") |> - flextable::hline(i = c(1, 2, 3)) -} diff --git a/R/table_harvest_projection.R b/R/table_harvest_projection.R deleted file mode 100644 index 525f91d8..00000000 --- a/R/table_harvest_projection.R +++ /dev/null @@ -1,52 +0,0 @@ -# AFSC Tier Table -table_harvest_projection <- function() { - # REMINDERS: add in code that - # -adds make_rda and tables_dir as arguments - # -defines topic_label, fig_or_table; and - # -makes an rda if make_rda = TRUE - # (see table_index.R for reference) - # for the rda-related fxns to work, the final table has to be called tab - - level <- c( - "Level 1: Normal", - "Level 2: Substantially Increased Concerns", - "Level 3: Major Concern", - "Level 4: Extreme COncern" - ) - ass_considerations <- c( - "Typical to moderately increased uncertainty/minor unresolved issues in assessment.", - "Substantially increased assessment uncertainty/ unresolved issues.", - "Major problems with the stock assessment; very poor fits to data; high level of uncertainty; strong retrospective bias.", - "Severe problems with the stock assessment; severe retrospective bias. Assessment considered unreliable." - ) - popdy_considerations <- c( - "Stock trends are typical for the stock; recent recruitment is within normal range.", - "Stock trends are unusual; abundance increasing or decreasing faster than has been seen recently, or recruitment pattern is atypical.", - "Stock trends are highly unusual; very rapid changes in stock abundance, or highly atypical recruitment patterns.", - "Stock trends are unprecedented; More rapid changes in stock abundance than have ever been seen previously, or a very long stretch o poor recruitment compared to previous patterns." - ) - eco_considerations <- c( - "No apparent environmental/ecosystem concerns", - "Some indicators showing adverse signals relevant to the stock but the pattern is not consistent across all indicators.", - "Multiple indicators showing consistent adverse signals a) across the same trophic level as the stock, and/or b) up or down trophic levels (i.e., predators and prey of the stock)", - "Extreme anomalies in multiple ecosystem indicators that are highly likely to impact the stock; Potential for cascading effects on other ecosystem components" - ) - fish_performance <- c( - "No apparent fishery/resourceuse performance and/or behavior concerns", - "Some indicators showing adverse signals but the pattern is not consistent across all indicators", - "Multiple indicators showing consistent adverse signals a) across different sectors, and/or b) different gear types", - "Extreme anomaliesin multiple performance indicators that are highly likely to impact the stock" - ) - tier_df <- data.frame(level, ass_considerations, popdy_considerations, eco_considerations, fish_performance) - flextable::flextable(tier_df) |> - flextable::set_header_labels( - level = "", - ass_considerations = "Assessment-related considerations", - popdy_considerations = "Population dynamics considerations", - eco_considerations = "Environmental/ecosystems considerations", - fish_performance = "Fishery Performance" - ) |> - flextable::italic(part = "header") |> - flextable::bold(part = "header") |> - flextable::hline(i = c(1, 2, 3)) -} diff --git a/vignettes/figure-table-workflow.Rmd b/vignettes/figure-table-workflow.Rmd index 9f8b1a2e..4e5e8686 100644 --- a/vignettes/figure-table-workflow.Rmd +++ b/vignettes/figure-table-workflow.Rmd @@ -91,7 +91,6 @@ The data-driven table functions use a shorter version of the same workflow: 5. **Render the table.** - `table_index()` and `table_landings()` convert the prepared data to `gt` tables and apply `add_theme()` - - the static reference tables (`table_afsc_tier()` and `table_harvest_projection()`) are built directly with `flextable` 6. **Optionally export the accessibility package.** As with plots, `make_rda = TRUE` triggers `export_kqs()`, `insert_kqs()`, and `create_rda()`. @@ -99,7 +98,6 @@ The data-driven table functions use a shorter version of the same workflow: ## Table families in this package - **Data-driven tables:** `table_index()`, `table_landings()` -- **Static reference tables:** `table_afsc_tier()`, `table_harvest_projection()` - **Legacy/incomplete table workflow:** `table_bnc()` is present but commented out # A simple recipe for a new function @@ -122,4 +120,3 @@ When adding a new `plot_x` or `table_x` function, follow this order: - `plot_catch_comp()` for age-composition plotting - `table_landings()` for a standard data-driven table - `table_index()` for label selection and uncertainty formatting - From b3bf6c010db176ba03bafbf55fce9fd057cd5c0f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 19:57:09 +0000 Subject: [PATCH 3/9] Restore removed static table files --- R/save_all_plots.R | 7 ++++ R/table_afsc_tier.R | 66 ++++++++++++++++++++++++++++++++++++ R/table_harvest_projection.R | 52 ++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 R/table_afsc_tier.R create mode 100644 R/table_harvest_projection.R diff --git a/R/save_all_plots.R b/R/save_all_plots.R index a420d812..a7433344 100644 --- a/R/save_all_plots.R +++ b/R/save_all_plots.R @@ -152,10 +152,12 @@ save_all_plots <- function( biomass_at_age_unit_label = "mt", # imported from plot_index index_unit_label = "", + # imported from table_afsc_tier- add potential unique arguments after dev # imported from table_bnc biomass_unit_label = "mt", catch_unit_label = "mt", catch_scale_amount = 1 + # imported from table_harvest_projection- add potential unique arguments after dev # imported from table_index- zero unique arguments # imported from table_landings- zero unique arguments ) { @@ -497,5 +499,10 @@ save_all_plots <- function( } ) + # uncomment when finished + # + # undeveloped tables - add arguments after more development + # table_afsc_tier() #|> suppressWarnings() |> invisible() + # table_harvest_projection() #|> suppressWarnings() |> invisible() cli::cli_h1("Finished export of figures and tables.") } diff --git a/R/table_afsc_tier.R b/R/table_afsc_tier.R new file mode 100644 index 00000000..abb24da8 --- /dev/null +++ b/R/table_afsc_tier.R @@ -0,0 +1,66 @@ +# AFSC Tier Table +table_afsc_tier <- function() { + # REMINDERS: add in code that + # -adds make_rda and tables_dir as arguments + # -defines topic_label, fig_or_table; and + # -makes an rda if make_rda = TRUE + # (see table_index.R for reference) + # for the rda-related fxns to work, the final table has to be called tab + + # identify output + fig_or_table <- "table" + + # run write_captions.R if its output doesn't exist + # if (!file.exists( + # fs::path(getwd(), "captions_alt_text.csv") + # ) + # ) { + # stockplotr::write_captions( + # dat = dat, + # dir = tables_dir, + # year = NULL + # ) + # } + level <- c( + "Level 1: Normal", + "Level 2: Substantially Increased Concerns", + "Level 3: Major Concern", + "Level 4: Extreme COncern" + ) + ass_considerations <- c( + "Typical to moderately increased uncertainty/minor unresolved issues in assessment.", + "Substantially increased assessment uncertainty/ unresolved issues.", + "Major problems with the stock assessment; very poor fits to data; high level of uncertainty; strong retrospective bias.", + "Severe problems with the stock assessment; severe retrospective bias. Assessment considered unreliable." + ) + popdy_considerations <- c( + "Stock trends are typical for the stock; recent recruitment is within normal range.", + "Stock trends are unusual; abundance increasing or decreasing faster than has been seen recently, or recruitment pattern is atypical.", + "Stock trends are highly unusual; very rapid changes in stock abundance, or highly atypical recruitment patterns.", + "Stock trends are unprecedented; More rapid changes in stock abundance than have ever been seen previously, or a very long stretch o poor recruitment compared to previous patterns." + ) + eco_considerations <- c( + "No apparent environmental/ecosystem concerns", + "Some indicators showing adverse signals relevant to the stock but the pattern is not consistent across all indicators.", + "Multiple indicators showing consistent adverse signals a) across the same trophic level as the stock, and/or b) up or down trophic levels (i.e., predators and prey of the stock)", + "Extreme anomalies in multiple ecosystem indicators that are highly likely to impact the stock; Potential for cascading effects on other ecosystem components" + ) + fish_performance <- c( + "No apparent fishery/resourceuse performance and/or behavior concerns", + "Some indicators showing adverse signals but the pattern is not consistent across all indicators", + "Multiple indicators showing consistent adverse signals a) across different sectors, and/or b) different gear types", + "Extreme anomaliesin multiple performance indicators that are highly likely to impact the stock" + ) + tier_df <- data.frame(level, ass_considerations, popdy_considerations, eco_considerations, fish_performance) + flextable::flextable(tier_df) |> + flextable::set_header_labels( + level = "", + ass_considerations = "Assessment-related considerations", + popdy_considerations = "Population dynamics considerations", + eco_considerations = "Environmental/ecosystems considerations", + fish_performance = "Fishery Performance" + ) |> + flextable::italic(part = "header") |> + flextable::bold(part = "header") |> + flextable::hline(i = c(1, 2, 3)) +} diff --git a/R/table_harvest_projection.R b/R/table_harvest_projection.R new file mode 100644 index 00000000..525f91d8 --- /dev/null +++ b/R/table_harvest_projection.R @@ -0,0 +1,52 @@ +# AFSC Tier Table +table_harvest_projection <- function() { + # REMINDERS: add in code that + # -adds make_rda and tables_dir as arguments + # -defines topic_label, fig_or_table; and + # -makes an rda if make_rda = TRUE + # (see table_index.R for reference) + # for the rda-related fxns to work, the final table has to be called tab + + level <- c( + "Level 1: Normal", + "Level 2: Substantially Increased Concerns", + "Level 3: Major Concern", + "Level 4: Extreme COncern" + ) + ass_considerations <- c( + "Typical to moderately increased uncertainty/minor unresolved issues in assessment.", + "Substantially increased assessment uncertainty/ unresolved issues.", + "Major problems with the stock assessment; very poor fits to data; high level of uncertainty; strong retrospective bias.", + "Severe problems with the stock assessment; severe retrospective bias. Assessment considered unreliable." + ) + popdy_considerations <- c( + "Stock trends are typical for the stock; recent recruitment is within normal range.", + "Stock trends are unusual; abundance increasing or decreasing faster than has been seen recently, or recruitment pattern is atypical.", + "Stock trends are highly unusual; very rapid changes in stock abundance, or highly atypical recruitment patterns.", + "Stock trends are unprecedented; More rapid changes in stock abundance than have ever been seen previously, or a very long stretch o poor recruitment compared to previous patterns." + ) + eco_considerations <- c( + "No apparent environmental/ecosystem concerns", + "Some indicators showing adverse signals relevant to the stock but the pattern is not consistent across all indicators.", + "Multiple indicators showing consistent adverse signals a) across the same trophic level as the stock, and/or b) up or down trophic levels (i.e., predators and prey of the stock)", + "Extreme anomalies in multiple ecosystem indicators that are highly likely to impact the stock; Potential for cascading effects on other ecosystem components" + ) + fish_performance <- c( + "No apparent fishery/resourceuse performance and/or behavior concerns", + "Some indicators showing adverse signals but the pattern is not consistent across all indicators", + "Multiple indicators showing consistent adverse signals a) across different sectors, and/or b) different gear types", + "Extreme anomaliesin multiple performance indicators that are highly likely to impact the stock" + ) + tier_df <- data.frame(level, ass_considerations, popdy_considerations, eco_considerations, fish_performance) + flextable::flextable(tier_df) |> + flextable::set_header_labels( + level = "", + ass_considerations = "Assessment-related considerations", + popdy_considerations = "Population dynamics considerations", + eco_considerations = "Environmental/ecosystems considerations", + fish_performance = "Fishery Performance" + ) |> + flextable::italic(part = "header") |> + flextable::bold(part = "header") |> + flextable::hline(i = c(1, 2, 3)) +} From 635c5d6c161dec844168ed45a4f5b5391d737061 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 20:00:30 +0000 Subject: [PATCH 4/9] Move workflow guidance into contributing --- CONTRIBUTING.md | 23 +++++++++++++++++++++++ vignettes/figure-table-workflow.Rmd | 8 +------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f75e4ea..66a9dca8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,3 +70,26 @@ If possible, please submit a reproducible example ([reprex](https://reprex.tidyv ## Contributing questions Have a question? Ask it in our [Discussions page](https://github.com/nmfs-ost/stockplotr/discussions). You can categorize it under General, Ideas, Q&A, and more. + +## Workflow guide for new figure/table functions + +When adding a new `plot_x` or `table_x` function, follow this order: + +1. Identify the source label(s) in the standardized output. +2. Filter with `filter_data()`. +3. Process with `process_data()` or `process_table()`. +4. Build the figure or table with the helper that matches the display type. +5. Add domain-specific layers or table formatting. +6. Apply the package theme. +7. Export key quantities and the `.rda` package if the function supports accessibility output. +8. Document the workflow in the function's roxygen file and add an example. + +If a new figure or table does not fit an existing category, explain the new category and we can try to build the pipeline to incorporate it into the existing workflow. + +### Existing functions to use as models + +- `plot_biomass()` and `plot_spawning_biomass()` for reference-line time series +- `plot_index()` for observed vs predicted comparisons +- `plot_catch_comp()` for age-composition plotting +- `table_landings()` for a standard data-driven table +- `table_index()` for label selection and uncertainty formatting diff --git a/vignettes/figure-table-workflow.Rmd b/vignettes/figure-table-workflow.Rmd index 4e5e8686..aa866f41 100644 --- a/vignettes/figure-table-workflow.Rmd +++ b/vignettes/figure-table-workflow.Rmd @@ -113,10 +113,4 @@ When adding a new `plot_x` or `table_x` function, follow this order: 7. Export key quantities and the `.rda` package if the function supports accessibility output. 8. Document the workflow in the function's roxygen file and add an example. -# Existing functions to use as models - -- `plot_biomass()` and `plot_spawning_biomass()` for reference-line time series -- `plot_index()` for observed vs predicted comparisons -- `plot_catch_comp()` for age-composition plotting -- `table_landings()` for a standard data-driven table -- `table_index()` for label selection and uncertainty formatting +If a new figure or table does not fit an existing category, explain the new category and we can try to build the pipeline to incorporate it into the existing workflow. From fdc8df7e69e3edfbe8905f688127649680d52a85 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 20:03:02 +0000 Subject: [PATCH 5/9] Move workflow guide into CONTRIBUTING and remove vignette --- CONTRIBUTING.md | 94 +++++++++++++++++++--- pkgdown/_pkgdown.yml | 2 - vignettes/figure-table-workflow.Rmd | 116 ---------------------------- 3 files changed, 85 insertions(+), 127 deletions(-) delete mode 100644 vignettes/figure-table-workflow.Rmd diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 66a9dca8..9a3cdfec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,7 +71,91 @@ If possible, please submit a reproducible example ([reprex](https://reprex.tidyv Have a question? Ask it in our [Discussions page](https://github.com/nmfs-ost/stockplotr/discussions). You can categorize it under General, Ideas, Q&A, and more. -## Workflow guide for new figure/table functions +## Figure and Table Workflow Guide + +This guide summarizes the workflow used by the `plot_x` and `table_x` functions in `R/`. +Use it as a template when building a new figure or table function from the existing package patterns. + +### The common starting point + +Most functions begin with standardized output from `convert_output()`. +That data is then narrowed to one label or related labels, reshaped if needed, and finally rendered as a plot or table. + +The recurring helpers are: + +- `filter_data()` to isolate the target label(s) and apply module, era, grouping, faceting, and scaling choices. +- `process_data()` to detect indexing variables, set `group_var`, and decide whether additional variables should become grouping or facetting variables. +- `process_table()` for table-specific label handling and row/column organization. +- `create_rda()` when `make_rda = TRUE`. + +### How the figure functions are built + +The figure functions in `R/` follow the same basic sequence: + +1. **Filter the data.** + Pick the relevant label with `filter_data()`. + This is where each figure decides whether it needs `year`, `age`, `fleet`, `area`, `sex`, a specific module, or a specific era. + +2. **Process the filtered data.** + Run `process_data()` to identify the index structure and to decide how the data should be grouped or faceted. + +3. **Choose the plot builder.** + - `plot_timeseries()` for standard time-series figures + - `plot_obsvpred()` for observed-vs-predicted index figures + - `plot_aa()` for age-composition bubble plots + - `plot_error()` for point/error summaries + +4. **Add figure-specific layers.** + Examples from the existing functions include: + - `reference_line()` and `calculate_reference_point()` for biomass and fishing mortality plots + - `average_age_line()` for abundance/biomass-at-age plots + - `cohort_line()` for catch-composition plots + - extra overlays for expected recruitment or stock-recruit curves + +5. **Apply the final theme.** + Most figures end with `theme_noaa()`. + +6. **Optionally export the accessibility package.** + If `make_rda = TRUE`, the figure function usually: + - calculates key quantities, + - writes them with `export_kqs()`, + - inserts them into captions and alt text with `insert_kqs()`, + - and saves the final object with `create_rda()`. + +### Figure families in this package + +- **Time-series plots:** `plot_biomass()`, `plot_spawning_biomass()`, `plot_recruitment()`, `plot_landings()`, `plot_fishing_mortality()`, `plot_natural_mortality()` +- **Observation/comparison plots:** `plot_index()`, `plot_stock_recruitment()`, `plot_recruitment_deviations()` +- **Age-composition plots:** `plot_abundance_at_age()`, `plot_biomass_at_age()`, `plot_catch_comp()` + +### How the table functions are built + +The data-driven table functions use a shorter version of the same workflow: + +1. **Filter the data.** + Use `filter_data()` to isolate the label or labels needed for the table. + +2. **Clean and round values.** + The existing tables round `estimate` and `uncertainty` before formatting. + +3. **Process the table structure.** + `process_table()` determines which variables are indexing the data, handles multiple labels, and prepares the data for table formatting. + +4. **Merge estimates and uncertainty.** + `merge_error()` combines the value and error columns into a single presentation-ready column where needed. + +5. **Render the table.** + - `table_index()` and `table_landings()` convert the prepared data to `gt` tables and apply `add_theme()` + +6. **Optionally export the accessibility package.** + As with plots, `make_rda = TRUE` triggers `export_kqs()`, `insert_kqs()`, and `create_rda()`. + +### Table families in this package + +- **Data-driven tables:** `table_index()`, `table_landings()` +- **Legacy/incomplete table workflow:** `table_bnc()` is present but commented out + +### A simple recipe for a new function When adding a new `plot_x` or `table_x` function, follow this order: @@ -85,11 +169,3 @@ When adding a new `plot_x` or `table_x` function, follow this order: 8. Document the workflow in the function's roxygen file and add an example. If a new figure or table does not fit an existing category, explain the new category and we can try to build the pipeline to incorporate it into the existing workflow. - -### Existing functions to use as models - -- `plot_biomass()` and `plot_spawning_biomass()` for reference-line time series -- `plot_index()` for observed vs predicted comparisons -- `plot_catch_comp()` for age-composition plotting -- `table_landings()` for a standard data-driven table -- `table_index()` for label selection and uncertainty formatting diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 339c320b..6ad964d2 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -23,8 +23,6 @@ navbar: menu: - text: FAQs href: articles/faqs.html - - text: Figure and Table Workflow Guide - href: articles/figure-table-workflow.html - text: How captions and alternative text are generated href: articles/how-caps-alttext-are-made.html - text: Standardizing Assessment Model Output diff --git a/vignettes/figure-table-workflow.Rmd b/vignettes/figure-table-workflow.Rmd deleted file mode 100644 index aa866f41..00000000 --- a/vignettes/figure-table-workflow.Rmd +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: "Figure and Table Workflow Guide" -output: - html_document: - toc: true -vignette: > - %\VignetteIndexEntry{Figure and Table Workflow Guide} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r setup, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -# Purpose - -This guide summarizes the workflow used by the `plot_x` and `table_x` functions in `R/`. -Use it as a template when building a new figure or table function from the existing package patterns. - -# The common starting point - -Most functions begin with standardized output from `convert_output()`. -That data is then narrowed to one label or related labels, reshaped if needed, and finally rendered as a plot or table. - -The recurring helpers are: - -- `filter_data()` to isolate the target label(s) and apply module, era, grouping, faceting, and scaling choices. -- `process_data()` to detect indexing variables, set `group_var`, and decide whether additional variables should become grouping or facetting variables. -- `process_table()` for table-specific label handling and row/column organization. -- `create_rda()` when `make_rda = TRUE`. - -# How the figure functions are built - -The figure functions in `R/` follow the same basic sequence: - -1. **Filter the data.** - Pick the relevant label with `filter_data()`. - This is where each figure decides whether it needs `year`, `age`, `fleet`, `area`, `sex`, a specific module, or a specific era. - -2. **Process the filtered data.** - Run `process_data()` to identify the index structure and to decide how the data should be grouped or faceted. - -3. **Choose the plot builder.** - - `plot_timeseries()` for standard time-series figures - - `plot_obsvpred()` for observed-vs-predicted index figures - - `plot_aa()` for age-composition bubble plots - - `plot_error()` for point/error summaries - -4. **Add figure-specific layers.** - Examples from the existing functions include: - - `reference_line()` and `calculate_reference_point()` for biomass and fishing mortality plots - - `average_age_line()` for abundance/biomass-at-age plots - - `cohort_line()` for catch-composition plots - - extra overlays for expected recruitment or stock-recruit curves - -5. **Apply the final theme.** - Most figures end with `theme_noaa()`. - -6. **Optionally export the accessibility package.** - If `make_rda = TRUE`, the figure function usually: - - calculates key quantities, - - writes them with `export_kqs()`, - - inserts them into captions and alt text with `insert_kqs()`, - - and saves the final object with `create_rda()`. - -## Figure families in this package - -- **Time-series plots:** `plot_biomass()`, `plot_spawning_biomass()`, `plot_recruitment()`, `plot_landings()`, `plot_fishing_mortality()`, `plot_natural_mortality()` -- **Observation/comparison plots:** `plot_index()`, `plot_stock_recruitment()`, `plot_recruitment_deviations()` -- **Age-composition plots:** `plot_abundance_at_age()`, `plot_biomass_at_age()`, `plot_catch_comp()` - -# How the table functions are built - -The data-driven table functions use a shorter version of the same workflow: - -1. **Filter the data.** - Use `filter_data()` to isolate the label or labels needed for the table. - -2. **Clean and round values.** - The existing tables round `estimate` and `uncertainty` before formatting. - -3. **Process the table structure.** - `process_table()` determines which variables are indexing the data, handles multiple labels, and prepares the data for table formatting. - -4. **Merge estimates and uncertainty.** - `merge_error()` combines the value and error columns into a single presentation-ready column where needed. - -5. **Render the table.** - - `table_index()` and `table_landings()` convert the prepared data to `gt` tables and apply `add_theme()` - -6. **Optionally export the accessibility package.** - As with plots, `make_rda = TRUE` triggers `export_kqs()`, `insert_kqs()`, and `create_rda()`. - -## Table families in this package - -- **Data-driven tables:** `table_index()`, `table_landings()` -- **Legacy/incomplete table workflow:** `table_bnc()` is present but commented out - -# A simple recipe for a new function - -When adding a new `plot_x` or `table_x` function, follow this order: - -1. Identify the source label(s) in the standardized output. -2. Filter with `filter_data()`. -3. Process with `process_data()` or `process_table()`. -4. Build the figure or table with the helper that matches the display type. -5. Add domain-specific layers or table formatting. -6. Apply the package theme. -7. Export key quantities and the `.rda` package if the function supports accessibility output. -8. Document the workflow in the function's roxygen file and add an example. - -If a new figure or table does not fit an existing category, explain the new category and we can try to build the pipeline to incorporate it into the existing workflow. From 766a32ed7f5f42dccf7b7d1b6eec2f985a549582 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Thu, 9 Jul 2026 16:18:14 -0400 Subject: [PATCH 6/9] Update guide with edits --- CONTRIBUTING.md | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9a3cdfec..b431ab88 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,12 +71,14 @@ If possible, please submit a reproducible example ([reprex](https://reprex.tidyv Have a question? Ask it in our [Discussions page](https://github.com/nmfs-ost/stockplotr/discussions). You can categorize it under General, Ideas, Q&A, and more. -## Figure and Table Workflow Guide +## Figure and Table Development Guide This guide summarizes the workflow used by the `plot_x` and `table_x` functions in `R/`. Use it as a template when building a new figure or table function from the existing package patterns. -### The common starting point +If a new figure or table does not fit an existing category, please let us know. We can try to build the pipeline to incorporate it into the existing workflow. + +### Overview Most functions begin with standardized output from `convert_output()`. That data is then narrowed to one label or related labels, reshaped if needed, and finally rendered as a plot or table. @@ -86,15 +88,15 @@ The recurring helpers are: - `filter_data()` to isolate the target label(s) and apply module, era, grouping, faceting, and scaling choices. - `process_data()` to detect indexing variables, set `group_var`, and decide whether additional variables should become grouping or facetting variables. - `process_table()` for table-specific label handling and row/column organization. -- `create_rda()` when `make_rda = TRUE`. +- `create_rda()` to export the figure/table as an rda file, and the figure/table's associated information. ### How the figure functions are built -The figure functions in `R/` follow the same basic sequence: +The figure functions follow the same basic sequence: 1. **Filter the data.** Pick the relevant label with `filter_data()`. - This is where each figure decides whether it needs `year`, `age`, `fleet`, `area`, `sex`, a specific module, or a specific era. + This is where the data used as the basis for each figure is filtered from its original state. Variables such as `year`, `age`, `fleet`, `area`, `sex`, a specific module, or a specific era are used to remove unnecessary data. 2. **Process the filtered data.** Run `process_data()` to identify the index structure and to decide how the data should be grouped or faceted. @@ -115,14 +117,15 @@ The figure functions in `R/` follow the same basic sequence: 5. **Apply the final theme.** Most figures end with `theme_noaa()`. -6. **Optionally export the accessibility package.** +6. **Add capability to export the figure and associated materials.** If `make_rda = TRUE`, the figure function usually: - calculates key quantities, - writes them with `export_kqs()`, - inserts them into captions and alt text with `insert_kqs()`, - and saves the final object with `create_rda()`. + These steps are important for creating alternative text and captions for the figures. Make sure to reference inst/resources/captions_alt_text_template.csv and inst/resources/key_quantity_template.csv to ensure the key quantities are properly inserted into an accurate caption and alt text. -### Figure families in this package +#### Figure families - **Time-series plots:** `plot_biomass()`, `plot_spawning_biomass()`, `plot_recruitment()`, `plot_landings()`, `plot_fishing_mortality()`, `plot_natural_mortality()` - **Observation/comparison plots:** `plot_index()`, `plot_stock_recruitment()`, `plot_recruitment_deviations()` @@ -142,30 +145,23 @@ The data-driven table functions use a shorter version of the same workflow: `process_table()` determines which variables are indexing the data, handles multiple labels, and prepares the data for table formatting. 4. **Merge estimates and uncertainty.** - `merge_error()` combines the value and error columns into a single presentation-ready column where needed. + `merge_error()` combines the value and error columns into a single column where needed. 5. **Render the table.** - `table_index()` and `table_landings()` convert the prepared data to `gt` tables and apply `add_theme()` -6. **Optionally export the accessibility package.** +6. **Add capability to export the figure and associated materials.** As with plots, `make_rda = TRUE` triggers `export_kqs()`, `insert_kqs()`, and `create_rda()`. -### Table families in this package - -- **Data-driven tables:** `table_index()`, `table_landings()` -- **Legacy/incomplete table workflow:** `table_bnc()` is present but commented out +#### Table families -### A simple recipe for a new function +All tables are in the same family. -When adding a new `plot_x` or `table_x` function, follow this order: +### Last steps -1. Identify the source label(s) in the standardized output. -2. Filter with `filter_data()`. -3. Process with `process_data()` or `process_table()`. -4. Build the figure or table with the helper that matches the display type. -5. Add domain-specific layers or table formatting. -6. Apply the package theme. -7. Export key quantities and the `.rda` package if the function supports accessibility output. -8. Document the workflow in the function's roxygen file and add an example. +Once your figure or table is developed (🎉!), please complete these tasks: -If a new figure or table does not fit an existing category, explain the new category and we can try to build the pipeline to incorporate it into the existing workflow. +1. Test it with different kinds of model outputs: SS3, BAM, Rceattle, r4ss, etc. +2. Add the figure to `save_all_plots()`. Depending on the plot, you may need to add a new argument to the Roxygen. +3. Update the `save_all_plots()` test in `tests/testthat/test-save_all_plots.R`. +4. Create unit tests for your figure or table function in `tests/testthat/`. This will entail creating a new test file (e.g., `test-plot_new_function.R`) and adding unit tests. Most/all can be copied from an existing test file and modified for your new function. From 45d1703287b6eef7eb681ee1e4898a858f10e57f Mon Sep 17 00:00:00 2001 From: Sophie Breitbart Date: Mon, 13 Jul 2026 13:47:11 -0400 Subject: [PATCH 7/9] Update CONTRIBUTING.md Co-authored-by: Sam (Schiano) Bredeck <125507018+Schiano-NOAA@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b431ab88..d3fc7d36 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -164,4 +164,4 @@ Once your figure or table is developed (🎉!), please complete these tasks: 1. Test it with different kinds of model outputs: SS3, BAM, Rceattle, r4ss, etc. 2. Add the figure to `save_all_plots()`. Depending on the plot, you may need to add a new argument to the Roxygen. 3. Update the `save_all_plots()` test in `tests/testthat/test-save_all_plots.R`. -4. Create unit tests for your figure or table function in `tests/testthat/`. This will entail creating a new test file (e.g., `test-plot_new_function.R`) and adding unit tests. Most/all can be copied from an existing test file and modified for your new function. +4. Create unit tests for your figure or table function in `tests/testthat/`. This will entail creating a new test file (e.g., `test-plot_new_function.R`) and adding unit tests. Most/all can be copied from an existing test file and modified for your new function. If you are unfamiliar with the {testthat} framework, please leave a comment on your PR and let us know. We are happy to work with you to develop a unit test. From cb7e8cae2bc43b704a9fe27c85b451800b39cc71 Mon Sep 17 00:00:00 2001 From: Sophie Breitbart Date: Mon, 13 Jul 2026 13:47:54 -0400 Subject: [PATCH 8/9] Update CONTRIBUTING.md Co-authored-by: Sam (Schiano) Bredeck <125507018+Schiano-NOAA@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d3fc7d36..865f0dde 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -104,7 +104,7 @@ The figure functions follow the same basic sequence: 3. **Choose the plot builder.** - `plot_timeseries()` for standard time-series figures - `plot_obsvpred()` for observed-vs-predicted index figures - - `plot_aa()` for age-composition bubble plots + - `plot_aa()` for age- or length-composition bubble plots - `plot_error()` for point/error summaries 4. **Add figure-specific layers.** From 4e932c91687c6a16b46cdefa6a02dc87266dd871 Mon Sep 17 00:00:00 2001 From: sbreitbart-NOAA Date: Mon, 13 Jul 2026 15:51:29 -0400 Subject: [PATCH 9/9] Address comments from @Schiano-NOAA --- CONTRIBUTING.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 865f0dde..d6ac99ff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -83,7 +83,7 @@ If a new figure or table does not fit an existing category, please let us know. Most functions begin with standardized output from `convert_output()`. That data is then narrowed to one label or related labels, reshaped if needed, and finally rendered as a plot or table. -The recurring helpers are: +The recurring helper functions are executed in the following order: - `filter_data()` to isolate the target label(s) and apply module, era, grouping, faceting, and scaling choices. - `process_data()` to detect indexing variables, set `group_var`, and decide whether additional variables should become grouping or facetting variables. @@ -95,11 +95,11 @@ The recurring helpers are: The figure functions follow the same basic sequence: 1. **Filter the data.** - Pick the relevant label with `filter_data()`. - This is where the data used as the basis for each figure is filtered from its original state. Variables such as `year`, `age`, `fleet`, `area`, `sex`, a specific module, or a specific era are used to remove unnecessary data. + Pick the relevant label (a regular expression) with `filter_data()`. + This is where the data used as the basis for each figure is filtered from its original state. Variables such as `year`, `age`, `fleet`, `area`, `sex`, a specific module, or a specific era are used to remove unnecessary data. Confidence intervals are calculated in this step. 2. **Process the filtered data.** - Run `process_data()` to identify the index structure and to decide how the data should be grouped or faceted. + Run `process_data()` to identify the index structure and to decide how the data should be grouped or faceted. In this step, the data gets narrowed down to the indexed data columns. 3. **Choose the plot builder.** - `plot_timeseries()` for standard time-series figures @@ -109,13 +109,13 @@ The figure functions follow the same basic sequence: 4. **Add figure-specific layers.** Examples from the existing functions include: - - `reference_line()` and `calculate_reference_point()` for biomass and fishing mortality plots + - `reference_line()` and `calculate_reference_point()` - `average_age_line()` for abundance/biomass-at-age plots - `cohort_line()` for catch-composition plots - extra overlays for expected recruitment or stock-recruit curves 5. **Apply the final theme.** - Most figures end with `theme_noaa()`. + Add NOAA theming to figures with `theme_noaa()`. 6. **Add capability to export the figure and associated materials.** If `make_rda = TRUE`, the figure function usually: @@ -147,15 +147,15 @@ The data-driven table functions use a shorter version of the same workflow: 4. **Merge estimates and uncertainty.** `merge_error()` combines the value and error columns into a single column where needed. -5. **Render the table.** - - `table_index()` and `table_landings()` convert the prepared data to `gt` tables and apply `add_theme()` +5. **Render the final table.** + - The prepared data are converted to a `gt` table. `add_theme()` applies formatting to the table. 6. **Add capability to export the figure and associated materials.** As with plots, `make_rda = TRUE` triggers `export_kqs()`, `insert_kqs()`, and `create_rda()`. #### Table families -All tables are in the same family. +Tables are unique and do not have the same system of families as the figures. ### Last steps