Skip to content

Commit a645898

Browse files
committed
Adding function, needed files, and test_run for fishable production request received on 04/27/2026
1 parent 086b879 commit a645898

9 files changed

Lines changed: 203 additions & 0 deletions

R/calc_fishable_production.R

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#' Calculate Fishable Production with Automated Area Calculation
2+
#'
3+
#' @param model A balanced Rpath model object.
4+
#' @param ecosystem_name Character. The name of the ecosystem.
5+
#' Accepted values: "Georges Bank", "Gulf of Maine", "Mid-Atlantic Bight".
6+
#' @param base_year Numeric. Base year of the model.
7+
#' @param citation Character. Citation for the model.
8+
#' @param exclude_groups Character vector. Names of groups to exclude.
9+
#' @param area_km2 Numeric. Optional. If provided, overrides the shapefile calculation.
10+
#' @param shapefile_path Character. Path to the EPU shapefile.
11+
#' @param fleet_name Character. Optional name of the dominant fleet.
12+
#' @param kappa Numeric. Harvesting factor. Default is 0.175.
13+
#' @export
14+
calc_fishable_production <- function(model, ecosystem_name, base_year,
15+
citation, exclude_groups = c(),
16+
area_km2 = NULL,
17+
shapefile_path = "data-raw/EPU_extended.shp",
18+
fleet_name = NULL, kappa = 0.175) {
19+
20+
# 1. Automated Area Calculation (if area_km2 is not provided)
21+
if (is.null(area_km2)) {
22+
if (!file.exists(shapefile_path)) {
23+
stop("Shapefile not found at ", shapefile_path, ". Please provide area_km2 manually or check the path.")
24+
}
25+
26+
# Map user-friendly names to the EPU codes in your shapefile
27+
epu_map <- c("Georges Bank" = "GB",
28+
"Gulf of Maine" = "GOM",
29+
"Mid-Atlantic Bight" = "MAB")
30+
31+
target_epu <- epu_map[ecosystem_name]
32+
33+
if (is.na(target_epu)) {
34+
stop("ecosystem_name must be 'Georges Bank', 'Gulf of Maine', or 'Mid-Atlantic Bight' to use automated area.")
35+
}
36+
37+
# Temporarily disable strict s2 spherical geometry to bypass vertex errors
38+
current_s2 <- sf::sf_use_s2()
39+
suppressMessages(sf::sf_use_s2(FALSE))
40+
41+
# Read, fix geometry, and calculate area
42+
epu_sf <- sf::st_read(shapefile_path, quiet = TRUE)
43+
44+
area_km2 <- epu_sf %>%
45+
dplyr::filter(EPU == target_epu) %>%
46+
sf::st_make_valid() %>% # Repairs self-intersections
47+
sf::st_area() %>%
48+
as.numeric() / 1000000 # Convert m2 to km2
49+
50+
# Restore s2 to its original state so we don't mess up the user's environment
51+
suppressMessages(sf::sf_use_s2(current_s2))
52+
53+
message(paste("Automated Area Lookup:", round(area_km2, 2), "km2 for", ecosystem_name))
54+
}
55+
56+
# 2. Extract parameters from Rpath model
57+
groups <- model$Group
58+
TL <- model$TL
59+
Biomass <- model$Biomass
60+
PB <- model$PB
61+
catch_mat <- model$Landings + model$Discards
62+
63+
# 3. Determine dominant fleet
64+
fleet_totals <- colSums(catch_mat, na.rm = TRUE)
65+
if (is.null(fleet_name)) {
66+
fleet_name <- names(fleet_totals)[which.max(fleet_totals)]
67+
}
68+
69+
# 4. Calculate Fleet Trophic Level
70+
fleet_catch <- catch_mat[, fleet_name]
71+
fleet_TL <- sum(fleet_catch * TL, na.rm = TRUE) / sum(fleet_catch, na.rm = TRUE)
72+
73+
# 5. Set TL Threshold & 90% Catch Coverage Loop
74+
initial_tl_threshold <- fleet_TL - 1.0
75+
current_tl_threshold <- initial_tl_threshold
76+
total_catch <- sum(catch_mat, na.rm = TRUE)
77+
perc_catch <- 0
78+
79+
while(perc_catch < 0.90 && current_tl_threshold > 0) {
80+
valid_taxa <- !(groups %in% exclude_groups) & (TL >= current_tl_threshold)
81+
catch_cov <- sum(catch_mat[valid_taxa, ], na.rm = TRUE)
82+
perc_catch <- catch_cov / total_catch
83+
if(perc_catch < 0.90) current_tl_threshold <- current_tl_threshold - 0.01
84+
}
85+
86+
# 6. Calculate Fishable Production
87+
valid_taxa_final <- !(groups %in% exclude_groups) & (TL >= current_tl_threshold)
88+
total_production <- sum(Biomass[valid_taxa_final] * PB[valid_taxa_final], na.rm = TRUE)
89+
90+
fishable_prod_km2 <- total_production * kappa
91+
fishable_prod_total <- fishable_prod_km2 * area_km2
92+
93+
# 7. Format Result Paragraph
94+
extension_text <- ""
95+
if (current_tl_threshold < initial_tl_threshold) {
96+
extension_text <- sprintf(
97+
" This trophic level cutoff was extended down to TL %.2f, to ensure that at least 90%% of harvest in the base model was included.",
98+
current_tl_threshold
99+
)
100+
}
101+
102+
template_text <- sprintf(
103+
"We applied the Fishable Production method to an Rpath food web model of %s, which represented a base year of %d. This model (%s) is intended to represent a spatial domain of %s km2. In this Rpath model, the single fleet or dominant fleet %s had a trophic level of %.2f, and hence we include production estimates of all species >= trophic level %.2f.%s We estimate Fishable production to be %.2f tons km-2, equivalent to %.2f million tons over the model spatial domain.",
104+
ecosystem_name, base_year, citation, format(round(area_km2), big.mark = ","),
105+
fleet_name, fleet_TL, initial_tl_threshold, extension_text,
106+
fishable_prod_km2, fishable_prod_total / 1000000
107+
)
108+
109+
return(list(metrics = data.frame(Ecosystem = ecosystem_name, Area = area_km2, Fishable_Prod_km2 = fishable_prod_km2),
110+
report_text = template_text))
111+
}

