## ----include = FALSE---------------------------------------------------------- # rmd style knitr::opts_chunk$set( collapse = TRUE, comment = "#>", warning = FALSE, message = FALSE, fig.align = "center", fig.width = 6 ) options(tibble.print_min = 5, tibble.print_max = 5) # load packages library(hatchR) library(tibble) library(ggplot2) library(purrr) library(dplyr) library(lubridate) library(tidyr) ## ----------------------------------------------------------------------------- library(hatchR) # for data and phenology modeling library(ggplot2) # for additional plotting options library(purrr) # for iteration library(lubridate) # for date manipulation library(tibble) # for data manipulation library(dplyr) # for data manipulation library(tidyr) # for data manipulation ## ----------------------------------------------------------------------------- WI_spawn_dates <- c("1990-08-14", "1990-08-18", "1990-09-3") ## ----------------------------------------------------------------------------- sockeye_hatch_mod <- model_select( author = "Beacham and Murray 1990", species = "sockeye", model_id = 2, development_type = "hatch" ) ## ----------------------------------------------------------------------------- # Loop storage objects OUT_loop_all <- NULL OUT_loop_d2h <- NULL # Loop body for (d in 1:length(WI_spawn_dates)) { # d will be our numerical iterator # subset the element d of the vector and assign to object WI_spawn <- WI_spawn_dates[d] # predict phenology WI_hatch <- predict_phenology( data = woody_island, dates = date, temperature = temp_c, spawn.date = WI_spawn, model = sockeye_hatch_mod ) ### ALL output ### # do this if we want to maintain all info predict_phenology OUT_loop_all[[d]] <- WI_hatch ### A single element of output ### # alternatively, subsets out output temp <- tibble(matrix(data = NA, ncol = 2, nrow = 1)) # empty dataframe to add in data colnames(temp) <- c("spawn_date", "days_2_hatch") # change column names temp$spawn_date <- WI_spawn # assign spawn date temp$days_2_hatch <- WI_hatch$days_to_develop # assign days to hatch OUT_loop_d2h <- rbind(OUT_loop_d2h, temp) # row bind temp object and OUT object } ## ----------------------------------------------------------------------------- glimpse(OUT_loop_all) ## ----------------------------------------------------------------------------- OUT_loop_d2h ## ----------------------------------------------------------------------------- # map works by applying a function over a list (our vector is a very simple list) # if you are familiar with apply() functions, map is essentially the same results_map <- map( WI_spawn_dates, # vector we are mapping over predict_phenology, # function we are mapping with (note no "()"), data = woody_island, # additional arguments required by predict_phenology dates = date, temperature = temp_c, model = sockeye_hatch_mod ) # we now have a list of lists the same as OUT_loop_all glimpse(results_map) # we can then access days to hatch easily as such results_map |> map_dbl("days_to_develop") ## ----------------------------------------------------------------------------- # lapply() is the equivalent function as map() in the apply family # they both output lists results_lapply <- lapply(WI_spawn_dates, # vector we are mapping over predict_phenology, # function we are mapping with (note no "()"), data = woody_island, # additional arguments required by predict phenology dates = date, temperature = temp_c, model = sockeye_hatch_mod ) ## ----------------------------------------------------------------------------- glimpse(results_lapply) ## ----------------------------------------------------------------------------- # look at data structure glimpse(crooked_river) # visually check data plot_check_temp( data = crooked_river, dates = date, temperature = temp_c, temp_min = 0, temp_max = 12 ) ## ----------------------------------------------------------------------------- crooked_river |> mutate(year = lubridate::year(date)) |> group_by(year) |> tally() ## ----warning=TRUE------------------------------------------------------------- # select bull trout hatch and emergence models bull_hatch_mod <- model_select( author = "Austin et al. 2019", species = "bull trout", model = "MM", development_type = "hatch" # note we are using hatch model here ) bull_emerge_mod <- model_select( author = "Austin et al. 2019", species = "bull trout", model = "MM", development_type = "emerge" # note we are using emerge model here ) # set spawning dates in 2015 dates_2015 <- c("2015-09-01", "2015-09-15", "2015-09-30") ## hatch first hatch_2015 <- dates_2015 |> purrr::map( predict_phenology, data = crooked_river, dates = date, temperature = temp_c, model = bull_hatch_mod ) ## ----------------------------------------------------------------------------- ## mini loop to make vector of dates spawn_dates <- NULL for (year in 2011:2014) { temp_dates <- c(paste0(year, "-09-01"), paste0(year, "-09-15"), paste0(year, "-09-30")) spawn_dates <- c(spawn_dates, temp_dates) } spawn_dates ### loop for prediction OUT <- NULL i <- 1 # build a counter for adding to our list of lists (OUT) for (mod in c("hatch", "emerge")) { # loop for hatch and emerge # here we just iterate model selection over the two hatch and emerge options # in the first for loop dev_mod <- model_select( author = "Austin et al. 2019", species = "bull trout", model = "MM", development_type = mod ) for (d in 1:length(spawn_dates)) { # nested loop over spawn dates # here we iterate over every date of spawn_dates but run this loop twice, # once for each value of the first for loop spawn <- spawn_dates[d] # get spawn date temp <- predict_phenology( data = crooked_river, dates = date, temperature = temp_c, spawn.date = spawn, model = dev_mod ) # notice we are calling the mod we set in the fist loop OUT[[i]] <- temp i <- i + 1 # add to your counter } } ## ----------------------------------------------------------------------------- mapped_results <- OUT |> purrr:::map_df("ef_table") mapped_results ## ----------------------------------------------------------------------------- # slightly cleaner spawn dates with map output is a list of vectors spawn_dates <- map( c(2011:2014), # year vector to map for custom function function(year) { # custom function to make dates c( paste0(year, "-09-01"), paste0(year, "-09-15"), paste0(year, "-09-30") ) } ) |> unlist() dev_mods <- map( c("hatch", "emerge"), model_select, author = "Austin et al. 2019", species = "bull trout", model = "MM" ) # we then set up a variable grid for all combinations of our models and dates # it is very important to make the names of the columns in var_grid to match the # arguments of the predict_phenology function (e.i., model = and spawn.date =) var_grid <- expand_grid(model = dev_mods, spawn.date = spawn_dates) head(var_grid) ### multiple input mapping crooked_predictions <- pmap(var_grid, # combos of variables to iterate over predict_phenology, # function data = crooked_river, # additional arguments required by function dates = date, temperature = temp_c ) ## ----------------------------------------------------------------------------- # loop predictions preds_loop <- OUT |> map_dbl("days_to_develop") preds_pmap <- crooked_predictions |> map_dbl("days_to_develop") # everything matches! preds_loop == preds_pmap ## ----------------------------------------------------------------------------- # get predictions days <- crooked_predictions |> map_dbl("days_to_develop") # make a vector of what type of phenology we were predicting # remember we ran hatch over 15 spawn dates then emerge over those same 15 phenology <- c(rep("hatch", 12), rep("emerge", 12)) # make a vector of our spawn dates replicated twice and turn into a timepoint spawning <- rep(spawn_dates, 2) |> ymd(tz = "UTC") # we do this because the crooked_river dataset is ymd_hms # put them all together in an object bull_trout_phenology <- tibble(phenology, spawning, days) head(bull_trout_phenology) ## ----------------------------------------------------------------------------- # filter crooked_river to correct size crooked_river_11_15 <- crooked_river |> filter(date < ymd_hms("2015-06-01 00:00:00")) ggplot(data = crooked_river_11_15, aes(x = date, y = temp_c)) + geom_point(size = 0.25) + geom_line() + geom_point( data = bull_trout_phenology, aes(x = spawning, y = 10), color = "darkblue", shape = 25, size = 2.5 ) + geom_point( data = bull_trout_phenology |> filter(phenology == "hatch"), aes(x = spawning + days(days), y = 0), color = "darkgreen", shape = 24, size = 2.5 ) + geom_point( data = bull_trout_phenology |> filter(phenology == "emerge"), aes(x = spawning + days(days), y = 0), color = "darkorange", shape = 24, size = 2.5 ) + labs( title = "Crooked River Bull Trout Developmental Phenology", subtitle = "Blue = Spawn, Green = Hatch, Orange = Emerge", x = "Date", y = "Temperature" ) + theme_classic() ## ----------------------------------------------------------------------------- # the tibble with all temperature and effective values for each phenological period all_data <- crooked_predictions |> map_df("ef_table") head(all_data) # the phenological durations for each prediction set development_period <- crooked_predictions |> map_df("dev.period") head(development_period) ## ----------------------------------------------------------------------------- # to use the simple Iliamna Lake example within a single season WI_named_list <- WI_spawn_dates |> set_names() |> map(predict_phenology, # note we leave out the input row (WI_spawn_dates) because we are piping it in as input data = woody_island, # additional arguments required by predict phenology dates = date, temperature = temp_c, model = sockeye_hatch_mod ) # you can now see each list is named according to its respective spawn date glimpse(WI_named_list) # therefore a single element could be accessed with its name and the $ operator # if we wanted the dev.period for fish spawning on August 18th we would do the following WI_named_list$`1990-08-18`$dev.period