|
| 1 | +#' Extract daily ET data from OpenET |
| 2 | +#' |
| 3 | +#' Note that this requires the environment variable `OPENET_API_KEY` to be set. |
| 4 | +#' A convenient way to do this is via a `.Renviron`, either globally |
| 5 | +#' (`~/.Renviron`) or in the current working directory (`./.Renviron`), with |
| 6 | +#' contents like: |
| 7 | +#' |
| 8 | +#' ``` |
| 9 | +#' OPENET_API_KEY="abcdefg123456" |
| 10 | +#' ``` |
| 11 | +#' |
| 12 | +#' You can obtain an OpenET API key from the OpenET data portal. |
| 13 | +#' |
| 14 | +#' @param design_points `data.frame` of design points with columns `lat` and `lon` |
| 15 | +#' @param start_date Start date for data extraction |
| 16 | +#' @param end_date End date for data extraction |
| 17 | +#' |
| 18 | +#' @return `design_points` `data.frame` with additional columns `date`, and |
| 19 | +#' `et_mm_day` (ET, mm/day) |
| 20 | +#' @export |
| 21 | +extract_openet_daily <- function(design_points, start_date, end_date) { |
| 22 | + api_key <- Sys.getenv("OPENET_API_KEY") |
| 23 | + if (api_key == "") { |
| 24 | + stop("OPENET_API_KEY environment variable is not set") |
| 25 | + } |
| 26 | + |
| 27 | + start_date_str <- format(start_date, "%Y-%m-%d") |
| 28 | + end_date_str <- format(end_date, "%Y-%m-%d") |
| 29 | + |
| 30 | + request_body_template <- list( |
| 31 | + date_range = c(start_date_str, end_date_str), |
| 32 | + interval = "daily", |
| 33 | + model = "Ensemble", |
| 34 | + variable = "ET", |
| 35 | + reference_et = "gridMET", |
| 36 | + units = "mm", |
| 37 | + file_format = "JSON" |
| 38 | + ) |
| 39 | + |
| 40 | + prep_request <- function(lon, lat) { |
| 41 | + request_body <- request_body_template |
| 42 | + request_body$geometry <- c(lon, lat) |
| 43 | + |
| 44 | + httr2::request("https://openet-api.org/raster/timeseries/point") |> |
| 45 | + httr2::req_headers(Authorization = api_key) |> |
| 46 | + httr2::req_body_json(request_body) |> |
| 47 | + httr2::req_throttle(capacity = 10, fill_time_s = 1) |> |
| 48 | + httr2::req_retry(max_tries = 3) |> |
| 49 | + httr2::req_timeout(seconds = 150) |
| 50 | + } |
| 51 | + |
| 52 | + raw_results <- design_points |> |
| 53 | + dplyr::mutate( |
| 54 | + reqs = purrr::map2(.data$lon, .data$lat, prep_request), |
| 55 | + resps = httr2::req_perform_parallel( |
| 56 | + raw_results[["reqs"]], |
| 57 | + max_active = 10, |
| 58 | + on_error = "continue" |
| 59 | + ) |
| 60 | + ) |
| 61 | + |
| 62 | + parse_response <- function(resp) { |
| 63 | + if (!inherits(resp, "httr2_response")) { |
| 64 | + return(NULL) |
| 65 | + } |
| 66 | + data <- httr2::resp_body_json(resp) |
| 67 | + if (length(data) == 0 || is.null(data[[1]]$time)) { |
| 68 | + return(NULL) |
| 69 | + } |
| 70 | + tibble::tibble( |
| 71 | + date = as.Date(purrr::map_chr(data, "time")), |
| 72 | + et_mm_day = purrr::map_dbl(data, "et") |
| 73 | + ) |
| 74 | + } |
| 75 | + |
| 76 | + results <- raw_results |> |
| 77 | + dplyr::mutate(results = purrr::map(.data$resps, parse_response)) |> |
| 78 | + dplyr::select(-c("reqs", "resps")) |> |
| 79 | + tidyr::unnest("results", keep_empty = TRUE) |
| 80 | + |
| 81 | + results |
| 82 | +} |
0 commit comments