diff --git a/.gitignore b/.gitignore index 7ec7968..0bb2ca7 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ ODM-MH-Data_log/data/results/Archived_DataLogs/ # Gaitlyn's Personal Exploratory Files Examples/Testfiles/ + +*.env diff --git a/ODM-MH-Analysis_ready/Catch Limits/CatchLimits.R b/ODM-MH-Analysis_ready/Catch Limits/CatchLimits.R index 8bf97fc..3bbf1d1 100644 --- a/ODM-MH-Analysis_ready/Catch Limits/CatchLimits.R +++ b/ODM-MH-Analysis_ready/Catch Limits/CatchLimits.R @@ -6,7 +6,7 @@ librarian::shelf(here, tidyverse, gt, flextable, officer, dplyr, gt, officer, lu #### Load data #### # Load the MH Data Log -mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Sep10.RDS")) +mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Nov18.RDS")) #### Define species, region, and sector of interest #### species = c('SNAPPER, CUBERA', 'AMBERJACK, GREATER', 'AMBERJACK, LESSER', 'JACK, ALMACO', 'SNAPPER, SILK', 'SNAPPER, QUEEN', 'SNAPPER, BLACKFIN', 'WENCHMAN', @@ -24,9 +24,9 @@ ACLs <- mh %>% REGION %in% region, SECTOR == sector, DETAILED == "YES", - NEVER_IMPLEMENTED %in% c(0, NA), + #NEVER_IMPLEMENTED == 0 | is.na(NEVER_IMPLEMENTED), REG_REMOVED == 0, - MANAGEMENT_TYPE_USE == "ACL") %>% + MANAGEMENT_TYPE_USE == "ACL") #%>% arrange(CLUSTER, START_DATE2) %>% mutate(Species = case_when(str_detect(COMMON_NAME_USE, ",") ~ {parts <- str_split_fixed(COMMON_NAME_USE, ",", 2) str_to_title(str_trim(parts[,2])) %>% paste(str_to_title(str_trim(parts[,1])))}, @@ -62,7 +62,7 @@ Quotas <- mh %>% REGION %in% region, SECTOR == sector, DETAILED == "YES", - NEVER_IMPLEMENTED %in% c(0, NA), + NEVER_IMPLEMENTED == 0 | is.na(NEVER_IMPLEMENTED), REG_REMOVED == 0, MANAGEMENT_TYPE_USE == "QUOTA") %>% arrange(CLUSTER, START_DATE2) %>% @@ -100,7 +100,7 @@ ACTs <- mh %>% REGION %in% region, SECTOR == sector, DETAILED == "YES", - NEVER_IMPLEMENTED %in% c(0, NA), + NEVER_IMPLEMENTED == 0 | is.na(NEVER_IMPLEMENTED), MANAGEMENT_TYPE_USE == "ACT") %>% arrange(CLUSTER, START_DATE2) %>% mutate(Species = case_when(str_detect(COMMON_NAME_USE, ",") ~ {parts <- str_split_fixed(COMMON_NAME_USE, ",", 2) @@ -137,7 +137,7 @@ TACs <- mh %>% REGION %in% region, SECTOR == sector, DETAILED == "YES", - NEVER_IMPLEMENTED %in% c(0, NA), + NEVER_IMPLEMENTED == 0 | is.na(NEVER_IMPLEMENTED), REG_REMOVED == 0, MANAGEMENT_TYPE_USE == "TAC") %>% arrange(CLUSTER, START_DATE2) %>% diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_COBIA2025Dec17.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_COBIA2025Dec17.RDS new file mode 100644 index 0000000..47fdcaf Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_COBIA2025Dec17.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_COBIA2026Jan16.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_COBIA2026Jan16.RDS new file mode 100644 index 0000000..8569aa4 Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_COBIA2026Jan16.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_GROUPER, GAG2026Feb17.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_GROUPER, GAG2026Feb17.RDS new file mode 100644 index 0000000..c540f2a Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_GROUPER, GAG2026Feb17.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_TILEFISH, BLUELINE2026Feb18.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_TILEFISH, BLUELINE2026Feb18.RDS new file mode 100644 index 0000000..62ed2ad Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_TILEFISH, BLUELINE2026Feb18.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_TILEFISH, GOLDFACE2026Feb18.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_TILEFISH, GOLDFACE2026Feb18.RDS new file mode 100644 index 0000000..8b30d79 Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Close_TILEFISH, GOLDFACE2026Feb18.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_COBIA2025Dec17.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_COBIA2025Dec17.RDS new file mode 100644 index 0000000..5cc7a70 Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_COBIA2025Dec17.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_COBIA2026Jan16.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_COBIA2026Jan16.RDS new file mode 100644 index 0000000..86859df Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_COBIA2026Jan16.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_GROUPER, GAG2026Feb17.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_GROUPER, GAG2026Feb17.RDS new file mode 100644 index 0000000..23bc154 Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_GROUPER, GAG2026Feb17.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_TILEFISH, BLUELINE2026Feb18.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_TILEFISH, BLUELINE2026Feb18.RDS new file mode 100644 index 0000000..e65f4c6 Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_TILEFISH, BLUELINE2026Feb18.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_TILEFISH, GOLDFACE2026Feb18.RDS b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_TILEFISH, GOLDFACE2026Feb18.RDS new file mode 100644 index 0000000..96a040c Binary files /dev/null and b/ODM-MH-Analysis_ready/Closures/Closure_outputs/Open_TILEFISH, GOLDFACE2026Feb18.RDS differ diff --git a/ODM-MH-Analysis_ready/Closures/func_expand_status.R b/ODM-MH-Analysis_ready/Closures/func_expand_status.R index 8bbf0b2..74f6295 100644 --- a/ODM-MH-Analysis_ready/Closures/func_expand_status.R +++ b/ODM-MH-Analysis_ready/Closures/func_expand_status.R @@ -5,7 +5,7 @@ expand_status <- function(x, y) { # x = data frame # y = management type - df = filter(x, MANAGEMENT_TYPE_USE == y, + df = dplyr::filter(x, MANAGEMENT_TYPE_USE == y, # only retain records that were in effect NEVER_IMPLEMENTED == 0, REG_REMOVED == 0) @@ -16,28 +16,28 @@ expand_status <- function(x, y) { if('ONCE' %in% mstats){ # One-time event - df_one <- filter(df, MANAGEMENT_STATUS_USE == 'ONCE') %>% - # this filter should not be needed once we clean up errors in date processing - filter(END_DATE2 >= START_DATE2) %>% - mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "1 day")) %>% + df_one <- dplyr::filter(df, MANAGEMENT_STATUS_USE == 'ONCE') %>% + # this dplyr::filter should not be needed once we clean up errors in date processing + dplyr::filter(END_DATE2 >= START_DATE2) %>% + dplyr::mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "1 day")) %>% unnest(date_sequence) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% - mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% + dplyr::mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, date_sequence == END_DATE2 & !is.na(END_TIME) ~ END_TIME, TRUE ~ NA_character_)) %>% - ungroup(0) %>% - select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, + dplyr::ungroup(0) %>% + dplyr::select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, CLUSTER, REGULATION_ID, FR_CITATION, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE, MULTI_REG_VALUE) %>% - arrange(date_sequence, desc(FR_CITATION)) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% + dplyr::arrange(date_sequence, desc(FR_CITATION)) %>% + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% # Retain only most recent FR if there are 2 records with the same date_sequence - mutate(num_records = n()) %>% - mutate(action_value = case_when(num_records > 1 & MULTI_REG_VALUE != 1 & COMMON_NAME_USE == lag(COMMON_NAME_USE) ~ "slice", + dplyr::mutate(num_records = n()) %>% + dplyr::mutate(action_value = case_when(num_records > 1 & MULTI_REG_VALUE != 1 & COMMON_NAME_USE == lag(COMMON_NAME_USE) ~ "slice", num_records > 1 & MULTI_REG_VALUE == 1 ~ "keep", num_records > 1 & MULTI_REG_VALUE != 1 & COMMON_NAME_USE != lag(COMMON_NAME_USE) ~ "keep", TRUE ~ "other")) %>% - filter(!(action_value == "slice")) %>% - rename(CLUSTER_one = "CLUSTER", + dplyr::filter(!(action_value == "slice")) %>% + dplyr::rename(CLUSTER_one = "CLUSTER", REGULATION_ID_one = "REGULATION_ID", FR_CITATION_one = "FR_CITATION", TIME_one = "TIME", @@ -45,7 +45,7 @@ expand_status <- function(x, y) { VALUE_UNITS_one = "VALUE_UNITS", VALUE_TYPE_one = "VALUE_TYPE", VALUE_RATE_one = "VALUE_RATE") %>% - select(-num_records, -action_value) + dplyr::select(-num_records, -action_value) } else { df_one <- data.frame(FMP = character(), COMMON_NAME_USE = character(), REGION = character(), ZONE_USE = character(), SECTOR_USE = character(), SUBSECTOR_USE = character(), MANAGEMENT_TYPE_USE = character(), @@ -56,21 +56,21 @@ expand_status <- function(x, y) { if('SEASONAL' %in% mstats){ # Seasonal - df_seasonal <- filter(df, MANAGEMENT_STATUS_USE == 'SEASONAL') %>% - mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "days")) %>% + df_seasonal <- dplyr::filter(df, MANAGEMENT_STATUS_USE == 'SEASONAL') %>% + dplyr::mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "days")) %>% unnest(date_sequence) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% - mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% + dplyr::mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, date_sequence == END_DATE2 & !is.na(END_TIME) ~ END_TIME, TRUE ~ NA_character_)) %>% - ungroup() %>% - mutate(START_YEAR_expand = year(date_sequence), + dplyr::ungroup() %>% + dplyr::mutate(START_YEAR_expand = year(date_sequence), END_YEAR_expand = year(date_sequence)) %>% - mutate(START_DATE_EXPAND = as.Date(paste(START_YEAR_expand, START_MONTH, START_DAY, sep = "-")), + dplyr::mutate(START_DATE_EXPAND = as.Date(paste(START_YEAR_expand, START_MONTH, START_DAY, sep = "-")), END_DATE_EXPAND = as.Date(paste(END_YEAR_expand, END_MONTH, END_DAY, sep = "-"))) %>% # Create START_DATE_EXPAND2 & END_DATE_EXPAND2 for cases where the duration of the closure goes from the end of the year to the beginning of the enxt year # Create START_DATE_EXPAND_FINAL & END_DATE_EXPAND_FINAL to choose the correct START_DATE_EXPAND and END_DATE_EXPAND for each set of circumstances - mutate(START_DATE_EXPAND2 = case_when(START_DATE_EXPAND > END_DATE_EXPAND ~ START_DATE_EXPAND - lubridate::years(1), + dplyr::mutate(START_DATE_EXPAND2 = case_when(START_DATE_EXPAND > END_DATE_EXPAND ~ START_DATE_EXPAND - lubridate::years(1), TRUE ~ START_DATE_EXPAND), END_DATE_EXPAND2 = case_when(START_DATE_EXPAND > END_DATE_EXPAND ~ END_DATE_EXPAND + lubridate::years(1), TRUE ~ END_DATE_EXPAND), @@ -79,15 +79,15 @@ expand_status <- function(x, y) { END_DATE_EXPAND_FINAL = case_when(START_DATE_EXPAND > END_DATE_EXPAND & date_sequence >= START_DATE_EXPAND & date_sequence >= END_DATE_EXPAND ~ END_DATE_EXPAND2, TRUE ~ END_DATE_EXPAND)) %>% # Remove date_sequence records outside expand range - filter(date_sequence >= START_DATE_EXPAND_FINAL, + dplyr::filter(date_sequence >= START_DATE_EXPAND_FINAL, END_DATE_EXPAND_FINAL >= date_sequence) %>% - select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, + dplyr::select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, CLUSTER, REGULATION_ID, FR_CITATION, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% - arrange(date_sequence, desc(FR_CITATION)) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% + dplyr::arrange(date_sequence, desc(FR_CITATION)) %>% + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% # Retain only most recent FR if there are 2 records with the same date_sequence - slice(1) %>% - rename(CLUSTER_seasonal = "CLUSTER", + dplyr::slice(1) %>% + dplyr::rename(CLUSTER_seasonal = "CLUSTER", REGULATION_ID_seasonal = "REGULATION_ID", FR_CITATION_seasonal = "FR_CITATION", TIME_seasonal = "TIME", @@ -105,18 +105,18 @@ expand_status <- function(x, y) { if('MONTHLY RECURRING' %in% mstats){ # Monthly - df_monthly <- filter(df, MANAGEMENT_STATUS == 'MONTHLY RECURRING') %>% - mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "days")) %>% + df_monthly <- dplyr::filter(df, MANAGEMENT_STATUS == 'MONTHLY RECURRING') %>% + dplyr::mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "days")) %>% unnest(date_sequence) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% - mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% + dplyr::mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, date_sequence == END_DATE2 & !is.na(END_TIME) ~ END_TIME, day(date_sequence) == START_DAY ~ START_TIME, day(date_sequence) == END_DAY ~ END_TIME, TRUE ~ NA_character_)) %>% - ungroup() %>% + dplyr::ungroup() %>% # Extract year from date_sequence - mutate(START_YEAR_expand = year(date_sequence), + dplyr::mutate(START_YEAR_expand = year(date_sequence), END_YEAR_expand = year(date_sequence), # Create START_MONTH_expand and END_MONTH_expand to eventually create the dates that are the bounds of which expansion dates should still be included # The conditions address cases where the monthly recurring goes from the middle of one month to the start of next and eventually crosses year boundaries (Gulf red snapper - 15th to the 1st of the following month or 10th to the 1st of the following month) @@ -151,22 +151,22 @@ expand_status <- function(x, y) { # when monthly recurring, the start/end month range refers to the first and last month where the recurring closure applies # i.e. start month = 2 and end month = 11 # mean recurring closures start in Feb and end in Nov - # can't use END_MONTH_expand in filter for cases when the recurring closures spans 2 months (i.e. 15th -1st) - #filter(START_MONTH_expand >= START_MONTH & + # can't use END_MONTH_expand in dplyr::filter for cases when the recurring closures spans 2 months (i.e. 15th -1st) + #dplyr::filter(START_MONTH_expand >= START_MONTH & # START_MONTH_expand <= END_MONTH) %>% - mutate(START_DATE_EXPAND = as.Date(paste(START_YEAR_expand, START_MONTH_expand, START_DAY_USE, sep = "-")), + dplyr::mutate(START_DATE_EXPAND = as.Date(paste(START_YEAR_expand, START_MONTH_expand, START_DAY_USE, sep = "-")), END_DATE_EXPAND = as.Date(paste(END_YEAR_expand, END_MONTH_expand, END_DAY_USE, sep = "-"))) %>% # Remove date_sequence records outside expand range - filter(date_sequence == START_DATE_EXPAND | + dplyr::filter(date_sequence == START_DATE_EXPAND | date_sequence == END_DATE_EXPAND | date_sequence > START_DATE_EXPAND & date_sequence < END_DATE_EXPAND) %>% - select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, + dplyr::select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, CLUSTER, REGULATION_ID, FR_CITATION, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% - arrange(date_sequence, desc(FR_CITATION)) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% + dplyr::arrange(date_sequence, desc(FR_CITATION)) %>% + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% # Retain only most recent FR if there are 2 records with the same date_sequence - slice(1) %>% - rename(CLUSTER_monthly = "CLUSTER", + dplyr::slice(1) %>% + dplyr::rename(CLUSTER_monthly = "CLUSTER", REGULATION_ID_monthly = "REGULATION_ID", FR_CITATION_monthly = "FR_CITATION", TIME_monthly = "TIME", @@ -184,12 +184,12 @@ expand_status <- function(x, y) { if('WEEKLY RECURRING' %in% mstats){ # Weekly - df_weekly <- filter(df, MANAGEMENT_STATUS_USE == 'WEEKLY RECURRING') %>% - mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "days")) %>% + df_weekly <- dplyr::filter(df, MANAGEMENT_STATUS_USE == 'WEEKLY RECURRING') %>% + dplyr::mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "days")) %>% unnest(date_sequence) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, CLUSTER) %>% # need to get expanded days of the week to match - mutate(START_DAY_OF_WEEK_EXPAND = case_when( + dplyr::mutate(START_DAY_OF_WEEK_EXPAND = case_when( START_DAY_OF_WEEK_USE == "MONDAY" ~ "Mon", START_DAY_OF_WEEK_USE == "TUESDAY" ~ "Tue", START_DAY_OF_WEEK_USE == "WEDNESDAY" ~ "Wed", @@ -207,26 +207,26 @@ expand_status <- function(x, y) { END_DAY_OF_WEEK_USE == "SATURDAY" ~ "Sat", END_DAY_OF_WEEK_USE == "SUNDAY" ~ "Sun", TRUE ~ END_DAY_OF_WEEK_USE)) %>% - mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, + dplyr::mutate(TIME = case_when(date_sequence == START_DATE2 & !is.na(START_TIME) ~ START_TIME, date_sequence == END_DATE2 & !is.na(END_TIME) ~ END_TIME, wday(date_sequence) == START_DAY_OF_WEEK_EXPAND ~ START_TIME, wday(date_sequence) == END_DAY_OF_WEEK_EXPAND ~ END_TIME, TRUE ~ NA_character_)) %>% - ungroup() %>% - mutate(START_YEAR_expand = year(date_sequence), + dplyr::ungroup() %>% + dplyr::mutate(START_YEAR_expand = year(date_sequence), END_YEAR_expand = year(date_sequence)) %>% # function wday formats at Mon, Tue, etc. - mutate(Expand_day_of_week = wday(date_sequence, label = TRUE)) %>% + dplyr::mutate(Expand_day_of_week = wday(date_sequence, label = TRUE)) %>% # Retain on records within expand range - filter(Expand_day_of_week >= START_DAY_OF_WEEK_EXPAND | + dplyr::filter(Expand_day_of_week >= START_DAY_OF_WEEK_EXPAND | Expand_day_of_week <= END_DAY_OF_WEEK_EXPAND) %>% - select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, + dplyr::select(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence, TIME, CLUSTER, REGULATION_ID, FR_CITATION, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% - arrange(date_sequence, desc(FR_CITATION)) %>% - group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% + dplyr::arrange(date_sequence, desc(FR_CITATION)) %>% + dplyr::group_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence) %>% # Retain only most recent FR if there are 2 records with the same date_sequence - slice(1) %>% - rename(CLUSTER_weekly = "CLUSTER", + dplyr::slice(1) %>% + dplyr::rename(CLUSTER_weekly = "CLUSTER", REGULATION_ID_weekly = "REGULATION_ID", FR_CITATION_weekly = "FR_CITATION", TIME_weekly = "TIME", @@ -249,21 +249,21 @@ expand_status <- function(x, y) { # Then limit variables and rename # Then create final VALUE fields based on all status events combine <- df_one %>% - full_join(df_weekly, + dplyr::full_join(df_weekly, by = join_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence)) %>% - full_join(df_seasonal, + dplyr::full_join(df_seasonal, by = join_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence)) %>% - full_join(df_monthly, + dplyr::full_join(df_monthly, by = join_by(FMP, COMMON_NAME_USE, REGION, ZONE_USE, SECTOR_USE, SUBSECTOR_USE, MANAGEMENT_TYPE_USE, date_sequence)) %>% # Remove records from empty dataframes - filter(!is.na(FMP)) %>% + dplyr::filter(!is.na(FMP)) %>% # create final VALUE fields - ungroup() %>% - rowwise() %>% + dplyr::ungroup() %>% + dplyr::rowwise() %>% # For MANAGEMENT_TYPE_USE == "CLOSURE": On a specific date_sequence, if the most recent FR_CITATION applies to multiple closure types (i.e., one time closure and monthly recurring) # Then maintain the more restrictive value (CLOSE) # Otherwise, the most recent FR_CITATION should be maintained with associated value fields - mutate(max_citation = pmax(FR_CITATION_one, FR_CITATION_seasonal, FR_CITATION_weekly, FR_CITATION_monthly, na.rm = TRUE), + dplyr::mutate(max_citation = pmax(FR_CITATION_one, FR_CITATION_seasonal, FR_CITATION_weekly, FR_CITATION_monthly, na.rm = TRUE), matched_values = list(c( if (isTRUE(FR_CITATION_one == max_citation)) VALUE_one else NULL, if (isTRUE(FR_CITATION_seasonal == max_citation)) VALUE_seasonal else NULL, @@ -295,7 +295,7 @@ expand_status <- function(x, y) { FR_CITATION == FR_CITATION_weekly ~ VALUE_RATE_weekly, FR_CITATION == FR_CITATION_seasonal ~ VALUE_RATE_seasonal, FR_CITATION == FR_CITATION_monthly ~ VALUE_RATE_monthly)) %>% - ungroup() + dplyr::ungroup() return(combine) diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/MH_percentages.jpeg b/ODM-MH-Analysis_ready/Management History Comparison Files/MH_percentages.jpeg new file mode 100644 index 0000000..ad47727 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/MH_percentages.jpeg differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_SEDARfiles.R b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_SEDARfiles.R new file mode 100644 index 0000000..a31dad4 --- /dev/null +++ b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_SEDARfiles.R @@ -0,0 +1,1010 @@ +#### Management History Documentation #### +# This script creates standardized tables of management regulations for use in SEDAR stock assessment processes. +# It compiles data from the Management History Data Log and the closure expansion process into clean formats +# that summarize management values, such as ACLs, size limits, trip limits, bag limits, and closure periods by +# year for commercial and recreational sectors. +# The first portion of this script creates a table that can be more easily utilized by data analysts +# The second portion of this script creates tables that can be more easily utilized in reports + +# Part 1. Data Analyst Tables #### +##### Load packages #### +librarian::shelf(here, tidyverse, gt, flextable, officer, dplyr, gt, officer, lubridate, htmltools, rmarkdown, tidyr, openxlsx, stringr) + +#### Load data #### +# Load the MH Data Log +# This includes the full regulatory time series across species and FMPs +mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Nov18.RDS")) +# Correct the order for common name +mh <- mh %>% + mutate(COMMON_NAME_USE = str_to_title(trimws(gsub("^(.*), (.*)$", "\\2 \\1", COMMON_NAME_USE)))) + +# Load Closure file for species of interest +closures <- readRDS(here("ODM-MH-Analysis_ready", "Closures", "Closure_outputs", "Close_TILEFISH, GOLDFACE2026Feb18.RDS")) + +#### Define species and region of interest #### +spp = c('Caribbean Spiny Lobster', 'All') +region = c('CARIBBEAN') + + +#### Commercial sector processing #### +# Retain regulations for species and region of interest +# Remove non-detailed regulations and those that were never implemented +# Retain only full-region (ZONE_USE = ALL) and sector-wide (COMMERCIAL/ALL) regulations +mh_commercial <- mh %>% + filter(COMMON_NAME_USE == spp, + REGION %in% region, + ZONE_USE == "ALL", + DETAILED == "YES", + NEVER_IMPLEMENTED %in% c(0, NA), + SECTOR_USE == "COMMERCIAL", + SUBSECTOR_USE == "ALL") %>% + # Format data for table columns + # FMP_START = month-day when the FMP began + # YEAR = extract the year value from the START_DATE2 of the regulation + # Extract the value, start, end, and FR notice information for all of the MANAGEMENT_TYPE_USE of interest + mutate(FMP_START = case_when(ACTION_TYPE == "ORIGINAL FMP" ~ format(START_DATE2, "%m-%d"), + TRUE ~ NA), + YEAR = year(START_DATE2), + ACL = case_when(MANAGEMENT_TYPE_USE == "ACL" ~ VALUE, + TRUE ~ NA), + acl_value_prep = case_when(MANAGEMENT_TYPE_USE == "ACL" & VALUE_UNITS == "POUNDS" ~ "lbs", + TRUE ~ NA), + acl_type_prep = case_when(MANAGEMENT_TYPE_USE == "ACL" & VALUE_TYPE == "GUTTED WEIGHT" ~ "gw", + MANAGEMENT_TYPE_USE == "ACL" & VALUE_TYPE == "ROUND (WHOLE) WEIGHT" ~ "ww", + TRUE ~ NA), + ACL_UNIT = case_when(MANAGEMENT_TYPE_USE == "ACL" ~ paste(acl_value_prep, " ", acl_type_prep), + TRUE ~ NA), + ACL_FR = case_when(MANAGEMENT_TYPE_USE == "ACL" ~ FR_CITATION, + TRUE ~ NA), + MIN_SIZE = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ VALUE, + TRUE ~ NA), + MIN_START = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ START_DATE2, + TRUE ~ NA), + MIN_END = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ END_DATE2, + TRUE ~ NA), + MIN_FR = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ FR_CITATION, + TRUE ~ NA), + TRIP_LIMIT = case_when(MANAGEMENT_TYPE_USE == "TRIP LIMIT" ~ VALUE, + TRUE ~ NA), + TRIP_START = case_when(MANAGEMENT_TYPE_USE == "TRIP LIMIT" ~ START_DATE2, + TRUE ~ NA), + TRIP_END = case_when(MANAGEMENT_TYPE_USE == "TRIP LIMIT" ~ END_DATE2, + TRUE ~ NA), + TRIP_FR = case_when(MANAGEMENT_TYPE_USE == "TRIP LIMIT" ~ FR_CITATION, + TRUE ~ NA)) + +#### Determine Time Range #### +# Define the first year in the time series (min_year), the current year, and the terminal year +# Terminal year definition may need to be adjusted +mh_year_commercial <- mh_commercial %>% + summarise(min_year = min(YEAR, na.rm = TRUE)) %>% + mutate(current_year = year(Sys.Date()), + terminal_year = current_year - 1) + +#### Create a complete year sequence #### +# Year sequence should start from first year in time series to terminal year +years <- tibble(YEAR = mh_year_commercial$min_year:mh_year_commercial$terminal_year) + +#### Add Closure information #### +# Filter to commercial closures for the entire region +# Convert CLOSE/OPEN to sentence case +closure_commercial <- closures %>% + filter(SECTOR_USE == "COMMERCIAL") %>% + filter(ZONE_USE == "ALL") %>% + mutate(VALUE_CLOSURE = case_when(VALUE == "CLOSE" ~ "CLOSED", + TRUE ~ VALUE), + VALUE_CLOSURE = str_to_sentence(VALUE_CLOSURE)) + +#### Expand regulations across applicable years #### +# Each regulation is expanded across all years between its START and END date information +mh_commercial_expanded <- mh_commercial %>% + mutate(START_YEAR = year(START_DATE2), + END_YEAR = year(END_DATE2)) %>% + rowwise() %>% + mutate(YEAR_TEMP = list(START_YEAR:ifelse(is.na(END_YEAR), START_YEAR, END_YEAR))) %>% + unnest(cols = c(YEAR_TEMP)) %>% + ungroup() + +#### Ensure all years from min_year to current_year are included in full sequence +mh_commercial_complete <- years %>% + full_join(mh_commercial_expanded, by = c("YEAR" = "YEAR_TEMP")) + +#### Fill missing values for regulations so that each year has regulation values +mh_commercial_complete <- mh_commercial_complete %>% + arrange(YEAR) %>% + group_by(YEAR) %>% + fill(ACL, ACL_UNIT, ACL_FR, MIN_SIZE, MIN_START, MIN_END, MIN_FR, + TRIP_LIMIT, TRIP_START, TRIP_END, TRIP_FR, .direction = "downup") %>% + ungroup() + +#### Join closure data #### +# Combine closure days with regulation records +# If closure not available, default to full open year (Jan 1-Dec 31) +mh_commercial_closure <- mh_commercial_complete %>% + left_join(closure_commercial, by = "YEAR") %>% + mutate(VALUE_CLOSURE = ifelse(is.na(VALUE_CLOSURE), "Open", VALUE_CLOSURE), + start = case_when(is.na(start) ~ as.Date(paste0(YEAR, "-01-01")), + TRUE ~ start), + end = case_when(is.na(end) ~ as.Date(paste0(YEAR, "-12-31")), + TRUE ~ end), + ndays = case_when(is.na(ndays) ~ as.numeric(end - start + 1), + TRUE ~ ndays)) + +#### Collapse duplicate rows #### +# Retain multiple rows per YEAR with if there are distinct combinations of VALUE_CLOSURE, start, and end +mh_commercial_closure <- mh_commercial_closure %>% + group_by(YEAR, VALUE_CLOSURE) %>% + arrange(start, end) %>% + mutate(regulation_change = case_when(lag(MIN_SIZE, default = first(MIN_SIZE)) != MIN_SIZE ~ TRUE, + lag(TRIP_LIMIT, default = first(TRIP_LIMIT)) != TRIP_LIMIT ~ TRUE, + TRUE ~ FALSE), + period_change = case_when(lag(VALUE_CLOSURE, default = first(VALUE_CLOSURE)) != VALUE_CLOSURE ~ TRUE, + lag(start, default = first(start)) != start ~ TRUE, + TRUE ~ FALSE), + change_flag = regulation_change | period_change) %>% + filter(row_number() == 1 | change_flag) %>% + ungroup() + +#### Adjust start/end dates #### +# Align regulation start/end dates to closure periods +mh_commercial_closure <- mh_commercial_closure %>% + # Adjust START dates for each regulation type based on season open and closed dates + mutate(FMP_START_date = as.Date(FMP_START, format = "%Y-%m-%d"), + MIN_START = case_when(!is.na(MIN_START) & year(MIN_START) == YEAR & month(MIN_START) > month(start) ~ MIN_START, # Keep MIN_START if same year and regulation month is after start of fishing year + !is.na(MIN_START) & year(MIN_START) == YEAR & month(MIN_START) < month(start) ~ start, # Keep start if same year and regulation month is before start of fishing year + !is.na(MIN_START) & year(MIN_START) != YEAR ~ start, # Otherwise, use start if year is not the same + TRUE ~ MIN_START), + TRIP_START = case_when(!is.na(TRIP_START) & year(TRIP_START) == YEAR & month(TRIP_START) > month(start) ~ TRIP_START, # Keep TRIP_START if same year and month is after start of fishing year + !is.na(TRIP_START) & year(TRIP_START) == YEAR & month(TRIP_START) < month(start) ~ start, # Keep start if same year and regulation month is before start of fishing year + !is.na(TRIP_START) & year(TRIP_START) != YEAR ~ start, # Otherwise, use start if year is not the same + TRUE ~ TRIP_START), + # Adjust END dates for each regulation type based on season open and closed dates + MIN_END = case_when(!is.na(MIN_END) & year(MIN_END) == YEAR & month(MIN_END) < month(end) ~ MIN_END, # Keep MIN_END if same year and regulation end is prior to end of fishing season + !is.na(MIN_END) & year(MIN_END) == YEAR & month(MIN_END) > month(end) ~ end, # Keep end if same year and regulation ends after end of fishing season + !is.na(MIN_END) & year(MIN_END) != YEAR ~ end, # Otherwise, use end if year is not the same + TRUE ~ MIN_END), + TRIP_END = case_when(!is.na(TRIP_END) & year(TRIP_END) == YEAR & month(TRIP_END) >= month(start) & month(TRIP_END) < month(end) ~ TRIP_END, # Keep TRIP_END if same year and regulation end is prior to end of fishing season + !is.na(TRIP_END) & year(TRIP_END) != YEAR & month(TRIP_END) >= month(start)& month(TRIP_END) > month(end) ~ end, # Keep end if same year and regulation end is after end of fishing season + !is.na(TRIP_END) & year(TRIP_END) != YEAR ~ end, + TRUE ~ TRIP_END), + # If FMP_START_date exists, use that. Otherwise, use start + start = case_when(!is.na(FMP_START_date) ~ FMP_START_date, + TRUE ~ as.Date(start))) + +# Create final commercial table #### +# Indicate column order, adjust column labels, and date formats +mh_commercial_table <- mh_commercial_closure %>% + select(YEAR, VALUE_CLOSURE, ndays, start, end, ACL, ACL_UNIT, ACL_FR, MIN_SIZE, MIN_START, MIN_END, MIN_FR, + TRIP_LIMIT, TRIP_START, TRIP_END, TRIP_FR) %>% + arrange(YEAR, start, MIN_START, TRIP_START) %>% + mutate(YEAR = as.character(YEAR), + MIN_START = case_when(!is.na(MIN_START) ~ format(MIN_START, "%e-%b"), + TRUE ~ NA_character_), + MIN_END = case_when(!is.na(MIN_END) ~ format(MIN_END, "%e-%b"), + TRUE ~ NA_character_), + TRIP_START = case_when(!is.na(TRIP_START) ~ format(TRIP_START, "%e-%b"), + TRUE ~ NA_character_), + TRIP_END = case_when(!is.na(TRIP_END) ~ format(TRIP_END, "%e-%b"), + TRUE ~ NA_character_), + start = case_when(!is.na(start) ~ format(start, "%e-%b"), + TRUE ~ NA_character_), + end = case_when(!is.na(end) ~ format(end, "%e-%b"), + TRUE ~ NA_character_), + # Retain values when fishery is open + ACL = case_when(VALUE_CLOSURE == "Open" ~ ACL, + TRUE ~ NA_character_), + ACL_UNIT = case_when(VALUE_CLOSURE == "Open" ~ ACL_UNIT, + TRUE ~ NA_character_), + ACL_FR = case_when(VALUE_CLOSURE == "Open" ~ ACL_FR, + TRUE ~ NA_character_), + MIN_SIZE = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_SIZE, + TRUE ~ NA_character_), + MIN_START = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_START, + TRUE ~ NA_character_), + MIN_END = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_END, + TRUE ~ NA_character_), + MIN_FR = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_FR, + TRUE ~ NA_character_), + TRIP_LIMIT = case_when(VALUE_CLOSURE == "Open" & TRIP_START >= start & TRIP_START <= end ~ TRIP_LIMIT, + TRUE ~ NA_character_), + TRIP_START = case_when(VALUE_CLOSURE == "Open" & TRIP_START >= start & TRIP_START <= end~ TRIP_START, + TRUE ~ NA_character_), + TRIP_END = case_when(VALUE_CLOSURE == "Open" & TRIP_START >= start & TRIP_START <= end ~ TRIP_END, + TRUE ~ NA_character_), + TRIP_FR = case_when(VALUE_CLOSURE == "Open" & TRIP_START >= start & TRIP_START <= end ~ TRIP_FR, + TRUE ~ NA_character_)) %>% + rename("Year" = YEAR, + "ACL Unit" = ACL_UNIT, + "ACL FR Citation" = ACL_FR, + "Number of Days" = ndays, + "Fishing Season" = VALUE_CLOSURE, + "Season Start Date (first day implemented)" = start, + "Season End Date (last day effective)" = end, + "Minimum Size Limit (inches TL)" = MIN_SIZE, + "Minimum Size Limit Start Date" = MIN_START, + "Minimum Size Limit End Date" = MIN_END, + "Minimum Size Limit FR Citation" = MIN_FR, + "Retention (Trip) Limit (lbs gw)" = TRIP_LIMIT, + "Retention Limit Start Date" = TRIP_START, + "Retention Limit End Date" = TRIP_END, + "Retention Limit FR Citation" = TRIP_FR) + +#### Recreational sector processing #### +# Retain regulations for species and region of interest +# Remove non-detailed regulations and those that were never implemented +# Retain only full-region (ZONE_USE = ALL) and sector-wide (RECREATIONAL/ALL) regulations +mh_recreational <- mh %>% + filter(COMMON_NAME_USE == spp, + REGION %in% region, + ZONE_USE == "ALL", + DETAILED == "YES", + NEVER_IMPLEMENTED %in% c(0, NA), + SECTOR_USE == "RECREATIONAL", + SUBSECTOR_USE == "ALL") %>% + # Format data for table columns + # FMP_START = month-day when the FMP began + # YEAR = extract the year value from the START_DATE2 of the regulation + # Extract the value, start, end, and FR notice information for all of the MANAGEMENT_TYPE_USE of interest + mutate(FMP_START = case_when(ACTION_TYPE == "ORIGINAL FMP" ~ format(START_DATE2, "%m-%d"), + TRUE ~ NA), + YEAR = year(START_DATE2), + ACL = case_when(MANAGEMENT_TYPE_USE == "ACL" ~ VALUE, + TRUE ~ NA), + acl_value_prep = case_when(MANAGEMENT_TYPE_USE == "ACL" & VALUE_UNITS == "POUNDS" ~ "lbs", + TRUE ~ NA), + acl_type_prep = case_when(MANAGEMENT_TYPE_USE == "ACL" & VALUE_TYPE == "GUTTED WEIGHT" ~ "gw", + MANAGEMENT_TYPE_USE == "ACL" & VALUE_TYPE == "ROUND (WHOLE) WEIGHT" ~ "ww", + TRUE ~ NA), + ACL_UNIT = case_when(MANAGEMENT_TYPE_USE == "ACL" ~ paste(acl_value_prep, " ", acl_type_prep), + TRUE ~ NA), + ACL_FR = case_when(MANAGEMENT_TYPE_USE == "ACL" ~ FR_CITATION, + TRUE ~ NA), + MIN_SIZE = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ VALUE, + TRUE ~ NA), + MIN_START = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ START_DATE2, + TRUE ~ NA), + MIN_END = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ END_DATE2, + TRUE ~ NA), + MIN_FR = case_when(MANAGEMENT_TYPE_USE == "MINIMUM SIZE LIMIT" ~ FR_CITATION, + TRUE ~ NA), + BAG_LIMIT = case_when(MANAGEMENT_TYPE_USE == "BAG LIMIT" ~ VALUE, + TRUE ~ NA), + BAG_START = case_when(MANAGEMENT_TYPE_USE == "BAG LIMIT" ~ START_DATE2, + TRUE ~ NA), + BAG_END = case_when(MANAGEMENT_TYPE_USE == "BAG LIMIT" ~ END_DATE2, + TRUE ~ NA), + BAG_FR = case_when(MANAGEMENT_TYPE_USE == "BAG LIMIT" ~ FR_CITATION, + TRUE ~ NA)) + +#### Determine Time Range #### +# Define the first year in the time series (min_year), the current year, and the terminal year +# Terminal year definition may need to be adjusted +mh_year_recreational <- mh_recreational %>% + summarise(min_year = min(YEAR, na.rm = TRUE)) %>% + mutate(current_year = year(Sys.Date()), + terminal_year = current_year - 1) + +#### Create a complete year sequence #### +# Year sequence should start from first year in time series to terminal year +years <- tibble(YEAR = mh_year_recreational$min_year:mh_year_recreational$terminal_year) + +#### Add Closure information #### +# Filter to recreational closures for the entire region +# Convert CLOSE/OPEN to sentence case +closure_recreational <- closures %>% + filter(SECTOR_USE == "RECREATIONAL") %>% + filter(ZONE_USE == "ALL") %>% + mutate(VALUE_CLOSURE = case_when(VALUE == "CLOSE" ~ "CLOSED", + TRUE ~ VALUE), + VALUE_CLOSURE = str_to_sentence(VALUE_CLOSURE)) + +#### Expand regulations across applicable years #### +# Each regulation is expanded across all years between its START and END date information +mh_recreational_expanded <- mh_recreational %>% + mutate(START_YEAR = year(START_DATE2), + END_YEAR = year(END_DATE2)) %>% + rowwise() %>% + mutate(YEAR_TEMP = list(START_YEAR:ifelse(is.na(END_YEAR), START_YEAR, END_YEAR))) %>% + unnest(cols = c(YEAR_TEMP)) %>% + ungroup() + +#### Ensure all years from min_year to current_year are included in full sequence +mh_recreational_complete <- years %>% + full_join(mh_recreational_expanded, by = c("YEAR" = "YEAR_TEMP")) + +#### Fill missing values for regulations so that each year has regulation values +mh_recreational_complete <- mh_recreational_complete %>% + arrange(YEAR) %>% + group_by(YEAR) %>% + fill(ACL, ACL_UNIT, ACL_FR, MIN_SIZE, MIN_START, MIN_END, MIN_FR, + BAG_LIMIT, BAG_START, BAG_END, BAG_FR, .direction = "downup") %>% + ungroup() + +#### Join closure data #### +# Combine closure days with regulation records +# If closure not available, default to full open year (Jan 1-Dec 31) +mh_recreational_closure <- mh_recreational_complete %>% + left_join(closure_recreational, by = "YEAR") %>% + mutate(VALUE_CLOSURE = ifelse(is.na(VALUE_CLOSURE), "Open", VALUE_CLOSURE), + start = case_when(is.na(start) ~ as.Date(paste0(YEAR, "-01-01")), + TRUE ~ start), + end = case_when(is.na(end) ~ as.Date(paste0(YEAR, "-12-31")), + TRUE ~ end), + ndays = case_when(is.na(ndays) ~ as.numeric(end - start + 1), + TRUE ~ ndays)) + +#### Collapse duplicate rows #### +# Retain multiple rows per YEAR with if there are distinct combinations of VALUE_CLOSURE, start, and end +mh_recreational_closure <- mh_recreational_closure %>% + group_by(YEAR, VALUE_CLOSURE) %>% + arrange(start, end) %>% + mutate(regulation_change = case_when(lag(MIN_SIZE, default = first(MIN_SIZE)) != MIN_SIZE ~ TRUE, + lag(BAG_LIMIT, default = first(BAG_LIMIT)) != BAG_LIMIT ~ TRUE, + TRUE ~ FALSE), + period_change = case_when(lag(VALUE_CLOSURE, default = first(VALUE_CLOSURE)) != VALUE_CLOSURE ~ TRUE, + lag(start, default = first(start)) != start ~ TRUE, + TRUE ~ FALSE), + change_flag = regulation_change | period_change) %>% + filter(row_number() == 1 | change_flag) %>% + ungroup() + + +#### Adjust start/end dates #### +# Align regulation start/end dates to closure periods +mh_recreational_closure <- mh_recreational_closure %>% + # Adjust START dates for each regulation type based on season open and closed dates + mutate(FMP_START_date = as.Date(FMP_START, format = "%Y-%m-%d"), + MIN_START = case_when(!is.na(MIN_START) & year(MIN_START) == YEAR & month(MIN_START) > month(start) ~ MIN_START, # Keep MIN_START if same year and regulation month is after start of fishing year + !is.na(MIN_START) & year(MIN_START) == YEAR & month(MIN_START) < month(start) ~ start, # Keep start if same year and regulation month is before start of fishing year + !is.na(MIN_START) & year(MIN_START) != YEAR ~ start, # Otherwise, use start if year is not the same + TRUE ~ MIN_START), + BAG_START = case_when(!is.na(BAG_START) & year(BAG_START) == YEAR & month(BAG_START) > month(start) ~ BAG_START, # Keep BAG_START if same year and month is after start of fishing year + !is.na(BAG_START) & year(BAG_START) == YEAR & month(BAG_START) < month(start) ~ start, # Keep start if same year and regulation month is before start of fishing year + !is.na(BAG_START) & year(BAG_START) != YEAR ~ start, # Otherwise, use start if year is not the same + TRUE ~ BAG_START), + # Adjust END dates for each regulation type based on season open and closed dates + MIN_END = case_when(!is.na(MIN_END) & year(MIN_END) == YEAR & month(MIN_END) < month(end) ~ MIN_END, # Keep MIN_END if same year and regulation end is prior to end of fishing season + !is.na(MIN_END) & year(MIN_END) == YEAR & month(MIN_END) > month(end) ~ end, # Keep end if same year and regulation ends after end of fishing season + !is.na(MIN_END) & year(MIN_END) != YEAR ~ end, # Otherwise, use end if year is not the same + TRUE ~ MIN_END), + BAG_END = case_when(!is.na(BAG_END) & year(BAG_END) == YEAR & month(BAG_END) >= month(start) & month(BAG_END) < month(end) ~ BAG_END, # Keep BAG_END if same year and regulation end is prior to end of fishing season + !is.na(BAG_END) & year(BAG_END) != YEAR & month(BAG_END) >= month(start)& month(BAG_END) > month(end) ~ end, # Keep end if same year and regulation end is after end of fishing season + !is.na(BAG_END) & year(BAG_END) != YEAR ~ end, + TRUE ~ BAG_END), + # If FMP_START_date exists, use that. Otherwise, use start + start = case_when(!is.na(FMP_START_date) ~ FMP_START_date, + TRUE ~ as.Date(start))) + + +# Create final recreational table #### +# Indicate column order, adjust column labels, and date formats +mh_recreational_table <- mh_recreational_closure %>% + select(YEAR, VALUE_CLOSURE, ndays, start, end, ACL, ACL_UNIT, ACL_FR, MIN_SIZE, MIN_START, MIN_END, MIN_FR, + BAG_LIMIT, BAG_START, BAG_END, BAG_FR) %>% + arrange(YEAR, start, MIN_START, BAG_START) %>% + mutate(YEAR = as.character(YEAR), + MIN_START = case_when(!is.na(MIN_START) ~ format(MIN_START, "%e-%b"), + TRUE ~ NA_character_), + MIN_END = case_when(!is.na(MIN_END) ~ format(MIN_END, "%e-%b"), + TRUE ~ NA_character_), + BAG_START = case_when(!is.na(BAG_START) ~ format(BAG_START, "%e-%b"), + TRUE ~ NA_character_), + BAG_END = case_when(!is.na(BAG_END) ~ format(BAG_END, "%e-%b"), + TRUE ~ NA_character_), + start = case_when(!is.na(start) ~ format(start, "%e-%b"), + TRUE ~ NA_character_), + end = case_when(!is.na(end) ~ format(end, "%e-%b"), + TRUE ~ NA_character_), + # Retain values when fishery is open + ACL = case_when(VALUE_CLOSURE == "Open" ~ ACL, + TRUE ~ NA_character_), + ACL_UNIT = case_when(VALUE_CLOSURE == "Open" ~ ACL_UNIT, + TRUE ~ NA_character_), + ACL_FR = case_when(VALUE_CLOSURE == "Open" ~ ACL_FR, + TRUE ~ NA_character_), + MIN_SIZE = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_SIZE, + TRUE ~ NA_character_), + MIN_START = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_START, + TRUE ~ NA_character_), + MIN_END = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_END, + TRUE ~ NA_character_), + MIN_FR = case_when(VALUE_CLOSURE == "Open" & MIN_START >= start & MIN_START <= end ~ MIN_FR, + TRUE ~ NA_character_), + BAG_LIMIT = case_when(VALUE_CLOSURE == "Open" & BAG_START >= start & BAG_START <= end ~ BAG_LIMIT, + TRUE ~ NA_character_), + BAG_START = case_when(VALUE_CLOSURE == "Open" & BAG_START >= start & BAG_START <= end ~ BAG_START, + TRUE ~ NA_character_), + BAG_END = case_when(VALUE_CLOSURE == "Open" & BAG_START >= start & BAG_START <= end ~ BAG_END, + TRUE ~ NA_character_), + BAG_FR = case_when(VALUE_CLOSURE == "Open" & BAG_START >= start & BAG_START <= end ~ BAG_FR, + TRUE ~ NA_character_)) %>% + rename("Year" = YEAR, + "ACL Unit" = ACL_UNIT, + "ACL FR Citation" = ACL_FR, + "Number of Days" = ndays, + "Fishing Season" = VALUE_CLOSURE, + "Season Start Date (first day implemented)" = start, + "Season End Date (last day effective)" = end, + "Minimum Size Limit (inches TL)" = MIN_SIZE, + "Minimum Size Limit Start Date" = MIN_START, + "Minimum Size Limit End Date" = MIN_END, + "Minimum Size Limit FR Citation" = MIN_FR, + "Retention (Bag) Limit (# fish)" = BAG_LIMIT, + "Retention Limit Start Date" = BAG_START, + "Retention Limit End Date" = BAG_END, + "Retention Limit FR Citation" = BAG_FR) + +#### Add commercial and recreational tables to Excel file #### +# Create workbook +wb <- createWorkbook() +region_label <- "Gulf" + +# Add worksheets for each table +addWorksheet(wb, "Commercial") +addWorksheet(wb, "Recreational") + +# Add the data frames to their respective sheets +writeData(wb, "Commercial", mh_commercial_table) +writeData(wb, "Recreational", mh_recreational_table) + +# Save workbook as Excel +saveWorkbook(wb, here("ODM-MH-Analysis_ready", "Management History Comparison Files", "ManagementHistory_outputs", paste0("Management History_DataAnalyst", spp, "_", region_label, format(Sys.Date(), "%d%b%Y"),".xlsx")), + overwrite = TRUE) + +# Part 2. Management History Report Tables #### +#### TRIP LIMIT #### +trip_tab <- mh %>% + filter(COMMON_NAME_USE == spp, REGION == region, MANAGEMENT_TYPE_USE == 'TRIP LIMIT', NEVER_IMPLEMENTED == 0, REG_REMOVED == 0) %>% + arrange(FR_CITATION) %>% + ungroup() %>% + mutate(START_DATE = format(START_DATE2, "%m/%d/%Y"), + END_DATE = format(END_DATE2, "%m/%d/%Y"), + SECTOR = str_to_title(paste0(SECTOR_USE, " ", "-", " ", SUBSECTOR_USE)), + ZONE = str_to_title(paste0(REGION, " ", "-", " ", ZONE_USE)), + VALUE = paste0(VALUE, " ", tolower(VALUE_UNITS), " ", tolower(VALUE_TYPE), " ", tolower(VALUE_RATE)), + ACTION = case_when(is.na(AMENDMENT_NUMBER) & !is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE)), + is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION)), + !is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", AMENDMENT_NUMBER)), + !is.na(AMENDMENT_NUMBER) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE, " ", AMENDMENT_NUMBER))), + START_YEAR = format(START_DATE2, "%Y"), + COMMON_NAME_USE = str_to_title(paste0(COMMON_NAME_USE)), + MANAGEMENT_TYPE_USE = str_to_title(paste0(MANAGEMENT_TYPE_USE)), + Flag = case_when(FLAG == "YES" ~ "Yes", + FLAG == "NO" ~ "No", + TRUE ~ NA_character_)) + +trip_tab_export <- trip_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, VALUE, ZONE, + FR_CITATION, ACTION, FR_URL, Flag) %>% + rename(`Species Affected` = COMMON_NAME_USE, + `First Year in Effect`= START_YEAR, + `Effective Date`= START_DATE, + `End Date` = END_DATE, + Fishery = SECTOR, + `Trip Limit`= VALUE, + `Region Affected`= ZONE, + `FR Reference(s)`= FR_CITATION, + `Amendment Number or Rule Type` = ACTION, + `Flag` = Flag, + `FR URL` = FR_URL) %>% + arrange(Fishery, `First Year in Effect`) + + +trip_tab2 <- trip_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, VALUE, ZONE, + FR_CITATION, ACTION, FR_URL, Flag) %>% + do(tab = flextable(.) %>% + set_header_labels(MANAGEMENT_TYPE_USE = "Management Type", + COMMON_NAME_USE = "Species Affected", + START_YEAR = "First Year in Effect", + START_DATE = "Effective Date", + END_DATE = "End Date", + SECTOR = "Fishery", + VALUE = "Trip Limit", + ZONE = "Region Affected", + FR_CITATION = "FR Reference(s)", + ACTION = "Amendment Number or Rule Type", + Flag = "Flag", + FR_URL = "FR URL") %>% + merge_v(j = 1, part = "body") %>% + merge_v(j = 2, part = "body") %>% + merge_v(j = 3, part = "body") %>% + merge_v(j = 4, part = "body") %>% + theme_box() %>% + hline_top(part = "header", border = fp_border(color = "black", width = 2)) %>% + hline_bottom(part = "header", border = fp_border(color = "black", width = 2)) %>% + fontsize(part = "all", size = 12) %>% + font(part = "all", fontname = "Times New Roman") %>% + align(part = "all", align = "center")) + +#### BAG LIMIT #### +bag_tab <- mh %>% + filter(COMMON_NAME_USE == spp, REGION == region, MANAGEMENT_TYPE_USE == 'BAG LIMIT', NEVER_IMPLEMENTED == 0, REG_REMOVED == 0) %>% + arrange(FR_CITATION) %>% + ungroup() %>% + mutate(START_DATE = format(START_DATE2, "%m/%d/%Y"), + END_DATE = format(END_DATE2, "%m/%d/%Y"), + SECTOR = str_to_title(paste0(SECTOR_USE, " ", "-", " ", SUBSECTOR_USE)), + ZONE = str_to_title(paste0(REGION, " ", "-", " ", ZONE_USE)), + VALUE = paste0(VALUE, " ", tolower(VALUE_RATE)), + ACTION = case_when(is.na(AMENDMENT_NUMBER) & !is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE)), + is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION)), + !is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", AMENDMENT_NUMBER)), + !is.na(AMENDMENT_NUMBER) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE, " ", AMENDMENT_NUMBER))), + START_YEAR = format(START_DATE2, "%Y"), + COMMON_NAME_USE = str_to_title(paste0(COMMON_NAME_USE)), + MANAGEMENT_TYPE_USE = str_to_title(paste0(MANAGEMENT_TYPE_USE)), + Flag = case_when(FLAG == "YES" ~ "Yes", + FLAG == "NO" ~ "No", + TRUE ~ NA_character_)) + +bag_tab_export <- bag_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, VALUE, ZONE, + FR_CITATION, ACTION, FR_URL, Flag) %>% + rename(`Species Affected` = COMMON_NAME_USE, + `First Year in Effect`= START_YEAR, + `Effective Date`= START_DATE, + `End Date` = END_DATE, + Fishery = SECTOR, + `Bag Limit`= VALUE, + `Region Affected`= ZONE, + `FR Reference(s)`= FR_CITATION, + `Amendment Number or Rule Type` = ACTION, + `Flag` = Flag, + `FR URL` = FR_URL) %>% + arrange(Fishery, `First Year in Effect`) + + +bag_tab2 <- bag_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, VALUE, ZONE, + FR_CITATION, ACTION, FR_URL, Flag) %>% + do(tab = flextable(.) %>% + set_header_labels(MANAGEMENT_TYPE_USE = "Management Type", + COMMON_NAME_USE = "Species Affected", + START_YEAR = "First Year in Effect", + START_DATE = "Effective Date", + END_DATE = "End Date", + SECTOR = "Fishery", + VALUE = "Bag Limit", + ZONE = "Region Affected", + FR_CITATION = "FR Reference(s)", + ACTION = "Amendment Number or Rule Type", + Flag = "Flag", + FR_URL = "FR URL") %>% + merge_v(j = 1, part = "body") %>% + merge_v(j = 2, part = "body") %>% + merge_v(j = 3, part = "body") %>% + merge_v(j = 4, part = "body") %>% + theme_box() %>% + hline_top(part = "header", border = fp_border(color = "black", width = 2)) %>% + hline_bottom(part = "header", border = fp_border(color = "black", width = 2)) %>% + fontsize(part = "all", size = 12) %>% + font(part = "all", fontname = "Times New Roman") %>% + align(part = "all", align = "center")) + +#### MAXIMUM/MINIMUM SIZE LIMIT #### +size_tab <- mh %>% + filter(COMMON_NAME_USE == spp, REGION == region, MANAGEMENT_CATEGORY == 'SELECTIVITY CONTROLS', NEVER_IMPLEMENTED == 0, REG_REMOVED == 0) %>% + ungroup() %>% + mutate(START_DATE = format(START_DATE2, "%m/%d/%Y"), + END_DATE = format(END_DATE2, "%m/%d/%Y"), + SECTOR = str_to_title(paste0(SECTOR_USE, " ", "-", " ", SUBSECTOR_USE)), + ZONE = str_to_title(paste0(REGION, " ", "-", " ", ZONE_USE)), + VALUE = paste0(VALUE, " ", tolower(VALUE_UNITS), " ", tolower(VALUE_TYPE)), + ACTION = case_when(is.na(AMENDMENT_NUMBER) & !is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE)), + is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION)), + !is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", AMENDMENT_NUMBER)), + !is.na(AMENDMENT_NUMBER) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE, " ", AMENDMENT_NUMBER))), + START_YEAR = format(START_DATE2, "%Y"), + VALUE_TYPE = case_when(MANAGEMENT_TYPE_USE == 'MINIMUM SIZE LIMIT' ~ paste0("Minimum ", str_to_title(VALUE_TYPE)), + MANAGEMENT_TYPE_USE == 'MAXIMUM SIZE LIMIT' ~ paste0("Maximum ", str_to_title(VALUE_TYPE))), + COMMON_NAME_USE = str_to_title(paste0(COMMON_NAME_USE)), + MANAGEMENT_TYPE_USE = str_to_title(paste0(MANAGEMENT_TYPE_USE)), + Flag = case_when(FLAG == "YES" ~ "Yes", + FLAG == "NO" ~ "No", + TRUE ~ NA_character_)) + +size_tab_export <- size_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, VALUE, ZONE, FR_CITATION, ACTION, FR_URL, Flag) %>% + arrange(SECTOR, START_YEAR) %>% + rename(`Species Affected`= COMMON_NAME_USE, + `First Year in Effect` = START_YEAR, + `Effective Date` = START_DATE, + `End Date` = END_DATE, + Fishery = SECTOR, + `Size Limit` = VALUE, + `Region Affected` = ZONE, + `FR Reference(s)` = FR_CITATION, + `Amendment Number or Rule Type` = ACTION, + Flag = Flag, + `FR URL` = FR_URL) %>% + arrange(Fishery, `First Year in Effect`) + +size_tab2 <- size_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, VALUE, ZONE, FR_CITATION, ACTION, FR_URL, Flag) %>% + arrange(SECTOR, START_YEAR) %>% + do(tab = flextable(.) %>% + set_header_labels(MANAGEMENT_TYPE_USE = "Management Type", + COMMON_NAME_USE = "Species Affected", + START_YEAR = "Start Year", + START_DATE = "Effective Date", + END_DATE = "End Date", + SECTOR = "Fishery", + VALUE = "Size Limit", + ZONE = "Region Affected", + FR_CITATION = "FR Reference(s)", + ACTION = "Amendment Number or Rule Type", + Flag = "Flag", + FR_URL = "FR URL") %>% + merge_v(j = 1, part = "body") %>% + merge_v(j = 2, part = "body") %>% + merge_v(j = 3, part = "body") %>% + merge_v(j = 4, part = "body") %>% + theme_box() %>% + hline_top(part = "header", border = fp_border(color = "black", width = 2)) %>% + hline_bottom(part = "header", border = fp_border(color = "black", width = 2)) %>% + fontsize(part = "all", size = 12) %>% + font(part = "all", fontname = "Times New Roman") %>% + align(part = "all", align = "center")) + + +#### ACL #### +ACL_table <- mh %>% + filter(COMMON_NAME_USE == spp, REGION == region, MANAGEMENT_TYPE_USE == 'ACL') %>% + ungroup() %>% + mutate(START_DATE = format(START_DATE2, "%m/%d/%Y"), + END_DATE = format(END_DATE2, "%m/%d/%Y"), + SECTOR = str_to_title(paste0(SECTOR_USE, " ", "-", " ", SUBSECTOR_USE)), + ZONE = str_to_title(paste0(REGION, " ", "-", " ", ZONE_USE)), + VALUE = paste0(VALUE, " ", tolower(VALUE_UNITS), " ", tolower(VALUE_TYPE)), + ACTION = case_when(is.na(AMENDMENT_NUMBER) & !is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE)), + is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION)), + !is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", AMENDMENT_NUMBER)), + !is.na(AMENDMENT_NUMBER) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE, " ", AMENDMENT_NUMBER))), + START_YEAR = format(START_DATE2, "%Y"), + COMMON_NAME_USE = str_to_title(paste0(COMMON_NAME_USE)), + MANAGEMENT_TYPE_USE = str_to_title(paste0(MANAGEMENT_TYPE_USE)), + Flag = case_when(FLAG == "YES" ~ "Yes", + FLAG == "NO" ~ "No", + TRUE ~ NA_character_)) + +ACL_table_export <- ACL_table %>% + select(COMMON_NAME_USE, START_YEAR, SECTOR, VALUE, ZONE, FR_CITATION, FR_URL, ACTION, Flag) %>% + distinct() %>% + arrange(SECTOR, START_YEAR) %>% + rename(`Species Affected` = COMMON_NAME_USE, + `First Year in Effect` = START_YEAR, + Fishery = SECTOR, + `ACL` = VALUE, + `Region Affected`= ZONE, + `FR Reference(s)`= FR_CITATION, + `Amendment Number or Rule Type` = ACTION, + `Flag` = Flag, + `FR URL` = FR_URL) + +ACL_table1 <- ACL_table %>% + select(COMMON_NAME_USE, START_YEAR, SECTOR, VALUE, ZONE, FR_CITATION, FR_URL, ACTION, Flag) %>% + distinct() %>% + arrange(SECTOR, START_YEAR) %>% + do(tab = flextable(.) %>% + set_header_labels(COMMON_NAME_USE = "Species Affected", + START_YEAR = "First YEar in Effect", + START_DATE = "Effective Date", + END_DATE = "End Date", + SECTOR = "Fishery", + VALUE = "ACL", + ZONE = "Region Affected", + FR_CITATION = "FR Reference(s)", + ACTION = "Amendment Number or Rule Type", + Flag = "Flag", + FR_URL = "FR URL") %>% + merge_v(j = 1, part = "body") %>% + merge_v(j = 2, part = "body") %>% + merge_v(j = 3, part = "body") %>% + merge_v(j = 4, part = "body") %>% + merge_v(j = 5, part = "body") %>% + merge_v(j = 6, part = "body") %>% + theme_box() %>% + hline_top(part = "header", border = fp_border(color = "black", width = 2)) %>% + hline_bottom(part = "header", border = fp_border(color = "black", width = 2)) %>% + fontsize(part = "all", size = 12) %>% + font(part = "all", fontname = "Times New Roman") %>% + align(part = "all", align = "center")) + + +# TEMPORAL CLOSURE #### +clos_tab <- mh %>% + filter(COMMON_NAME_USE == spp, REGION == region, MANAGEMENT_TYPE_USE == 'CLOSURE', NEVER_IMPLEMENTED == 0, REG_REMOVED == 0, ZONE_USE == "ALL") %>% + group_by(VALUE, ZONE_USE) %>% + ungroup() %>% + mutate(START_DATE = format(START_DATE2, "%m/%d/%Y"), + END_DATE = format(END_DATE2, "%m/%d/%Y"), + SECTOR = str_to_title(paste0(SECTOR_USE, " ", "-", " ", SUBSECTOR_USE)), + ZONE = str_to_title(paste0(REGION, " ", "-", " ", ZONE_USE)), + VALUE = paste0(str_to_title(VALUE)), + ACTION = case_when(is.na(AMENDMENT_NUMBER) & !is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE)), + is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION)), + !is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", AMENDMENT_NUMBER)), + !is.na(AMENDMENT_NUMBER) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE, " ", AMENDMENT_NUMBER))), + START_YEAR = format(START_DATE2, "%Y"), + COMMON_NAME_USE = str_to_title(paste0(COMMON_NAME_USE)), + MANAGEMENT_TYPE_USE = str_to_title(paste0(MANAGEMENT_TYPE_USE)), + MANAGEMENT_STATUS_USE = str_to_sentence(paste0(MANAGEMENT_STATUS_USE)), + Flag = case_when(FLAG == "YES" ~ "Yes", + FLAG == "NO" ~ "No", + TRUE ~ NA_character_), + FIRST_DAY = paste0(START_MONTH, "-", START_DAY_USE), + LAST_DAY = paste0(END_MONTH_USE, "-", END_DAY_USE)) + +clos_tab_export <- clos_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, START_TIME_USE, FIRST_DAY, LAST_DAY, END_TIME_USE, SECTOR, VALUE, MANAGEMENT_STATUS_USE, ZONE, FR_CITATION, ACTION, FR_URL, Flag) %>% + distinct() %>% + arrange(SECTOR, ZONE, START_YEAR, START_DATE) %>% + rename(`Species Affected` = COMMON_NAME_USE, + `First Year in Effect` = START_YEAR, + `Effective Date` = START_DATE, + `End Date` = END_DATE, + `Start Time` = START_TIME_USE, + `First Day Closed` = FIRST_DAY, + `Last Day Closed` = LAST_DAY, + `END_TIME` = END_TIME_USE, + Fishery = SECTOR, + Status = VALUE, + `Closure Type` = MANAGEMENT_STATUS_USE, + `Region Affected` = ZONE, + `FR Reference(s)` = FR_CITATION, + `Amendment Number or Rule Type` = ACTION, + Flag = Flag, + `FR URL` = FR_URL) + +clos_tab1 <- clos_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, START_TIME_USE, FIRST_DAY, LAST_DAY, END_TIME_USE, SECTOR, VALUE, MANAGEMENT_STATUS_USE, ZONE, FR_CITATION, ACTION, FR_URL, Flag) %>% + distinct() %>% + arrange(SECTOR, ZONE, START_DATE) %>% + do(tab = flextable(.) %>% + set_header_labels(COMMON_NAME_USE = "Species Affected", + START_YEAR = "First Year in Effect", + START_DATE = "Effective Date", + END_DATE = "End Date", + START_TIME_USE = "Start Time", + FIRST_DAY = "First Day Closed", + LAST_DAY = "Last Day Closed", + END_TIME_USE = "End Time", + SECTOR = "Fishery", + VALUE = "Status", + MANAGEMENT_STATUS_USE = "Closure Type", + ZONE = "Region Affected", + FR_CITATION = "FR Reference(s)", + ACTION = "Amendment Number or Rule Type", + Flag = "Flag", + FR_URL = "FR URL") %>% + merge_v(j = 1, part = "body") %>% + merge_v(j = 2, part = "body") %>% + merge_v(j = 3, part = "body") %>% + merge_v(j = 4, part = "body") %>% + merge_v(j = 5, part = "body") %>% + merge_v(j = 6, part = "body") %>% + theme_box() %>% + hline_top(part = "header", border = fp_border(color = "black", width = 2)) %>% + hline_bottom(part = "header", border = fp_border(color = "black", width = 2)) %>% + fontsize(part = "all", size = 12) %>% + font(part = "all", fontname = "Times New Roman") %>% + align(part = "all", align = "center")) + +# SPATIAL CLOSURE #### +spatclos_tab <- mh %>% + filter(COMMON_NAME_USE %in% c("Caribbean Spiny Lobster", 'All'), REGION == region, MANAGEMENT_TYPE_USE == 'CLOSURE', NEVER_IMPLEMENTED == 0, REG_REMOVED == 0, + ZONE %in% c("PUERTO RICO MANAGEMENT AREA", "BAJO DE SICO REEF FISH FISHERY MANAGEMENT AREA", "TOURMALINE BANK RED HIND SPAWNING AGGREGATION AREA", "ABRIR LA SIERRA BANK RED HIND SPAWNING AGGREGATION AREA"), + SUBSECTOR_USE != "ALL") %>% + group_by(VALUE, ZONE) %>% + ungroup() %>% + mutate(START_DATE = format(START_DATE2, "%m/%d/%Y"), + END_DATE = format(END_DATE2, "%m/%d/%Y"), + SECTOR_USE = str_to_title(paste0(SECTOR_USE)), + SUBSECTOR_USE = str_to_title(paste0(SUBSECTOR_USE)), + ZONE_USE = str_to_title(paste0(ZONE)), + VALUE = paste0(VALUE, " ", tolower(VALUE_UNITS)), + ACTION = case_when(is.na(AMENDMENT_NUMBER) & !is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE)), + is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION)), + !is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", AMENDMENT_NUMBER)), + !is.na(AMENDMENT_NUMBER) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE, " ", AMENDMENT_NUMBER))), + START_YEAR = format(START_DATE2, "%Y"), + COMMON_NAME_USE = str_to_title(paste0(COMMON_NAME_USE)), + MANAGEMENT_TYPE_USE = str_to_title(paste0(MANAGEMENT_TYPE_USE)), + Flag = case_when(FLAG == "YES" ~ "Yes", + FLAG == "NO" ~ "No", + TRUE ~ NA_character_), + FIRST_DAY = paste0(START_MONTH, "-", START_DAY_USE), + LAST_DAY = paste0(END_MONTH_USE, "-", END_DAY_USE), + END_DATE = case_when(END_DATE == "12/31/2025" ~ "Ongoing", + TRUE ~ END_DATE), + LAST_DAY = case_when(LAST_DAY == "NA-NA" ~ "12-31", + TRUE ~ LAST_DAY), + FIRST_DAY = case_when(FIRST_DAY == "10-13" ~ "1-1", + TRUE ~ FIRST_DAY)) %>% + filter(!(FR_CITATION == "75 FR 27217")) + +spatclos_tab_export <- spatclos_tab %>% + select(COMMON_NAME_USE, ZONE_USE,START_YEAR, START_DATE, END_DATE, SECTOR_USE, FIRST_DAY, LAST_DAY, SUBSECTOR_USE, FR_CITATION, ACTION, FR_URL, Flag) %>% + distinct() %>% + arrange(SECTOR_USE, ZONE_USE, SUBSECTOR_USE, START_YEAR) %>% + rename(`Species Affected` = COMMON_NAME_USE, + `Area` = ZONE_USE, + `First Year in Effect` = START_YEAR, + `Effective Date` = START_DATE, + `End Date` = END_DATE, + `Fishery` = SECTOR_USE, + `First Day Closed` = FIRST_DAY, + `Last Day Closed` = LAST_DAY, + `Fishing Restriction in Area` = SUBSECTOR_USE, + `FR Reference(s)` = FR_CITATION, + `Amendment Number or Rule Type` = ACTION, + Flag = Flag, + `FR URL` = FR_URL) + +library(flextable) + +ft <- flextable(spatclos_tab_export) %>% + theme_booktabs() %>% + autofit() + +save_as_image(ft, path = "spatial_closure_table.png") + +spatclos_tab1 <- spatclos_tab %>% + select(COMMON_NAME_USE, ZONE_USE,START_YEAR, START_DATE, END_DATE, SECTOR_USE, FIRST_DAY, LAST_DAY, SUBSECTOR_USE, FR_CITATION, ACTION, FR_URL, Flag) %>% + distinct() %>% + arrange(SECTOR_USE, SUBSECTOR_USE, ZONE_USE, START_DATE) %>% + do(tab = flextable(.) %>% + set_header_labels(COMMON_NAME_USE = "Species Affected", + ZONE_USE = "Area", + START_YEAR = "First Year in Effect", + START_DATE = "Effective Date", + END_DATE = "End Date", + SECTOR_USE = "Fishery", + FIRST_DAY = "First Day Closed", + LAST_DAY = "Last Day Closed", + SUBSECTOR_USE = "Fishing Restriction in Area", + FR_CITATION = "FR Reference(s)", + ACTION = "Amendment Number or Rule Type", + Flag = "Flag", + FR_URL = "FR URL") %>% + merge_v(j = 1, part = "body") %>% + merge_v(j = 2, part = "body") %>% + merge_v(j = 3, part = "body") %>% + merge_v(j = 4, part = "body") %>% + merge_v(j = 5, part = "body") %>% + merge_v(j = 6, part = "body") %>% + theme_box() %>% + hline_top(part = "header", border = fp_border(color = "black", width = 2)) %>% + hline_bottom(part = "header", border = fp_border(color = "black", width = 2)) %>% + fontsize(part = "all", size = 12) %>% + font(part = "all", fontname = "Times New Roman") %>% + align(part = "all", align = "center")) + +#### GEAR REQUIREMENTS #### +gear_tab <- mh %>% + filter(COMMON_NAME_USE == spp, REGION == region, + MANAGEMENT_TYPE_USE %in% c('ANCHORING RESTRICTION', 'BRD REQUIREMENT', 'DEHOOKING DEVICE', 'DESCENDING DEVICE', + 'GILLNET SPECIFICATIONS', 'GOLDEN CRAB TRAP SPECIFICATIONS', 'HARVEST METHOD', 'HOOK SIZE/TYPE/#', + 'MAXIMUM GEAR', 'NON-OFFSET, NON-STAINLESS STEEL CIRCLE HOOKS', 'NON-STAINLESS STEEL CIRCLE HOOKS', + 'NON-STAINLESS STEEL HOOKS', 'PERMITTED AND AUTHORIZED GEAR', 'PROHIBITED GEAR', 'SEA BASS POT/TRAP SPECIFICATIONS', + 'TRAP SPECIFICATIONS', 'TRAWL SPECIFICATIONS', 'TURTLE RELEASE GEAR', 'VENTING TOOL'), + NEVER_IMPLEMENTED == 0, REG_REMOVED == 0, + ZONE_USE %in% c('ALL', 'PUERTO RICO MANAGEMENT AREA')) %>% + ungroup() %>% + mutate(START_DATE = format(START_DATE2, "%m/%d/%Y"), + END_DATE = format(END_DATE2, "%m/%d/%Y"), + SECTOR = str_to_title(paste0(SECTOR_USE, " ", "-", " ", SUBSECTOR_USE)), + ZONE = str_to_title(paste0(REGION, " ", "-", " ", ZONE_USE)), + ACTION = case_when(is.na(AMENDMENT_NUMBER) & !is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE)), + is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION)), + !is.na(AMENDMENT_NUMBER) & is.na(ACTION_TYPE) ~ str_to_title(paste0(ACTION, " ", AMENDMENT_NUMBER)), + !is.na(AMENDMENT_NUMBER) ~ str_to_title(paste0(ACTION, " ", ACTION_TYPE, " ", AMENDMENT_NUMBER))), + START_YEAR = format(START_DATE2, "%Y"), + COMMON_NAME_USE = str_to_title(paste0(COMMON_NAME_USE)), + MANAGEMENT_TYPE_USE = str_to_title(paste0(MANAGEMENT_TYPE_USE)), + Flag = case_when(FLAG == "YES" ~ "Yes", + FLAG == "NO" ~ "No", + TRUE ~ NA_character_), + END_DATE = case_when(FR_CITATION == "49 FR 50049" ~ "10/12/2022", + FR_CITATION == "70 FR 62073" ~ "10/12/2022", + END_DATE == "12/31/2025" ~ "Ongoing", + TRUE ~ END_DATE)) + +gear_tab_export <- gear_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, MANAGEMENT_TYPE_USE, ZONE, FR_CITATION, ACTION, FR_URL, Flag) %>% + arrange(ZONE, START_YEAR, SECTOR) %>% + rename(`Species Affected`= COMMON_NAME_USE, + `First Year in Effect` = START_YEAR, + `Effective Date` = START_DATE, + `End Date` = END_DATE, + Gear = SECTOR, + `Regulation Type` = MANAGEMENT_TYPE_USE, + `Region Affected` = ZONE, + `FR Reference(s)` = FR_CITATION, + `Amendment Number or Rule Type` = ACTION, + Flag = Flag, + `FR URL` = FR_URL) + +library(flextable) + +ft <- flextable(gear_tab_export) %>% + theme_booktabs() %>% + autofit() + +save_as_image(ft, path = "gear_regulations_table.png") + +gear_tab1 <- gear_tab %>% + select(COMMON_NAME_USE, START_YEAR, START_DATE, END_DATE, SECTOR, MANAGEMENT_TYPE_USE, ZONE, FR_CITATION, ACTION, FR_URL, Flag) %>% + arrange(ZONE, SECTOR, START_YEAR) %>% + do(tab = flextable(.) %>% + set_header_labels(COMMON_NAME_USE = "Species Affected", + START_YEAR = "First Year in Effect", + START_DATE = "Effective Date", + END_DATE = "End Date", + SECTOR = "Gear", + MANAGEMENT_TYPE_USE = "Regulation Type", + ZONE = "Region Affected", + FR_CITATION = "FR Reference(s)", + ACTION = "Amendment Number or Rule Type", + Flag = "Flag", + FR_URL = "FR URL") %>% + merge_v(j = 1, part = "body") %>% + merge_v(j = 2, part = "body") %>% + merge_v(j = 3, part = "body") %>% + merge_v(j = 4, part = "body") %>% + theme_box() %>% + hline_top(part = "header", border = fp_border(color = "black", width = 2)) %>% + hline_bottom(part = "header", border = fp_border(color = "black", width = 2)) %>% + fontsize(part = "all", size = 12) %>% + font(part = "all", fontname = "Times New Roman") %>% + align(part = "all", align = "center")) + + +# Export each table as sheet in Excel workbook +wb <- createWorkbook() +addWorksheet(wb, "Trip Limit") +addWorksheet(wb, "Bag Limit") +addWorksheet(wb, "Size Limit") +addWorksheet(wb, "ACL") +addWorksheet(wb, "Closure") +addWorksheet(wb, "Spatial Restrictions") +addWorksheet(wb, "Gear Restrictions") + +writeData(wb, "Trip Limit", trip_tab_export) +writeData(wb, "Bag Limit", bag_tab_export) +writeData(wb, "Size Limit", size_tab_export) +writeData(wb, "ACL", ACL_table_export) +writeData(wb, "Closure", clos_tab_export) +writeData(wb, "Spatial Restrictions", spatclos_tab_export) +writeData(wb, "Gear Restrictions", gear_tab_export) + +saveWorkbook(wb, here("ODM-MH-Analysis_ready", "Management History Comparison Files", "ManagementHistory_outputs", paste0("Management History_Report_", spp, "_", region, format(Sys.Date(), "%d%b%Y"),".xlsx")), +overwrite = TRUE) + +# Export each table into a Word Document +doc_path <- here("ODM-MH-Analysis_ready", "Management History Comparison Files", "ManagementHistory_outputs", paste0("ManagementHistory_Report_", str_replace_all(spp, "[^A-Za-z0-9]+", "_"), + "_", str_replace_all(region, "[^A-Za-z0-9]+", "_"), "_", + format(Sys.Date(), "%d%b%Y"), ".docx")) + +doc <- read_docx() + +add_section <- function(doc, title_text, ft_obj) { + doc %>% + body_add_par(value = title_text, style = "heading 1") %>% + body_add_par(value = "", style = "Normal") %>% + body_add_flextable(ft_obj) %>% + body_add_par(value = "", style = "Normal") %>% + body_add_break() +} + +doc <- add_section(doc, "Trip Limit", trip_tab2$tab[[1]]) +doc <- add_section(doc, "Size Limit", size_tab2$tab[[1]]) +doc <- add_section(doc, "ACL", ACL_table1$tab[[1]]) +doc <- add_section(doc, "Closure", clos_tab1$tab[[1]]) +doc <- add_section(doc, "Gear Requirements", gear_tab1$tab[[1]]) + +doc <- body_remove(doc) + +print(doc, target = doc_path) + diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystBlueline Tilefish_Gulf18Feb2026.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystBlueline Tilefish_Gulf18Feb2026.xlsx new file mode 100644 index 0000000..a32a4aa Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystBlueline Tilefish_Gulf18Feb2026.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystCobia_ATLANTIC12Jan2026.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystCobia_ATLANTIC12Jan2026.xlsx new file mode 100644 index 0000000..8d5522e Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystCobia_ATLANTIC12Jan2026.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystCobia_Gulf16Jan2026.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystCobia_Gulf16Jan2026.xlsx new file mode 100644 index 0000000..301e9d6 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystCobia_Gulf16Jan2026.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystGag Grouper_Gulf17Feb2026.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystGag Grouper_Gulf17Feb2026.xlsx new file mode 100644 index 0000000..7c81706 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystGag Grouper_Gulf17Feb2026.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystGoldface Tilefish_Gulf18Feb2026.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystGoldface Tilefish_Gulf18Feb2026.xlsx new file mode 100644 index 0000000..26df562 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystGoldface Tilefish_Gulf18Feb2026.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystRed Snapper_SOUTH ATLANTIC24Sep2025.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystRed Snapper_SOUTH ATLANTIC24Sep2025.xlsx new file mode 100644 index 0000000..ac1c8f4 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_DataAnalystRed Snapper_SOUTH ATLANTIC24Sep2025.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_Report_Caribbean Spiny Lobster_CARIBBEAN24Feb2026.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_Report_Caribbean Spiny Lobster_CARIBBEAN24Feb2026.xlsx new file mode 100644 index 0000000..2e90b1f Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_Report_Caribbean Spiny Lobster_CARIBBEAN24Feb2026.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_Report_Red Snapper_SOUTH ATLANTIC24Sep2025.xlsx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_Report_Red Snapper_SOUTH ATLANTIC24Sep2025.xlsx new file mode 100644 index 0000000..65b0064 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/Management History_Report_Red Snapper_SOUTH ATLANTIC24Sep2025.xlsx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/ManagementHistory_Report_Caribbean_Spiny_Lobster_CARIBBEAN_24Feb2026.docx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/ManagementHistory_Report_Caribbean_Spiny_Lobster_CARIBBEAN_24Feb2026.docx new file mode 100644 index 0000000..b16c7ff Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/ManagementHistory_Report_Caribbean_Spiny_Lobster_CARIBBEAN_24Feb2026.docx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/ManagementHistory_Report_Red_Snapper_SOUTH_ATLANTIC_24Sep2025.docx b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/ManagementHistory_Report_Red_Snapper_SOUTH_ATLANTIC_24Sep2025.docx new file mode 100644 index 0000000..90862a6 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/ManagementHistory_outputs/ManagementHistory_Report_Red_Snapper_SOUTH_ATLANTIC_24Sep2025.docx differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/NumberofFrs.jpeg b/ODM-MH-Analysis_ready/Management History Comparison Files/NumberofFrs.jpeg new file mode 100644 index 0000000..2004fa9 Binary files /dev/null and b/ODM-MH-Analysis_ready/Management History Comparison Files/NumberofFrs.jpeg differ diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_BagLimit.R b/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_BagLimit.R new file mode 100644 index 0000000..323fbef --- /dev/null +++ b/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_BagLimit.R @@ -0,0 +1,1025 @@ +############################# +# Recreational Bag Limits # +############################# + +librarian::shelf(here, tidyverse, lubridate, openxlsx, neatRanges, splitstackshape, dplyr) + +# Set output directory for plots +Dirout<-paste0(getwd(),"/Bag and crew limits/") +if(!file.exists(Dirout)) dir.create(Dirout) + +# MH dataset +mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Nov18.RDS")) + +# Set end year for plots +termyr<-2025 + +# Subset for Gulf Reef Fish recreational bag limits +mh_carib_pr_bag <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + #"FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + #"FMP FOR THE EEZ AROUND ST. CROIX", + "FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'RECREATIONAL', + MANAGEMENT_TYPE_USE == 'BAG LIMIT', + ZONE_USE %in% c("ALL", "PUERTO RICO MANAGEMENT AREA")) +mh_carib_pr_bag <- mh_carib_pr_bag %>% + mutate(END_DATE2 = case_when(FR_CITATION == "61 FR 32151" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82413" & SPP_NAME == "BAG LIMIT: OTHER REEF FISH SPECIES COMBINED" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: GROUPERS, SNAPPERS, AND PARROTFISHES COMBINED" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "2" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "6" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "5" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "15" ~ as.Date("2022-10-13"), + TRUE ~ END_DATE2)) %>% + filter(!(FR_CITATION == "87 FR 56204" & COMMON_NAME_USE == "LOBSTER, CARIBBEAN SPINY"))%>% + filter(!(FR_CITATION == "87 FR 56204" & COMMON_NAME_USE == "SURGEONFISH")) + + +# Confirm bag limits +unique(mh_carib_pr_bag$MANAGEMENT_TYPE_USE) + +# Confirm all recreational +table(mh_carib_pr_bag$SECTOR_USE) + +source(here("ODM-MH-Analysis_ready", "Closures", "func_expand_status.R")) + +############## +# Bag limits # +############## + + +bag_df_pr <- expand_status(mh_carib_pr_bag, "BAG LIMIT") + +# Collapse to annual value +bag_yr_df_pr <- bag_df_pr %>% + dplyr::mutate(YEAR = year(date_sequence)) %>% + dplyr::select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + distinct() + +# Explore Zone +table(bag_yr_df_pr$ZONE_USE) +# All (hogfish zone removed when excluding FR) + +# Explore Subsector +table(bag_yr_df_pr$SUBSECTOR_USE) +# All for all data + +# Explore year - only include complete years +table(bag_yr_df_pr$YEAR) +bag_yr_df_pr<-bag_yr_df_pr %>% filter(YEAR <=termyr) +table(bag_yr_df_pr$YEAR) + +parrotfish_species <- c( + "PARROTFISH, PRINCESS", + "PARROTFISH, QUEEN", + "PARROTFISH, REDBAND", + "PARROTFISH, REDTAIL", + "PARROTFISH, STOPLIGHT", + "PARROTFISH, STRIPED" +) + +years_add <- 2022:2025 +year_cast <- if(is.numeric(bag_yr_df_pr$YEAR)) as.numeric else as.character() + +# Use the Parrotfish 2 rows as a "template" for ZONE_USE / SUBSECTOR_USE. +# This is what typically creates "two rows" per species-year (two distinct combos). +template <- bag_yr_df_pr %>% + dplyr::filter(COMMON_NAME_USE == "PARROTFISH 2", YEAR %in% years_add) %>% + dplyr::distinct(ZONE_USE, SUBSECTOR_USE) + +# If template isn't exactly 2 rows, force it to be 2 (duplicate first row if needed) +template2 <- dplyr::bind_rows(template, template) %>% + dplyr::slice(1:2) + +rate_specs <- tibble::tibble( + VALUE = c("2", "6"), + VALUE_UNITS = c("NUMBERS", "NUMBERS"), + VALUE_TYPE = c("COUNT", "COUNT"), + VALUE_RATE = c("PER PERSON PER DAY", "PER VESSEL PER DAY") + ) + +add_rows <- tidyr::crossing( + COMMON_NAME_USE = parrotfish_species, + YEAR = year_cast(years_add), + template2, + rate_specs +) + +# Optionally REMOVE the original Parrotfish 2 records for those years +# (recommended if you're replacing them with the six species) +bag_yr_df_pr_aug <- bag_yr_df_pr %>% + dplyr::filter(!(COMMON_NAME_USE == "PARROTFISH 2" & YEAR %in% year_cast(years_add))) %>% + dplyr::bind_rows(add_rows) + + +bag_yr_df2_pr <- bag_yr_df_pr_aug %>% + dplyr::mutate( + VALUE_UNITS = dplyr::case_when( + VALUE_UNITS == "NUMBERS" ~ "fish", + VALUE_UNITS == "CONCH" ~ "conch", + VALUE_UNITS == "LOBSTER" ~ "lobster", + TRUE ~ VALUE_UNITS + ), + COMMON_NAME_USE = dplyr::case_when( + COMMON_NAME_USE == "Calamus pennatula" ~ "PORGY, PLUMA", + TRUE ~ COMMON_NAME_USE + ), + VAL_LAB = paste(VALUE, VALUE_UNITS, stringr::str_to_lower(VALUE_RATE)), + LAB = paste(stringr::str_to_title(sub("(.*)\\,\\s+(.*)", "\\2 \\1", COMMON_NAME_USE)), "-", VAL_LAB), + n = 1 + ) %>% + dplyr::select(LAB, YEAR, n) %>% + dplyr::arrange(YEAR) %>% + tidyr::pivot_wider(names_from = YEAR, values_from = n) %>% + dplyr::arrange(LAB) + + +# Format for plot - Don't use +bag_yr_df2_pr <- bag_yr_df_pr %>% + dplyr::mutate( + VALUE_UNITS = case_when(VALUE_UNITS == 'NUMBERS' ~ 'conch', + VALUE_UNITS == "CONCH" ~ 'conch', + TRUE ~ VALUE_UNITS), + COMMON_NAME_USE = case_when(COMMON_NAME_USE == "Calamus pennatula" ~ "PORGY, PLUMA", + TRUE ~ COMMON_NAME_USE), + VAL_LAB = paste(VALUE, VALUE_UNITS, str_to_lower(VALUE_RATE)), + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1', COMMON_NAME_USE)),"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE,"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE, "(Zone ", ZONE_USE, ")", VAL_LAB), + n = 1) %>% + dplyr::select(LAB, YEAR, n) %>% + arrange(YEAR) %>% + pivot_wider(names_from = YEAR, values_from = n) %>% + arrange(LAB) + +# Code below no longer needed if remove 82 FR 34574 (single bag limit for hogfish) + +# Checking on two FRs in 1 year that both set a bag limit of 5 fish: 64 FR 57403 82 FR 34574 +#chk <- filter(bag_df, COMMON_NAME_USE == 'HOGFISH', year(date_sequence) == 2017) +#table(chk$FR_CITATION) + +# Need to replace c(1,1) with 1 +#bag_yr_df2[bag_yr_df2$LAB=="HOGFISH - 5 fish Per Person Per Day",29]<-bag_yr_df2[bag_yr_df2$LAB=="HOGFISH - 5 fish Per Person Per Day",28] +#bag_yr_df2<-as.data.frame(bag_yr_df2) + +# Subset aggregate groups and then species limits; reorder by family/species (manually for now...) +bag_yr_df2_pr<-bag_yr_df2_pr[c(2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15, + 18, 17, 20, 19, 22, 21, 24, 23, 26, 25, 27, 29, 30, 28, + 32, 31, 34, 33, 36, 35, 38, 37, 39, 41, 42, 40, 44, 43, + 46, 45, 48, 47, 50, 49, 54, 53, 56, 55, 58, 57, 60, 59, + 62, 61, 64, 63, 66, 65, 68, 67, 70, 69, 72, 71, 74, 73, + ),] + +# Need to redefine aggregate limits +#bag_yr_df3$LAB[bag_yr_df3$LAB=="Golden Tilefish - 20 Fish Per Person Per Day"]<-"Gulf Reef Fish - 20 Fish Per Person Per Day" +#bag_yr_df3$LAB[bag_yr_df3$LAB=="Banded Rudderfish - 5 Fish Per Person Per Day"]<-"Banded Rudderfish and Lesser Amberjack - 5 Fish Per Person Per Day" +#bag_yr_df3$LAB[bag_yr_df3$LAB=="Queen Snapper - 10 Fish Per Person Per Day"]<-"Snapper - 10 Fish Per Person Per Day" +#bag_yr_df3$LAB[bag_yr_df3$LAB=="Snowy Grouper - 3 Fish Per Person Per Day"]<-"Grouper - 3 Fish Per Person Per Day" +#bag_yr_df3$LAB[bag_yr_df3$LAB=="Snowy Grouper - 4 Fish Per Person Per Day"]<-"Grouper - 4 Fish Per Person Per Day" +#bag_yr_df3$LAB[bag_yr_df3$LAB=="Snowy Grouper - 5 Fish Per Person Per Day"]<-"Grouper - 5 Fish Per Person Per Day" + +# Need to extend hogfish since we had to remove FR +#bag_yr_df3[bag_yr_df3$LAB=="Hogfish - 5 Fish Per Person Per Day",(which(colnames(bag_yr_df3)=="2018")):dim(bag_yr_df3)[2]]<-1 #2018+ + +# Save outputs before we clean up labels +#saveRDS(bag_yr_df3,paste0(Dirout,"recreational_bag_limits.rds")) + +# Remove species name in consecutive rows +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Almaco Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 5 fish per vessel per day")]<-"Groupers, Parrotfishes, and Snappers combined - 5 fish per vessel per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 5 fish per vessel per day")]<-"Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes, and Wrasses combined - 5 fish per vessel per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bar Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bigeye - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Durgon - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Grouper - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Snapper - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Blackbar Soldierfish - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Blackfin Snapper - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Blackline Tilefish - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Blue Runner - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Black Jack - 15 fish per person per day")]<-"- 15 fish per person per day" + +############### +# Crew limits # +############### + +crew_df <- expand_status(mh_grf, "CREW BAG LIMIT") + +# Collapse to annual value +crew_yr_df <- crew_df %>% + mutate(YEAR = year(date_sequence)) %>% + select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + distinct() + +# Explore Zone +table(crew_yr_df$ZONE_USE) +# All for all data + +# Explore Subsector +table(crew_yr_df$SUBSECTOR_USE) +# For-Hire + +# Explore year - only include complete years +table(crew_yr_df$YEAR) +crew_yr_df<-crew_yr_df %>% filter(YEAR <=termyr) +table(crew_yr_df$YEAR) + +# Format for plot +crew_yr_df2 <- crew_yr_df %>% + mutate(VALUE_UNITS = case_when(VALUE_UNITS == 'NUMBERS' ~ 'Fish', + TRUE ~ VALUE_UNITS), + VAL_LAB = paste(VALUE, VALUE_UNITS, str_to_title(VALUE_RATE)), + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)),"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE,"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE, "(Zone ", ZONE_USE, ")", VAL_LAB), + n = 1) %>% + dplyr::select(LAB, YEAR, n) %>% + arrange(YEAR) %>% + pivot_wider(names_from = YEAR, values_from = n) %>% + arrange(LAB) + +# Save outputs before we clean up labels +saveRDS(crew_yr_df2,paste0(Dirout,"recreational_crew_bag_limits.rds")) + +######### +# Plots # +######### + +library(raster) +#Note: importing this package masks select from dplyr... + +######################### +# Bag limits by species # +######################### + +bag<-raster(as.matrix(bag_yr_df2[,2:dim(bag_yr_df2)[2]])) +groups<-dplyr::select(bag_yr_df2, LAB) %>% pull() +names<-c(min(bag_yr_df$YEAR):max(bag_yr_df$YEAR)) + +# Note: Labels were too long, which ends up messing up the "square" shape of the plot; +# The longer the LABEL gets, the more white space there is above/below the actual data + +jpeg(paste0(Dirout,"Recreational_bag_limits_species.jpeg"),res=300,height=4.8,width=6.7, units="in") +par(mar=c(0.1, 9.5, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(bag,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(bag_yr_df2)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +axis(2,at=seq(((1/dim(bag_yr_df2)[1])/2),1,(1/dim(bag_yr_df2)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.2,font=1) +axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.5,las=2,hadj=0.7) +dev.off() + +bag2<-raster(as.matrix(bag_yr_df3[,2:dim(bag_yr_df3)[2]])) +groups<-dplyr::select(bag_yr_df3, LAB) %>% pull() +names<-c(min(bag_yr_df$YEAR):max(bag_yr_df$YEAR)) + +# Note: Labels were too long, which ends up messing up the "square" shape of the plot; +# The longer the LABEL gets, the more white space there is above/below the actual data + +######################################## +# Bag limits by aggregates and species # +######################################## + +jpeg(paste0(Dirout,"Recreational_bag_limits.jpeg"),res=300,height=3.6,width=6.7, units="in") +par(mar=c(0.1, 14.5, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(bag2,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(bag_yr_df3)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +axis(2,at=seq(((1/dim(bag_yr_df3)[1])/2),1,(1/dim(bag_yr_df3)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.5,font=1) +axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.5,las=2,hadj=0.7) +dev.off() + +########################## +# Crew limits by species # +########################## + +# Reorder by family/species (manually for now...) +crew_yr_df2<-crew_yr_df2[c(3,5,2,11,1,17,16,15,13,12,14,6,10,4,7:9),] + +crew<-raster(as.matrix(crew_yr_df2[,2:dim(crew_yr_df2)[2]])) +groups<-dplyr::select(crew_yr_df2, LAB) %>% pull() +names<-c(min(crew_yr_df$YEAR):max(crew_yr_df$YEAR)) + +# Note: Labels were too long, which ends up messing up the "square" shape of the plot; +# The longer the LABEL gets, the more white space there is above/below the actual data + +jpeg(paste0(Dirout,"Recreational_crew_limits.jpeg"),res=300,height=4.8,width=7, units="in") +par(mar=c(0.1, 11.5, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(crew,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(crew_yr_df2)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +axis(2,at=seq(((1/dim(crew_yr_df2)[1])/2),1,(1/dim(crew_yr_df2)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.5,font=1) +axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.6,las=2,hadj=0.7) +dev.off() + +######### +library(dplyr) +library(tidyr) +library(lubridate) +library(stringr) + +termyr <- 2025 + +bag_yr_df_pr <- mh_carib_pr_bag %>% + # keep only bag limit records you want + dplyr::filter( + NEVER_IMPLEMENTED == 0, + SECTOR_USE == "RECREATIONAL", + MANAGEMENT_TYPE_USE == "BAG LIMIT" + ) %>% + # ensure dates exist; if your fields are START_DATE2/END_DATE2 use those + dplyr::mutate( + start = as.Date(START_DATE2), + end = as.Date(dplyr::coalesce(END_DATE2, Sys.Date())) + ) %>% + dplyr::filter(!is.na(start), !is.na(end), end >= start) %>% + # (optional) if you only want complete years + dplyr::mutate( + start_year = year(start), + end_year = year(end) + ) %>% + # expand to years, NOT days + tidyr::uncount(end_year - start_year + 1, .id = "k") %>% + dplyr::mutate(YEAR = start_year + (k - 1L)) %>% + dplyr::filter(YEAR <= termyr) %>% + # keep SPP_NAME (and anything else you need) + dplyr::select(SPP_NAME, COMMON_NAME_USE, SUBSECTOR_USE, + YEAR, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + dplyr::distinct(SPP_NAME, SUBSECTOR_USE, YEAR, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) + +bag_yr_df2_pr <- bag_yr_df_pr %>% + dplyr::mutate( + VALUE_UNITS = case_when( + VALUE_UNITS == "NUMBERS" ~ "fish", + VALUE_UNITS == "CONCH" ~ "conch", + VALUE_UNITS == "LOBSTER" ~ "lobster", + TRUE ~ VALUE_UNITS + ), + VAL_LAB = paste(VALUE, VALUE_UNITS, str_to_lower(VALUE_RATE)), + # include SPP_NAME in label (optional but recommended if you want that instead of COMMON_NAME_USE) + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',SPP_NAME)),"-", VAL_LAB), + n = 1 + ) %>% + dplyr::select(LAB, YEAR, n) %>% + dplyr::distinct() %>% + tidyr::pivot_wider(names_from = YEAR, values_from = n) %>% + dplyr::arrange(LAB) + +bag_yr_df2_pr<-bag_yr_df2_pr[c(2, 1, 4, 3, 6, 5, 8, 7, 9:12, 14, 13, 16, 15, 17:18, 20, 19, 21:22, 24, 23),] + +# Remove species name in consecutive rows +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Parrotfishes Combined Bag Limit: Groupers, Snappers - 5 fish per person per day")]<-"Groupers, Snappers, and Parrotfishes combined - 5 fish per vessel per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Parrotfishes Combined Bag Limit: Groupers, Snappers - 15 fish per vessel per day")]<-"Groupers, Snappers, and Parrotfishes combined - 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 5 fish per person per day")]<-"Groupers, Parrotfishes, and Snappers combined - 5 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 15 fish per vessel per day")]<-"Groupers, Parrotfishes, and Snappers combined - 15 fish per vessel per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 5 fish per person per day")]<-"Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes, and Wrasses combined - 5 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 15 fish per vessel per day")]<-"Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes, and Wrasses combined - 15 fish per vessel per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bag Limit: Other Reef Fish Species Combined - 5 fish per person per day")]<-"Other Reef Fish Species Combined - 5 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bag Limit: Other Reef Fish Species Combined - 15 fish per vessel per day")]<-"Other Reef Fish Species Combined - 15 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bag Limit: Parrotfishes - 2 fish per person per day")]<-"Parrotfishes - 2 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bag Limit: Parrotfishes - 6 fish per vessel per day")]<-"Parrotfishes - 6 fish per vessel per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bag Limit: Surgeonfish - 1 fish per person per day")]<-"Surgeonfish - 1 fish per person per day" +bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Bag Limit: Surgeonfish - 4 fish per vessel per day")]<-"Surgeonfish - 4 fish per vessel per day" +#bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Caribbean Spiny Lobster - 10 lobster per vessel per day")]<-"- 10 lobster per vessel per day" +#bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Dolphin - 15 fish per vessel per day")]<-"- 15 fish per person per day" +#bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Parrotfish 2 - 6 fish per person per day")]<-"- 6 fish per person per day" +#bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Queen Conch - 12 conch per vessel per day")]<-"- 12 conch per vessel per day" +#bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Surgeonfish - 4 fish per vessel per day")]<-"- 4 fish per vessel per day" +#bag_yr_df2_pr$LAB[which(bag_yr_df2_pr$LAB=="Wahoo - 10 fish per vessel per day")]<-"- 10 fish per vessel per day" + +library(tidyverse) + +# 1) Get just the year columns (handles if LAB is col 1) +yrs <- names(bag_yr_df2_pr) +yrs <- yrs[grepl("^\\d{4}$", yrs)] # keep only "1985", "1986", ... +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# 2) Optional: drop empty rows (all NA across years) +keep_rows <- rowSums(!is.na(bag_yr_df2_pr[, yrs, drop = FALSE])) > 0 + +plot_df_pr <- bag_yr_df2_pr %>% + # dplyr::filter(keep_rows) %>% + # keep LAB + years + dplyr::select(LAB, all_of(yrs)) %>% + # long format: one row per LAB-year + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + # presence flag (you can keep n as-is if you later want 2 = highlight) + present = !is.na(n), + # order so your first row is at the top (like your raster plot with rev()) + LAB = factor(LAB, levels = rev(unique(LAB))) + ) + +# 3) Plot +p_pr_bag <- ggplot(plot_df_pr, aes(x = YEAR, y = LAB, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete(expand = c(0, 0)) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) +print(p_pr_bag) +ggsave(filename = paste0(Dirout, "Commercial_size_limits_SC.jpeg"), + plot = p_pr_bag, width = 6.5, height = 4.6, dpi = 300) + + + +############################# +library(dplyr) +library(tidyr) +library(ggplot2) + +termyr <- 2025 + +# Make sure it's not grouped, and LAB has no NA +bag_plot_base <- bag_yr_df2_pr %>% + dplyr::ungroup() %>% + dplyr::mutate(LAB = dplyr::coalesce(as.character(LAB), "(blank)")) + +# 1) Year columns +yrs <- names(bag_plot_base) +yrs <- yrs[grepl("^\\d{4}$", yrs)] +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# 2) Create unique row IDs *once* in the same order you want +bag_row_map <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::arrange(LAB) %>% # alphabetical A→Z + dplyr::select(LAB, LAB_ID) + +# 3) Long format for tiles (use the SAME LAB_ID logic as above) +plot_df_pr <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::select(LAB, LAB_ID, dplyr::all_of(yrs)) %>% + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + present = !is.na(n), + # top-to-bottom A→Z: + LAB_ID = factor(LAB_ID, levels = rev(bag_row_map$LAB_ID)) + ) + +# Optional: drop rows that are empty across all years +plot_df_pr <- plot_df_pr %>% + dplyr::group_by(LAB_ID) %>% + dplyr::filter(any(present)) %>% + dplyr::ungroup() + +# 4) Plot +p_pr_bag <- ggplot(plot_df_pr, aes(x = YEAR, y = LAB_ID, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete( + expand = c(0, 0), + labels = function(x) sub("___\\d+$", "", x) # show original LAB text + ) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) + +print(p_pr_bag) + +# 5) Save +ggsave( + filename = paste0(Dirout, "Recreational_bag_limits_PR.jpeg"), + plot = p_pr_bag, + width = 7.0, height = 5.0, dpi = 300 +) + + + + +################################ + +library(dplyr) +library(tidyr) +library(ggplot2) + +# Make a unique internal id per row, preserving your designed order +bag_row_map <- bag_yr_df2_pr %>% + dplyr::mutate(LAB_ID = make.unique(as.character(LAB), sep = "___")) %>% + dplyr::select(LAB, LAB_ID) + +bag_plot_long <- bag_yr_df2_pr %>% + dplyr::mutate(LAB_ID = make.unique(as.character(LAB), sep = "___")) %>% + tidyr::pivot_longer( + cols = -c(LAB, LAB_ID), + names_to = "YEAR", + values_to = "n" + ) %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + present = !is.na(n), + # enforce your exact row order (top-to-bottom as in bag_yr_df2_pr) + LAB_ID = factor(LAB_ID, levels = rev(bag_row_map$LAB_ID)) + ) %>% + dplyr::filter(YEAR <= termyr) + +p_bag <- ggplot(bag_plot_long, aes(x = YEAR, y = LAB_ID, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_fill_manual(values = c(`TRUE` = "red", `FALSE` = "white"), guide = "none") + + scale_x_continuous( + breaks = seq(min(bag_plot_long$YEAR, na.rm = TRUE), termyr, by = 2), + expand = c(0, 0) + ) + + scale_y_discrete( + expand = c(0, 0), + # show original LAB text (remove the make.unique suffix) + labels = function(x) sub("___\\d+$", "", x) + ) + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 8), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) + +ggsave( + filename = paste0(Dirout, "Recreational_bag_limits_PR.jpeg"), + plot = p_bag, + width = 7.0, height = 5.0, dpi = 300 +) + + + + + + + + + + +########### +#Try this +# ========================= +# Bag-limit heatmap plot +# Y-axis: alphabetical by species/group, then numeric limit ascending (5 before 15, 3 before 10, etc.) +# Retains duplicate display labels as separate rows +# Assumes you already created + cleaned: bag_yr_df2_pr +# ========================= + +library(dplyr) +library(tidyr) +library(stringr) +library(ggplot2) + +termyr <- 2025 + +# ---- Base table (ensure ungrouped, clean LAB) ---- +bag_plot_base <- bag_yr_df2_pr %>% + dplyr::ungroup() %>% + dplyr::mutate( + LAB = dplyr::coalesce(as.character(LAB), "(blank)"), + # species/group text = everything before " - " + species = sub(" - .*", "", LAB), + # first number in the label (2, 5, 10, 12, 15, etc.) + limit_value = as.numeric(stringr::str_extract(LAB, "\\d+")) + ) + +# ---- Identify year columns ---- +yrs <- names(bag_plot_base) +yrs <- yrs[grepl("^\\d{4}$", yrs)] +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# ---- Create a unique internal row id, then order alphabetically + numerically ---- +bag_row_map <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::arrange(species, limit_value) %>% # A→Z by species, then 2<3<5<10<12<15... + dplyr::select(LAB, LAB_ID) + +# ---- Long data for tiles ---- +plot_df_pr <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::select(LAB, LAB_ID, species, limit_value, dplyr::all_of(yrs)) %>% + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + present = !is.na(n), + # ggplot draws lowest factor at bottom, so reverse to get A→Z from top to bottom + LAB_ID = factor(LAB_ID, levels = rev(bag_row_map$LAB_ID)) + ) + +# Optional: drop rows that are empty across all years +plot_df_pr <- plot_df_pr %>% + dplyr::group_by(LAB_ID) %>% + dplyr::filter(any(present)) %>% + dplyr::ungroup() + +# ---- Plot ---- +p_pr_bag <- ggplot(plot_df_pr, aes(x = YEAR, y = LAB_ID, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete( + expand = c(0, 0), + labels = function(x) sub("___\\d+$", "", x) # remove internal suffix for display + ) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) + +print(p_pr_bag) + +# ---- Save ---- +ggsave( + filename = paste0(Dirout, "Recreational_bag_limits_PR.jpeg"), + plot = p_pr_bag, + width = 12.0, height = 5.0, dpi = 300 +) + +#### St thomas st John +# Subset for Gulf Reef Fish recreational bag limits +mh_carib_st_bag <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + #"FMP FOR THE EEZ AROUND ST. CROIX", + #"FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'RECREATIONAL', + MANAGEMENT_TYPE_USE == 'BAG LIMIT', + ZONE_USE %in% c("ALL", "ST. THOMAS/ST. JOHN MANAGEMENT AREA")) +mh_carib_st_bag <- mh_carib_st_bag %>% + mutate(END_DATE2 = case_when(FR_CITATION == "61 FR 32151" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82413" & SPP_NAME == "BAG LIMIT: OTHER REEF FISH SPECIES COMBINED" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: GROUPERS, SNAPPERS, AND PARROTFISHES COMBINED" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "2" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "6" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "5" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "15" ~ as.Date("2022-10-13"), + TRUE ~ END_DATE2)) %>% + filter(!(FR_CITATION == "87 FR 56204" & COMMON_NAME_USE == "LOBSTER, CARIBBEAN SPINY"))%>% + filter(!(FR_CITATION == "87 FR 56204" & COMMON_NAME_USE == "SURGEONFISH")) + +# Explore Zone +table(mh_carib_st_bag$ZONE_USE) +# All (hogfish zone removed when excluding FR) + +# Explore Subsector +table(mh_carib_st_bag$SUBSECTOR_USE) +# All for all data + +library(dplyr) +library(tidyr) +library(lubridate) +library(stringr) + +termyr <- 2025 + +bag_yr_df_st <- mh_carib_st_bag %>% + # keep only bag limit records you want + dplyr::filter( + NEVER_IMPLEMENTED == 0, + SECTOR_USE == "RECREATIONAL", + MANAGEMENT_TYPE_USE == "BAG LIMIT" + ) %>% + # ensure dates exist; if your fields are START_DATE2/END_DATE2 use those + dplyr::mutate( + start = as.Date(START_DATE2), + end = as.Date(dplyr::coalesce(END_DATE2, Sys.Date())) + ) %>% + dplyr::filter(!is.na(start), !is.na(end), end >= start) %>% + # (optional) if you only want complete years + dplyr::mutate( + start_year = year(start), + end_year = year(end) + ) %>% + # expand to years, NOT days + tidyr::uncount(end_year - start_year + 1, .id = "k") %>% + dplyr::mutate(YEAR = start_year + (k - 1L)) %>% + dplyr::filter(YEAR <= termyr) %>% + # keep SPP_NAME (and anything else you need) + dplyr::select(SPP_NAME, COMMON_NAME_USE, SUBSECTOR_USE, + YEAR, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + dplyr::distinct(SPP_NAME, SUBSECTOR_USE, YEAR, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) + +bag_yr_df_st <- bag_yr_df_st %>% + dplyr::mutate( + VALUE_UNITS = case_when( + VALUE_UNITS == "NUMBERS" ~ "fish", + VALUE_UNITS == "CONCH" ~ "conch", + VALUE_UNITS == "LOBSTER" ~ "lobster", + TRUE ~ VALUE_UNITS + ), + VAL_LAB = paste(VALUE, VALUE_UNITS, str_to_lower(VALUE_RATE)), + # include SPP_NAME in label (optional but recommended if you want that instead of COMMON_NAME_USE) + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',SPP_NAME)),"-", VAL_LAB), + n = 1 + ) %>% + dplyr::select(LAB, YEAR, n) %>% + dplyr::distinct() %>% + tidyr::pivot_wider(names_from = YEAR, values_from = n) %>% + dplyr::arrange(LAB) + +# Remove species name in consecutive rows +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="And Parrotfishes Combined Bag Limit: Groupers, Snappers - 5 fish per person per day")]<-"Groupers, Snappers, and Parrotfishes combined - 5 fish per vessel per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="And Parrotfishes Combined Bag Limit: Groupers, Snappers - 15 fish per vessel per day")]<-"Groupers, Snappers, and Parrotfishes combined - 15 fish per person per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 5 fish per person per day")]<-"Groupers, Parrotfishes, and Snappers combined - 5 fish per person per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 15 fish per vessel per day")]<-"Groupers, Parrotfishes, and Snappers combined - 15 fish per vessel per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 5 fish per person per day")]<-"Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes, and Wrasses combined - 5 fish per person per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 15 fish per vessel per day")]<-"Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes, and Wrasses combined - 15 fish per vessel per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="Bag Limit: Other Reef Fish Species Combined - 5 fish per person per day")]<-"Other Reef Fish Species Combined - 5 fish per person per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="Bag Limit: Other Reef Fish Species Combined - 15 fish per vessel per day")]<-"Other Reef Fish Species Combined - 15 fish per person per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="Bag Limit: Parrotfishes - 2 fish per person per day")]<-"Parrotfishes - 2 fish per person per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="Bag Limit: Parrotfishes - 6 fish per vessel per day")]<-"Parrotfishes - 6 fish per vessel per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="Bag Limit: Surgeonfish - 1 fish per person per day")]<-"Surgeonfish - 1 fish per person per day" +bag_yr_df_st$LAB[which(bag_yr_df_st$LAB=="Bag Limit: Surgeonfish - 4 fish per vessel per day")]<-"Surgeonfish - 4 fish per vessel per day" + + +# ========================= +# Bag-limit heatmap plot +# Y-axis: alphabetical by species/group, then numeric limit ascending (5 before 15, 3 before 10, etc.) +# Retains duplicate display labels as separate rows +# Assumes you already created + cleaned: bag_yr_df2_pr +# ========================= + +library(dplyr) +library(tidyr) +library(stringr) +library(ggplot2) + +termyr <- 2025 + +# ---- Base table (ensure ungrouped, clean LAB) ---- +bag_plot_base <- bag_yr_df_st %>% + dplyr::ungroup() %>% + dplyr::mutate( + LAB = dplyr::coalesce(as.character(LAB), "(blank)"), + # species/group text = everything before " - " + species = sub(" - .*", "", LAB), + # first number in the label (2, 5, 10, 12, 15, etc.) + limit_value = as.numeric(stringr::str_extract(LAB, "\\d+")) + ) + +# ---- Identify year columns ---- +yrs <- names(bag_plot_base) +yrs <- yrs[grepl("^\\d{4}$", yrs)] +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# ---- Create a unique internal row id, then order alphabetically + numerically ---- +bag_row_map <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::arrange(species, limit_value) %>% # A→Z by species, then 2<3<5<10<12<15... + dplyr::select(LAB, LAB_ID) + +# ---- Long data for tiles ---- +plot_df_st <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::select(LAB, LAB_ID, species, limit_value, dplyr::all_of(yrs)) %>% + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + present = !is.na(n), + # ggplot draws lowest factor at bottom, so reverse to get A→Z from top to bottom + LAB_ID = factor(LAB_ID, levels = rev(bag_row_map$LAB_ID)) + ) + +# Optional: drop rows that are empty across all years +plot_df_st <- plot_df_st %>% + dplyr::group_by(LAB_ID) %>% + dplyr::filter(any(present)) %>% + dplyr::ungroup() + +# ---- Plot ---- +p_st_bag <- ggplot(plot_df_st, aes(x = YEAR, y = LAB_ID, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete( + expand = c(0, 0), + labels = function(x) sub("___\\d+$", "", x) # remove internal suffix for display + ) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) + +print(p_st_bag) + +# ---- Save ---- +ggsave( + filename = paste0(Dirout, "Recreational_bag_limits_PR.jpeg"), + plot = p_pr_bag, + width = 7.0, height = 5.0, dpi = 300 +) + +#### St croix +# Subset for Gulf Reef Fish recreational bag limits +mh_carib_sc_bag <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + #"FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + "FMP FOR THE EEZ AROUND ST. CROIX", + #"FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'RECREATIONAL', + MANAGEMENT_TYPE_USE == 'BAG LIMIT', + ZONE_USE %in% c("ALL", "ST. CROIX MANAGEMENT AREA")) +mh_carib_sc_bag <- mh_carib_sc_bag %>% + mutate(END_DATE2 = case_when(FR_CITATION == "61 FR 32151" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82413" & SPP_NAME == "BAG LIMIT: OTHER REEF FISH SPECIES COMBINED" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: GROUPERS, SNAPPERS, AND PARROTFISHES COMBINED" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "2" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "6" ~ as.Date("2021-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "5" ~ as.Date("2022-10-13"), + FR_CITATION == "76 FR 82403" & SPP_NAME == "BAG LIMIT: PARROTFISHES" & VALUE == "15" ~ as.Date("2022-10-13"), + TRUE ~ END_DATE2)) %>% + filter(!(FR_CITATION == "87 FR 56204" & COMMON_NAME_USE == "LOBSTER, CARIBBEAN SPINY"))%>% + filter(!(FR_CITATION == "87 FR 56204" & COMMON_NAME_USE == "SURGEONFISH")) + +# Explore Zone +table(mh_carib_sc_bag$ZONE_USE) +# All (hogfish zone removed when excluding FR) + +# Explore Subsector +table(mh_carib_sc_bag$SUBSECTOR_USE) +# All for all data + +library(dplyr) +library(tidyr) +library(lubridate) +library(stringr) + +termyr <- 2025 + +bag_yr_df_sc <- mh_carib_sc_bag %>% + # keep only bag limit records you want + dplyr::filter( + NEVER_IMPLEMENTED == 0, + SECTOR_USE == "RECREATIONAL", + MANAGEMENT_TYPE_USE == "BAG LIMIT" + ) %>% + # ensure dates exist; if your fields are START_DATE2/END_DATE2 use those + dplyr::mutate( + start = as.Date(START_DATE2), + end = as.Date(dplyr::coalesce(END_DATE2, Sys.Date())) + ) %>% + dplyr::filter(!is.na(start), !is.na(end), end >= start) %>% + # (optional) if you only want complete years + dplyr::mutate( + start_year = year(start), + end_year = year(end) + ) %>% + # expand to years, NOT days + tidyr::uncount(end_year - start_year + 1, .id = "k") %>% + dplyr::mutate(YEAR = start_year + (k - 1L)) %>% + dplyr::filter(YEAR <= termyr) %>% + # keep SPP_NAME (and anything else you need) + dplyr::select(SPP_NAME, COMMON_NAME_USE, SUBSECTOR_USE, + YEAR, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + dplyr::distinct(SPP_NAME, SUBSECTOR_USE, YEAR, VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) + +bag_yr_df_sc <- bag_yr_df_sc %>% + dplyr::mutate( + VALUE_UNITS = case_when( + VALUE_UNITS == "NUMBERS" ~ "fish", + VALUE_UNITS == "CONCH" ~ "conch", + VALUE_UNITS == "LOBSTER" ~ "lobster", + TRUE ~ VALUE_UNITS + ), + VAL_LAB = paste(VALUE, VALUE_UNITS, str_to_lower(VALUE_RATE)), + # include SPP_NAME in label (optional but recommended if you want that instead of COMMON_NAME_USE) + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',SPP_NAME)),"-", VAL_LAB), + n = 1 + ) %>% + dplyr::select(LAB, YEAR, n) %>% + dplyr::distinct() %>% + tidyr::pivot_wider(names_from = YEAR, values_from = n) %>% + dplyr::arrange(LAB) + +# Remove species name in consecutive rows +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="And Parrotfishes Combined Bag Limit: Groupers, Snappers - 5 fish per person per day")]<-"Groupers, Snappers, and Parrotfishes combined - 5 fish per vessel per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="And Parrotfishes Combined Bag Limit: Groupers, Snappers - 15 fish per vessel per day")]<-"Groupers, Snappers, and Parrotfishes combined - 15 fish per person per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 5 fish per person per day")]<-"Groupers, Parrotfishes, and Snappers combined - 5 fish per person per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="And Snappers Combined Bag Limit: Groupers, Parrotfishes - 15 fish per vessel per day")]<-"Groupers, Parrotfishes, and Snappers combined - 15 fish per vessel per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 5 fish per person per day")]<-"Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes, and Wrasses combined - 5 fish per person per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="And Wrasses Combined Bag Limit: Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes - 15 fish per vessel per day")]<-"Angelfishes, Grunts, Jacks, Surgeonfishes, Triggerfishes, and Wrasses combined - 15 fish per vessel per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="Bag Limit: Other Reef Fish Species Combined - 5 fish per person per day")]<-"Other Reef Fish Species Combined - 5 fish per person per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="Bag Limit: Other Reef Fish Species Combined - 15 fish per vessel per day")]<-"Other Reef Fish Species Combined - 15 fish per person per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="Bag Limit: Parrotfishes - 2 fish per person per day")]<-"Parrotfishes - 2 fish per person per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="Bag Limit: Parrotfishes - 6 fish per vessel per day")]<-"Parrotfishes - 6 fish per vessel per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="Bag Limit: Surgeonfish - 1 fish per person per day")]<-"Surgeonfish - 1 fish per person per day" +bag_yr_df_sc$LAB[which(bag_yr_df_sc$LAB=="Bag Limit: Surgeonfish - 4 fish per vessel per day")]<-"Surgeonfish - 4 fish per vessel per day" + + +# ========================= +# Bag-limit heatmap plot +# Y-axis: alphabetical by species/group, then numeric limit ascending (5 before 15, 3 before 10, etc.) +# Retains duplicate display labels as separate rows +# Assumes you already created + cleaned: bag_yr_df2_pr +# ========================= + +library(dplyr) +library(tidyr) +library(stringr) +library(ggplot2) + +termyr <- 2025 + +# ---- Base table (ensure ungrouped, clean LAB) ---- +bag_plot_base <- bag_yr_df_sc %>% + dplyr::ungroup() %>% + dplyr::mutate( + LAB = dplyr::coalesce(as.character(LAB), "(blank)"), + # species/group text = everything before " - " + species = sub(" - .*", "", LAB), + # first number in the label (2, 5, 10, 12, 15, etc.) + limit_value = as.numeric(stringr::str_extract(LAB, "\\d+")) + ) + +# ---- Identify year columns ---- +yrs <- names(bag_plot_base) +yrs <- yrs[grepl("^\\d{4}$", yrs)] +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# ---- Create a unique internal row id, then order alphabetically + numerically ---- +bag_row_map <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::arrange(species, limit_value) %>% # A→Z by species, then 2<3<5<10<12<15... + dplyr::select(LAB, LAB_ID) + +# ---- Long data for tiles ---- +plot_df_sc <- bag_plot_base %>% + dplyr::mutate(LAB_ID = make.unique(LAB, sep = "___")) %>% + dplyr::select(LAB, LAB_ID, species, limit_value, dplyr::all_of(yrs)) %>% + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + present = !is.na(n), + # ggplot draws lowest factor at bottom, so reverse to get A→Z from top to bottom + LAB_ID = factor(LAB_ID, levels = rev(bag_row_map$LAB_ID)) + ) + +# Optional: drop rows that are empty across all years +plot_df_sc <- plot_df_sc %>% + dplyr::group_by(LAB_ID) %>% + dplyr::filter(any(present)) %>% + dplyr::ungroup() + +# ---- Plot ---- +p_sc_bag <- ggplot(plot_df_sc, aes(x = YEAR, y = LAB_ID, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete( + expand = c(0, 0), + labels = function(x) sub("___\\d+$", "", x) # remove internal suffix for display + ) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) + +print(p_sc_bag) + +# ---- Save ---- +ggsave( + filename = paste0(Dirout, "Recreational_bag_limits_PR.jpeg"), + plot = p_pr_bag, + width = 7.0, height = 5.0, dpi = 300 +) + diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_ComSize.R b/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_ComSize.R new file mode 100644 index 0000000..e743134 --- /dev/null +++ b/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_ComSize.R @@ -0,0 +1,670 @@ +############################ +# Commercial Size Limits # +############################ + +librarian::shelf(here, tidyverse, lubridate, openxlsx, neatRanges, splitstackshape, dplyr) + +# Set output directory for plots +Dirout<-paste0(getwd(),"/Size limits/") +if(!file.exists(Dirout)) dir.create(Dirout) + +# MH dataset +mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Nov18.RDS")) + +# Set end year for plots +termyr<-2025 + +####################### +# Minimum Size limits # +####################### + +# Subset for Gulf Reef Fish size limits - Puerto Rico +mh_carib_pr <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + #"FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + #"FMP FOR THE EEZ AROUND ST. CROIX", + "FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'COMMERCIAL', + MANAGEMENT_CATEGORY == 'SELECTIVITY CONTROLS', + ZONE_USE %in% c("ALL", "PUERTO RICO MANAGEMENT AREA")) +mh_carib_pr <- mh_carib_pr %>% +mutate(END_DATE2 = case_when(FR_CITATION == "49 FR 50049" & COMMON_NAME_USE == "LOBSTER, CARIBBEAN SPINY" ~ as.Date("2021-10-12"), + FR_CITATION == "55 FR 46214" & COMMON_NAME_USE == "SNAPPER, YELLOWTAIL" & VALUE == 12 ~ as.Date("2021-10-12"), + FR_CITATION == "50 FR 34850" & COMMON_NAME_USE == "GROUPER, NASSAU" & VALUE == 17 ~ as.Date("1990-11-29"), + FR_CITATION == "81 FR 29166" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2022-10-13"), + TRUE ~ END_DATE2)) %>% + filter(!(FR_CITATION == "50 FR 34850" & START_YEAR >= "1991")) + +# Confirm size limits +unique(mh_carib_pr$MANAGEMENT_TYPE_USE) + +# Confirm only commercial +table(mh_carib_pr$SECTOR_USE) + +source(here("ODM-MH-Analysis_ready", "Closures", "func_expand_status.R")) + +# Min size limits +min_df_pr <- expand_status(mh_carib_pr, "MINIMUM SIZE LIMIT") + +# Collapse to annual value +min_yr_df_pr <- min_df_pr %>% + mutate(YEAR = year(date_sequence)) %>% + select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + distinct() + +# Explore Zone +table(min_yr_df_pr$ZONE_USE) + +# Explore Subsector +table(min_yr_df_pr$SUBSECTOR_USE) +# All for all data + +# Explore year - only include complete years +table(min_yr_df_pr$YEAR) +min_yr_df_pr<-min_yr_df_pr %>% filter(YEAR <=termyr) +table(min_yr_df_pr$YEAR) + +# Format for plot +min_yr_df2_pr <- min_yr_df_pr %>% + mutate(VALUE_UNITS = case_when(VALUE_UNITS == 'INCHES' ~ 'in', + TRUE ~ VALUE_UNITS), + VALUE_TYPE = case_when(VALUE_TYPE == 'FORK LENGTH' ~ 'FL', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == 'TOTAL LENGTH' ~ 'TL', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == "CARAPACE LENGTH" ~ "Carapace Length", + TRUE ~ VALUE_TYPE), + VAL_LAB = paste(VALUE, VALUE_UNITS, VALUE_TYPE), + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)),"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE,"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE, "(Zone ", ZONE_USE, ")", VAL_LAB), + n = 1) %>% + dplyr::select(LAB, YEAR, n) %>% + arrange(YEAR) %>% + pivot_wider(names_from = YEAR, values_from = n) %>% + arrange(LAB) + + +# ###################### +# # Prohibited Species # +# ###################### +# +# # Subset for Gulf Reef Fish size limits +# mh_carib2 <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + # "FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + # "FMP FOR THE EEZ AROUND ST. CROIX", + # "FMP FOR THE EEZ AROUND PUERTO RICO", + # "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + # "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + #filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'COMMERCIAL', + # MANAGEMENT_TYPE_USE == 'PROHIBITED SPECIES') +# +# # Confirm prohibited + #unique(mh_carib2$MANAGEMENT_TYPE_USE) +# +# # Confirm only commercial + #table(mh_carib2$SECTOR_USE) +# +# # Min size limits + #Prohib_df <- expand_status(mh_carib2, "PROHIBITED SPECIES") +# +# # Collapse to annual value + #Prohib_yr_df <- Prohib_df %>% + # mutate(YEAR = year(date_sequence)) %>% + # select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + # VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + #distinct() +# +# # Explore Zone + #table(Prohib_yr_df$ZONE_USE) +# # All for all data +# +# # Explore Subsector + #table(Prohib_yr_df$SUBSECTOR_USE) +# # All for all data +# +# # Explore year - only include complete years + #table(Prohib_yr_df$YEAR) + #Prohib_yr_df<-Prohib_yr_df %>% filter(YEAR <=termyr) + #table(Prohib_yr_df$YEAR) +# +# # Format for plot + #Prohib_yr_df2 <- Prohib_yr_df %>% + # mutate(LAB = str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)), + # n = 1) %>% + # dplyr::select(LAB, YEAR, n) %>% + #arrange(YEAR) %>% + # pivot_wider(names_from = YEAR, values_from = n) %>% + #arrange(LAB) + +# Want to highlight years where species prohibited or removed from FMP +# Goliath prohibited 1990+ +#min_yr_df2[min_yr_df2$LAB=="Goliath Grouper - 50 in TL", which(colnames(min_yr_df2)=="1990")]<-2 +#min_yr_df2[min_yr_df2$LAB=="Goliath Grouper - 50 in TL", which(colnames(min_yr_df2)=="1991"):dim(min_yr_df2)[2]]<-NA +# Nassau prohibited 1997+ +#min_yr_df2[min_yr_df2$LAB=="Nassau Grouper - 20 in TL", which(colnames(min_yr_df2)=="1997")]<-2 +#min_yr_df2[min_yr_df2$LAB=="Nassau Grouper - 20 in TL", which(colnames(min_yr_df2)=="1998"):dim(min_yr_df2)[2]]<-NA +# Schoolmaster removed from FMP in 2012 +#min_yr_df2[min_yr_df2$LAB=="Schoolmaster - 12 in TL", which(colnames(min_yr_df2)=="2012")]<-2 +# Dog snapper removed from FMP in 2012 +#min_yr_df2[min_yr_df2$LAB=="Dog Snapper - 12 in TL",which(colnames(min_yr_df2)=="2012")]<-2 +# Mahogany snapper, Black Sea Bass removed from FMP in 2012 +#min_yr_df2[min_yr_df2$LAB=="Mahogany Snapper - 12 in TL",which(colnames(min_yr_df2)=="2012")]<-2 +# Black Sea Bass removed from FMP in 1998 +#min_yr_df2[min_yr_df2$LAB=="Black Sea Bass - 8 in TL",which(colnames(min_yr_df2)=="1998")]<-2 + +# Need to add in Max Size Limit for banded rudderfish and lesser amberjack +#subset(mh_grf,MANAGEMENT_TYPE_USE=="MAXIMUM SIZE LIMIT") +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Banded Rudderfish - 14 in FL")]<-"Banded Rudderfish - 14 in FL (22 Max)" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Lesser Amberjack - 14 in FL")]<-"Lesser Amberjack - 14 in FL (22 Max)" + +# Rename Scamp +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Scamp - 16 in TL")]<-"Scamp Grouper - 16 in TL" + +# Reorder by family (manually for now...) +dim(min_yr_df2_pr) #15 x 42 +min_yr_df2_pr<-min_yr_df2_pr[c(1:10, 14:15, 11:13),] +dim(min_yr_df2_pr) #37 x 42 + +# Save outputs before we clean up labels +saveRDS(min_yr_df2_pr,paste0(Dirout,"commercial_pr_size_limits.rds")) + +# Remove species name in consecutive rows +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Nassau Grouper - 13 in TL")]<-"- 13 in TL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Nassau Grouper - 14 in TL")]<-"- 14 in TL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Nassau Grouper - 15 in TL")]<-"- 15 in TL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Nassau Grouper - 16 in TL")]<-"- 16 in TL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Nassau Grouper - 17 in TL")]<-"- 17 in FL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Yellowtail Snapper - 9 in TL")]<-"- 9 in TL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Yellowtail Snapper - 10 in TL")]<-"- 10 in TL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Yellowtail Snapper - 11 in TL")]<-"- 11 in TL" +min_yr_df2_pr$LAB[which(min_yr_df2_pr$LAB=="Yellowtail Snapper - 12 in TL")]<-"- 12 in TL" + + +# Add asterisk to indicate size limits that are consist between com/rec +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Banded Rudderfish - 14 in FL (22 Max)")]<-"*Banded Rudderfish - 14 in FL (22 Max)" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Lesser Amberjack - 14 in FL (22 Max)")]<-"*Lesser Amberjack - 14 in FL (22 Max)" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Black Sea Bass - 8 in TL")]<-"*Black Sea Bass - 8 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Goliath Grouper - 50 in TL")]<-"*Goliath Grouper - 50 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Nassau Grouper - 20 in TL")]<-"*Nassau Grouper - 20 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Scamp Grouper - 16 in TL")]<-"*Scamp Grouper - 16 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Yellowfin Grouper - 20 in TL")]<-"*Yellowfin Grouper - 20 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Hogfish - 12 in FL")]<-"*Hogfish - 12 in FL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Schoolmaster - 12 in TL")]<-"*Schoolmaster - 12 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Cubera Snapper - 12 in TL")]<-"*Cubera Snapper - 12 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Dog Snapper - 12 in TL")]<-"*Dog Snapper - 12 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Gray Snapper - 12 in TL")]<-"*Gray Snapper - 12 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Lane Snapper - 8 in TL")]<-"*Lane Snapper - 8 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Mahogany Snapper - 12 in TL")]<-"*Mahogany Snapper - 12 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Mutton Snapper - 12 in TL")]<-"*Mutton Snapper - 12 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Vermilion Snapper - 8 in TL")]<-"*Vermilion Snapper - 8 in TL" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Yellowtail Snapper - 12 in TL")]<-"*Yellowtail Snapper - 12 in TL" + +library(tidyverse) + +# 1) Get just the year columns (handles if LAB is col 1) +yrs <- names(min_yr_df2_pr) +yrs <- yrs[grepl("^\\d{4}$", yrs)] # keep only "1985", "1986", ... +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# 2) Optional: drop empty rows (all NA across years) +keep_rows <- rowSums(!is.na(min_yr_df2_pr[, yrs, drop = FALSE])) > 0 + +plot_df_pr <- min_yr_df2_pr %>% + dplyr::filter(keep_rows) %>% + # keep LAB + years + dplyr::select(LAB, all_of(yrs)) %>% + # long format: one row per LAB-year + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + # presence flag (you can keep n as-is if you later want 2 = highlight) + present = !is.na(n), + # order so your first row is at the top (like your raster plot with rev()) + LAB = factor(LAB, levels = rev(unique(LAB))) + ) + +# 3) Plot +p_pr <- ggplot(plot_df_pr, aes(x = YEAR, y = LAB, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete(expand = c(0, 0)) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) +print(p_pr) +ggsave(filename = paste0(Dirout, "Commercial_size_limits_PR.jpeg"), + plot = p_pr, width = 6.5, height = 4.6, dpi = 300) + + +######################################################## +# Plot size limits over time +#library(raster) +#Note: importing this package masks select from dplyr... + +#yrs <- as.character(1985:2025) +#yrs <- names(min_yr_df2_pr) +#yrs <- yrs[grepl("^\\d{4}$", yrs)] +#yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= 2025] + +#MinSize_pr<-raster(as.matrix(min_yr_df2_pr[,2:dim(min_yr_df2_pr)[2]])) +#m <- as.matrix(min_yr_df2_pr[, -1]) +#keep_rows <- which(rowSums(!is.na(m))>0) +#m_trim <- m[keep_rows, , drop = FALSE] +#groups_trim <- groups[keep_rows] + + +#groups<-dplyr::select(min_yr_df2_pr, LAB) %>% pull() +#m_trim <- m[keep_rows, , drop = FALSE] +#minsize_pr_trim <- raster::raster(m_trim) +#names<-c(min(min_yr_df2_pr$):max(min_yr_df2_pr$YEAR)) +#names <- as.character(1985:2025) + +#nrows <- nrow(m_trim) +#ncols <- ncol(m_trim) + +#y_at <- seq(from = (1/nrows)/ 2, + # to = 1 - (1/nrows)/ 2, + # by = 1/ nrows) + +#x_at <- seq(from = (1/ncols)/ 2, + # to = 1 - (1/ncols)/2, + # by = 1/ncols) + +#jpeg(paste0(Dirout,"Commercial_size_limits.jpeg"),res=300,height=4.6,width=6.5, units="in") +#par(mar=c(0.1, 12, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +#brks<-c(0,1,2); cols<-c("lightblue","red") +#plot(MinSize_pr,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +#abline(h=c(seq(0,1,(1/dim(min_yr_df2_pr)[1]))),col="lightgray") +#abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +#axis(2,at=seq(((1/dim(min_yr_df2_pr)[1])/2),1,(1/dim(min_yr_df2_pr)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.5,font=1) +#axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.5,las=2,hadj=0.7) +#axis(2, at = y_at, labels = rev(groups_trim), las = 2, tck = 0, cex.axis = 0.5) +#axis(3, at = x_at, labels = names, las = 2, tck = 0, cex.axis = 0.5, hadj = 0.7) +#dev.off() + +##### ST. Thomas/St. John +# Subset for Gulf Reef Fish size limits - St. Thomas and ST. John. +mh_carib_st <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + #"FMP FOR THE EEZ AROUND ST. CROIX", + #"FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'COMMERCIAL', + MANAGEMENT_CATEGORY == 'SELECTIVITY CONTROLS', + ZONE_USE %in% c("ALL", "ST. THOMAS/ST. JOHN MANAGEMENT AREA")) +mh_carib_st <- mh_carib_st %>% + mutate(END_DATE2 = case_when(FR_CITATION == "49 FR 50049" & COMMON_NAME_USE == "LOBSTER, CARIBBEAN SPINY" ~ as.Date("2021-10-12"), + FR_CITATION == "55 FR 46214" & COMMON_NAME_USE == "SNAPPER, YELLOWTAIL" & VALUE == 12 ~ as.Date("2021-10-12"), + FR_CITATION == "50 FR 34850" & COMMON_NAME_USE == "GROUPER, NASSAU" & VALUE == 17 ~ as.Date("1990-11-29"), + FR_CITATION == "81 FR 29166" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2022-10-13"), + TRUE ~ END_DATE2)) + +# Confirm size limits +unique(mh_carib_st$MANAGEMENT_TYPE_USE) + +# Confirm only commercial +table(mh_carib_st$SECTOR_USE) + +source(here("ODM-MH-Analysis_ready", "Closures", "func_expand_status.R")) + +# Min size limits +min_df_st <- expand_status(mh_carib_st, "MINIMUM SIZE LIMIT") + +# Collapse to annual value +min_yr_df_st <- min_df_st %>% + mutate(YEAR = year(date_sequence)) %>% + select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + distinct() + +# Explore Zone +table(min_yr_df_st$ZONE_USE) + +# Explore Subsector +table(min_yr_df_st$SUBSECTOR_USE) +# All for all data + +# Explore year - only include complete years +table(min_yr_df_st$YEAR) +min_yr_df_st<-min_yr_df_st %>% filter(YEAR <=termyr) +table(min_yr_df_st$YEAR) + +# Format for plot +min_yr_df2_st <- min_yr_df_st %>% + mutate(VALUE_UNITS = case_when(VALUE_UNITS == 'INCHES' ~ 'in', + TRUE ~ VALUE_UNITS), + VALUE_TYPE = case_when(VALUE_TYPE == 'FORK LENGTH' ~ 'FL', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == 'TOTAL LENGTH' ~ 'TL', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == "CARAPACE LENGTH" ~ "Carapace Length", + TRUE ~ VALUE_TYPE), + VAL_LAB = paste(VALUE, VALUE_UNITS, VALUE_TYPE), + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)),"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE,"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE, "(Zone ", ZONE_USE, ")", VAL_LAB), + n = 1) %>% + dplyr::select(LAB, YEAR, n) %>% + arrange(YEAR) %>% + pivot_wider(names_from = YEAR, values_from = n) %>% + arrange(LAB) + + +# ###################### +# # Prohibited Species # +# ###################### +# +# # Subset for Gulf Reef Fish size limits +# mh_carib2 <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", +# "FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", +# "FMP FOR THE EEZ AROUND ST. CROIX", +# "FMP FOR THE EEZ AROUND PUERTO RICO", +# "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", +# "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% +# Remove recs that were never implemented +#filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'COMMERCIAL', +# MANAGEMENT_TYPE_USE == 'PROHIBITED SPECIES') +# +# # Confirm prohibited +#unique(mh_carib2$MANAGEMENT_TYPE_USE) +# +# # Confirm only commercial +#table(mh_carib2$SECTOR_USE) +# +# # Min size limits +#Prohib_df <- expand_status(mh_carib2, "PROHIBITED SPECIES") +# +# # Collapse to annual value +#Prohib_yr_df <- Prohib_df %>% +# mutate(YEAR = year(date_sequence)) %>% +# select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, +# VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% +#distinct() +# +# # Explore Zone +#table(Prohib_yr_df$ZONE_USE) +# # All for all data +# +# # Explore Subsector +#table(Prohib_yr_df$SUBSECTOR_USE) +# # All for all data +# +# # Explore year - only include complete years +#table(Prohib_yr_df$YEAR) +#Prohib_yr_df<-Prohib_yr_df %>% filter(YEAR <=termyr) +#table(Prohib_yr_df$YEAR) +# +# # Format for plot +#Prohib_yr_df2 <- Prohib_yr_df %>% +# mutate(LAB = str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)), +# n = 1) %>% +# dplyr::select(LAB, YEAR, n) %>% +#arrange(YEAR) %>% +# pivot_wider(names_from = YEAR, values_from = n) %>% +#arrange(LAB) + +# Want to highlight years where species prohibited or removed from FMP +# Goliath prohibited 1990+ +#min_yr_df2[min_yr_df2$LAB=="Goliath Grouper - 50 in TL", which(colnames(min_yr_df2)=="1990")]<-2 +#min_yr_df2[min_yr_df2$LAB=="Goliath Grouper - 50 in TL", which(colnames(min_yr_df2)=="1991"):dim(min_yr_df2)[2]]<-NA +# Nassau prohibited 1997+ +#min_yr_df2[min_yr_df2$LAB=="Nassau Grouper - 20 in TL", which(colnames(min_yr_df2)=="1997")]<-2 +#min_yr_df2[min_yr_df2$LAB=="Nassau Grouper - 20 in TL", which(colnames(min_yr_df2)=="1998"):dim(min_yr_df2)[2]]<-NA +# Schoolmaster removed from FMP in 2012 +#min_yr_df2[min_yr_df2$LAB=="Schoolmaster - 12 in TL", which(colnames(min_yr_df2)=="2012")]<-2 +# Dog snapper removed from FMP in 2012 +#min_yr_df2[min_yr_df2$LAB=="Dog Snapper - 12 in TL",which(colnames(min_yr_df2)=="2012")]<-2 +# Mahogany snapper, Black Sea Bass removed from FMP in 2012 +#min_yr_df2[min_yr_df2$LAB=="Mahogany Snapper - 12 in TL",which(colnames(min_yr_df2)=="2012")]<-2 +# Black Sea Bass removed from FMP in 1998 +#min_yr_df2[min_yr_df2$LAB=="Black Sea Bass - 8 in TL",which(colnames(min_yr_df2)=="1998")]<-2 + +# Need to add in Max Size Limit for banded rudderfish and lesser amberjack +#subset(mh_grf,MANAGEMENT_TYPE_USE=="MAXIMUM SIZE LIMIT") +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Banded Rudderfish - 14 in FL")]<-"Banded Rudderfish - 14 in FL (22 Max)" +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Lesser Amberjack - 14 in FL")]<-"Lesser Amberjack - 14 in FL (22 Max)" + +# Rename Scamp +#min_yr_df2$LAB[which(min_yr_df2$LAB=="Scamp - 16 in TL")]<-"Scamp Grouper - 16 in TL" + +# Reorder by family (manually for now...) +dim(min_yr_df2_st) #22 x 42 +min_yr_df2_st<-min_yr_df2_st[c(1:17, 21:22, 18:20),] +dim(min_yr_df2_st) #37 x 42 + +# Save outputs before we clean up labels +saveRDS(min_yr_df2_st,paste0(Dirout,"commercial_pr_size_limits.rds")) + +# Remove species name in consecutive rows +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 13 in TL")]<-"- 13 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 14 in TL")]<-"- 14 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 15 in TL")]<-"- 15 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 16 in TL")]<-"- 16 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 17 in TL")]<-"- 17 in FL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 18 in TL")]<-"- 18 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 19 in TL")]<-"- 19 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 20 in TL")]<-"- 20 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 21 in TL")]<-"- 21 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 22 in TL")]<-"- 22 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 23 in TL")]<-"- 23 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Nassau Grouper - 24 in TL")]<-"- 24 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Yellowtail Snapper - 9 in TL")]<-"- 9 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Yellowtail Snapper - 10 in TL")]<-"- 10 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Yellowtail Snapper - 11 in TL")]<-"- 11 in TL" +min_yr_df2_st$LAB[which(min_yr_df2_st$LAB=="Yellowtail Snapper - 12 in TL")]<-"- 12 in TL" + + +# Add asterisk to indicate size limits that are consist between com/rec +min_yr_df2$LAB[which(min_yr_df2$LAB=="Banded Rudderfish - 14 in FL (22 Max)")]<-"*Banded Rudderfish - 14 in FL (22 Max)" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Lesser Amberjack - 14 in FL (22 Max)")]<-"*Lesser Amberjack - 14 in FL (22 Max)" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Black Sea Bass - 8 in TL")]<-"*Black Sea Bass - 8 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Goliath Grouper - 50 in TL")]<-"*Goliath Grouper - 50 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Nassau Grouper - 20 in TL")]<-"*Nassau Grouper - 20 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Scamp Grouper - 16 in TL")]<-"*Scamp Grouper - 16 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Yellowfin Grouper - 20 in TL")]<-"*Yellowfin Grouper - 20 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Hogfish - 12 in FL")]<-"*Hogfish - 12 in FL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Schoolmaster - 12 in TL")]<-"*Schoolmaster - 12 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Cubera Snapper - 12 in TL")]<-"*Cubera Snapper - 12 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Dog Snapper - 12 in TL")]<-"*Dog Snapper - 12 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Gray Snapper - 12 in TL")]<-"*Gray Snapper - 12 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Lane Snapper - 8 in TL")]<-"*Lane Snapper - 8 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Mahogany Snapper - 12 in TL")]<-"*Mahogany Snapper - 12 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Mutton Snapper - 12 in TL")]<-"*Mutton Snapper - 12 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Vermilion Snapper - 8 in TL")]<-"*Vermilion Snapper - 8 in TL" +min_yr_df2$LAB[which(min_yr_df2$LAB=="Yellowtail Snapper - 12 in TL")]<-"*Yellowtail Snapper - 12 in TL" + +# Plot size limits over time +library(raster) +#Note: importing this package masks select from dplyr... + +yrs <- as.character(1985:2025) +yrs <- names(min_yr_df2_st) +yrs <- yrs[grepl("^\\d{4}$", yrs)] +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= 2025] + +MinSize_st<-raster(as.matrix(min_yr_df2_st[,2:dim(min_yr_df2_st)[2]])) +groups<-dplyr::select(min_yr_df2_st, LAB) %>% pull() +#names<-c(min(min_yr_df2_pr$):max(min_yr_df2_pr$YEAR)) +names <- as.character(1985:2025) + +nrows <- nrow(min_yr_df2_st) +ncols <- ncol(min_yr_df2_st) - 1 + +y_at <- seq(from = (1/nrows)/ 2, + to = 1 - (1/nrows)/ 2, + by = 1/ nrows) + +x_at <- seq(from = (1/ncols)/ 2, + to = 1 - (1/ncols)/2, + by = 1/ncols) + +jpeg(paste0(Dirout,"Commercial_size_limitsst.jpeg"),res=300,height=4.6,width=6.5, units="in") +par(mar=c(0.1, 12, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(MinSize_st,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(min_yr_df2_st)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +#axis(2,at=seq(((1/dim(min_yr_df2_pr)[1])/2),1,(1/dim(min_yr_df2_pr)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.5,font=1) +#axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.5,las=2,hadj=0.7) +axis(2, at = y_at, labels = rev(groups), las = 2, tck = 0, cex.axis = 0.5) +axis(3, at = x_at, labels = names, las = 2, tck = 0, cex.axis = 0.5, hadj = 0.7) +dev.off() + + +########################## +# St. Croix +# Subset for Gulf Reef Fish size limits - Puerto Rico +mh_carib_sc <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + #"FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + "FMP FOR THE EEZ AROUND ST. CROIX", + #"FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'COMMERCIAL', + MANAGEMENT_CATEGORY == 'SELECTIVITY CONTROLS', + ZONE_USE %in% c("ALL", "ST. CROIX MANAGEMENT AREA")) +mh_carib_sc <- mh_carib_sc %>% + mutate(END_DATE2 = case_when(FR_CITATION == "49 FR 50049" & COMMON_NAME_USE == "LOBSTER, CARIBBEAN SPINY" ~ as.Date("2021-10-12"), + FR_CITATION == "55 FR 46214" & COMMON_NAME_USE == "SNAPPER, YELLOWTAIL" & VALUE == 12 ~ as.Date("2021-10-12"), + FR_CITATION == "50 FR 34850" & COMMON_NAME_USE == "GROUPER, NASSAU" & VALUE == 17 ~ as.Date("1990-11-29"), + FR_CITATION == "81 FR 29166" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2021-10-13"), + FR_CITATION == "78 FR 45894" ~ as.Date("2022-10-13"), + TRUE ~ END_DATE2)) %>% + filter(!(FR_CITATION == "50 FR 34850" & START_YEAR >= "1991")) + +mh_carib_sc <-mh_carib_sc %>% + dplyr::ungroup() + +# Confirm size limits +unique(mh_carib_sc$MANAGEMENT_TYPE_USE) + +# Confirm only commercial +table(mh_carib_sc$SECTOR_USE) + +source(here("ODM-MH-Analysis_ready", "Closures", "func_expand_status.R")) + +# Min size limits +min_df_sc <- expand_status(mh_carib_sc, "MINIMUM SIZE LIMIT") + +# Collapse to annual value +min_yr_df_sc <- min_df_sc %>% + dplyr::mutate(YEAR = year(date_sequence)) %>% + dplyr::select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + distinct() + +# Explore Zone +table(min_yr_df_sc$ZONE_USE) + +# Explore Subsector +table(min_yr_df_sc$SUBSECTOR_USE) +# All for all data + +# Explore year - only include complete years +table(min_yr_df_sc$YEAR) +min_yr_df_sc<-min_yr_df_sc %>% filter(YEAR <=termyr) +table(min_yr_df_sc$YEAR) + +# Format for plot +min_yr_df2_sc <- min_yr_df_sc %>% + mutate(VALUE_UNITS = case_when(VALUE_UNITS == 'INCHES' ~ 'in', + TRUE ~ VALUE_UNITS), + VALUE_TYPE = case_when(VALUE_TYPE == 'FORK LENGTH' ~ 'FL', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == 'TOTAL LENGTH' ~ 'TL', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == "CARAPACE LENGTH" ~ "Carapace Length", + TRUE ~ VALUE_TYPE), + VAL_LAB = paste(VALUE, VALUE_UNITS, VALUE_TYPE), + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)),"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE,"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE, "(Zone ", ZONE_USE, ")", VAL_LAB), + n = 1) %>% + dplyr::select(LAB, YEAR, n) %>% + arrange(YEAR) %>% + pivot_wider(names_from = YEAR, values_from = n) %>% + arrange(LAB) + +# Reorder by family (manually for now...) +dim(min_yr_df2_sc) #22 x 42 +min_yr_df2_sc<-min_yr_df2_sc[c(1:17, 21:22, 18:20),] +dim(min_yr_df2_sc) #37 x 42 + +# Save outputs before we clean up labels +saveRDS(min_yr_df2_sc,paste0(Dirout,"commercial_pr_size_limits.rds")) + +# Remove species name in consecutive rows +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 13 in TL")]<-"- 13 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 14 in TL")]<-"- 14 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 15 in TL")]<-"- 15 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 16 in TL")]<-"- 16 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 17 in TL")]<-"- 17 in FL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 18 in TL")]<-"- 18 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 19 in TL")]<-"- 19 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 20 in TL")]<-"- 20 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 21 in TL")]<-"- 21 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 22 in TL")]<-"- 22 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 23 in TL")]<-"- 23 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Nassau Grouper - 24 in TL")]<-"- 24 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Yellowtail Snapper - 9 in TL")]<-"- 9 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Yellowtail Snapper - 10 in TL")]<-"- 10 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Yellowtail Snapper - 11 in TL")]<-"- 11 in TL" +min_yr_df2_sc$LAB[which(min_yr_df2_sc$LAB=="Yellowtail Snapper - 12 in TL")]<-"- 12 in TL" + +library(tidyverse) + +# 1) Get just the year columns (handles if LAB is col 1) +yrs <- names(min_yr_df2_sc) +yrs <- yrs[grepl("^\\d{4}$", yrs)] # keep only "1985", "1986", ... +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# 2) Optional: drop empty rows (all NA across years) +keep_rows <- rowSums(!is.na(min_yr_df2_sc[, yrs, drop = FALSE])) > 0 + +plot_df_sc <- min_yr_df2_sc %>% + dplyr::filter(keep_rows) %>% + # keep LAB + years + dplyr::select(LAB, all_of(yrs)) %>% + # long format: one row per LAB-year + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + # presence flag (you can keep n as-is if you later want 2 = highlight) + present = !is.na(n), + # order so your first row is at the top (like your raster plot with rev()) + LAB = factor(LAB, levels = rev(unique(LAB))) + ) + +# 3) Plot +p_sc <- ggplot(plot_df_sc, aes(x = YEAR, y = LAB, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete(expand = c(0, 0)) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) +print(p_sc) +ggsave(filename = paste0(Dirout, "Commercial_size_limits_SC.jpeg"), + plot = p_sc, width = 6.5, height = 4.6, dpi = 300) + + diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_TripLim.R b/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_TripLim.R new file mode 100644 index 0000000..d619367 --- /dev/null +++ b/ODM-MH-Analysis_ready/Management History Comparison Files/S103Carib_TripLim.R @@ -0,0 +1,427 @@ +########################################## +# Commercial Trip Limits & IFQ Program # +########################################## + +librarian::shelf(here, tidyverse, lubridate, openxlsx, neatRanges, splitstackshape, dplyr) + +# Set output directory for plots +Dirout<-paste0(getwd(),"/Trip limits and IFQ/") +if(!file.exists(Dirout)) dir.create(Dirout) + +# MH dataset +mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Nov18.RDS")) + +# Set end year for plots +termyr<-2025 + +# Subset for Gulf Reef Fish commercial trip limits and IFQ +# Subset for Gulf Reef Fish size limits - Puerto Rico +mh_carib_pr_trip <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + #"FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + #"FMP FOR THE EEZ AROUND ST. CROIX", + "FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'COMMERCIAL', + MANAGEMENT_TYPE_USE == 'TRIP LIMIT', + ZONE_USE %in% c("ALL", "PUERTO RICO MANAGEMENT AREA")) +mh_carib_pr_trip <- mh_carib_pr_trip %>% + mutate(END_DATE2 = case_when(FR_CITATION == "78 FR 56171" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2022-10-13"), + TRUE ~ END_DATE2)) + +# Confirm trip limits +unique(mh_carib_pr_trip$MANAGEMENT_TYPE_USE) + +# Confirm only commercial +table(mh_carib_pr_trip$SECTOR_USE) + +source(here("ODM-MH-Analysis_ready", "Closures", "func_expand_status.R")) + +############# +# Trip limits +############# + +trip_df_pr <- expand_status(mh_carib_pr_trip, "TRIP LIMIT") + +# Collapse to annual value +trip_df_pr <- trip_df_pr %>% + mutate(YEAR = year(date_sequence)) %>% + dplyr::select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + distinct() + +# Explore Zone +table(trip_df_pr$ZONE_USE) +# All for all data + +# Explore Subsector +table(trip_df_pr$SUBSECTOR_USE) +# All for all data + +# Explore year - only include complete years +table(trip_df_pr$YEAR) +trip_df_pr<-trip_df_pr %>% filter(YEAR <=termyr) +table(trip_df_pr$YEAR) + +# Format for plot +trip_df_pr2 <- trip_df_pr %>% + mutate(VALUE_UNITS = case_when(VALUE_UNITS == 'POUNDS' ~ 'lb', + TRUE ~ VALUE_UNITS), + VALUE_UNITS = case_when(VALUE_UNITS == 'CONCH' ~ 'conch', + TRUE ~ VALUE_UNITS), + VALUE_TYPE = case_when(VALUE_TYPE == 'GUTTED WEIGHT' ~ 'GW', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == 'ROUND (WHOLE) WEIGHT' ~ 'WW', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == 'COUNT' ~ '', + TRUE ~ VALUE_TYPE), + VALUE_RATE = case_when(VALUE_RATE == 'PER VESSEL PER DAY' ~ 'per vessel per day', + VALUE_RATE == "PER PERSON PER DAY" ~ "per person per day", + TRUE ~ VALUE_RATE), + VAL_LAB = paste(VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE), + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)),"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE,"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE, "(Zone ", ZONE_USE, ")", VAL_LAB), + n = 1) %>% + dplyr::select(LAB, YEAR, n) %>% + arrange(YEAR) %>% + pivot_wider(names_from = YEAR, values_from = n) %>% + arrange(LAB) + +view(trip_df_pr2) +trip_df_pr2$LAB +# Individual species are showing up, rather than aggregates +# Black Grouper (10000, 6000, 7500, 5500) +# Dwarf Sand Perch (10000, 7500) +# Gag Grouper (10000, 6000, 7500, 5500) +# Gray Triggerfish (12, 16, 25) +# Greater Amberjack (1000, 1500, 2000, 250, 7) +# Misty Grouper (10000, 6000, 7500) +# Red Grouper (10000, 6000, 7500, 5500) +# Red Hind (10000, 6000, 7500, 5500) +# Red Snapper (1000, 200, 2000) +# Rock Hind (10000, 6000, 7500, 5500) +# Sand Perch (10000, 7500) +# Scamp (10000, 6000, 7500, 5500) +# Snowy Grouper (10000, 6000, 7500) +# Speckled Hind (10000, 6000, 7500) +# Warsaw Grouper (10000, 6000, 7500) +# Yellowedge Grouper (10000, 6000, 7500) +# Yellowfin Grouper (10000, 6000, 7500, 5500) +# Yellowmouth Grouper (10000, 6000, 7500, 5500) + +# Need to end trip limits when IFQ comes in +#trip_yr_df2[trip_yr_df2$LAB=="Red Snapper - 200 lb WW per trip",which(colnames(trip_yr_df2)=="2007"):dim(trip_yr_df2)[2]]<-NA #2007+ +#trip_yr_df2[trip_yr_df2$LAB=="Red Snapper - 2000 lb WW per trip",which(colnames(trip_yr_df2)=="2007"):dim(trip_yr_df2)[2]]<-NA #2007+ +#trip_yr_df2[trip_yr_df2$LAB=="Black Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Gag Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Misty Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Red Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Red Hind - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Rock Hind - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Scamp - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +##trip_yr_df2[trip_yr_df2$LAB=="Snowy Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Speckled Hind - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Warsaw Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Yellowedge Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Yellowfin Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ +#trip_yr_df2[trip_yr_df2$LAB=="Yellowmouth Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df2)=="2010"):dim(trip_yr_df2)[2]]<-NA #2010+ + + +# Keep Gray Triggerfish, Greater Amberjack, Red Snapper, D&SWG (Black Grouper), DWG (e.g.,Misty) +#trip_yr_df3<-trip_yr_df2[c(11:13,17,14:16,18,31,30,32,2:4,1,20:21,19),] + +# Need to end trip limits when IFQ comes in for D&SWG (2010), DWG (2010), and RSN (2007) +#trip_yr_df3[trip_yr_df3$LAB=="Red Snapper - 200 lb WW per trip",which(colnames(trip_yr_df3)=="2007"):dim(trip_yr_df3)[2]]<-NA #2007+ +#trip_yr_df3[trip_yr_df3$LAB=="Red Snapper - 2000 lb WW per trip",which(colnames(trip_yr_df3)=="2007"):dim(trip_yr_df3)[2]]<-NA #2007+ +#trip_yr_df3[trip_yr_df3$LAB=="Black Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df3)=="2010"):dim(trip_yr_df3)[2]]<-NA #2010+ +#trip_yr_df3[trip_yr_df3$LAB=="Misty Grouper - 6000 lb GW per trip",which(colnames(trip_yr_df3)=="2010"):dim(trip_yr_df3)[2]]<-NA #2010+ + +# Need to redefine Misty Grouper as Deepwater Grouper +#trip_yr_df3$LAB[trip_yr_df3$LAB=="Misty Grouper - 6000 lb GW per trip"]<-"Deep-Water Grouper - 6000 lb GW per trip" +#trip_yr_df3$LAB[trip_yr_df3$LAB=="Misty Grouper - 7500 lb GW per trip"]<-"Deep-Water Grouper - 7500 lb GW per trip" +#trip_yr_df3$LAB[trip_yr_df3$LAB=="Misty Grouper - 10000 lb GW per trip"]<-"Deep-Water Grouper - 10000 lb GW per trip" + +# Need to redefine Black Grouper as Deep & Shallowwater Grouper +#trip_yr_df3$LAB[trip_yr_df3$LAB=="Black Grouper - 5500 lb GW per trip"]<-"Shallow-Water Grouper - 5500 lb GW per trip" +#trip_yr_df3$LAB[trip_yr_df3$LAB=="Black Grouper - 6000 lb GW per trip"]<-"Shallow-Water Grouper - 6000 lb GW per trip" +#trip_yr_df3$LAB[trip_yr_df3$LAB=="Black Grouper - 7500 lb GW per trip"]<-"Shallow-Water Grouper - 7500 lb GW per trip" +#trip_yr_df3$LAB[trip_yr_df3$LAB=="Black Grouper - 10000 lb GW per trip"]<-"Shallow-Water Grouper - 10000 lb GW per trip" + +# Save outputs before we clean up labels +saveRDS(trip_df_pr2,paste0(Dirout,"commercial_trip_limits.rds")) + +# Remove extra space in label +trip_df_pr2$LAB[which(trip_df_pr2$LAB=="Queen Conch - 200 conch per vessel per day")]<-"- 200 conch per vessel per day" + +########################################################### +library(tidyverse) + +# 1) Get just the year columns (handles if LAB is col 1) +yrs <- names(trip_df_pr2) +yrs <- yrs[grepl("^\\d{4}$", yrs)] # keep only "1985", "1986", ... +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# 2) Optional: drop empty rows (all NA across years) +keep_rows <- rowSums(!is.na(trip_df_pr2[, yrs, drop = FALSE])) > 0 + +plot_df_pr <- trip_df_pr2 %>% + dplyr::filter(keep_rows) %>% + # keep LAB + years + dplyr::select(LAB, all_of(yrs)) %>% + # long format: one row per LAB-year + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + # presence flag (you can keep n as-is if you later want 2 = highlight) + present = !is.na(n), + # order so your first row is at the top (like your raster plot with rev()) + LAB = factor(LAB, levels = rev(unique(LAB))) + ) + +# 3) Plot +p_pr_trip <- ggplot(plot_df_pr, aes(x = YEAR, y = LAB, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete(expand = c(0, 0)) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) +print(p_pr_trip) +ggsave(filename = paste0(Dirout, "Commercial_trip_limits_pr.jpeg"), + plot = p_pr_trip, width = 6.5, height = 4.6, dpi = 300) + + +######### +# Plots # +######### + +library(raster) +#Note: importing this package masks select from dplyr... + + +groups<-dplyr::select(trip_df_pr2, LAB) %>% pull() +names<-c(min(trip_df_pr2$YEAR):max(trip_df_pr2$YEAR)) + +yrs <- as.character(1997:2025) +yrs <- names(trip_df_pr2) +yrs <- yrs[grepl("^\\d{4}$", yrs)] +yrs <- yrs[as.integer(yrs) >= 1997 & as.integer(yrs) <= 2025] + +Trip<-raster(as.matrix(trip_df_pr2[,2:dim(trip_df_pr2)[2]])) +m <- as.matrix(trip_df_pr2[, -1]) +keep_rows <- which(rowSums(!is.na(m))>0) +m_trim <- m[keep_rows, , drop = FALSE] +groups<-dplyr::select(trip_df_pr2, LAB) %>% pull() +trip_pr_trim <- raster::raster(m_trim) +#names<-c(min(trip_df_pr2$YEAR):max(trip_df_pr2$YEAR)) +names <- as.character(1997:2025) +groups_trim <- groups[keep_rows] + + +nrows <- nrow(m_trim) +ncols <- ncol(m_trim) + +y_at <- seq(from = (1/nrows)/ 2, + to = 1 - (1/nrows)/ 2, + by = 1/ nrows) + +x_at <- seq(from = (1/ncols)/ 2, + to = 1 - (1/ncols)/2, + by = 1/ncols) + + +jpeg(paste0(Dirout,"Commercial_trip.jpeg"),res=300,height=4.8,width=6.9, units="in") +par(mar=c(0.1, 11.5, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(Trip,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(trip_df_pr2)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +axis(2,at=seq(((1/dim(trip_df_pr2)[1])/2),1,(1/dim(trip_df_pr2)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.5,font=1) +axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.6,las=2,hadj=0.7) +dev.off() + +Trip2<-raster(as.matrix(trip_yr_df2[,2:dim(trip_yr_df2)[2]])) +groups<-dplyr::select(trip_yr_df2, LAB) %>% pull() +names<-c(min(trip_yr_df$YEAR):max(trip_yr_df$YEAR)) + +jpeg(paste0(Dirout,"Commercial_trip_species.jpeg"),res=300,height=4.8,width=6.3, units="in") +par(mar=c(0.1, 6.5, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(Trip2,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(trip_yr_df2)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +axis(2,at=seq(((1/dim(trip_yr_df2)[1])/2),1,(1/dim(trip_yr_df2)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.3,font=1) +axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.6,las=2,hadj=0.7) +dev.off() + +# Plot +IFQ<-raster(as.matrix(IFQ_yr_df2[,2:dim(IFQ_yr_df2)[2]])) +groups<-dplyr::select(IFQ_yr_df2, LAB) %>% pull() +names<-c(min(IFQ_yr_df$YEAR):max(IFQ_yr_df$YEAR)) + +jpeg(paste0(Dirout,"Commercial_IFQ_species.jpeg"),res=300,height=4.8,width=6.1, units="in") +par(mar=c(0.1, 5.5, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(IFQ,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(IFQ_yr_df2)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +axis(2,at=seq(((1/dim(IFQ_yr_df2)[1])/2),1,(1/dim(IFQ_yr_df2)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.5,font=1) +axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.6,las=2,hadj=0.7) +dev.off() + +# Combine trip limits and IFQ into dataframe +trip_yr_df4<-as.data.frame(rbind(trip_yr_df3, + as.numeric(c("SNAPPER, RED IFQ",rep(NA,15),rep(1,18))), + as.numeric(c("GROUPER-TILEFISH IFQ",rep(NA,18),rep(1,15))))) +trip_yr_df4$LAB[(dim(trip_yr_df4)[1]-1):dim(trip_yr_df4)[1]]<-c("- IFQ","Grouper-Tilefish IFQ") +trip_yr_df4<-trip_yr_df4[c(1:11,19,12:18,20),] # Reorder by family/species (manually for now...) +Trip3<-raster(as.matrix(trip_yr_df4[,2:dim(trip_yr_df4)[2]])) +groups<-dplyr::select(trip_yr_df4, LAB) %>% pull() +names<-c(min(trip_yr_df$YEAR):max(trip_yr_df$YEAR)) + +jpeg(paste0(Dirout,"Commercial_trip_IFQ.jpeg"),res=300,height=4.2,width=6.3, units="in") +par(mar=c(0.1, 9.5, 2, 0), xpd=TRUE,oma=c(0,0,1.5,0)) +brks<-c(0,1,2); cols<-c("lightblue","red") +plot(Trip3,breaks=brks,col=cols,axes=F,legend=F,legend.shrink=0.1,xlab="",main="") +abline(h=c(seq(0,1,(1/dim(trip_yr_df4)[1]))),col="lightgray") +abline(v=c(seq(0,1,(1/length(names)))),col="lightgray") +axis(2,at=seq(((1/dim(trip_yr_df4)[1])/2),1,(1/dim(trip_yr_df4)[1])),labels=rev(groups),las=2,tck=0,cex.axis=0.5,font=1) +axis(3,at=seq(((1/length(names))/2),1,(1/length(names))),labels=names,las=2,tck=0,cex.axis=0.6,las=2,hadj=0.7) +dev.off() + +################################################################# +# Subset for Gulf Reef Fish commercial trip limits and IFQ +# Subset for Gulf Reef Fish size limits - Puerto Rico +mh_carib_sc_trip <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + #"FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + "FMP FOR THE EEZ AROUND ST. CROIX", + #"FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0, SECTOR_USE == 'COMMERCIAL', + MANAGEMENT_TYPE_USE == 'TRIP LIMIT', + ZONE_USE %in% c("ALL", "ST. CROIX MANAGEMENT AREA")) +mh_carib_sc_trip <- mh_carib_sc_trip %>% + mutate(END_DATE2 = case_when(FR_CITATION == "78 FR 56171" & COMMON_NAME_USE == "CONCH, QUEEN" ~ as.Date("2021-10-13"), + TRUE ~ END_DATE2)) + +# Confirm trip limits +unique(mh_carib_sc_trip$MANAGEMENT_TYPE_USE) + +# Confirm only commercial +table(mh_carib_sc_trip$SECTOR_USE) + +source(here("ODM-MH-Analysis_ready", "Closures", "func_expand_status.R")) + +############# +# Trip limits +############# + +trip_df_sc <- expand_status(mh_carib_sc_trip, "TRIP LIMIT") + +# Collapse to annual value +trip_df_sc <- trip_df_sc %>% + mutate(YEAR = year(date_sequence)) %>% + dplyr::select(COMMON_NAME_USE, ZONE_USE, SUBSECTOR_USE, YEAR, + VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE) %>% + distinct() + +# Explore Zone +table(trip_df_sc$ZONE_USE) +# All for all data + +# Explore Subsector +table(trip_df_sc$SUBSECTOR_USE) +# All for all data + +# Explore year - only include complete years +table(trip_df_sc$YEAR) +trip_df_sc<-trip_df_sc %>% filter(YEAR <=termyr) +table(trip_df_sc$YEAR) + +# Format for plot +trip_df_sc2 <- trip_df_sc %>% + mutate(VALUE_UNITS = case_when(VALUE_UNITS == 'POUNDS' ~ 'lb', + TRUE ~ VALUE_UNITS), + VALUE_UNITS = case_when(VALUE_UNITS == 'CONCH' ~ 'conch', + TRUE ~ VALUE_UNITS), + VALUE_TYPE = case_when(VALUE_TYPE == 'GUTTED WEIGHT' ~ 'GW', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == 'ROUND (WHOLE) WEIGHT' ~ 'WW', + TRUE ~ VALUE_TYPE), + VALUE_TYPE = case_when(VALUE_TYPE == 'COUNT' ~ '', + TRUE ~ VALUE_TYPE), + VALUE_RATE = case_when(VALUE_RATE == 'PER VESSEL PER DAY' ~ 'per vessel per day', + VALUE_RATE == "PER PERSON PER DAY" ~ "per person per day", + TRUE ~ VALUE_RATE), + VAL_LAB = paste(VALUE, VALUE_UNITS, VALUE_TYPE, VALUE_RATE), + LAB = paste(str_to_title(sub('(.*)\\,\\s+(.*)','\\2 \\1',COMMON_NAME_USE)),"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE,"-", VAL_LAB), + # LAB = paste(COMMON_NAME_USE, "(Zone ", ZONE_USE, ")", VAL_LAB), + n = 1) %>% + dplyr::select(LAB, YEAR, n) %>% + arrange(YEAR) %>% + pivot_wider(names_from = YEAR, values_from = n) %>% + arrange(LAB) + +view(trip_df_sc2) +trip_df_sc2$LAB + + +# Save outputs before we clean up labels +saveRDS(trip_df_sc2,paste0(Dirout,"commercial_trip_limits.rds")) + +# Remove extra space in label +trip_df_sc2$LAB[which(trip_df_sc2$LAB=="Queen Conch - 200 conch per vessel per day")]<-"- 200 conch per vessel per day" + +########################################################### +library(tidyverse) + +# 1) Get just the year columns (handles if LAB is col 1) +yrs <- names(trip_df_sc2) +yrs <- yrs[grepl("^\\d{4}$", yrs)] # keep only "1985", "1986", ... +yrs <- yrs[as.integer(yrs) >= 1985 & as.integer(yrs) <= termyr] + +# 2) Optional: drop empty rows (all NA across years) +keep_rows <- rowSums(!is.na(trip_df_sc2[, yrs, drop = FALSE])) > 0 + +plot_df_sc <- trip_df_sc2 %>% + dplyr::filter(keep_rows) %>% + # keep LAB + years + dplyr::select(LAB, all_of(yrs)) %>% + # long format: one row per LAB-year + tidyr::pivot_longer(cols = dplyr::all_of(yrs), names_to = "YEAR", values_to = "n") %>% + dplyr::mutate( + YEAR = as.integer(YEAR), + # presence flag (you can keep n as-is if you later want 2 = highlight) + present = !is.na(n), + # order so your first row is at the top (like your raster plot with rev()) + LAB = factor(LAB, levels = rev(unique(LAB))) + ) + +# 3) Plot +p_sc_trip <- ggplot(plot_df_sc, aes(x = YEAR, y = LAB, fill = present)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(1985, termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete(expand = c(0, 0)) + + scale_fill_manual(values = c(`TRUE` = "lightblue", `FALSE` = "white"), guide = "none") + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 9), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) +print(p_sc_trip) +ggsave(filename = paste0(Dirout, "Commercial_trip_limits_sc.jpeg"), + plot = p_sc_trip, width = 6.5, height = 4.6, dpi = 300) diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/S103CaribbeanVisualizations.R b/ODM-MH-Analysis_ready/Management History Comparison Files/S103CaribbeanVisualizations.R new file mode 100644 index 0000000..7c0da00 --- /dev/null +++ b/ODM-MH-Analysis_ready/Management History Comparison Files/S103CaribbeanVisualizations.R @@ -0,0 +1,260 @@ +# Management History Visualizations for Caribbean (S103) + +library(tidyverse) +library(here) +library(lubridate) +library(ggrepel) +library(openxlsx) + +# MH dataset +mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Nov18.RDS")) + +mh <- mh %>% + mutate(COMMON_NAME_USE = case_when(REGULATION_ID == '1411' ~ "MALACANTHIDAE—TILEFISHES", + TRUE ~ COMMON_NAME_USE)) + +# Subset for South Atlantic Snapper Grouper +mh_carib <- mh %>% filter(FMP %in% c("REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "FMP FOR THE EEZ AROUND ST. THOMAS AND ST. JOHN", + "FMP FOR THE EEZ AROUND ST. CROIX", + "FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS")) %>% + # Remove recs that were never implemented + filter(NEVER_IMPLEMENTED == 0) + +management_sector_counts <- mh_carib %>% + group_by(MANAGEMENT_CATEGORY, SECTOR_USE) %>% + summarise(total_records = n_distinct(REGULATION_ID)) + +mh_carib_closure <- mh_carib %>% + filter(MANAGEMENT_TYPE_USE == "CLOSURE") +total_records_by_sector <- mh_carib_closure %>% + filter(MANAGEMENT_TYPE_USE == "CLOSURE") %>% + group_by(SECTOR_USE) %>% + summarise(total_records = n()) + +# Summarize management types by sector +plot1 <- ggplot(mh_carib %>% + group_by(SECTOR_USE, MANAGEMENT_CATEGORY) %>% + summarise(nrecs = n_distinct(REGULATION_ID)) %>% + group_by(SECTOR_USE) %>% + mutate(tot = sum(nrecs), perc = nrecs/tot, labels = paste0(round(perc * 100,1), "%")), aes(x = "" , y = perc, fill = MANAGEMENT_CATEGORY)) + + geom_col(width = 1, color = 1) + + coord_polar(theta = "y") + + geom_text(aes(x = 1.7, label = labels), size=4.5, + position = position_stack(vjust = 0.5))+ + facet_wrap(~SECTOR_USE) + + guides(fill = guide_legend(title = "Management Category")) + + theme_void() +print(plot1) + +# Timeline - number of regulations by sector by year +reg_yr <- mh_carib %>% + mutate(YEAR = year(EFFECTIVE_DATE)) %>% + group_by(SECTOR_USE, YEAR, MANAGEMENT_CATEGORY, MANAGEMENT_TYPE_USE) %>% + summarize(nFRs = n_distinct(FR_CITATION), + nregs = n()) + +# Plot by management cat and sector +plot2 <- ggplot(reg_yr) + + geom_bar(aes(y=nFRs, x=YEAR), stat = 'identity') + + labs(x = "Year", y = "Number of FRs Published") + + facet_grid(SECTOR_USE~MANAGEMENT_CATEGORY, scales = "free_y") + + theme_bw() +print(plot2) + +# FRs published by year and species +# Clean up species into removed and currently managed categories +species_list <- read.csv(here("Examples", "Testfiles", "snappergrouper_specieslist.csv")) + +species_list <- species_list %>% + mutate(REMOVED_DT = case_when(REMOVED_DT == '' ~ NA, + TRUE ~ REMOVED_DT)) + +currently_managed <- species_list %>% filter(is.na(REMOVED_DT)) %>% select(COMMON_NAME) %>% pull() + +# Prep for join +sp_list_all <- species_list %>% + select(COMMON_NAME, ADDED_DT, REMOVED_DT) %>% + mutate(COMMON_NAME_USE = 'ALL', + ) %>% + mutate(ADDED_DATE = as.Date(ADDED_DT, origin = "1899-12-30"), + REMOVED_DATE = as.Date(REMOVED_DT, origin = "1899-12-30")) + + +# Aggregate species list +species_aggs <- read.csv(here("Examples", "Testfiles", "snappergrouper_aggregatefinal.csv")) %>% + mutate(COMMON_NAME_USE = COMMON_NAME, + SPP_NAME = FMP_SPECIES_AGG_NAME, + ADDED_DATE = as.Date(ADDED_DT, origin = "1899-12-30"), + REMOVED_DATE = as.Date(REMOVED_DT, origin = "1899-12-30"), + # convert FMP agg name to uppercase + FMP_SPECIES_AGG_NAME = toupper(FMP_SPECIES_AGG_NAME)) + + +# Prep for join +#species_ifq_agg <- species_aggs %>% +# filter(FMP_SPECIES_AGG_NAME %in% c('IFQ: DEEP-WATER GROUPERS (DWG)', +# 'IFQ: OTHER SHALLOW-WATER GROUPERS (OTHER SWG)', +# 'IFQ: TILEFISHES')) %>% +#select(FMP_SPECIES_AGG_NAME, COMMON_NAME, ADDED_DATE, REMOVED_DATE) + +mh_srgr_cleaned <- mh_srgr %>% + # Expand common name all species + full_join(sp_list_all, by = join_by(COMMON_NAME_USE), multiple = 'all') %>% + mutate(YEAR = year(EFFECTIVE_DATE), + SPECIES = case_when(COMMON_NAME_USE == 'ALL' ~ COMMON_NAME, + TRUE ~ COMMON_NAME_USE), + flg_dt = case_when(COMMON_NAME_USE == 'ALL' & EFFECTIVE_DATE% + # Remove regs expanded for species before they were in the FMP + filter(flg_dt == 0) %>% + select(-c(ADDED_DATE, REMOVED_DATE, flg_dt)) %>% + # Fix effective dates + left_join(sp_list_all %>% select(-COMMON_NAME_USE), by=join_by(SPECIES == COMMON_NAME)) %>% + mutate(flg_dt = case_when(EFFECTIVE_DATEREMOVED_DATE ~ 1, + END_DATE2 > REMOVED_DATE ~ 1, + TRUE ~ 0)) %>% + filter(flg_dt == 0) %>% + select(-c(COMMON_NAME, ADDED_DATE, REMOVED_DATE, flg_dt)) %>% + full_join(species_aggs, by = join_by(SPECIES == FMP_SPECIES_AGG_NAME), multiple='all') %>% + filter(!is.na(FR_CITATION)) %>% + mutate(SPECIES = case_when(!is.na(COMMON_NAME) ~ COMMON_NAME, + TRUE ~ SPECIES), + flg_dt = case_when(!is.na(ADDED_DATE) & EFFECTIVE_DATE REMOVED_DATE ~ 1, + TRUE ~ 0)) %>% + filter(flg_dt == 0) %>% + mutate(SPECIES = case_when(SPECIES == 'JEWFISH' ~ 'GROUPER, GOLIATH', + TRUE ~ SPECIES), + #SPECIES == 'Caulolatilus' ~ 'TILEFISHES', + # + # SPECIES == 'Centropristis melana' ~ 'BASS, BLACK SEA', + # TRUE ~ SPECIES), + managed = case_when(SPECIES %in% currently_managed ~ 'Currently managed', TRUE ~ 'Removed from FMP')) + +chk <- mh_srgr_cleaned %>% ungroup() %>% + select(SPECIES, managed) %>% distinct() + +sp_yr <- mh_srgr_cleaned %>% group_by(managed, SPECIES, YEAR) %>% + summarize(nFRs = n_distinct(FR_CITATION)) + +plot <- ggplot(sp_yr %>% filter(managed == 'Currently managed') + , aes(x=YEAR, y=SPECIES, fill=nFRs)) + + geom_tile() + + scale_fill_gradientn(colours = c("#44ce1b", "#f7e379", "#e51f1f"), values = c(0,0.5,1)) + + theme_classic() + +# Timeline - number of regulations by sector by year +reg_yr <- mh_srgr %>% + mutate(YEAR = year(EFFECTIVE_DATE)) %>% + group_by(SECTOR_USE, YEAR, MANAGEMENT_CATEGORY, MANAGEMENT_TYPE_USE) %>% + summarize(nFRs = n_distinct(FR_CITATION), + nregs = n()) + +# Plot by management cat and sector +plot3 <- ggplot(reg_yr) + + geom_bar(aes(y=nFRs, x=YEAR), stat = 'identity') + + facet_grid(SECTOR_USE~MANAGEMENT_CATEGORY, scales = "free_y") + + theme_bw() + + +# Type of closures - mostly once and seasonal +mh_srgr_closure <- mh_srgr %>% + filter(MANAGEMENT_TYPE_USE == "CLOSURE") + +total_records <- mh_srgr_closure %>% + # distinct(REGULATION_ID) %>% + nrow() +print(total_records) + +total_records_by_sector <- mh_srgr_closure %>% + filter(MANAGEMENT_TYPE_USE == "CLOSURE") %>% + #distinct(REGULATION_ID, .keep_all = TRUE) %>% + group_by(SECTOR_USE, MANAGEMENT_STATUS_USE) %>% + summarise(total_records = n()) +print(total_records_by_sector) + +plot4 <- mh_srgr %>% + filter(MANAGEMENT_TYPE_USE == 'CLOSURE') %>% + group_by(SECTOR_USE, MANAGEMENT_STATUS_USE) %>% + summarise(nrecs = n()) %>% + group_by(SECTOR_USE) %>% + mutate(totregs = sum(nrecs), + percentage = nrecs/totregs*100) %>% + ggplot(aes(x=1, y=nrecs, fill = MANAGEMENT_STATUS_USE)) + + geom_bar(stat="identity", width = .1, position = "fill") + + coord_polar("y", start = 0) + + facet_wrap(~SECTOR_USE) + + geom_text(aes(label = paste0(round(percentage), "%")), position = position_fill(vjust = 0.5), size = 5) + + theme_void() + + labs(fill = 'Type of Closure') + +# Heat map of commercial closures overtime by species when closure for all of Gulf +# Read in management status function +source("C:/Users/gaitlyn.malone/Documents/SEFSC-ODM-Management-History/ODM-MH-Analysis_ready/Closures/func_expand_status.R") + +# Expand closures +closures <- expand_status(mh_srgr, "CLOSURE") + +# Filter to main closures for subsector all, zone all +# Add IFQ +sum_closures <- closures %>% + mutate(value = 1, + managed = case_when(COMMON_NAME_USE %in% currently_managed ~ 'Currently managed', TRUE ~ 'Removed from FMP'), + SECTOR_lab = paste(SECTOR_USE, SUBSECTOR_USE, sep="-"), + type = 'Closure') %>% + filter(VALUE == 'CLOSE', SUBSECTOR_USE == 'ALL', ZONE_USE == 'ALL', managed == 'Currently managed') %>% + # Add IFQ + bind_rows(mh_srgr %>% filter(MANAGEMENT_TYPE_USE == "ITQ PROGRAM ESTABLISHED") %>% ungroup() %>% + select(REGULATION_ID, CLUSTER, FR_CITATION, SECTOR_USE, SUBSECTOR_USE, COMMON_NAME_USE, VALUE, + START_DATE2, END_DATE2) %>% + mutate(date_sequence = map2(START_DATE2, END_DATE2, seq, by = "days")) %>% + unnest(date_sequence) %>% + mutate(value = 2, + type = "ITQ", + SECTOR_lab = paste(SECTOR_USE, SUBSECTOR_USE, sep="-"))) + +# Plot using expand function +plot5 <- ggplot(sum_closures, aes(x=date_sequence, y = COMMON_NAME_USE, fill=value)) + + geom_tile() + + facet_wrap(~SECTOR_lab, ncol = 1) + + scale_x_date(date_breaks = "1 year",date_labels = "%Y", + limits = c(min(sum_closures$date_sequence), max = max(sum_closures$date_sequence)), expand=c(0,0)) + + #geom_vline(xintercept = as.Date("2010-01-01"), linetype = 'dashed', color = 'red') + + #geom_vline(xintercept = as.Date("2007-01-01"), linetype = 'dashed', color = 'red') + + labs(y = "Species", x = "Date") + + theme_minimal() + + theme(legend.position = "none", + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) + +# Get count of FRs by species, consol. mcat, and sector +sum_sp_mtype_sect <- mh_srgr_cleaned %>% + filter(managed == "Currently managed") %>% ungroup() %>% + # Consolidate management category into 4 groups + mutate(MCAT_GRP = case_when(MANAGEMENT_CATEGORY %in% c('EFFORT LIMITS', 'GEAR REQUIREMENTS', 'HARVEST LIMITATIONS', + 'UNIVERSAL', 'SELECTIVITY CONTROLS') ~ 'EFFORT/GEAR LIMITS', + TRUE ~ MANAGEMENT_CATEGORY)) %>% + filter(MANAGEMENT_CATEGORY != 'OTHER') %>% + group_by(SPECIES, managed, MANAGEMENT_CATEGORY) %>% + summarize(nFRs = n_distinct(FR_CITATION), + nregs = n_distinct(REGULATION_ID)) + +plot_sms <- ggplot(sum_sp_mtype_sect) + + geom_bar(aes(x=nregs, y = SPECIES, fill=MANAGEMENT_CATEGORY), stat="identity") + + labs(fill="Management Category", x = "Number of Regulations")+ + theme_classic() + +# Look into 'other' category +other_reg_yr <- mh_srgr %>% + mutate(YEAR = year(EFFECTIVE_DATE)) %>% + filter(MANAGEMENT_CATEGORY == 'OTHER') %>% + group_by(YEAR, MANAGEMENT_TYPE_USE) %>% + summarize(nFRs = n_distinct(FR_CITATION), + nregs = n()) %>% + ggplot() + + geom_bar(aes(y=nFRs, x=YEAR), stat = 'identity') + + facet_wrap(~MANAGEMENT_TYPE_USE, ncol=2, scales = "free_y") + + theme_bw() diff --git a/ODM-MH-Analysis_ready/Management History Comparison Files/S103_Closures.R b/ODM-MH-Analysis_ready/Management History Comparison Files/S103_Closures.R new file mode 100644 index 0000000..ed17574 --- /dev/null +++ b/ODM-MH-Analysis_ready/Management History Comparison Files/S103_Closures.R @@ -0,0 +1,217 @@ +librarian::shelf(here, tidyverse, lubridate, openxlsx, neatRanges, splitstackshape, dplyr) + +# Set output directory for plots +Dirout<-paste0(getwd(),"/Closures/") +if(!file.exists(Dirout)) dir.create(Dirout) + +# MH dataset +mh <- readRDS(here("ODM-MH-Data_log", "data", "results", "MH_DL_2025Nov18.RDS")) + +# Set end year for plots +termyr<-2025 + +####################### +# Closures # +####################### + + +# --- Your subset (as provided) --- +mh_carib_pr_lob <- mh %>% + dplyr::filter( + FMP %in% c( + "REEF FISH FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "FMP FOR THE EEZ AROUND PUERTO RICO", + "SPINY LOBSTER FISHERY OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS", + "QUEEN CONCH RESOURCES OF PUERTO RICO AND THE U.S. VIRGIN ISLANDS" + ), + NEVER_IMPLEMENTED == 0, + SECTOR_USE == "COMMERCIAL", + MANAGEMENT_CATEGORY == "TEMPORAL CONTROLS", + COMMON_NAME_USE == "LOBSTER, CARIBBEAN SPINY", + REGION == "CARIBBEAN", + ZONE_USE == "PUERTO RICO MANAGEMENT AREA" + ) + +unique(mh_carib_pr_lob$MANAGEMENT_TYPE_USE) +table(mh_carib_pr_lob$SECTOR_USE) + +# =========================== +# Create closure visualization +# Method: expand to YEARS + tile heatmap (ggplot) +# =========================== + +library(dplyr) +library(tidyr) +library(lubridate) +library(stringr) +library(ggplot2) + +termyr <- 2025 + +# 1) Keep closure-type records (adjust if your closure type label differs) +lob_cl <- mh_carib_pr_lob %>% + dplyr::filter(MANAGEMENT_TYPE_USE == "CLOSURE") %>% + dplyr::mutate( + start = as.Date(START_DATE2), + end = as.Date(dplyr::coalesce(END_DATE2, as.Date(paste0(termyr, "-12-31")))) + ) %>% + dplyr::filter(!is.na(start), !is.na(end), end >= start) + +# If you get "no records", check what closure type is called: +# unique(mh_carib_pr_lob$MANAGEMENT_TYPE_USE) + +# 2) Expand to YEAR (not days) +lob_yr <- lob_cl %>% + dplyr::mutate( + start_year = lubridate::year(start), + end_year = lubridate::year(end) + ) %>% + tidyr::uncount(end_year - start_year + 1, .id = "k") %>% + dplyr::mutate(YEAR = start_year + (k - 1L)) %>% + dplyr::filter(YEAR <= termyr) + +# 3) Create row label (edit if you want it simpler) +lob_yr <- lob_yr %>% + dplyr::mutate( + # interpret closure status; adjust if your VALUE field uses different text + status = dplyr::case_when( + VALUE %in% c("CLOSE", "CLOSED", "CLOSURE") ~ "CLOSE", + VALUE %in% c("OPEN") ~ "OPEN", + TRUE ~ as.character(VALUE) + ), + LAB = paste0( + "Caribbean Spiny Lobster - Commercial (PR)" + ) + ) + +# 4) Collapse to one status per year (CLOSE wins if mixed) +lob_yr_status <- lob_yr %>% + dplyr::group_by(LAB, YEAR) %>% + dplyr::summarise( + status = dplyr::if_else(any(status == "CLOSE"), "CLOSE", "OPEN"), + .groups = "drop" + ) + +# 5) Ensure all years appear on x-axis +all_years <- seq(min(lob_yr_status$YEAR, na.rm = TRUE), termyr) + +lob_yr_status <- lob_yr_status %>% + tidyr::complete(LAB, YEAR = all_years, fill = list(status = NA_character_)) %>% + dplyr::mutate(LAB = factor(LAB, levels = rev(sort(unique(LAB))))) + +# 6) Plot (tile heatmap) +p_lob_pr <- ggplot(lob_yr_status, aes(x = YEAR, y = LAB, fill = status)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_continuous(breaks = seq(min(all_years), termyr, by = 2), expand = c(0, 0)) + + scale_y_discrete(expand = c(0, 0)) + + scale_fill_manual( + values = c("CLOSE" = "lightblue", "OPEN" = "lightblue"), + na.value = "white", + guide = "none" + ) + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_text(size = 10), + axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), + plot.margin = margin(5, 5, 5, 5) + ) + +print(p_lob_pr) + +# 7) Save (uses your existing Dirout if defined; otherwise saves to wd) +out_file <- if (exists("Dirout")) file.path(Dirout, "Commercial_PR_SpinyLobster_Closures.jpeg") else "Commercial_PR_SpinyLobster_Closures.jpeg" +ggsave(out_file, plot = p_lob_pr, width = 7, height = 2.2, dpi = 300) + + +#####3 monthly value +library(dplyr) +library(tidyr) +library(lubridate) +library(ggplot2) + +# --------------------------- +# Monthly closure visualization +# --------------------------- + +# 1) Keep closure-type records (adjust if your closure type label differs) +lob_cl <- mh_carib_pr_lob %>% + dplyr::filter(MANAGEMENT_TYPE_USE == "CLOSURE") %>% + dplyr::mutate( + start = as.Date(START_DATE2), + end = as.Date(dplyr::coalesce(END_DATE2, as.Date("2025-12-31"))) + ) %>% + dplyr::filter(!is.na(start), !is.na(end), end >= start) + +# If you get "no records", check: +# unique(mh_carib_pr_lob$MANAGEMENT_TYPE_USE) + +# 2) Expand to MONTHS (not days) +lob_mo <- lob_cl %>% + dplyr::mutate( + start_m = floor_date(start, "month"), + end_m = floor_date(end, "month") + ) %>% + tidyr::uncount( + as.integer((year(end_m) - year(start_m)) * 12 + (month(end_m) - month(start_m)) + 1), + .id = "k" + ) %>% + dplyr::mutate(MONTH = start_m %m+% months(k - 1L)) + +# 3) Status mapping (adjust if VALUE uses different text) +lob_mo <- lob_mo %>% + dplyr::mutate( + status = dplyr::case_when( + VALUE %in% c("CLOSE", "CLOSED", "CLOSURE") ~ "CLOSE", + VALUE %in% c("OPEN") ~ "OPEN", + TRUE ~ as.character(VALUE) + ), + LAB = "Caribbean Spiny Lobster" + ) + +# 4) Collapse to one status per month (CLOSE wins) +lob_mo_status <- lob_mo %>% + dplyr::group_by(LAB, MONTH) %>% + dplyr::summarise( + status = dplyr::if_else(any(status == "CLOSE"), "CLOSE", "OPEN"), + .groups = "drop" + ) + +# 5) Make a complete month grid (so missing months plot as blank/white) +all_months <- seq(min(lob_mo_status$MONTH, na.rm = TRUE), + max(lob_mo_status$MONTH, na.rm = TRUE), + by = "1 month") + +lob_mo_status <- lob_mo_status %>% + tidyr::complete(LAB, MONTH = all_months, fill = list(status = NA_character_)) %>% + dplyr::mutate(LAB = factor(LAB, levels = rev(sort(unique(LAB))))) + +# 6) Plot +p_lob_pr_month <- ggplot(lob_mo_status, aes(x = MONTH, y = LAB, fill = status)) + + geom_tile(color = "lightgray", linewidth = 0.25) + + scale_x_date( + date_breaks = "1 month", + date_labels = "%b %Y", + expand = c(0, 0) + ) + + scale_y_discrete(expand = c(0, 0)) + + scale_fill_manual( + values = c("CLOSE" = "lightblue", "OPEN" = "lightblue"), + na.value = "white", + guide = "none" + ) + + labs(x = NULL, y = NULL) + + theme_minimal(base_size = 11) + + theme( + panel.grid = element_blank(), + axis.text.y = element_blank(), + axis.text.x = element_text(size = 6, angle = 45, vjust = 1, hjust = 1), + plot.margin = margin(t= 5, r = 40, b = 20, l = 40) + ) + +print(p_lob_pr_month) + +# 7) Save +out_file <- if (exists("Dirout")) file.path(Dirout, "Commercial_PR_SpinyLobster_Closures_Monthly.jpeg") else "Commercial_PR_SpinyLobster_Closures_Monthly.jpeg" +ggsave(out_file, plot = p_lob_pr_month, width = 9.5, height = 5, dpi = 300) diff --git a/ODM-MH-Data_log/MH00_clean_spp_tables.R b/ODM-MH-Data_log/MH00_clean_spp_tables.R index 650ca5b..ed8572d 100644 --- a/ODM-MH-Data_log/MH00_clean_spp_tables.R +++ b/ODM-MH-Data_log/MH00_clean_spp_tables.R @@ -2,6 +2,10 @@ # Standardize and fill in common name for FMP species, species aggregate and species group tables # Create work space containing the species list data frame to use in expansion (sp_info_use) +library(ROracle) +library(sqldf) +library(dotenv) +library(dplyr) # Connect to the server #### con <- dbConnect(dbDriver("Oracle"), @@ -134,5 +138,6 @@ sp_info_use = bind_rows(fmp_info_use, grp_info_use, agg_info_use) %>% rm(con, spp_grp_view, spp_agg_view, spp_itis_xref) # Save work space -saveRDS(sp_info_use, here('data', 'interim', 'MH_clean_spp_tables.RDS')) +library(here) +saveRDS(sp_info_use, here('ODM-MH-Data_log', 'data', 'interim', 'MH_clean_spp_tables.RDS')) diff --git a/ODM-MH-Data_log/data/interim/MH_clean_spp_tables.RDS b/ODM-MH-Data_log/data/interim/MH_clean_spp_tables.RDS index 995a14f..5e170d3 100644 Binary files a/ODM-MH-Data_log/data/interim/MH_clean_spp_tables.RDS and b/ODM-MH-Data_log/data/interim/MH_clean_spp_tables.RDS differ diff --git a/ODM-MH-Data_log/data/results/MH_DL_2025Sep10.RDS b/ODM-MH-Data_log/data/results/MH_DL_2025Nov18.RDS similarity index 100% rename from ODM-MH-Data_log/data/results/MH_DL_2025Sep10.RDS rename to ODM-MH-Data_log/data/results/MH_DL_2025Nov18.RDS