Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,98 @@ 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.

## 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.

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.

The recurring helpers are:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe include some language like "in order" or "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.
- `process_table()` for table-specific label handling and row/column organization.
- `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 follow the same basic sequence:

1. **Filter the data.**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a mention that the label is a regular expresssion

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also would mention that the confidence intervals get calculated here as well (I think it's this one)

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.

2. **Process the filtered data.**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add information that the data gets narrowed down to the indexed data columns

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention or x/y type of plots

- `plot_obsvpred()` for observed-vs-predicted index figures
- `plot_aa()` for age- or length-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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- `reference_line()` and `calculate_reference_point()` for biomass and fishing mortality plots
- `reference_line()` and `calculate_reference_point()`

I wouldn't mention specific plots because this can apply to anything that needs a reference line

- `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()`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all figures?


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

- **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 column where needed.

5. **Render the table.**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is inaccurate and should be removed. This is the function itself not inside of it

- `table_index()` and `table_landings()` convert the prepared data to `gt` tables and apply `add_theme()`

6. **Add capability to export the figure and associated materials.**
As with plots, `make_rda = TRUE` triggers `export_kqs()`, `insert_kqs()`, and `create_rda()`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the contributor only needs to know about create_rda() since the others are functions inside that one


#### Table families

All tables are in the same family.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say they are unique and familiar don't exist for tables (at the moment at least)


### Last steps

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. 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.
Loading