This index uses herring observed in predator stomachs to evaluate potential herring trends for the 2025 RT assessment.
Methods are based on the forage index for Bluefish (Gaichas et al. 2023) and the State of the Ecosystem forage index. These indices were inspired by Ng et al. (2021), which specifically looked at herring in stomachs of predators, but for each predator separately.
Will discuss a good starting point with the team. Preliminary models started in 1973 and used data through 2022. Data are thin prior to 1982 and I can’t bring in SST data from OISST before then, so for these examples we start in 1982. The herring RT model will start in 1987 so a 1982 start covers that.
Operational updates to the forage index submitted to the State of the Ecosystem report are in the forageindex github repository: https://github.com/NOAA-EDAB/forageindex
Data input files are in the folder fhdat
and were processed with the script VASTherringWG_ProcessInputDat.R
in that folder: https://github.com/NOAA-EDAB/forageindex/blob/main/fhdat/VASTherringWG_ProcessInputDat.R
# Streamlined version of CreateVASTInputs.Rmd for operational updates to forage index indicators
# February 2024
# This one uses only herring in stomachs, otherwise the same as SOE forage index
# To be presented to the 2025 herring RT WG
library(tidyverse)
library(here)
library(dendextend)
# Load NEFSC stomach data received from Brian Smith
# object is called `allfh`
load(here("fhdat/allfh.Rdata"))
#object is called allfh21
load(here("fhdat/allfh21.Rdata"))
#object is called allfh22
load(here("fhdat/allfh22.Rdata"))
# bind all NEFSC stomach datasets
allfh <- allfh %>%
dplyr::bind_rows(allfh21) |>
dplyr::bind_rows(allfh22)
###############################################################################
# read predator similarity info to generate predator list
# Input NEFSC food habits overlap matrix:
dietoverlap <- read_csv(here("fhdat/tgmat.2022-02-15.csv"))
# use dendextend functions to get list
d_dietoverlap <- dist(dietoverlap)
guilds <- hclust(d_dietoverlap, method = "complete")
dend <- as.dendrogram(guilds)
dend <- color_branches(dend, k=6) # Brian uses 6 categories
labels(dend) <- paste(as.character(names(dietoverlap[-1]))[order.dendrogram(dend)],
"(",labels(dend),")",
sep = "")
pisccomplete <- partition_leaves(dend)[[
which_node(dend, c("Bluefish..S(37)", "Bluefish..M(36)", "Bluefish..L(35)"))
]]
# Filter NEFSC food habits data with predator list
pisccompletedf <- data.frame("COMNAME" = toupper(str_remove(pisccomplete, "\\..*")),
"SizeCat" = str_remove(str_extract(pisccomplete, "\\..*[:upper:]+"), "\\.."),
"feedguild" = "pisccomplete")
fh.nefsc.pisc.pisccomplete <- allfh %>%
#filter(pynam != "EMPTY") %>%
left_join(pisccompletedf, by = c("pdcomnam" = "COMNAME",
"sizecat" = "SizeCat")) %>%
filter(!is.na(feedguild))
##############################################################################
# Get prey list from NEFSC and NEAMAP
# Irrelevant! The prey list is now Atlantic herring and unid clupeids.
# preycount <- fh.nefsc.pisc.pisccomplete %>%
# #group_by(year, season, pdcomnam, pynam) %>%
# group_by(pdcomnam, pynam) %>%
# summarise(count = n()) %>%
# #arrange(desc(count))
# pivot_wider(names_from = pdcomnam, values_from = count)
#
#
# gencomlist <- allfh %>%
# select(pynam, pycomnam2, gencom2) %>%
# distinct()
#
# NEFSCblueprey <- preycount %>%
# #filter(BLUEFISH > 9) %>%
# filter(!pynam %in% c("EMPTY", "BLOWN",
# "FISH", "OSTEICHTHYES",
# "ANIMAL REMAINS",
# "FISH SCALES")) %>%
# #filter(!str_detect(pynam, "SHRIMP|CRAB")) %>%
# left_join(gencomlist) %>%
# filter(!gencom2 %in% c("ARTHROPODA", "ANNELIDA",
# "CNIDARIA", "UROCHORDATA",
# "ECHINODERMATA", "WORMS",
# "BRACHIOPODA", "COMB JELLIES",
# "BRYOZOA", "SPONGES",
# "MISCELLANEOUS", "OTHER")) %>%
# arrange(desc(BLUEFISH))
#
# # March 2023, formally add NEAMAP to prey decisions
# NEAMAPblueprey <- read.csv(here("fhdat/Full Prey List_Common Names.csv")) %>%
# #filter(BLUEFISH > 9) %>%
# filter(!SCIENTIFIC.NAME %in% c("Actinopterygii", "fish scales",
# "Decapoda (megalope)",
# "unidentified material",
# "Plantae",
# "unidentified animal"))
#
# NEAMAPprey <- NEAMAPblueprey %>%
# dplyr::select(COMMON.NAME, SCIENTIFIC.NAME, BLUEFISH) %>%
# dplyr::filter(!is.na(BLUEFISH)) %>%
# dplyr::mutate(pynam2 = tolower(SCIENTIFIC.NAME),
# pynam2 = stringr::str_replace(pynam2, "spp.", "sp")) %>%
# dplyr::rename(NEAMAP = BLUEFISH)
#
#
# NEFSCprey <- NEFSCblueprey %>%
# dplyr::select(pycomnam2, pynam, BLUEFISH) %>%
# dplyr::filter(!is.na(BLUEFISH)) %>%
# dplyr::mutate(pynam2 = tolower(pynam)) %>%
# dplyr::rename(NEFSC = BLUEFISH)
#
# # new criteria March 2023, >20 observations NEAMAP+NEFSC, but keep mackerel
# # removes the flatfish order (too broad) and unid Urophycis previously in NEAMAP
# blueprey <- NEFSCprey %>%
# dplyr::full_join(NEAMAPprey) %>%
# dplyr::mutate(NEAMAP = ifelse(is.na(NEAMAP), 0, NEAMAP),
# NEFSC = ifelse(is.na(NEFSC), 0, NEFSC),
# total = NEFSC + NEAMAP,
# PREY = ifelse(is.na(SCIENTIFIC.NAME), pynam, SCIENTIFIC.NAME),
# COMMON = ifelse(is.na(COMMON.NAME), pycomnam2, COMMON.NAME),
# pynam = ifelse(is.na(pynam), toupper(pynam2), pynam)) %>%
# dplyr::arrange(desc(total)) %>%
# dplyr::filter(total>20 | pynam=="SCOMBER SCOMBRUS") %>% # >20 leaves out mackerel
# dplyr::mutate(COMMON = case_when(pynam=="ILLEX SP" ~ "Shortfin squids",
# pynam2=="teuthida" ~ "Unidentified squids",
# TRUE ~ COMMON)) %>%
# dplyr::mutate(PREY = stringr::str_to_sentence(PREY),
# COMMON = stringr::str_to_sentence(COMMON))
fh.nefsc.pisc.pisccomplete.herring <- fh.nefsc.pisc.pisccomplete %>%
mutate(herring = case_when(pynam %in% c("CLUPEA HARENGUS",
"CLUPEIDAE",
"CLUPEA HARENGUS SCALES",
"CLUPEIDAE SCALES",
"CLUPEA HARENGUS LARVAE",
"CLUPEIDAE LARVAE") ~ "herring",
TRUE ~ "othprey"))
###############################################################################
# Make the NEFSC dataset aggregating prey based on prey list
herringpyall_stn <- fh.nefsc.pisc.pisccomplete.herring %>%
#create id linking cruise6_station
#create season_ng spring and fall Spring=Jan-May, Fall=June-Dec
mutate(id = paste0(cruise6, "_", station),
year = as.numeric(year),
month = as.numeric(month),
season_ng = case_when(month <= 6 ~ "SPRING",
month >= 7 ~ "FALL",
TRUE ~ as.character(NA))
) %>%
dplyr::select(year, season_ng, id, stratum,
pynam, pyamtw, pywgti, pyvoli, herring,
pdcomnam, pdid, pdlen, pdsvol, pdswgt,
beglat, beglon, declat, declon,
bottemp, surftemp, setdepth) %>%
group_by(id) %>%
#mean blueprey g per stomach per tow: sum all blueprey g/n stomachs in tow
mutate(herringwt = case_when(herring == "herring" ~ pyamtw,
TRUE ~ 0.0),
herringpynam = case_when(herring == "herring" ~ pynam,
TRUE ~ NA_character_))
# Optional: save at prey disaggregated stage for paper
#saveRDS(bluepyall_stn, here("fhdat/bluepyall_stn.rds"))
# Now get station data in one line
stndat <- herringpyall_stn %>%
dplyr::select(year, season_ng, id,
beglat, beglon, declat, declon,
bottemp, surftemp, setdepth) %>%
distinct()
#pisc stomachs in tow count pdid for each pred and sum
piscstom <- herringpyall_stn %>%
group_by(id, pdcomnam) %>%
summarise(nstompd = n_distinct(pdid)) %>%
group_by(id) %>%
summarise(nstomtot = sum(nstompd))
#mean and var pred length per tow
pisclen <- herringpyall_stn %>%
summarise(meanpisclen = mean(pdlen),
varpisclen = var(pdlen))
# Aggregated prey at station level with predator covariates
herringpyagg_stn <- herringpyall_stn %>%
summarise(sumherringwt = sum(herringwt),
nherringsp = n_distinct(herringpynam, na.rm = T),
npreysp = n_distinct(pynam),
npiscsp = n_distinct(pdcomnam)) %>%
left_join(piscstom) %>%
mutate(meanherringwt = sumherringwt/nstomtot) %>%
left_join(pisclen) %>%
left_join(stndat)
# save at same stage as before, writing over old file
#saveRDS(bluepyagg_stn, here("fhdat/bluepyagg_stn.rds"))
# current dataset, fix declon, add vessel, rename NEFSC
#nefsc_bluepyagg_stn <- readRDS(here("fhdat/bluepyagg_stn.rds")) %>%
nefsc_herringpyagg_stn <- herringpyagg_stn %>%
mutate(declon = -declon,
vessel = case_when(year<2009 ~ "AL",
year>=2009 ~ "HB",
TRUE ~ as.character(NA)))
##############################################################################
# Add NEAMAP to make full aggregated stomach dataset
# Read in NEAMAP updated input from Jim Gartland, reformat with same names
neamap_herringagg_stn <- read_csv(here("fhdat/NEAMAP_Mean stomach weights_Bluefish Prey_wWQ_AH Only.csv")) %>%
mutate(vessel = "NEAMAP") %>%
rename(id = station,
sumherringwt = sumbluepreywt,
nherringsp = nbfpreyspp,
#npreysp = ,
npiscsp = npiscspp,
nstomtot = nstomtot,
meanherringwt = meanbluepreywt,
meanpisclen = meanpisclen.simple,
#varpisclen = ,
season_ng = season,
declat = lat,
declon = lon,
bottemp = bWT,
#surftemp = ,
setdepth = depthm)
# combine NEAMAP and NEFSC
herringagg_stn_all <- nefsc_herringpyagg_stn %>%
bind_rows(neamap_herringagg_stn)
# Save before SST integration step
#saveRDS(bluepyagg_stn_all, here("fhdat/bluepyagg_stn_all.rds"))
###############################################################################
# Add SST into NEAMAP and reintegrate into full dataset
# Read back in if needed for SST
#bluepyagg_stn_all <- readRDS(here("fhdat/bluepyagg_stn_all.rds"))
NEFSCstations <- allfh %>%
dplyr::mutate(id = paste0(cruise6, "_", station),
year = as.numeric(year),
month = as.numeric(month),
day = as.numeric(day),
declon = -declon) %>%
dplyr::select(id, year, month, day, declat, declon) %>%
dplyr::distinct()
# Need NEAMAP SST update! This is the old file
NEAMAPstationSST <- read.csv(here("fhdat/NEAMAP SST_2007_2022_Nov2023.csv"))
NEAMAPstations <- NEAMAPstationSST %>%
dplyr::mutate(id = station,
year = as.numeric(year),
month = as.numeric(month),
day = as.numeric(day)) %>%
dplyr::select(id, year, month, day) %>%
dplyr::distinct()
# remake diethauls
diethauls <- herringagg_stn_all %>%
dplyr::select(id, declat, declon)
NEFSCstations <- dplyr::select(NEFSCstations, c(-declat, -declon))
Allstations <- bind_rows(NEFSCstations, NEAMAPstations)
#station id, lat lon, year month day
diethauls <- left_join(diethauls, Allstations)
#add year month day to diet data
herringagg_stn_all <- left_join(herringagg_stn_all, diethauls)
# add NEAMAP SST to surftemp field
NEAMAPidSST <- NEAMAPstationSST %>%
mutate(id = station) %>%
dplyr::select(id, SST)
herringagg_stn_all <- left_join(herringagg_stn_all, NEAMAPidSST, by="id") %>%
mutate(surftemp = coalesce(surftemp, SST)) %>%
dplyr::select(-SST)
# save merged dataset with day, month, and NEAMAP surftemp, same name
#saveRDS(bluepyagg_stn_all, here("fhdat/bluepyagg_stn_all.rds"))
###############################################################################
#Now match stations to OISST
#make an SST dataframe for 2022! Add to saved sst_data in data-raw/gridded
library(sf)
library(raster)
library(terra)
library(nngeo)
# already have all OISST data as dataframes on this repo
# # Bastille function from https://github.com/kimberly-bastille/ecopull/blob/main/R/utils.R
#
# nc_to_raster <- function(nc,
# varname,
# extent = c(0, 360, -90, 90),
# crop = raster::extent(280, 300, 30, 50),
# show_images = FALSE) {
#
# message("Reading .nc as brick...")
#
# r <- raster::brick(nc, varname = varname)
#
# message("Setting CRS...")
# raster::crs(r) <- "+proj=longlat +lat_1=35 +lat_2=45 +lat_0=40 +lon_0=-77 +x_0=0 +y_0=0 +datum=NAD83 +no_defs +ellps=GRS80 +towgs84=0,0,0"
#
# # not sure if this is necessary?
# raster::extent(r) <- raster::extent(extent)
#
# if(show_images){
# par(mfrow = c(1,2))
# raster::plot(r, 1, sub = "Full dataset")
# }
#
# message("Cropping data...")
# ne_data <- raster::crop(r, crop)
# #ne_data <- raster::rotate(ne_data) add here for future pulls
#
# if(show_images){
# raster::plot(ne_data, 1, sub = "Cropped dataset")
# par(mfrow = c(1,1))
# }
#
# message("Done!")
#
# return(ne_data)
# }
#
# # function to convert to dataframe based on
# # https://towardsdatascience.com/transforming-spatial-data-to-tabular-data-in-r-4dab139f311f
#
# raster_to_sstdf <- function(brick,
# rotate=TRUE){
#
# if(rotate) brick_r <- raster::rotate(brick)
# brick_r <- raster::crop(brick_r, raster::extent(-77,-65,35,45))
# sstdf <- as.data.frame(raster::rasterToPoints(brick_r, spatial = TRUE))
# sstdf <- sstdf %>%
# dplyr::rename(Lon = x,
# Lat = y) %>%
# tidyr::pivot_longer(cols = starts_with("X"),
# names_to = c("year", "month", "day"),
# names_prefix = "X",
# names_sep = "\\.",
# values_to = "sst",
# )
# return(sstdf)
# }
#
# # pull the OISST data as raster brick, modified from
# # https://github.com/kimberly-bastille/ecopull/blob/main/.github/workflows/pull_satellite_data.yml
#
# varname <- "sst"
#
# # 1985-2021 previously pulled, processed and stored. add 2022.
# # add 1981-1984 to extend back in time. No OISST before 1981.
# # 1981 is only Sept-Dec so don't use
#
# years <- #1982:1984 # 2022
# for(i in years) {
# name <- paste0(i, ".nc")
# dir.create(here::here("data-raw","gridded", "sst_data"), recursive = TRUE)
# filename <- here::here("data-raw","gridded", "sst_data", paste0("test_", i, ".grd"))
# url <- paste0("https://downloads.psl.noaa.gov/Datasets/noaa.oisst.v2.highres/sst.day.mean.", i, ".nc")
# download.file(url, destfile = name)
#
# text <- knitr::knit_expand(text = "test_{{year}} <- nc_to_raster(nc = name, varname = varname)
# raster::writeRaster(test_{{year}}, filename = filename, overwrite=TRUE)",
# year = i)
# print(text)
# try(eval(parse(text = text)))
# unlink(name) # remove nc file to save space
# print(paste("finished",i))
# }
#
#
# # convert raster to dataframe
# #years <- 2022
# for(i in years) {
# name <- get(paste0("test_",i))
# filename <- here::here("data-raw","gridded", "sst_data", paste0("sst", i, ".rds"))
# text <- knitr::knit_expand(text = "sst{{year}} <- raster_to_sstdf(brick = name)
# saveRDS(sst{{year}}, filename)",
# year = i)
# print(text)
# try(eval(parse(text = text)))
#}
#read in diet data with month day fields
#bluepyagg_stn_all <- readRDS(here("fhdat/bluepyagg_stn_all.rds"))
stations <- herringagg_stn_all %>%
dplyr::mutate(day = str_pad(day, 2, pad='0'),
month = str_pad(month, 2, pad='0'),
yrmody = as.numeric(paste0(year, month, day))) %>%
dplyr::select(id, declon, declat, year, yrmody) %>%
na.omit() %>%
sf::st_as_sf(coords=c("declon","declat"), crs=4326, remove=FALSE)
#list of SST dataframes
SSTdfs <- list.files(here("data-raw/gridded/sst_data/"), pattern = "*.rds")
dietstn_OISST <- tibble()
for(df in SSTdfs){
sstdf <- readRDS(paste0(here("data-raw/gridded/sst_data/", df)))
# keep only bluefish dates in SST year
stationsyr <- stations %>%
filter(year == unique(sstdf$year))
# keep only sst days in bluefish dataset
sstdf_survdays <- sstdf %>%
dplyr::mutate(yrmody = as.numeric(paste0(year, month, day)) )%>%
dplyr::filter(yrmody %in% unique(stationsyr$yrmody)) %>%
dplyr::mutate(year = as.numeric(year),
month = as.numeric(month),
day = as.numeric(day),
declon = Lon,
declat = Lat) %>%
dplyr::select(-Lon, -Lat) %>%
sf::st_as_sf(coords=c("declon","declat"), crs=4326, remove=FALSE)
# now join by nearest neighbor and date
#https://stackoverflow.com/questions/71959927/spatial-join-two-data-frames-by-nearest-feature-and-date-in-r
yrdietOISST <- do.call('rbind', lapply(split(stationsyr, 1:nrow(stationsyr)), function(x) {
sf::st_join(x, sstdf_survdays[sstdf_survdays$yrmody == unique(x$yrmody),],
#join = st_nearest_feature
join = st_nn, k = 1, progress = FALSE
)
}))
# #datatable solution--works but doesnt seem faster?
# df1 <- data.table(stationsyr)
#
# .nearest_samedate <- function(x) {
# st_join(st_as_sf(x), sstdf_survdays[sstdf_survdays$yrmody == unique(x$yrmody),], join = st_nearest_feature)
# }
# #
# yrdietOISST <- df1[, .nearest_samedate(.SD), by = list(1:nrow(df1))]
dietstn_OISST <- rbind(dietstn_OISST, yrdietOISST)
}
#saveRDS(dietstn_OISST, here("data-raw/dietstn_OISST.rds"))
# Now join with OISST dataset
#bluepyagg_stn_all <- readRDS(here("fhdat/bluepyagg_stn_all.rds"))
#dietstn_OISST <- readRDS(here("data-raw/dietstn_OISST.rds"))
dietstn_OISST_merge <- dietstn_OISST %>%
dplyr::rename(declon = declon.x,
declat = declat.x,
year = year.x,
oisst = sst) %>%
dplyr::select(id, oisst) %>%
sf::st_drop_geometry()
herringagg_stn_all_OISST <- left_join(herringagg_stn_all, dietstn_OISST_merge)
saveRDS(herringagg_stn_all_OISST, here("fhdat/herringagg_stn_all_OISST_1982-2022.rds"))
VAST models were run using the script VASTunivariate_seasonalherringindex.R
in the folder VASTscripts
: https://github.com/NOAA-EDAB/forageindex/blob/main/VASTscripts/VASTunivariate_seasonalherringindex.R
# This is the exact VAST code used in Gaichas et al 2023, but with data years
# extended from 1973-2022
# VAST attempt 2 univariate model as a script
# modified from https://github.com/James-Thorson-NOAA/VAST/wiki/Index-standardization
# Load packages
library(here)
library(dplyr)
library(VAST)
#Read in data, separate spring and fall, and rename columns for VAST:
# this dataset created in SSTmethods.Rmd
herringagg_stn <- readRDS(here::here("fhdat/herringagg_stn_all_OISST_1982-2022.rds"))
# make SST column that uses surftemp unless missing or 0
# there are 3 surftemp 0 values in the dataset, all with oisst > 15
herringagg_stn <- herringagg_stn %>%
dplyr::mutate(sstfill = ifelse((is.na(surftemp)|surftemp==0), oisst, surftemp))
#herringagg_stn <- bluepyagg_pred_stn
# filter to assessment years at Tony's suggestion
# code Vessel as AL=0, HB=1, NEAMAP=2
herringagg_stn_fall <- herringagg_stn %>%
#ungroup() %>%
filter(season_ng == "FALL") |>
#,year > 1984) %>%
mutate(AreaSwept_km2 = 1, #Elizabeth's code
#declon = -declon already done before neamap merge
Vessel = as.numeric(as.factor(vessel))-1
) %>%
dplyr::select(Catch_g = meanherringwt, #use bluepywt for individuals input in example
Year = year,
Vessel,
AreaSwept_km2,
Lat = declat,
Lon = declon,
meanpisclen,
npiscsp,
#bottemp, #this leaves out many stations for NEFSC
#surftemp, #this leaves out many stations for NEFSC
#oisst, #leaves out everything before 1982
sstfill
) %>%
na.omit() %>%
as.data.frame()
herringagg_stn_spring <- herringagg_stn %>%
filter(season_ng == "SPRING") |>
#,year > 1984) %>%
mutate(AreaSwept_km2 =1, #Elizabeth's code
#declon = -declon already done before neamap merge
Vessel = as.numeric(as.factor(vessel))-1
) %>%
dplyr::select(Catch_g = meanherringwt,
Year = year,
Vessel,
AreaSwept_km2,
Lat = declat,
Lon = declon,
meanpisclen,
npiscsp,
#bottemp, #this leaves out many stations for NEFSC
#surftemp, #this leaves out many stations for NEFSC
#oisst, #leaves out everything before 1982
sstfill
) %>%
na.omit() %>%
as.data.frame()
# Make settings (turning off bias.correct to save time for example)
# NEFSC strata limits https://github.com/James-Thorson-NOAA/VAST/issues/302
# use only MAB, GB, GOM, SS EPUs
# leave out south of Cape Hatteras at Elizabeth's suggestion
# could also leave out SS?
# CHECK if these EPUs match what we use in SOE
MAB <- c(1010:1080, 1100:1120, 1600:1750, 3010:3450, 3470, 3500, 3510)
GB <- c(1090, 1130:1210, 1230, 1250, 3460, 3480, 3490, 3520:3550)
GOM <- c(1220, 1240, 1260:1290, 1360:1400, 3560:3830)
SS <- c(1300:1352, 3840:3990)
coast3nmbuffst <- readRDS(here::here("spatialdat/coast3nmbuffst.rds"))
# Mid Atlantic
MAB2 <- coast3nmbuffst %>%
dplyr::filter(stratum_number %in% MAB) %>%
dplyr::select(stratum_number2) %>%
dplyr::distinct()
# Georges Bank EPU
GB2 <- coast3nmbuffst %>%
dplyr::filter(stratum_number %in% GB) %>%
dplyr::select(stratum_number2) %>%
dplyr::distinct()
# gulf of maine EPU (for SOE)
GOM2 <- coast3nmbuffst %>%
dplyr::filter(stratum_number %in% GOM) %>%
dplyr::select(stratum_number2) %>%
dplyr::distinct()
# scotian shelf EPU (for SOE)
SS2 <- coast3nmbuffst %>%
dplyr::filter(stratum_number %in% SS) %>%
dplyr::select(stratum_number2) %>%
dplyr::distinct()
# needed to cover the whole northwest atlantic grid
allother2 <- coast3nmbuffst %>%
dplyr::filter(!stratum_number %in% c(MAB, GB, GOM, SS)) %>%
dplyr::select(stratum_number2) %>%
dplyr::distinct()
# all epus
allEPU2 <- coast3nmbuffst %>%
dplyr::filter(stratum_number %in% c(MAB, GB, GOM, SS)) %>%
dplyr::select(stratum_number2) %>%
dplyr::distinct()
# # configs same FieldConfig as below but formatted differently
# FieldConfig <- c(
# "Omega1" = 0, # number of spatial variation factors (0, 1, AR1)
# "Epsilon1" = 0, # number of spatio-temporal factors
# "Omega2" = 0,
# "Epsilon2" = 0
# )
# default configs, not really specified anyway
FieldConfig = matrix( "IID", ncol=2, nrow=3,
dimnames=list(c("Omega","Epsilon","Beta"),c("Component_1","Component_2")))
RhoConfig <- c(
"Beta1" = 0, # temporal structure on years (intercepts)
"Beta2" = 0,
"Epsilon1" = 0, # temporal structure on spatio-temporal variation
"Epsilon2" = 0
)
# 0 off (fixed effects)
# 1 independent
# 2 random walk
# 3 constant among years (fixed effect)
# 4 AR1
OverdispersionConfig <- c("eta1"=0, "eta2"=0)
# eta1 = vessel effects on prey encounter rate
# eta2 = vessel effects on prey weight
strata.limits <- as.list(c("AllEPU" = allEPU2,
"MAB" = MAB2,
"GB" = GB2,
"GOM" = GOM2,
"allother" = allother2))
settings = make_settings( n_x = 500,
Region = "northwest_atlantic",
Version = "VAST_v14_0_1", #needed to prevent error from newer dev version number
#strata.limits = list('All_areas' = 1:1e5), full area
strata.limits = strata.limits,
purpose = "index2",
bias.correct = TRUE,
#use_anisotropy = FALSE,
#fine_scale = FALSE,
#FieldConfig = FieldConfig,
#RhoConfig = RhoConfig,
OverdispersionConfig = OverdispersionConfig
)
New_Extrapolation_List <- readRDS(here::here("spatialdat/CustomExtrapolationList.rds"))
# select dataset and set directory for output
#########################################################
# Run model fall
season <- c("fall_500_lennosst_ALLsplit_biascorrect")
working_dir <- here::here(sprintf("herringpyindex/allagg_%s/", season))
if(!dir.exists(working_dir)) {
dir.create(working_dir)
}
# subset for faster testing
#herringagg_stn_fall <- herringagg_stn_fall %>% filter(Year<1990)
fit <- fit_model(
settings = settings,
extrapolation_list = New_Extrapolation_List,
Lat_i = herringagg_stn_fall$Lat,
Lon_i = herringagg_stn_fall$Lon,
t_i = herringagg_stn_fall$Year,
b_i = as_units(herringagg_stn_fall[,'Catch_g'], 'g'),
a_i = rep(1, nrow(herringagg_stn_fall)),
v_i = herringagg_stn_fall$Vessel,
Q_ik = as.matrix(herringagg_stn_fall[,c("npiscsp",
"meanpisclen",
"sstfill"
)]),
#Use_REML = TRUE,
working_dir = paste0(working_dir, "/"))
saveRDS(fit, file = paste0(working_dir, "/fit.rds"))
# Plot results
plot( fit,
working_dir = paste0(working_dir, "/"))
######################################################
# Run model spring
season <- c("spring_500_lennosst_ALLsplit_biascorrect")
working_dir <- here::here(sprintf("herringpyindex/allagg_%s/", season))
if(!dir.exists(working_dir)) {
dir.create(working_dir)
}
# subset for faster testing
#herringagg_stn_spring <- herringagg_stn_spring %>% filter(Year<1990)
fit <- fit_model( settings = settings,
extrapolation_list = New_Extrapolation_List,
Lat_i = herringagg_stn_spring[,'Lat'],
Lon_i = herringagg_stn_spring[,'Lon'],
t_i = herringagg_stn_spring[,'Year'],
b_i = as_units(herringagg_stn_spring[,'Catch_g'], 'g'),
a_i = rep(1, nrow(herringagg_stn_spring)),
v_i = herringagg_stn_spring$Vessel,
Q_ik = as.matrix(herringagg_stn_spring[,c("npiscsp",
"meanpisclen",
"sstfill"
)]),
# Use_REML = TRUE,
working_dir = paste0(working_dir, "/"))
saveRDS(fit, file = paste0(working_dir, "/fit.rds"))
# Plot results
plot( fit,
working_dir = paste0(working_dir, "/"))
The predator list used in initial runs was the same used for bluefish diet, which includes herring and 19 other prey. Therefore it included predators that may feed on smaller forage fish (squids).
This is the full piscivore list, derived from Brian Smith’s prey similarity matrix and using cluster analysis to identify the predator/sizes that have highest diet similarity to all size classes of bluefish:
# object is called `allfh`
load(here("fhdat/allfh.Rdata"))
#object is called allfh21
load(here("fhdat/allfh21.Rdata"))
#object is called allfh22
load(here("fhdat/allfh22.Rdata"))
# bind all NEFSC stomach datasets
allfh <- allfh %>%
dplyr::bind_rows(allfh21) |>
dplyr::bind_rows(allfh22)
dietoverlap <- read_csv(here("fhdat/tgmat.2022-02-15.csv"))
d_dietoverlap <- dist(dietoverlap)
# again directly from https://cran.r-project.org/web/packages/dendextend/vignettes/Cluster_Analysis.html
hclust_methods <- c("ward.D", "single", "complete", "average", "mcquitty",
"median", "centroid", "ward.D2")
diet_dendlist <- dendlist()
for(i in seq_along(hclust_methods)) {
hc_diet <- hclust(d_dietoverlap, method = hclust_methods[i])
diet_dendlist <- dendlist(diet_dendlist, as.dendrogram(hc_diet))
}
names(diet_dendlist) <- hclust_methods
# preds <- list()
#
# for(i in 1:8) {
# dendi <- diet_dendlist[[i]]
# namei <- names(diet_dendlist)[i]
# labels(dendi) <- paste(as.character(names(dietoverlap[-1]))[order.dendrogram(dendi)],
# "(",labels(dendi),")",
# sep = "")
# #preds[[namei]] <- partition_leaves(dendi)[[which_node(dendi, c("35", "36", "37"))]]
# preds[[namei]] <- partition_leaves(dendi)[[which_node(dendi, c("Bluefish..S(37)", "Bluefish..M(36)", "Bluefish..L(35)"))]]
#
# }
dendi <- diet_dendlist$complete
labels(dendi) <- paste(as.character(names(dietoverlap[-1]))[order.dendrogram(dendi)],
"(",labels(dendi),")",
sep = "")
pisccomplete <- partition_leaves(dendi)[[which_node(dendi, c("Bluefish..S(37)", "Bluefish..M(36)", "Bluefish..L(35)"))]]
sizedefs <- allfh %>%
select(pdcomnam, sizecat, pdlen) %>%
group_by(pdcomnam, sizecat) %>%
summarize(minlen = min(pdlen), maxlen = max(pdlen))
# add these in as a NEAMAP column
# + Summer Flounder 21-70 cm
# + Silver Hake 21-76 cm
# + Weakfish 26-50 cm
# + Atlantic Cod 81-150 cm
# + Bluefish 3 – 118 cm
# + Striped Bass 31 – 120 cm
# + Spanish Mackerel 10 – 33.5 cm
# + Spotted Sea Trout 15.5 – 34 cm
# + Spiny Dogfish 36 – 117 cm
# + Goosefish 5 – 124 cm
NEAMAPpisc <- data.frame("comname" = c("Summer Flounder",
"Silver Hake",
"Weakfish",
"Atlantic Cod",
"Bluefish",
"Striped Bass",
"Spanish Mackerel",
"Spotted Sea Trout",
"Spiny Dogfish",
"Goosefish"),
"mincm" = c(21, 21, 26, 81, 3, 31, 10, 15.5, 36, 5),
"maxcm" = c(70, 76, 50, 150, 118, 120, 33.5, 34, 117, 124)
) %>%
dplyr::mutate(comname = stringr::str_to_sentence(comname),
NEAMAP = TRUE)
pisccompletedf <- data.frame("COMNAME" = toupper(str_remove(pisccomplete, "\\..*")),
"SizeCat" = str_remove(str_extract(pisccomplete, "\\..*[:upper:]+"), "\\.."),
"feedguild" = "pisccomplete") %>%
left_join(sizedefs, by=c("COMNAME" = "pdcomnam",
"SizeCat" = "sizecat")) %>%
arrange(COMNAME, minlen)
piscall <- pisccompletedf %>%
dplyr::mutate(comname = stringr::str_to_sentence(COMNAME)) %>%
dplyr::group_by(comname) %>%
dplyr::summarise(mincm = min(minlen),
maxcm = max(maxlen),
NEFSC = TRUE) %>%
dplyr::full_join(NEAMAPpisc) %>%
dplyr::mutate(survey = dplyr::case_when(NEFSC & NEAMAP ~ "Both",
NEFSC ~ "NEFSC",
NEAMAP ~ "NEAMAP")) %>%
dplyr::arrange(comname)
flextable::flextable(piscall %>% dplyr::select(-c(NEFSC, NEAMAP))) %>%
flextable::set_header_labels(comname = 'Predator name',
#SizeCat = "Size category",
mincm = "Minimum length (cm)",
maxcm = "Maximum length (cm)",
survey = "Survey") %>%
flextable::set_caption("Predators with highest diet similarity to Bluefish, Northeast Fisheries Science Center (NEFSC, years 1973-2021) and Northeast Area Monitoring and Assessment Program (NEAMAP, years 2007-2021) databases.") %>%
#flextable::align_text_col(j=survey, align = "right", header = TRUE, footer = TRUE) %>%
#flextable::autofit()
flextable::width(width = c(3, 1, 1, 1))
Predator name | Minimum length (cm) | Maximum length (cm) | Survey |
Atlantic cod | 81.0 | 150.0 | Both |
Atlantic halibut | 31.0 | 90.0 | NEFSC |
Bluefish | 3.0 | 118.0 | Both |
Buckler dory | 21.0 | 50.0 | NEFSC |
Cusk | 51.0 | 104.0 | NEFSC |
Fourspot flounder | 41.0 | 49.0 | NEFSC |
Goosefish | 5.0 | 124.0 | Both |
Longfin squid | 1.0 | 30.0 | NEFSC |
Northern shortfin squid | 3.0 | 30.0 | NEFSC |
Pollock | 51.0 | 120.0 | NEFSC |
Red hake | 41.0 | 98.0 | NEFSC |
Sea raven | 4.0 | 68.0 | NEFSC |
Silver hake | 21.0 | 76.0 | Both |
Spanish mackerel | 10.0 | 33.5 | NEAMAP |
Spiny dogfish | 36.0 | 117.0 | Both |
Spotted hake | 21.0 | 40.0 | NEFSC |
Spotted sea trout | 15.5 | 34.0 | NEAMAP |
Striped bass | 31.0 | 120.0 | Both |
Summer flounder | 21.0 | 70.0 | Both |
Thorny skate | 81.0 | 108.0 | NEFSC |
Weakfish | 26.0 | 50.0 | Both |
White hake | 21.0 | 136.0 | NEFSC |
Here is an alternative:
Jim Gartland used the list of predators that had at least 5 locations with herring prey 1978-2019 across both NEFSC and NEAMAP surveys, but also only included predators sampled consistently over the full time series.
Let’s count all possible herring observations by predator in NEFSC. They are in the table, but for the index lets leave out observations of eggs and larvae so this covers the sizes and ages modeled in the assessment. This is a count of stomachs.
preycount <- allfh %>%
filter(pdcomnam != "",
pynam %in% c("CLUPEA HARENGUS",
"CLUPEIDAE",
"CLUPEA HARENGUS SCALES",
"CLUPEIDAE SCALES",
"CLUPEA HARENGUS LARVAE",
"CLUPEA HARENGUS EGGS",
"CLUPEIDAE LARVAE",
"CLUPEIDAE EGGS"
)) %>%
mutate(id = paste0(cruise6, "_", station)) |>
group_by(pdcomnam, pynam) %>%
summarise(count = n()) %>%
ungroup() |>
pivot_wider(names_from = pynam, values_from = count) |>
arrange(desc(`CLUPEA HARENGUS`))
flextable::flextable(preycount)
pdcomnam | CLUPEA HARENGUS | CLUPEA HARENGUS EGGS | CLUPEA HARENGUS LARVAE | CLUPEIDAE | CLUPEIDAE EGGS | CLUPEIDAE LARVAE | CLUPEA HARENGUS SCALES | CLUPEIDAE SCALES |
SPINY DOGFISH | 721 | 1 | 675 | 2 | 1 | 5 | ||
SILVER HAKE | 366 | 209 | ||||||
ATLANTIC COD | 347 | 1 | 1 | 253 | 42 | 4 | ||
WHITE HAKE | 221 | 141 | 2 | |||||
GOOSEFISH | 147 | 65 | 1 | |||||
POLLOCK | 78 | 7 | 25 | 1 | 8 | |||
STRIPED BASS | 63 | 29 | ||||||
WINTER SKATE | 62 | 39 | 13 | |||||
BLUEFISH | 37 | 30 | ||||||
SUMMER FLOUNDER | 32 | 24 | ||||||
HADDOCK | 21 | 9 | 50 | 4 | ||||
THORNY SKATE | 21 | 14 | ||||||
RED HAKE | 20 | 19 | ||||||
SEA RAVEN | 16 | 14 | 1 | |||||
ATLANTIC HALIBUT | 13 | 6 | ||||||
BARNDOOR SKATE | 12 | 2 | ||||||
ATLANTIC HERRING | 9 | 1 | 1 | 18 | ||||
WINDOWPANE | 9 | 4 | 8 | |||||
LITTLE SKATE | 7 | 5 | 3 | |||||
LONGHORN SCULPIN | 6 | 1 | 2 | 2 | ||||
ATLANTIC MACKEREL | 4 | 2 | 6 | 24 | 1 | 4 | ||
SMOOTH DOGFISH | 3 | 8 | ||||||
WEAKFISH | 3 | 4 | ||||||
BUCKLER DORY | 2 | 1 | ||||||
SPOTTED HAKE | 2 | 4 | ||||||
ACADIAN REDFISH | 1 | |||||||
BLACK SEA BASS | 1 | 1 | ||||||
FOURSPOT FLOUNDER | 1 | 1 | 2 | |||||
YELLOWTAIL FLOUNDER | 1 | 1 | 3 | |||||
ATLANTIC SHARPNOSE SHARK | 2 | |||||||
BLUEBACK HERRING | 1 | 1 | ||||||
CLEARNOSE SKATE | 2 | |||||||
DUSKY SHARK | 1 | |||||||
GREENLAND HALIBUT | 1 | |||||||
SPOT | 1 | |||||||
WINTER FLOUNDER | 5 |
Now a count of stations by predator with CLUPEA HARENGUS only
AHstncount <- allfh %>%
filter(pdcomnam != "",
pynam %in% c("CLUPEA HARENGUS"
)) %>%
mutate(id = paste0(cruise6, "_", station)) |>
dplyr::select(pdcomnam, id) %>%
dplyr::distinct() %>%
group_by(pdcomnam) |>
summarise(count = n()) |>
arrange(desc(count))
flextable::flextable(AHstncount)
pdcomnam | count |
SPINY DOGFISH | 572 |
SILVER HAKE | 278 |
ATLANTIC COD | 248 |
WHITE HAKE | 185 |
GOOSEFISH | 127 |
WINTER SKATE | 56 |
POLLOCK | 42 |
STRIPED BASS | 35 |
SUMMER FLOUNDER | 32 |
BLUEFISH | 28 |
THORNY SKATE | 19 |
RED HAKE | 18 |
HADDOCK | 16 |
SEA RAVEN | 14 |
ATLANTIC HALIBUT | 13 |
BARNDOOR SKATE | 12 |
LITTLE SKATE | 7 |
WINDOWPANE | 7 |
ATLANTIC HERRING | 6 |
LONGHORN SCULPIN | 4 |
ATLANTIC MACKEREL | 3 |
SMOOTH DOGFISH | 3 |
WEAKFISH | 3 |
BUCKLER DORY | 2 |
SPOTTED HAKE | 2 |
ACADIAN REDFISH | 1 |
BLACK SEA BASS | 1 |
FOURSPOT FLOUNDER | 1 |
YELLOWTAIL FLOUNDER | 1 |
Applying Jim’s criteria (CLUPEA HARENGUS only in 5 or more stations across the dataset) we include everything down to herring.
If we look at station counts by year to establish consistent sampling across the time series, do we drop any? These are all stations where the predator was sampled in a year, whether they had herring in stomachs or not.
AHstncountpreds <- AHstncount |> dplyr::filter(count >= 5) |> dplyr::select(pdcomnam)
sampstncountyr <- allfh %>%
dplyr::filter(pdcomnam != "",
pdcomnam %in% AHstncountpreds$pdcomnam) |>
dplyr::mutate(id = paste0(cruise6, "_", station)) |>
dplyr::select(year, pdcomnam, id) %>%
dplyr::distinct() %>%
dplyr::group_by(year, pdcomnam) |>
dplyr::summarise(count = n()) |>
tidyr::pivot_wider(names_from = year, values_from = count)
flextable::flextable(sampstncountyr)
pdcomnam | 1973 | 1974 | 1975 | 1976 | 1977 | 1978 | 1979 | 1980 | 1981 | 1982 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1989 | 1990 | 1991 | 1992 | 1993 | 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | NA |
ATLANTIC COD | 83 | 91 | 44 | 77 | 33 | 57 | 37 | 35 | 84 | 112 | 32 | 94 | 180 | 162 | 136 | 155 | 185 | 160 | 192 | 202 | 202 | 135 | 181 | 150 | 146 | 179 | 159 | 138 | 141 | 134 | 126 | 155 | 131 | 131 | 140 | 126 | 139 | 149 | 129 | 130 | 126 | 102 | 138 | 109 | 112 | 65 | 71 | 1 | 74 | 71 | 2 |
HADDOCK | 45 | 54 | 23 | 55 | 43 | 63 | 38 | 31 | 53 | 45 | 12 | 18 | 6 | 48 | 14 | 24 | 16 | 9 | 12 | 4 | 17 | 10 | 5 | 7 | 16 | 167 | 122 | 158 | 139 | 180 | 176 | 169 | 171 | 147 | 133 | 153 | 190 | 192 | 174 | 237 | 282 | 273 | 264 | 134 | 175 | 209 | 186 | 159 | 1 | ||
LITTLE SKATE | 32 | 45 | 26 | 49 | 36 | 50 | 12 | 7 | 6 | 11 | 10 | 15 | 44 | 92 | 111 | 67 | 202 | 193 | 247 | 319 | 379 | 338 | 392 | 362 | 265 | 408 | 414 | 394 | 359 | 370 | 338 | 297 | 290 | 324 | 335 | 231 | 352 | 328 | 290 | 318 | 366 | 293 | 337 | 313 | 189 | 274 | 308 | 56 | 287 | 300 | |
POLLOCK | 73 | 57 | 25 | 46 | 9 | 12 | 4 | 15 | 13 | 58 | 53 | 65 | 70 | 48 | 37 | 44 | 57 | 54 | 97 | 80 | 99 | 60 | 72 | 47 | 70 | 88 | 78 | 87 | 88 | 66 | 70 | 72 | 72 | 62 | 60 | 71 | 45 | 55 | 55 | 68 | 63 | 60 | 67 | 72 | 46 | 28 | 34 | 38 | 46 | 1 | |
RED HAKE | 13 | 18 | 9 | 35 | 81 | 87 | 81 | 62 | 14 | 83 | 115 | 129 | 113 | 96 | 96 | 104 | 148 | 137 | 173 | 207 | 279 | 247 | 304 | 228 | 196 | 313 | 296 | 267 | 258 | 245 | 250 | 225 | 242 | 297 | 281 | 229 | 354 | 293 | 245 | 351 | 379 | 365 | 358 | 350 | 293 | 240 | 329 | 19 | 296 | 302 | |
SILVER HAKE | 69 | 73 | 58 | 83 | 74 | 88 | 61 | 52 | 73 | 83 | 42 | 51 | 275 | 270 | 225 | 215 | 276 | 270 | 349 | 388 | 495 | 425 | 438 | 348 | 331 | 443 | 433 | 380 | 404 | 399 | 345 | 376 | 324 | 431 | 387 | 347 | 485 | 485 | 429 | 535 | 574 | 485 | 447 | 485 | 364 | 361 | 464 | 58 | 438 | 418 | |
WHITE HAKE | 34 | 35 | 16 | 25 | 7 | 29 | 12 | 9 | 25 | 93 | 118 | 96 | 93 | 139 | 105 | 109 | 124 | 136 | 223 | 197 | 239 | 214 | 186 | 114 | 114 | 159 | 146 | 132 | 125 | 119 | 112 | 135 | 112 | 146 | 140 | 136 | 201 | 193 | 171 | 174 | 157 | 153 | 191 | 181 | 144 | 111 | 182 | 163 | 114 | 1 | |
WINTER SKATE | 2 | 29 | 36 | 51 | 51 | 4 | 22 | 8 | 35 | 41 | 74 | 89 | 91 | 153 | 140 | 165 | 208 | 223 | 208 | 251 | 243 | 144 | 241 | 243 | 218 | 209 | 183 | 189 | 204 | 181 | 213 | 210 | 157 | 249 | 245 | 248 | 227 | 255 | 210 | 226 | 187 | 178 | 180 | 222 | 44 | 204 | 229 | ||||
ATLANTIC HALIBUT | 4 | 18 | 29 | 24 | 3 | 1 | 2 | 2 | 7 | 7 | 4 | 4 | 7 | 8 | 14 | 5 | 3 | 2 | 9 | 4 | 3 | 4 | 8 | 6 | 9 | 10 | 14 | 11 | 13 | 20 | 18 | 24 | 21 | 28 | 18 | 31 | 20 | 13 | 15 | 22 | 6 | 7 | 9 | 12 | 18 | ||||||
ATLANTIC HERRING | 5 | 8 | 6 | 6 | 5 | 11 | 1 | 25 | 14 | 19 | 4 | 4 | 6 | 214 | 357 | 297 | 349 | 305 | 214 | 372 | 335 | 236 | 246 | 267 | 270 | 314 | 231 | 274 | 302 | 225 | 295 | 332 | 311 | 315 | 314 | 233 | 260 | 218 | 157 | 140 | 158 | 6 | 177 | 145 | |||||||
BLUEFISH | 1 | 27 | 62 | 29 | 34 | 23 | 15 | 28 | 50 | 43 | 49 | 29 | 65 | 60 | 46 | 58 | 54 | 6 | 4 | 63 | 57 | 64 | 76 | 68 | 67 | 76 | 74 | 59 | 67 | 103 | 69 | 76 | 53 | 57 | 59 | 44 | 32 | 39 | 30 | 42 | 3 | 25 | 31 | 8 | 8 | 16 | |||||
GOOSEFISH | 95 | 119 | 130 | 114 | 37 | 92 | 88 | 56 | 64 | 72 | 64 | 63 | 75 | 71 | 158 | 128 | 217 | 145 | 229 | 186 | 163 | 206 | 241 | 242 | 264 | 271 | 197 | 212 | 188 | 193 | 191 | 87 | 271 | 255 | 260 | 316 | 293 | 283 | 324 | 377 | 247 | 266 | 314 | 31 | 291 | 270 | |||||
SEA RAVEN | 4 | 24 | 26 | 10 | 11 | 6 | 23 | 68 | 57 | 44 | 52 | 107 | 110 | 136 | 170 | 150 | 109 | 138 | 126 | 109 | 138 | 161 | 131 | 133 | 132 | 122 | 111 | 123 | 124 | 135 | 126 | 163 | 117 | 97 | 87 | 105 | 68 | 95 | 73 | 77 | 75 | 55 | 75 | 84 | |||||||
SPINY DOGFISH | 113 | 126 | 121 | 97 | 158 | 190 | 226 | 215 | 208 | 229 | 202 | 190 | 230 | 261 | 312 | 409 | 407 | 336 | 421 | 388 | 390 | 448 | 432 | 375 | 397 | 457 | 340 | 331 | 335 | 470 | 399 | 321 | 335 | 262 | 237 | 335 | 360 | 299 | 258 | 391 | 252 | 240 | 299 | 88 | 297 | 322 | |||||
SUMMER FLOUNDER | 22 | 40 | 95 | 45 | 22 | 33 | 18 | 6 | 61 | 74 | 66 | 58 | 69 | 72 | 106 | 187 | 186 | 130 | 204 | 220 | 214 | 249 | 286 | 279 | 280 | 307 | 239 | 270 | 223 | 266 | 274 | 172 | 221 | 205 | 177 | 194 | 206 | 173 | 184 | 194 | 124 | 149 | 205 | 65 | 140 | 177 | |||||
THORNY SKATE | 20 | 37 | 28 | 10 | 2 | 1 | 6 | 73 | 48 | 26 | 43 | 87 | 84 | 110 | 110 | 119 | 71 | 66 | 41 | 43 | 72 | 51 | 55 | 46 | 49 | 64 | 49 | 38 | 38 | 44 | 39 | 83 | 80 | 77 | 81 | 74 | 71 | 77 | 68 | 52 | 39 | 44 | 41 | 29 | |||||||
WINDOWPANE | 28 | 57 | 82 | 48 | 18 | 16 | 6 | 8 | 36 | 55 | 64 | 1 | 137 | 91 | 104 | 184 | 215 | 219 | 238 | 224 | 158 | 260 | 241 | 221 | 201 | 198 | 215 | 175 | 190 | 199 | 193 | 152 | 198 | 208 | 191 | 204 | 242 | 169 | 207 | 161 | 132 | 164 | 186 | 26 | 158 | 152 | 1 | ||||
STRIPED BASS | 1 | 1 | 1 | 1 | 2 | 1 | 4 | 1 | 1 | 1 | 13 | 2 | 36 | 20 | 35 | 16 | 38 | 30 | 27 | 31 | 30 | 23 | 21 | 8 | 13 | 6 | 15 | 9 | 2 | 4 | 18 | 10 | 13 | 2 | 14 | 4 | 6 | ||||||||||||||
BARNDOOR SKATE | 2 | 1 | 1 | 2 | 1 | 4 | 2 | 1 | 39 | 33 | 8 | 26 | 3 | 11 | 89 | 65 | 52 | 126 | 143 | 161 | 162 | 161 | 161 | 142 | 143 | 89 | 114 | 136 | 10 | 173 | 143 |
I’ll need to ask what we meant by consistent across the time series, but its possible that would drop striped bass and barndoor skate.
Compare the number of stations with herring and the sampling across time from the piscivore list with Jim G’s list:
altpredlist <- AHstncountpreds |>
dplyr::mutate(comname = stringr::str_to_sentence(AHstncountpreds$pdcomnam))
predlists <- piscall |>
dplyr::full_join(altpredlist)
flextable::flextable(predlists)
comname | mincm | maxcm | NEFSC | NEAMAP | survey | pdcomnam |
Atlantic cod | 81.0 | 150.0 | TRUE | TRUE | Both | ATLANTIC COD |
Atlantic halibut | 31.0 | 90.0 | TRUE | NEFSC | ATLANTIC HALIBUT | |
Bluefish | 3.0 | 118.0 | TRUE | TRUE | Both | BLUEFISH |
Buckler dory | 21.0 | 50.0 | TRUE | NEFSC | ||
Cusk | 51.0 | 104.0 | TRUE | NEFSC | ||
Fourspot flounder | 41.0 | 49.0 | TRUE | NEFSC | ||
Goosefish | 5.0 | 124.0 | TRUE | TRUE | Both | GOOSEFISH |
Longfin squid | 1.0 | 30.0 | TRUE | NEFSC | ||
Northern shortfin squid | 3.0 | 30.0 | TRUE | NEFSC | ||
Pollock | 51.0 | 120.0 | TRUE | NEFSC | POLLOCK | |
Red hake | 41.0 | 98.0 | TRUE | NEFSC | RED HAKE | |
Sea raven | 4.0 | 68.0 | TRUE | NEFSC | SEA RAVEN | |
Silver hake | 21.0 | 76.0 | TRUE | TRUE | Both | SILVER HAKE |
Spanish mackerel | 10.0 | 33.5 | TRUE | NEAMAP | ||
Spiny dogfish | 36.0 | 117.0 | TRUE | TRUE | Both | SPINY DOGFISH |
Spotted hake | 21.0 | 40.0 | TRUE | NEFSC | ||
Spotted sea trout | 15.5 | 34.0 | TRUE | NEAMAP | ||
Striped bass | 31.0 | 120.0 | TRUE | TRUE | Both | STRIPED BASS |
Summer flounder | 21.0 | 70.0 | TRUE | TRUE | Both | SUMMER FLOUNDER |
Thorny skate | 81.0 | 108.0 | TRUE | NEFSC | THORNY SKATE | |
Weakfish | 26.0 | 50.0 | TRUE | TRUE | Both | |
White hake | 21.0 | 136.0 | TRUE | NEFSC | WHITE HAKE | |
Winter skate | WINTER SKATE | |||||
Haddock | HADDOCK | |||||
Barndoor skate | BARNDOOR SKATE | |||||
Little skate | LITTLE SKATE | |||||
Windowpane | WINDOWPANE | |||||
Atlantic herring | ATLANTIC HERRING |
The current NEAMAP input data includes the list of piscivores. I would need to request a different dataset to use the other list. That said, there weren’t many herring in the NEAMAP dataset anyway.
The main question for the WG is whether we want to include haddock and the skates, which are not in the piscivore dataset. This would also require a new NEAMAP pull.
This depends on the predator list. For interest/sensitivity testing, I’ll first use the piscivore predator list (full forage index predator field) to do the footprint.
Then I’ll look at how the footprint changes with different predator lists.
Can run the model with each combination.
Not that many. Seems a spring model will run anyway using the forage index configuration but a fall model will not. This is the full time series from the stomach data for piscivores, we aren’t using all of it in the model.
herringagg_stn <- readRDS(here::here("fhdat/herringagg_stn_all_OISST_1982-2022.rds"))
# make SST column that uses surftemp unless missing or 0
# there are 3 surftemp 0 values in the dataset, all with oisst > 15
herringagg_stn <- herringagg_stn %>%
dplyr::mutate(sstfill = ifelse((is.na(surftemp)|surftemp==0), oisst, surftemp))
#herringagg_stn <- bluepyagg_pred_stn
# filter to assessment years at Tony's suggestion
# code Vessel as AL=0, HB=1, NEAMAP=2
herringagg_stn_all <- herringagg_stn %>%
#ungroup() %>%
#filter(season_ng == "FALL") |>
#,year > 1984) %>%
mutate(AreaSwept_km2 = 1, #Elizabeth's code
#declon = -declon already done before neamap merge
Vessel = as.numeric(as.factor(vessel))-1
) %>%
dplyr::select(Catch_g = meanherringwt, #use bluepywt for individuals input in example
Year = year,
Vessel,
AreaSwept_km2,
Lat = declat,
Lon = declon,
meanpisclen,
npiscsp,
#bottemp, #this leaves out many stations for NEFSC
#surftemp, #this leaves out many stations for NEFSC
#oisst, #leaves out everything before 1982
sstfill,
season_ng
) %>%
na.omit() %>%
as.data.frame()
nonzeroherring <- herringagg_stn_all |>
dplyr::filter(Catch_g > 0) |>
dplyr::group_by(season_ng, Year) |>
dplyr::summarise(n = dplyr::n()) |>
tidyr::pivot_wider(names_from = "season_ng", names_prefix = "Herring", values_from = "n")
tows <- herringagg_stn_all |>
dplyr::group_by(season_ng, Year) |>
dplyr::summarise(n = dplyr::n()) |>
tidyr::pivot_wider(names_from = "season_ng", names_prefix = "Total", values_from = "n")
pisctows <- dplyr::left_join(tows, nonzeroherring) |>
dplyr::select(Year, TotalSPRING, HerringSPRING, TotalFALL, HerringFALL)
tab1 <- flextable::flextable(pisctows) |>
flextable::set_caption("Number of piscivore stomach locations by season and year (TotalSPRING and TotalFALL), and number of piscivore stomach locations having nonzero herring prey (HerringSPRING and HerringFALL).")
flextable::colformat_double(tab1, big.mark = "", digits = 0)
Year | TotalSPRING | HerringSPRING | TotalFALL | HerringFALL |
1973 | 64 | 2 | 103 | |
1974 | 83 | 5 | 77 | 3 |
1975 | 14 | 70 | 2 | |
1976 | 84 | 2 | 67 | 2 |
1977 | 143 | 162 | 2 | |
1978 | 136 | 1 | 332 | 8 |
1979 | 171 | 8 | 380 | 11 |
1980 | 155 | 2 | 248 | 2 |
1981 | 200 | 3 | 181 | 3 |
1982 | 238 | 5 | 193 | 1 |
1983 | 224 | 1 | 168 | 2 |
1984 | 205 | 1 | 205 | 6 |
1985 | 255 | 6 | 233 | 3 |
1986 | 266 | 10 | 208 | 9 |
1987 | 252 | 9 | 232 | 16 |
1988 | 192 | 14 | 226 | 18 |
1989 | 242 | 14 | 267 | 19 |
1990 | 245 | 9 | 287 | 29 |
1991 | 280 | 25 | 348 | 57 |
1992 | 335 | 41 | 413 | 89 |
1993 | 353 | 46 | 403 | 85 |
1994 | 325 | 38 | 309 | 53 |
1995 | 395 | 53 | 362 | 67 |
1996 | 368 | 43 | 309 | 28 |
1997 | 375 | 52 | 288 | 33 |
1998 | 450 | 55 | 340 | 43 |
1999 | 469 | 76 | 341 | 31 |
2000 | 438 | 48 | 295 | 30 |
2001 | 416 | 45 | 293 | 30 |
2002 | 448 | 39 | 293 | 23 |
2003 | 343 | 25 | 301 | 18 |
2004 | 385 | 31 | 287 | 17 |
2005 | 341 | 19 | 290 | 19 |
2006 | 414 | 24 | 329 | 12 |
2007 | 411 | 15 | 454 | 25 |
2008 | 424 | 15 | 464 | 23 |
2009 | 506 | 25 | 475 | 25 |
2010 | 438 | 21 | 452 | 17 |
2011 | 421 | 23 | 441 | 18 |
2012 | 457 | 33 | 458 | 36 |
2013 | 488 | 28 | 483 | 24 |
2014 | 403 | 22 | 453 | 14 |
2015 | 446 | 17 | 461 | 25 |
2016 | 450 | 20 | 473 | 19 |
2017 | 353 | 8 | 260 | 7 |
2018 | 352 | 4 | 400 | 2 |
2019 | 419 | 3 | 453 | 8 |
2020 | 112 | 136 | ||
2021 | 391 | 16 | 425 | 5 |
2022 | 434 | 4 | 387 | 4 |
Visual: stations with herring observations across all years by season, 1982-2022, using the piscivores list
herringagg_stn_fall <- herringagg_stn %>%
#ungroup() %>%
filter(season_ng == "FALL") |>
#,year > 1984) %>%
mutate(AreaSwept_km2 = 1, #Elizabeth's code
#declon = -declon already done before neamap merge
Vessel = as.numeric(as.factor(vessel))-1
) %>%
dplyr::select(Catch_g = meanherringwt, #use bluepywt for individuals input in example
Year = year,
Vessel,
AreaSwept_km2,
Lat = declat,
Lon = declon,
meanpisclen,
npiscsp,
#bottemp, #this leaves out many stations for NEFSC
#surftemp, #this leaves out many stations for NEFSC
#oisst, #leaves out everything before 1982
sstfill
) %>%
na.omit() %>%
as.data.frame()
herringagg_stn_spring <- herringagg_stn %>%
filter(season_ng == "SPRING") |>
#,year > 1984) %>%
mutate(AreaSwept_km2 =1, #Elizabeth's code
#declon = -declon already done before neamap merge
Vessel = as.numeric(as.factor(vessel))-1
) %>%
dplyr::select(Catch_g = meanherringwt,
Year = year,
Vessel,
AreaSwept_km2,
Lat = declat,
Lon = declon,
meanpisclen,
npiscsp,
#bottemp, #this leaves out many stations for NEFSC
#surftemp, #this leaves out many stations for NEFSC
#oisst, #leaves out everything before 1982
sstfill
) %>%
na.omit() %>%
as.data.frame()
nonzerofall <- herringagg_stn_fall |>
dplyr::filter(Catch_g > 0,
Year > 1981)
nonzerospring <- herringagg_stn_spring |>
dplyr::filter(Catch_g > 0,
Year > 1981)
Fall <- ggplot(data = ecodata::coast) +
geom_sf() +
geom_point(data = FishStatsUtils::northwest_atlantic_grid, aes(x = Lon, y = Lat), colour = "coral4", size=0.05, alpha=0.1) +
geom_point(data = nonzerofall, aes(x = Lon, y = Lat), colour = "blue", size=0.5, alpha=1) +
coord_sf(xlim =c(-78.5, -65.5), ylim = c(33, 45)) + #zoomed to Hatteras and N
xlab("") +
ylab("") +
ggtitle("Fall herring in stomachs 1982-2022")+
theme(plot.margin = margin(0, 0, 0, 0, "cm"))
Spring <- ggplot(data = ecodata::coast) +
geom_sf() +
geom_point(data = FishStatsUtils::northwest_atlantic_grid, aes(x = Lon, y = Lat), colour = "coral4", size=0.05, alpha=0.1) +
geom_point(data = nonzerospring, aes(x = Lon, y = Lat), colour = "blue", size=0.5, alpha=1) +
coord_sf(xlim =c(-78.5, -65.5), ylim = c(33, 45)) + #zoomed to Hatteras and N
xlab("") +
ylab("") +
ggtitle("Spring herring in stomachs 1982-2022")+
theme(plot.margin = margin(0, 0, 0, 0, "cm"))
Spring + Fall
How does this compare to herring survey strata (in green here)?
# from Jon
herring_spring <- c(01010, 01020, 01030, 01040, 01050, 01060, 01070, 01080, 01090,
01100, 01110, 01120, 01130, 01140, 01150, 01160, 01170, 01180,
01190, 01200, 01210, 01220, 01230, 01240, 01250, 01260, 01270,
01280, 01290, 01300, 01360, 01370, 01380, 01390, 01400, 01610,
01620, 01630, 01640, 01650, 01660, 01670, 01680, 01690, 01700,
01710, 01720, 01730, 01740, 01750, 01760)
herring_fall <- c(01050, 01060, 01070, 01080, 01090, 01100, 01110, 01120, 01130,
01140, 01150, 01160, 01170, 01180, 01190, 01200, 01210, 01220,
01230, 01240, 01250, 01260, 01270, 01280, 01290, 01300, 01360,
01370, 01380, 01390, 01400)
herring_springgrid <- FishStatsUtils::northwest_atlantic_grid %>%
filter(stratum_number %in% herring_spring)
herring_fallgrid <- FishStatsUtils::northwest_atlantic_grid %>%
filter(stratum_number %in% herring_fall)
Fall <- ggplot(data = ecodata::coast) +
geom_sf() +
geom_point(data = FishStatsUtils::northwest_atlantic_grid, aes(x = Lon, y = Lat), colour = "coral4", size=0.05, alpha=0.1) +
geom_point(data = herring_fallgrid, aes(x = Lon, y = Lat), colour = "green", size=0.05, alpha=0.1) +
geom_point(data = nonzerofall, aes(x = Lon, y = Lat), colour = "blue", size=0.5, alpha=1) +
coord_sf(xlim =c(-78.5, -65.5), ylim = c(33, 45)) + #zoomed to Hatteras and N
xlab("") +
ylab("") +
ggtitle("Fall herring in stomachs 1982-2022")+
theme(plot.margin = margin(0, 0, 0, 0, "cm"))
Spring <- ggplot(data = ecodata::coast) +
geom_sf() +
geom_point(data = FishStatsUtils::northwest_atlantic_grid, aes(x = Lon, y = Lat), colour = "coral4", size=0.05, alpha=0.1) +
geom_point(data = herring_springgrid, aes(x = Lon, y = Lat), colour = "green", size=0.05, alpha=0.1) +
geom_point(data = nonzerospring, aes(x = Lon, y = Lat), colour = "blue", size=0.5, alpha=1) +
coord_sf(xlim =c(-78.5, -65.5), ylim = c(33, 45)) + #zoomed to Hatteras and N
xlab("") +
ylab("") +
ggtitle("Spring herring in stomachs 1982-2022")+
theme(plot.margin = margin(0, 0, 0, 0, "cm"))
Spring + Fall
Distribution from NEFSC BTS tows
survdat_nobio <- readRDS("~/Documents/0_Data/benthosindex/data/survdat_nobio.rds")
survdat_herring_tows <- survdat_nobio$survdat |>
dplyr::filter(SVSPP == 32) |> # Atlantic herring
dplyr::select(CRUISE6, STATION, STRATUM, SVSPP, YEAR, SEASON, LAT, LON, ABUNDANCE, BIOMASS) |>
dplyr::distinct()
saveRDS(survdat_herring_tows, here::here("herringpyindex/survdat_herring_tows.rds"))
survdat_herring_tows <- readRDS(here::here("herringpyindex/survdat_herring_tows.rds"))
surv_herr_fall <- survdat_herring_tows |>
dplyr::filter(SEASON == "FALL",
YEAR > 1981)
surv_herr_spring <- survdat_herring_tows |>
dplyr::filter(SEASON == "SPRING",
YEAR > 1981)
Fall <- ggplot(data = ecodata::coast) +
geom_sf() +
geom_point(data = FishStatsUtils::northwest_atlantic_grid, aes(x = Lon, y = Lat), colour = "coral4", size=0.05, alpha=0.1) +
geom_point(data = herring_fallgrid, aes(x = Lon, y = Lat), colour = "green", size=0.05, alpha=0.1) +
geom_point(data = surv_herr_fall, aes(x = LON, y = LAT), colour = "blue", size=0.5, alpha=1) +
coord_sf(xlim =c(-78.5, -65.5), ylim = c(33, 45)) + #zoomed to Hatteras and N
xlab("") +
ylab("") +
ggtitle("Fall herring NEFSC BTS 1982-2022")+
theme(plot.margin = margin(0, 0, 0, 0, "cm"))
Spring <- ggplot(data = ecodata::coast) +
geom_sf() +
geom_point(data = FishStatsUtils::northwest_atlantic_grid, aes(x = Lon, y = Lat), colour = "coral4", size=0.05, alpha=0.1) +
geom_point(data = herring_springgrid, aes(x = Lon, y = Lat), colour = "green", size=0.05, alpha=0.1) +
geom_point(data = surv_herr_spring, aes(x = LON, y = LAT), colour = "blue", size=0.5, alpha=1) +
coord_sf(xlim =c(-78.5, -65.5), ylim = c(33, 45)) + #zoomed to Hatteras and N
xlab("") +
ylab("") +
ggtitle("Spring herring NEFSC BTS 1982-2022")+
theme(plot.margin = margin(0, 0, 0, 0, "cm"))
Spring + Fall
I think we can define the fall model domain southern extent using the herring BTS strata.
About the same number of positive observations in spring and fall.
List of estimated fixed and random effects:
Coefficient_name Number_of_coefficients Type
1 beta1_ft 48 Fixed
2 beta2_ft 48 Fixed
3 L_epsilon1_z 1 Fixed
4 L_epsilon2_z 1 Fixed
5 L_omega1_z 1 Fixed
6 L_omega2_z 1 Fixed
7 lambda1_k 3 Fixed
8 lambda2_k 3 Fixed
9 ln_H_input 2 Fixed
10 logkappa1 1 Fixed
11 logkappa2 1 Fixed
12 logSigmaM 1 Fixed
13 Epsiloninput1_sff 27750 Random
14 Epsiloninput2_sff 27750 Random
15 Omegainput1_sf 555 Random
16 Omegainput2_sf 555 Random
### Checking model at initial values
All fixed effects have a nonzero gradient
... After 167 iterations...
The following parameters appear to be approaching zero:
Param starting_value Lower MLE Upper final_gradient
55 L_epsilon1_z 1 -Inf -8.171138e-07 Inf -7.579271e-05
Please turn off factor-model variance parameters `L_` that are approaching zero and re-run the model
Error: Please change model structure to avoid problems with parameter estimates and then re-try; see details in `?check_fit`
In addition: Warning message:
In nlminb(start = startpar, objective = fn, gradient = gr, control = nlminb.control, :
NA/NaN function evaluation
Trying spring model
Check diagnostics.
Abundance index:
SOEinputs <- function(infile, season, outfile) {
splitoutput <- read.csv(infile)
# warning, hardcoded. obviously
stratlook <- data.frame(Stratum = c("Stratum_1",
"Stratum_2",
"Stratum_3",
"Stratum_4",
"Stratum_5",
"Stratum_6",
"Stratum_7",
"Stratum_8",
"Stratum_9",
"Stratum_10",
"Stratum_11",
"Stratum_12",
"Stratum_13",
"Stratum_14",
"Stratum_15"),
Region = c("AllEPU",
"MABGB",
"MABGBstate",
"MABGBfed",
"MAB",
"GB",
"GOM",
"bfall",
"bfin",
"bfoff",
"MABGBalbinshore",
"MABGBothoffshore",
"albbfin",
"albbfall",
"allother"))
forageindex <- splitoutput %>%
left_join(stratlook) %>%
dplyr::select(Time,
EPU = Region,
"Forage Fish Biomass Estimate" = Estimate,
"Forage Fish Biomass Estimate SE" = Std..Error.for.Estimate) %>%
tidyr::pivot_longer(c("Forage Fish Biomass Estimate", "Forage Fish Biomass Estimate SE"),
names_to = "Var", values_to = "Value") %>%
dplyr::filter(EPU %in% c("MAB", "GB", "GOM", "AllEPU")) %>%
dplyr::mutate(Units = "relative grams per stomach") %>%
dplyr::select(Time, Var, Value, EPU, Units)
forageindex$Var <- stringr::str_c(season, forageindex$Var, sep = " ")
#readr::write_csv(forageindex, outfile)
#saveRDS(forageindex, outfile)
}
# make data files
SOEinputs(infile = here::here("herringpyindex/allagg_spring_500_lennosst_ALLsplit_biascorrect/Index.csv"),
season = "Spring",
outfile = here::here("herringpyindex/springherringindex.rds"))
forageindex <- readRDS(here::here("herringpyindex/springherringindex.rds"))
# test plot
foragewide <- forageindex %>%
pivot_wider(names_from = Var, values_from = Value)
ggplot(foragewide, aes(x=Time, y=`Spring Forage Fish Biomass Estimate`, colour = EPU)) +
geom_errorbar(aes(ymin=`Spring Forage Fish Biomass Estimate`+`Spring Forage Fish Biomass Estimate SE`,
ymax=`Spring Forage Fish Biomass Estimate`-`Spring Forage Fish Biomass Estimate SE`))+
geom_point()+
geom_line()
Log density pattern:
knitr::include_graphics(here::here("herringpyindex/allagg_spring_500_lennosst_ALLsplit_biascorrect/ln_density-predicted.png"))
Spatial residuals:
knitr::include_graphics(here::here("herringpyindex/allagg_spring_500_lennosst_ALLsplit_biascorrect/quantile_residuals_on_map.png"))