Nothing
#' @title Download environmental variables made by worldclim version 2.1.
#' @description Parse historic worldclim version 2.1 variables
#' with a setting of boundary and a few other options.
#' @param var (\code{character}) The option for the variable to download,
#' should be one of tvag, tmin, tmax, prec, srad, wind, vapr and bio.
#' The default is 'tmin'.
#' @param res (\code{numeric}) The option for the resolution of image to download.
#' Should be one of 0.5, 2.5, 5, 10 in minute degree.
#' The default is 10.
#' @param bry (\code{\link{sf}} or \code{sp}) The boundary to mask the downloaded original data.
#' If \code{NULL}, it would get global map. If not \code{NULL}, it can take \code{\link{sf}},
#' \code{\link{sfc}}, \code{SpatialPolygonsDataFrame}, \code{SpatialPolygons}, etc.
#' The default is \code{NULL}.
#' @param path (\code{character}) The path to save the downloaded imagery.
#' If \code{NULL}, it would use the current working directory.
#' The default is \code{NULL}.
#' @param nm_mark (\code{character}) the name mark of clipped images.
#' The default is "clip". It would be ignored if \code{bry} is \code{NULL}.
#' @param return_stack (\code{logical}) if \code{TRUE}, stack the imagery together and return.
#' If the area is large and resolution is high, it is better not to stack them.
#' The default is \code{TRUE}.
#' @return if \code{return_stack} is \code{TRUE}, the images would be
#' returned as a \code{stars}. Otherwise, nothing to return, but the user
#' would receive a message of where the images are.
#' @references
#' Fick, Stephen E., and Robert J.
#' Hijmans. "WorldClim 2: new 1-km spatial resolution climate surfaces for
#' global land areas." \emph{International journal of climatology}
#' 37.12 (2017): 4302-4315.\doi{10.1002/joc.5086}
#'
#' @details
#' \href{https://worldclim.org/data/index.html}{Web page page for this dataset}
#'
#' @note
#' If it fails due to slow internet, try to set a larger timeout option,
#' e.g., using `options(timeout = 1e3)`.
#'
#' @importFrom methods is
#' @importFrom utils download.file tail
#' @importFrom sf st_as_sf st_make_valid st_is_valid st_crop
#' @importFrom stars read_stars write_stars
#' @importFrom methods is
#' @export
#' @examples
#' \dontrun{
#' library(sf)
#' library(itsdm)
#'
#' bry <- sf::st_polygon(
#' list(rbind(c(29.34, -11.72), c(29.34, -0.95),
#' c(40.31, -0.95), c(40.31, -11.72),
#' c(29.34, -11.72)))) %>%
#' st_sfc(crs = 4326)
#'
#' bios <- worldclim2(var = "tmin", res = 10,
#' bry = bry, nm_mark = 'exp', path = tempdir())
#'}
#'
worldclim2 <- function(var = "tmin",
res = 10,
bry = NULL,
path = NULL,
nm_mark = "clip",
return_stack = TRUE) {
# Check the inputs
## Vars
stopifnot(var %in% c(
"tavg", "tmin", "tmax", "prec",
"srad", "wind", "vapr", "bio"
))
## res
stopifnot(res %in% c(0.5, 2.5, 5, 10))
## bry
if (is.null(bry)) {
message("No bry set, download global map.")
} else {
if (!(is(bry, "sf") | is(bry, 'sfc') |
is(bry, "SpatialPolygonsDataFrame") |
is(bry, 'SpatialPolygons'))) {
stop("Only support sf or sp.")
}
}
## path
if (is.null(path)) {
path <- getwd()
} else {
if (!dir.exists(path)) {
stop("Path does not exist!")
}
}
# Set up
if (res == 0.5) {
res <- "30s"
} else {
res <- sprintf("%sm", res)
}
path <- file.path(path, "wc2.1")
dir.create(path, showWarnings = FALSE)
# Prepare url and file name
url_base <- "https://biogeo.ucdavis.edu/data/worldclim/v2.1/base"
zip_name <- sprintf("wc2.1_%s_%s.zip", res, var)
url <- file.path(url_base, zip_name)
# Download to local
temp <- tempfile()
dl <- try(download.file(url, temp))
if (inherits(dl, "try-error")) {
Sys.sleep(10)
download.file(url, temp)
}
# Define file number
n <- ifelse(var == "bio", 19, 12)
# Process
if (is.null(bry)) {
# More stable way to unzip a huge file
decompression <- system2("unzip",
args = c("-j", "-o", temp, sprintf("-d %s", path)),
stdout = TRUE)
if (grepl("Warning message", tail(decompression, 1))) {
print(decompression)
}
unlink(temp)
if (return_stack == TRUE) {
## Check unzip files
imgs_in <- list.files(
path,
pattern = "*.tif", full.names = T
)
if(var == 'bio'){
imgs <- file.path(
path, sprintf("wc2.1_%s_%s_%s.tif", res, var, 1:n)
)
} else {
imgs <- file.path(
path, sprintf("wc2.1_%s_%s_%02d.tif", res, var, 1:n)
)
}
if (length(intersect(imgs, imgs_in)) != n) {
stop("Wrong file numbers unzipped.")
}
## Read imgs as stars
if (return_stack == TRUE) clip_imgs <- read_stars(imgs)
}
} else {
# Unzip to a temporary path
## Define temp dir
temp_path <- file.path(path, "global")
dir.create(temp_path, showWarnings = FALSE)
## Unzip
decompression <- system2(
"unzip",
args = c("-j", "-o", temp, sprintf("-d %s", temp_path)),
stdout = TRUE)
if (grepl("Warning message", tail(decompression, 1))) {
print(decompression)
}
unlink(temp)
# Clip the imagery to the boundary
## Check unzip files
imgs_in <- list.files(temp_path, pattern = "*.tif", full.names = T)
if(var == 'bio'){
imgs <- file.path(
temp_path, sprintf("wc2.1_%s_%s_%s.tif", res, var, 1:n)
)
} else {
imgs <- file.path(
temp_path, sprintf("wc2.1_%s_%s_%02d.tif", res, var, 1:n)
)
}
if (length(intersect(imgs, imgs_in)) != n) {
stop("Wrong file numbers unzipped.")}
## Read imgs as stars and clip
clip_imgs <- read_stars(imgs)
bry <- st_as_sf(bry)
if(!st_is_valid(bry)) {
stop('Not valid boundary.')
}
clip_imgs <- st_crop(clip_imgs, bry)
if (inherits(clip_imgs, "stars_proxy")) {
clip_imgs <- st_as_stars(clip_imgs)}
## Save out
invisible(lapply(1:n, function(n) {
rst_name <- paste(nm_mark, names(clip_imgs)[n], sep = "_")
rst_path <- file.path(path, rst_name)
write_stars(clip_imgs, rst_path, layer = n)
}))
## Clean the temp folder
unlink(temp_path, recursive = TRUE)
if (return_stack != TRUE) rm(clip_imgs)
}
if (return_stack == TRUE) {
names(clip_imgs) <- paste0(var, 1:n)
clip_imgs <- merge(clip_imgs, name = 'band')
names(clip_imgs) <- sprintf("wc2.1_%s_%s.tif", res, var)
clip_imgs
} else {
message(sprintf("Files are written to %s.", path))
}
}
# worldclim2 end
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.