-
Notifications
You must be signed in to change notification settings - Fork 320
Enhance ERA5 Download Function: Direct NetCDF, Flexible Parameters, and Improved Docs #3547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
c3bfd1f
39863c7
7584b61
98756c1
ab94ff7
41b15ff
e9edacb
93c779a
d103587
835597a
8b3ce23
7cdfdca
6b78dfd
d8de233
be1e5dd
52feafc
0c41613
be7e603
f26ea46
c81dea8
94d5e2c
00096ce
a6bfb60
cfe9e38
6cef9b5
f72deec
c62c89f
6f535ba
e43acd9
c91d76e
6768615
e4e0ca8
65d4f07
dae7402
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,26 +1,55 @@ | ||||||
| #' Download ERA5 Climate Data from the Copernicus CDS API | ||||||
| #' | ||||||
| #' @description | ||||||
| #' This function helps to download the yearly ERA5 data based on the prescribed features using the CDS API. | ||||||
| #' @title ERA5_cds_annual_download | ||||||
| #' | ||||||
| #' @param outfolder Character: physical path where the ERA5 data are stored. | ||||||
| #' Download ERA5 climate data from the Copernicus Climate Data Store (CDS) API as NetCDF files, year by year, according to user-specified parameters. | ||||||
| #' The function saves one NetCDF file per year in the specified output directory. | ||||||
| #' | ||||||
| #' @details | ||||||
| #' This function requires a valid CDS API key and the Python `cdsapi` package installed and accessible via the `reticulate` package in R. | ||||||
| #' If you do not have a `.cdsapirc` file with your API credentials, set `auto.create.key = TRUE` to be prompted for your CDS API URL and key. | ||||||
| #' To get a Copernicus CDS API key, register at \url{https://cds.climate.copernicus.eu/profile}. | ||||||
| #' The API URL is \url{https://cds.climate.copernicus.eu/api/v2}. | ||||||
| #' | ||||||
| #' @param outfolder Character. Directory where downloaded NetCDF files will be saved. | ||||||
| #' @param start_date character: the start date of the data to be downloaded. Format is YYYY-MM-DD (will only use the year part of the date) | ||||||
| #' @param end_date character: the end date of the data to be downloaded. Format is YYYY-MM-DD (will only use the year part of the date) | ||||||
| #' @param extent numeric: a vector of numbers contains the bounding box (formatted as xmin, xmax, ymin, ymax) to be downloaded. | ||||||
| #' @param extent numeric: a vector of numbers contains the bounding box (formatted as xmin, xmax, ymin, ymax) (longitude and latitude in degrees). | ||||||
| #' @param variables character: a vector contains variables to be downloaded (e.g., c("2m_temperature","surface_pressure")). | ||||||
| #' @param time Character vector or NULL. Hours of the day to download (e.g., c("00:00", "12:00")). Default to NULL to download all hours. | ||||||
| #' @param dataset Character. Name of the CDS dataset to use (default: "reanalysis-era5-single-levels"). | ||||||
| #' @param product_type Character. Product type to request from CDS (default: "ensemble_members"). | ||||||
| #' @param auto.create.key Boolean: decide if we want to generate the CDS RC file if it doesn't exist, the default is TRUE. | ||||||
| #' @param timeout numeric: the maximum time (in seconds) allowed to download the data. The default is 36000 seconds. | ||||||
| #' | ||||||
| #' @return A vector containing file paths to the downloaded files. | ||||||
| #' @return | ||||||
| #' A list where each element is a list containing: | ||||||
| #' \item{file}{File path to the downloaded NetCDF file.} | ||||||
| #' \item{host}{Host name where the file was downloaded.} | ||||||
| #' \item{startdate}{Start date and time of the data in the file.} | ||||||
| #' \item{enddate}{End date and time of the data in the file.} | ||||||
| #' \item{mimetype}{MIME type of the file ("application/x-netcdf").} | ||||||
| #' \item{formatname}{Format name ("ERA5_year.nc").} | ||||||
| #' | ||||||
| #' @examples | ||||||
| #' \dontrun{ | ||||||
| #' era5_files <- download.ERA5_cds( | ||||||
| #' outfolder = "D:/working/era5_func_test", | ||||||
|
divine7022 marked this conversation as resolved.
Outdated
|
||||||
| #' start_date = "2020-01-01", | ||||||
| #' end_date = "2022-12-31", | ||||||
| #' extent = c(-72.2215, -72.1215, 42.4878, 42.5878), | ||||||
| #' variables = c("2m_temperature","surface_pressure"), | ||||||
| #' time = NULL, | ||||||
| #' product_type = "reanalysis" | ||||||
| #' ) | ||||||
| #' } | ||||||
| #' @export | ||||||
| #' | ||||||
| #' @importFrom purrr %>% | ||||||
| #' @author Dongchen Zhang | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As commented elsewhere, we use |
||||||
| download.ERA5_cds <- function(outfolder, start_date, end_date, extent, variables, auto.create.key = T, timeout = 36000) { | ||||||
| # check shell environments. | ||||||
| if ("try-error" %in% class(try(system("grib_to_netcdf"), silent = T))) { | ||||||
| PEcAn.logger::logger.info("The grib_to_netcdf function is not detected in shell command.") | ||||||
| return(NA) | ||||||
| } | ||||||
| download.ERA5_cds <- function(outfolder, start_date, end_date, | ||||||
| extent, variables, time = NULL, dataset = "reanalysis-era5-single-levels", | ||||||
| product_type = "ensemble_members", auto.create.key = T, timeout = 36000) { | ||||||
|
divine7022 marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| # setup timeout for download. | ||||||
| options(timeout=timeout) | ||||||
| # convert arguments to CDS API specific arguments. | ||||||
|
|
@@ -29,10 +58,16 @@ download.ERA5_cds <- function(outfolder, start_date, end_date, extent, variables | |||||
| purrr::map(function(d)sprintf("%02d", d)) | ||||||
| days <- sort(unique(lubridate::day(seq(lubridate::date(start_date), lubridate::date(end_date), "1 day")))) %>% | ||||||
| purrr::map(function(d)sprintf("%02d", d)) | ||||||
| times <- list('00:00','03:00','06:00', | ||||||
| '09:00','12:00','15:00', | ||||||
| '18:00','21:00') | ||||||
| area <- paste(c(extent[4], extent[1], extent[3], extent[2]), collapse = "/") | ||||||
|
|
||||||
| # handle time argument: all hours if Null | ||||||
| if (is.null(time)) { | ||||||
| times <- sprintf("%02d:00", 0:23) | ||||||
| } else { | ||||||
| times <- time | ||||||
| } | ||||||
|
|
||||||
| # Format area for CDS API (North, West, South, East) | ||||||
| area <- round(c(extent[4], extent[1], extent[3], extent[2]), 2) | ||||||
| variables <- as.list(variables) | ||||||
| #load cdsapi from python environment. | ||||||
| tryCatch({ | ||||||
|
|
@@ -99,34 +134,30 @@ download.ERA5_cds <- function(outfolder, start_date, end_date, extent, variables | |||||
| # loop over years. | ||||||
| nc.paths <- c() | ||||||
| for (y in years) { | ||||||
| fname <- file.path(outfolder, paste0("ERA5_", y, ".grib")) | ||||||
| fname <- file.path(outfolder, paste0("ERA5_", y, ".nc")) | ||||||
| # start retrieving data. | ||||||
| # you need to have an account for downloaing the files | ||||||
| # Read the documantion for how to setup your account and settings before trying this | ||||||
| # https://confluence.ecmwf.int/display/CKB/How+to+download+ERA5#HowtodownloadERA5-3-DownloadERA5datathroughtheCDSAPI | ||||||
| c$retrieve( | ||||||
| 'reanalysis-era5-single-levels', | ||||||
|
dlebauer marked this conversation as resolved.
Outdated
|
||||||
| list( | ||||||
| 'product_type' = 'ensemble_members', | ||||||
| 'data_format' = 'grib', | ||||||
| 'product_type' = list(product_type), | ||||||
| 'data_format' = 'netcdf', | ||||||
| "download_format" = "unarchived", | ||||||
| 'day' = days, | ||||||
| 'time' = times, | ||||||
| 'month' = months, | ||||||
| 'year' = as.character(y), | ||||||
| 'year' = list(as.character(y)), | ||||||
| "area" = area, | ||||||
| 'variable' = variables | ||||||
| ), | ||||||
| fname | ||||||
| ) | ||||||
| # convert grib to nc file. | ||||||
| nc.path <- gsub(".grib", ".nc", fname, fixed = T) | ||||||
| cmd <- paste("grib_to_netcdf", fname, "-o", nc.path) | ||||||
| out <- system(cmd, intern = F, ignore.stdout = T, ignore.stderr = T) | ||||||
|
|
||||||
| # store the path. | ||||||
| nc.paths <- c(nc.paths, nc.path) | ||||||
| # remove previous grib file. | ||||||
| unlink(fname) | ||||||
| nc.paths <- c(nc.paths, fname) | ||||||
|
|
||||||
| } | ||||||
| # construct results to meet the requirements of pecan.met workflow. | ||||||
| results <- vector("list", length = length(years)) | ||||||
|
|
||||||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.