data-raw/EPU_extended.cpg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
UTF-8

data-raw/EPU_extended.dbf

486 Bytes
Binary file not shown.

data-raw/EPU_extended.prj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]

data-raw/EPU_extended.sbn

172 Bytes
Binary file not shown.

data-raw/EPU_extended.sbx

124 Bytes
Binary file not shown.

data-raw/EPU_extended.shp

772 KB
Binary file not shown.

data-raw/EPU_extended.shx

132 Bytes
Binary file not shown.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# GB ----------
2+
3+
# 1. Load required tools
4+
library(sf) # Required for the automated area calculation
5+
library(dplyr)
6+
7+
# 2. Load the function and the data
8+
# If you are actively building the package, devtools::load_all() is best.
9+
# Alternatively, you can just source the function directly:
10+
source("R/calc_fishable_production.R")
11+
12+
# Load the Georges Bank balanced model object
13+
load("data/GB.rda")
14+
15+
# 3. Define the groups to exclude
16+
exclude_list <- c(
17+
"SeaBirds", "Pinnipeds", "BaleenWhales", "Odontocetes",
18+
"Bacteria", "Detritus", "Phytoplankton",
19+
"LgCopepods", "SmCopepods", "Microzooplankton",
20+
"GelZooplankton", "Krill", "Micronekton",
21+
"Macrobenthos", "Megabenthos", "Fauna"
22+
)
23+
24+
# 4. Run the function
25+
Sys.setenv(SHAPE_RESTORE_SHX = "YES")
26+
27+
gb_test_run <- calc_fishable_production(
28+
model = GB, # The object loaded from GB.rda
29+
ecosystem_name = "Georges Bank",
30+
base_year = 1985,
31+
citation = "Weisberg et al. in review",
32+
exclude_groups = exclude_list
33+
)
34+
35+
Sys.unsetenv("SHAPE_RESTORE_SHX")
36+
37+
# 5. View the outputs
38+
print(gb_test_run$metrics)
39+
40+
cat("\n--- Generated Template Paragraph ---\n")
41+
cat(gb_test_run$report_text, "\n")
42+
43+
# GOM --------
44+
45+
# Load the Gulf of Maine balanced model object
46+
load("data/GOM.rda")
47+
48+
# 4. Run the function
49+
Sys.setenv(SHAPE_RESTORE_SHX = "YES")
50+
51+
gom_test_run <- calc_fishable_production(
52+
model = GOM,
53+
ecosystem_name = "Gulf of Maine",
54+
base_year = 1985,
55+
citation = "Weisberg et al. in review",
56+
exclude_groups = exclude_list
57+
)
58+
59+
Sys.unsetenv("SHAPE_RESTORE_SHX")
60+
61+
# 5. View the outputs
62+
print(gom_test_run$metrics)
63+
64+
cat("\n--- Generated Template Paragraph ---\n")
65+
cat(gom_test_run$report_text, "\n")
66+
67+
# MAB ---------
68+
69+
# Load the Gulf of Maine balanced model object
70+
load("data/MAB.rda")
71+
72+
73+
# 4. Run the function
74+
Sys.setenv(SHAPE_RESTORE_SHX = "YES")
75+
76+
mab_test_run <- calc_fishable_production(
77+
model = MAB,
78+
ecosystem_name = "Mid-Atlantic Bight",
79+
base_year = 1985,
80+
citation = "Weisberg et al. in review",
81+
exclude_groups = exclude_list
82+
)
83+
84+
Sys.unsetenv("SHAPE_RESTORE_SHX")
85+
86+
# 5. View the outputs
87+
print(mab_test_run$metrics)
88+
89+
cat("\n--- Generated Template Paragraph ---\n")
90+
cat(mab_test_run$report_text, "\n")

0 commit comments

Comments
 (0)