#' MABM annual report creation.
#'
#' This function generates an annual report for one or more MABM stations for, by default,
#' the current calendar year. The report includes, for each route associated with a
#' given station, (1) an overview of the year's efforts, (2) a night-by-night tabular
#' summary with notes, if present, (3) a night-by-night tabular summary of species
#' detections, (4) a tabular and graphical comparison of species detections from the
#' current season with previous season(s), and (5) a map of the route indicating the
#' locations of all bat detections for the season.
#'
#' @section Additional details on parameter inputs:
#' \describe{
#' \item{MABM_dir}{This is the base directory containing all relevant data for the whole
#' complement of MABM stations. In short, this base directory should contain a separate
#' directory for each MABM station (e.g., Big Oaks; name is not restricted). Each station
#' directory should in turn contain a directory for *each* route named according to its
#' shortened route name in the MABM database (e.g., BokNWR1 for Big Oaks NWR East route);
#' the station directory may also contain an 'Annual Report' directory. An example
#' hierarchy is shown below.}
#' \item{distribute}{When TRUE, the function attempts to place the output in an 'Annual
#' Report' directory located in the base directory for a given MABM station, alongside
#' the separate directories for each route of that station. For this to work properly,
#' the hierarchy outlined above must exist. If `distribute` = TRUE but a directory
#' matching the shortened route name (e.g., BokNWR1) is not located, or if `distribute`
#' = FALSE, the output is placed in an 'Annual Reports' directory just beneath the directory
#' identified by `MABM_dir`, which is created if does not exist.}
#' }
#'
#' @section Example directory hierarchy:
#' \itemize{
#' \item MABM
#' \itemize{
#' \item{Big Lake}
#' \itemize{
#' \item{BglNWR}
#' \itemize{
#' \item{BglNWR_canonical_route.shp}
#' }
#' \item{Annual Report}
#' }
#' \item{Big Oaks}
#' \itemize{
#' \item{BokNWR1}
#' \itemize{
#' \item{BokNWR1_canonical_route.shp}
#' }
#' \item{BokNWR2}
#' \itemize{
#' \item{BokNWR2_canonical_route.shp}
#' }
#' \item{Annual Report}
#' }
#' }
#' }
#'
#' @section Map generation in the annual reports:
#' Map generation of detected bats occurs only if three requirements are met:
#' \enumerate{
#' \item at least one bat call has been detected
#' \item the calls have been successfully georeferenced (i.e., they possess associated
#' location information).
#' \item a shapefile (point or line) named with the form 'shortname_canonical_route.shp'
#' (e.g., BokNWR1_canonical_route.shp') is present in its respective route directory
#' }
#'
#' @param station character string indicating the MABM station (e.g., refuge, ES office) for
#' which to produce a report. Default (NULL) prompts the user to select from a list of all
#' available MABM stations. The selection of multiple stations is allowed.
#' @param year integer indicating the year for which to generate the annual report; defaults
#' to the current year
#' @param MABM_dir character string indicating the base directory containing MABM station
#' related data (i.e., MABM route directories with call files, shapefiles, and annual reports).
#' See Details.
#' @param update logical (default = FALSE) indicating whether to call a macro inside the MABM
#' database that exports the data necessary for annual report generation. Generally used
#' (i.e., update = TRUE) only if (1) this is the first time running \code{MABM_report} or (2)
#' after the MABM database has been updated.
#' @param distribute logical (default = TRUE) indicating whether to attempt to place the
#' output report in an 'Annual Report' directory within the base directory for each station,
#' if located. To work properly, a specific directory hierarchy is expected (see Details).
#' If `distribute` = FALSE or distribute attempt fails (see Details), the output is placed
#' in an 'Annual Report' directory beneath \code{MABM_dir}.
#' @param key character scalar of Google Maps API key
#' @param interactive logical (default = TRUE) indicating whether to attach an interactive
#' leaflet map (*.html file) of bat detections along a route in a given year. If so, it is
#' attached to, and exported with, the report *.pdf
#' @export
MABM_report <- function(station = NULL, year = as.integer(format(Sys.Date(), "%Y")),
MABM_dir = NULL, update = FALSE, distribute = TRUE,
key = NULL, interactive = TRUE) {
if (is.null(key)) stop("This function now requires a Google API key. ",
"See https://developers.google.com/maps/documentation/maps-static/get-api-key")
if (is.null(MABM_dir)) {
ans <- yesno()
if (ans == "c") stop("Function cancelled.")
if (ans == "y") MABM_dir <- getwd()
if (ans == "n") {
MABM_dir <- choose.dir("C:/", caption = "Select folder with MABM database exports.")
message("Using database exports in ", normalizePath(MABM_dir, winslash = "/"))
}
if (is.na(MABM_dir)) stop("No directory selected.")
} else MABM_dir <- file.path(MABM_dir)
if (!update) {
if (!all(file.exists(file.path(MABM_dir, "MABM_calls.xlsx")),
file.exists(file.path(MABM_dir, "MABM_survey_details.xlsx")),
file.exists(file.path(MABM_dir, "MABM_spp_details.xlsx")),
file.exists(file.path(MABM_dir, "MABM_routes.xlsx"))))
stop("At least one required MABM output file is missing. ",
"Check your choice of `MABM_dir` or use `update = TRUE`.")
} else {
# setup_MABM_reports(export_dir = MABM_dir) # export_dir no longer used by function
setup_MABM_reports()
}
# Set up temporary directory
tmps <- tempfile("MABM", fileext = rep(".RDS", 4))
# Get list of completed routes (stations may host >1 route)
routes <- readxl::read_excel(file.path(MABM_dir, "MABM_routes.xlsx")) %>%
dplyr::select(station = ORGNAME,
site = Site_Name,
site_notes = Loc_Notes,
len_mi = Rte_length,
lat = Centroid_Y_Coord,
lon = Centroid_X_Coord,
state = State)
station_routes <- dplyr::select(routes, station, site)
# Pick a station, any station
menu_items <- routes$station %>% unique() %>% sort()
if (is.null(station)) {
station <- utils::select.list(menu_items, title="Select one or more MABM stations.",
multiple = TRUE, graphics = TRUE)
if (length(station) == 0) stop("You must select or provide a MABM station.")
} else {
if (!(all(station %in% routes$station))) stop("At least one unrecognized MABM station.")
}
### Make the report
make_report <- function(station, interactive) {
message("Processing report for ", station)
routes <- routes[routes$station == station, ] %>% dplyr::arrange(site)
station <- routes$station %>% unique() %>%
sub("NWR", "National Wildlife Refuge", .) %>%
sub("SERVICES", "Services", .) %>%
Cap()
# Store in temporary file
saveRDS(routes, file = tmps[1])
survey_info <- readxl::read_excel(file.path(MABM_dir, "MABM_survey_details.xlsx")) %>%
dplyr::select(site = dplyr::starts_with("Site Name"),
surv_date = dplyr::starts_with("Date Start"),
gps = dplyr::starts_with("GPS"),
complete = dplyr::starts_with("Rt Compl"),
notes = Notes) %>%
dplyr::filter(as.integer(format(surv_date, "%Y")) == year,
site %in% routes$site) %>%
dplyr::mutate(gps = as.logical(gps),
complete = as.logical(complete),
notes = ifelse(is.na(notes), "", notes)) %>%
dplyr::arrange(site, surv_date)
if (nrow(survey_info) == 0) stop(paste0("No MABM data found at ", station, " in ", year, ".\n"))
if (nrow(survey_info) > nrow(unique(survey_info))) {
print(survey_info)
stop("Duplicated records in the survey log on ", station, " in ", year, " (see above).",
"\n Check for duplicated survey entries in the `tbl_Events` table of the MABM database.",
call. = FALSE)
}
# Store it
saveRDS(survey_info, file = tmps[2])
# Get the call data for this station...
calls <- readxl::read_excel(file.path(MABM_dir, "MABM_calls.xlsx")) %>%
dplyr::select(site = Site_Name,
lat = LAT,
lon = LONG,
surv_date = dplyr::contains("Date Start"),
spp = A_SP) %>%
dplyr::mutate(year = as.integer(format(surv_date, "%Y"))) %>%
dplyr::filter(site %in% routes$site & year <= year) %>%
dplyr::arrange(site, surv_date)
start_yr <- min(calls$year)
#Store it
saveRDS(calls, tmps[3])
# Load species code/common name lookup table and store it...
spp_info <- readxl::read_excel(file.path(MABM_dir, "MABM_spp_details.xlsx")) %>%
dplyr::rename(spp = A_SP,
spp_cn = CommonName) %>%
dplyr::select(spp, spp_cn)
saveRDS(spp_info, tmps[4])
# Set the output directory
base_dir <- NULL
if (distribute) {
base_dir <- grep(paste0(survey_info$site[1], "$"), list.dirs(MABM_dir), value = TRUE)
if (length(base_dir) == 1) {
out_dir <- file.path(dirname(base_dir), "Annual Report")
} else {
out_dir <- file.path(MABM_dir, "Annual Reports")
if (!dir.exists(out_dir)) dir.create(out_dir)
out_dir <- normalizePath(out_dir)
if (length(base_dir) == 0) {
warning("Matching station/route directories not found. ",
"Annual report output to ", shQuote(out_dir))
} else {
warning("Multiple matching station/route directories found. ",
"Annual report output to ", shQuote(out_dir))
}
}
} else {
out_dir <- file.path(MABM_dir, "Annual Reports")
if (!dir.exists(out_dir)) dir.create(out_dir)
out_dir <- normalizePath(out_dir)
}
render_MABM(year = year, station = station,
stn_start_yr = start_yr, route_path = tmps[1],
survey_path = tmps[2], bat_path = tmps[3], spp_path = tmps[4],
out_dir = out_dir, key = key)
if (interactive) interactive_MABM(station, routes, calls, spp_info, year, out_dir)
}
invisible(lapply(station, function(stn) make_report(stn, interactive)))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.