diff --git a/.Rbuildignore b/.Rbuildignore index 9cbabd6..8fbecb1 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,6 +8,8 @@ ^CONDUCT\.md$ ^NEWS\.md$ ^docs$ +^data-raw$ +^analysis$ ^pkgdown$ ^LICENSE$ ^.*-logo\..*$ diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 8a86ab2..2c39720 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -1,14 +1,10 @@ -# For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag. -# https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: push: - branches: - - main - - master + branches: [main, master] pull_request: - branches: - - main - - master + branches: [main, master] name: R-CMD-check @@ -22,73 +18,32 @@ jobs: fail-fast: false matrix: config: + - {os: macos-latest, r: 'release'} - {os: windows-latest, r: 'release'} - - {os: macOS-latest, r: 'release'} - - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} - - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} env: - R_REMOTES_NO_ERRORS_FROM_WARNINGS: true - RSPM: ${{ matrix.config.rspm }} GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: r-lib/actions/setup-r@v1 + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 with: r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true - - uses: r-lib/actions/setup-pandoc@v1 - - - name: Query dependencies - run: | - install.packages('remotes') - saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) - writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") - shell: Rscript {0} - - - name: Restore R package cache - if: runner.os != 'Windows' - uses: actions/cache@v2 + - uses: r-lib/actions/setup-r-dependencies@v2 with: - path: ${{ env.R_LIBS_USER }} - key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} - restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- - - - name: Install system dependencies - if: runner.os == 'Linux' - run: | - while read -r cmd - do - eval sudo $cmd - done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') - - - name: Install system dependencies on MacOS (X11, gdal) - if: runner.os == 'macOS' - run: | - brew install --cask xquartz - brew install pkg-config - brew install proj - brew install gdal - - - name: Install dependencies - run: | - remotes::install_deps(dependencies = TRUE) - remotes::install_cran("rcmdcheck") - shell: Rscript {0} - - - name: Check - env: - _R_CHECK_CRAN_INCOMING_REMOTE_: false - run: | - options(crayon.enabled = TRUE) - rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check") - shell: Rscript {0} + extra-packages: any::rcmdcheck + needs: check - - name: Upload check results - if: failure() - uses: actions/upload-artifact@main + - uses: r-lib/actions/check-r-package@v2 with: - name: ${{ runner.os }}-r${{ matrix.config.r }}-results - path: check + upload-snapshots: true \ No newline at end of file diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index 505321e..cd22477 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -12,15 +12,16 @@ name: test-coverage jobs: test-coverage: - runs-on: macOS-latest + timeout-minutes: 120 + runs-on: windows-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + PASS: ${{secrets.PASS}} + steps: - uses: actions/checkout@v2 - - - uses: r-lib/actions/setup-r@v1 - - - uses: r-lib/actions/setup-pandoc@v1 + - uses: r-lib/actions/setup-r@v2 + - uses: r-lib/actions/setup-pandoc@v2 - name: Query dependencies run: | @@ -29,20 +30,14 @@ jobs: writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") shell: Rscript {0} - - name: Restore R package cache - uses: actions/cache@v2 - with: - path: ${{ env.R_LIBS_USER }} - key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} - restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- - - - name: Install system dependencies on MacOS (X11, gdal) - if: runner.os == 'macOS' + - name: Install system dependencies + if: runner.os == 'Linux' run: | - brew install --cask xquartz - brew install pkg-config - brew install proj@7 - brew install gdal + while read -r cmd + do + eval sudo $cmd + done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') + sudo apt-get install libgdal-dev libproj-dev libgeos-dev libudunits2-dev netcdf-bin libsodium-dev libsodium23 - name: Install dependencies run: | @@ -53,4 +48,4 @@ jobs: - name: Test coverage run: covr::codecov() - shell: Rscript {0} + shell: Rscript {0} \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index 1059265..b859f81 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -15,19 +15,20 @@ Description: Programmatic interface to the Harmonized World Soil Database or your computer. Routines for both single pixel data downloads and gridded data are provided. Depends: - R (>= 3.6) + R (>= 4.2) Imports: sf, terra, - httr + httr, + dplyr, + utils License: AGPL-3 LazyData: true ByteCompile: true -RoxygenNote: 7.2.1 +RoxygenNote: 7.2.3 Encoding: UTF-8 Suggests: ncdf4, - magrittr, knitr, markdown, covr, diff --git a/NAMESPACE b/NAMESPACE index 7826f15..cc23fcb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,4 +1,5 @@ # Generated by roxygen2: do not edit by hand +export(ws_download) export(ws_get) export(ws_subset) diff --git a/R/data.R b/R/data.R index 0609013..57201e7 100644 --- a/R/data.R +++ b/R/data.R @@ -1,4 +1,4 @@ -#' HWSD meta-data +#' HWSD v1.2 (ORNL DAAC) meta-data #' #' Data frame with meta-data on the ORNL DAAC parameters one can query #' using the THREDDS server. In addition a brief description of the @@ -11,4 +11,14 @@ #' \item{description}{general description of the variable} #' \item{units}{units of the variable} #' } -"hwsd_meta_data" \ No newline at end of file +"hwsd_meta_data" + + +#' HWSD v2.0 database +#' +#' Database holding the full HWSD v2.0 database layer information +#' for the main soil type specified. For the fields included (i.e. +#' the column names I refer to the FAO documentation). +#' +#' @format data.frame +"hwsd2" \ No newline at end of file diff --git a/R/ws_download.R b/R/ws_download.R new file mode 100644 index 0000000..75007bc --- /dev/null +++ b/R/ws_download.R @@ -0,0 +1,120 @@ +#' Download HWSD v2.0 data +#' +#' Downloads both the database and gridded HWSD v2.0 data products +#' to a desired output path for subsetting. +#' +#' When an existing path is used which is not the temporary directory +#' an environmental variable WS_PATH will be set. This variable will +#' override the default temporary directory if it exists. This allows +#' the gridded data to be stored elsewhere and be forgotten (while using the +#' {hwsdr} package for HWSD v2.0). +#' +#' Should you delete the gridded file, than it can be downloaded again but +#' the environmental variable should be set again using the new_path = TRUE +#' flag. +#' +#' @param ws_path the path / directory where to store the HWSD v2.0 database +#' @param new_path update the path, i.e. dowload data to a new local +#' location (logical, default FALSE) +#' +#' @return current data path +#' @export +#' +#' @examples +#' +#' \dontrun{ +#' +#' # Download the gridded soil map of +#' # HWSD v2.0 to the temporary directory +#' ws_download() +#' +#' # download the same data to a specific +#' # directory (which should exist) +#' ws_download( +#' ws_path = "~/my_path" +#' ) +#' +#' # download the same data to a specific +#' # directory (which should exist) and +#' # update the environmental variable +#' ws_download( +#' ws_path = "~/my_path", +#' new_path = TRUE +#' ) +#' } + +ws_download <- function( + ws_path = file.path(tempdir(), "ws_db"), + new_path = FALSE +) { + + # check if environmental variable is set + # if so use dir as overriding location + if(Sys.getenv("WS_PATH") != "" & !new_path ) { + ws_path <- Sys.getenv("WS_PATH") + } + + if (ws_path == file.path(tempdir(), "ws_db")) { + + message( + sprintf( + "Creating temporary HWSD v2.0 files at:\n %s", ws_path ) + ) + + # create storage path + if (!dir.exists(ws_path)) { + dir.create(ws_path, recursive = TRUE) + } + + } else { + + if (!dir.exists(ws_path)) { + stop( + "Database directory does not exist, please create the directory first!" + ) + } else { + + if(Sys.getenv("WS_PATH") == "" | new_path) { + Sys.setenv("WS_PATH" = ws_path) + } + + if (file.exists(file.path(ws_path, "HWSD2.bil"))) { + message("Grid file exists, skipping download!") + return(ws_path) + } + } + } + + # grab urls + urls <- server(version = "2.0") + + # download zipped gridded data + httr::GET( + urls$grid, + httr::write_disk( + file.path(ws_path, "hwsd2_raster.zip"), + overwrite = TRUE + ) + ) + + utils::unzip( + file.path(ws_path, "hwsd2_raster.zip"), + exdir = ws_path + ) + + # clean up zip files + status <- file.remove( + c( + file.path(ws_path, "hwsd2_raster.zip") + ) + ) + + message( + sprintf( + "Saving HWSD v2.0 files in at:\n %s", ws_path ) + ) + + # exit statement + message("Downloaded HWSD v2.0 files") + return(ws_path) +} \ No newline at end of file diff --git a/R/ws_get.R b/R/ws_get.R index c79f23c..b395e83 100644 --- a/R/ws_get.R +++ b/R/ws_get.R @@ -32,10 +32,10 @@ ws_get <- function( # formulate query to pass to httr query <- list( "var" = var, - "south" = location[1], - "west" = location[2], - "east" = location[4], - "north" = location[3], + "south" = location[2], + "west" = location[1], + "east" = location[3], + "north" = location[4], "disableProjSubset" = "on", "horizStride"= 1, "accept"="netcdf4" diff --git a/R/ws_subset.R b/R/ws_subset.R index 3001576..3c018b6 100644 --- a/R/ws_subset.R +++ b/R/ws_subset.R @@ -6,14 +6,21 @@ #' disk. #' #' @param site sitename for the extracted location -#' @param location location of a bounding box c(lat, lon, lat, lon) defined -#' by a bottom-left and top-right coordinates, a single location (lat, lon) -#' or a data frame with various locations listed (site, lat, lon) +#' @param location location of a bounding box c(lon, lat, lon, lat) defined +#' by a bottom-left and top-right coordinates, a single location (lon, lat) #' @param param soil parameters to provide, the default setting is ALL, this #' will download all available soil parameters.Check #' https://daac.ornl.gov/SOILS/guides/HWSD.html for parameter descriptions. +#' @param layer which soil depth layer of HWSD v2.0 to consider, layers are +#' named D1 to D7 from top to bottom #' @param path path where to download the data to (only applicable to #' spatial data) +#' @param ws_path path to the gridded HWSD v2.0 data, only required/used if +#' querying v2.0 data +#' @param version version of HWSD to query (numeric value). By default the +#' package will query the ORNL DAAC v1.2 via their API. If specifying the +#' later version (2.0) it will download or require the gridded spatial data +#' in addition to the included HWSD v2.0 database with soil parameters. #' @param internal do not store the data on disk #' @param rate request rate in seconds, determines how long to wait between #' queries to avoid bouncing because of rate limitations @@ -43,123 +50,275 @@ #' internal = TRUE #' ) #' -#' raster::plot(t_sand) +#' terra::plot(t_sand) #' } ws_subset <- function( location = c(32, -81, 34, -80), site = "HWSD", param = "ALL", + layer = "D1", path = tempdir(), + ws_path = file.path(tempdir(), "ws_db"), internal = TRUE, - rate = 0.1 + rate = 0.1, + version = 1.2 ){ - # grab meta-data from package - meta_data <- hwsdr::hwsd_meta_data - - if(tolower(param) != "all" & any(!(param %in% meta_data$parameter))){ - stop("One or more soil parameters are not valid!") - } - # check coordinate length if (!(length(location) == 2 || length(location) == 4)){ stop("Location parameters of insufficient length, check coordinates!") } - # check if there are enough coordinates specified - if (length(location) != 4){ - bbox <- FALSE - - # pad the point locations - # as the query needs a bounding box - location <- c( - location[1] - 0.05, - location[2] - 0.05, - location[1] + 0.05, - location[2] + 0.05 - ) + if (as.numeric(version) < 2) { - } else { - bbox <- TRUE - } - - # check the parameters we want to download in case of - # ALL list all available parameters for each frequency - if (any(grepl("ALL", toupper(param)))) { - - # Use meta-data file to select all but the CLM - # parameters when calling ALL - param <- meta_data$parameter[ - meta_data$parameter != "HWSD_SOIL_CLM_RES" - ] - } - - ws_stack <- - lapply(param, function(par){ - # Wait to avoid rate limitations - Sys.sleep(rate) + # grab meta-data from package + meta_data <- hwsdr::hwsd_meta_data + + if(tolower(param) != "all" & any(!(param %in% meta_data$parameter))){ + stop("One or more soil parameters are not valid!") + } + + # check if there are enough coordinates specified + if (length(location) != 4){ + bbox <- FALSE - # get data - ws_get( - location = location, - param = par, - path = tempdir()) - } - ) - - if(all(is.null(ws_stack))){ - warning("No data retrieved!") - return(NULL) - } + # pad the point locations + # as the query needs a bounding box + location <- c( + location[1] - 0.05, + location[2] - 0.05, + location[1] + 0.05, + location[2] + 0.05 + ) + + } else { + bbox <- TRUE + } + + # check the parameters we want to download in case of + # ALL list all available parameters for each frequency + if (any(grepl("ALL", toupper(param)))) { + + # Use meta-data file to select all but the CLM + # parameters when calling ALL + param <- meta_data$parameter[ + meta_data$parameter != "HWSD_SOIL_CLM_RES" + ] + } + + ws_stack <- + lapply(param, function(par){ + + # Wait to avoid rate limitations + Sys.sleep(rate) + + # get data + ws_get( + location = location, + param = par, + path = tempdir()) + } + ) + + if(all(is.null(ws_stack))){ + warning("No data retrieved!") + return(NULL) + } + + # convert the nested list to a nice + # raster stack + ws_stack <- terra::rast(ws_stack) + + # if only a single location is provided + # extract the pixel values and return + # as a data frame + if(!bbox){ + + # define sf point location + p <- sf::st_as_sf(data.frame( + lat = location[2], + lon = location[1]), + coords = c("lon","lat"), + crs = 4326) + + # extract values + values <- terra::extract(ws_stack, p) + + # convert to tidy data + values <- data.frame( + site = site, + parameter = names(values), + latitude = location[2], + longitude = location[1], + value = t(values), + row.names = NULL + ) + + # return data + return(values) + } - # convert the nested list to a nice - # raster stack - ws_stack <- terra::rast(ws_stack) + # if internal return the raster stack + # otherwise write to file as a geotiff + # in the desired path + if(internal){ + return(ws_stack) + } else { + suppressWarnings( + terra::writeRaster( + ws_stack, + filename = file.path(path, + sprintf("%s.tif", + site)), + overwrite = TRUE) + ) + } - # if only a single location is provided - # extract the pixel values and return - # as a data frame - if(!bbox){ - - # define sf point location - p <- sf::st_as_sf(data.frame( - lat = location[1], - lon = location[2]), - coords = c("lon","lat"), - crs = 4326) - - # extract values - values <- terra::extract(ws_stack, p) - - # convert to tidy data - values <- data.frame( - site = site, - parameter = names(values), - latitude = location[1], - longitude = location[2], - value = t(values), - row.names = NULL - ) - - # return data - return(values) - } - - # if internal return the raster stack - # otherwise write to file as a geotiff - # in the desired path - if(internal){ - return(ws_stack) } else { - suppressWarnings( + + # CRAN fix + LAYER <- HWSD2_SMU_ID <- NULL + + # grab the full database + hwsd2 <- hwsdr::hwsd2 |> + dplyr::filter( + LAYER == layer + ) + + # split out the meta-data (column names) + meta_data <- hwsd2 |> + names() + + if(all(tolower(param) != "all") & any(!(param %in% meta_data))){ + stop("One or more soil parameters are not valid!") + } + + # download the gridded data if not available in + # the tempdir() or elsewhere + if (ws_path == file.path(tempdir(), "ws_db")) { + if(!dir.exists(file.path(tempdir(), "ws_db"))) { + ws_path <- ws_download( + ws_path = file.path(tempdir(), "ws_db") + ) + } else { + if(!file.exists(file.path(ws_path, "HWSD2.bil"))) { + ws_path <- ws_download( + ws_path = file.path(tempdir(), "ws_db") + ) + } + } + + } else { + if (!dir.exists(ws_path)) { + stop( + " ws_path does not exist! + check the path location for your gridded + data file (to download with ws_download()) + " + ) + } + } + + ws_stack <- + lapply(param, function(par){ + + # read in raster grid, i.e IDs linking locations to + # database values + ids <- terra::rast(file.path(ws_path, "HWSD2.bil")) + + if (length(location) > 2) { + + # set filename + filename <- file.path( + path, + paste0(par, ".nc") + ) + + # set the extent of the subset + e <- terra::ext(location) + + # crop the full image to extent + c <- terra::crop(ids, e) + + # map values to the gridded indices + output <- try( + terra::subst( + c, + from = hwsd2$HWSD2_SMU_ID, + to = hwsd2[par] + ) + ) + + if(inherits(output, "try-error")){ + stop( + "Value subsitution requires numeric values,\n check selected values!" + ) + } + + return(output) + } else { + # define sf point location + p <- sf::st_as_sf(data.frame( + lon = location[1], + lat = location[2]), + coords = c("lon","lat"), + crs = 4326 + ) + + # extract values + pixel_id <- terra::extract( + ids, + p + ) + + # select and filter output + output <- hwsd2 |> + dplyr::filter( + HWSD2_SMU_ID == pixel_id$HWSD2 + ) |> + dplyr::select( + dplyr::all_of(par) + ) |> + dplyr::mutate( + latitude = location[2], + longitude = location[1], + site = site, + parameter = par + ) |> + dplyr::rename( + "value" = !!par + ) + + return(output) + } + }) + + if(all(is.null(ws_stack))){ + warning("No data retrieved!") + return(NULL) + } + + if (length(location) == 2) { + ws_stack <- dplyr::bind_rows(ws_stack) + return(ws_stack) + } + + if (length(location) == 4) { + ws_stack <- terra::rast(c(ws_stack)) + } + + # if internal return the raster stack + # otherwise write to file as a geotiff + # in the desired path + if(internal & length(location) == 4){ + return(ws_stack) + } else { terra::writeRaster( ws_stack, - filename = file.path(path, - sprintf("%s.tif", - site)), - gdal = c("COMPRESS=DEFLATE"), - overwrite = TRUE) - ) + file.path(path, paste0(c(site, layer, ".tif"), collapse = "_")), + overwrite = TRUE + ) + } } } diff --git a/R/zzz.R b/R/zzz.R index a81ef30..b151e03 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,6 +1,21 @@ # server end points -server <- function(){ - url <- "https://thredds.daac.ornl.gov/thredds/ncss/ornldaac/1247" - return(url) +server <- function( + version = "1.2" + ){ + + # fao AWS base url + fao_base <- "https://s3.eu-west-1.amazonaws.com/data.gaezdev.aws.fao.org" + + if (version == "1.2") { + # return ORNL DAAC url for HWSD v1.2 + url <- "https://thredds.daac.ornl.gov/thredds/ncss/ornldaac/1247" + return(url) + } else { + # return both files for HWSD v2.0 + url <- list( + mdb = file.path(fao_base, "HWSD/HWSD2_DB.zip"), + grid = file.path(fao_base, "HWSD/HWSD2_RASTER.zip") + ) + return(url) + } } - diff --git a/analysis/generate_db_file.R b/analysis/generate_db_file.R new file mode 100644 index 0000000..d6cda0f --- /dev/null +++ b/analysis/generate_db_file.R @@ -0,0 +1,99 @@ +# Convert Microsoft Access database file to an +# R serialized dataframe for inclusion in the +# package (only the grid layout will be +# downloaded externally to the package) +# +# The data returned by this routine will also +# only cover the main soil type, not the associated +# soil types. +# +# This data is included in the package as the main +# database is provided in a proprietary format which +# is difficult to read without additional tools. + +library(dplyr) + +#---- define MS Access reading function ---- + +# This function requires mdbtools to be installed +# on the system that runs the code (either linux +# or macOS). +# +# on Ubuntu run: sudo apt install mdbtools + +mdb_read <- function(file) +{ + + tables = c( + "HWSD2_LAYERS", + "HWSD2_SMU" + ) + + # dump database content to temporary file + df <- lapply(tables, function(table){ + + f <- tempfile() + system2( + command = 'mdb-export', + args = paste('-b strip', file, shQuote(table)), + stdout = f + ) + + # read in CSV file + data <- readr::read_csv(f) + + if (table == "HWSD2_SMU") { + data <- data |> + dplyr::select( + HWSD2_SMU_ID, + WRB4 + ) |> + rename( + 'WRB_main' = 'WRB4' + ) + } + + # return mdb data of sub-table + data + }) + + # left join both tables on common HWSD2_SMU_ID + # and filter the main WRB (dominant soil layer) + # from the data + df <- do.call("left_join", df) |> + dplyr::filter( + WRB4 == WRB_main + ) |> + select( + -WRB_main + ) + + # return the whole data frame + return(df) +} + +#---- download MS access HWSD v2.0 database ---- + +if(!dir.exists("./data-raw")) { + dir.create("./data-raw") +} + +curl::curl_download( + unlist(server(version = "2.0")$mdb), + destfile = "./data-raw/HWSD2.zip" +) + +unzip( + "./data-raw/HWSD2.zip", + exdir = "./data-raw/" + ) + +file.remove("./data-raw/HWSD2.zip") + +#---- grab the database values for tables ---- + +db <- mdb_read("./data-raw/HWSD2.mdb") + +# save as rda object +saveRDS(db, "data/hwsd2.rda", compress = "xz") + diff --git a/data/hwsd2.rda b/data/hwsd2.rda new file mode 100644 index 0000000..d43b820 Binary files /dev/null and b/data/hwsd2.rda differ diff --git a/man/hwsd2.Rd b/man/hwsd2.Rd new file mode 100644 index 0000000..9e2510d --- /dev/null +++ b/man/hwsd2.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{hwsd2} +\alias{hwsd2} +\title{HWSD v2.0 database} +\format{ +data.frame +} +\usage{ +hwsd2 +} +\description{ +Database holding the full HWSD v2.0 database layer information +for the main soil type specified. For the fields included (i.e. +the column names I refer to the FAO documentation). +} +\keyword{datasets} diff --git a/man/hwsd_meta_data.Rd b/man/hwsd_meta_data.Rd index 23123bc..4adabd6 100644 --- a/man/hwsd_meta_data.Rd +++ b/man/hwsd_meta_data.Rd @@ -3,7 +3,7 @@ \docType{data} \name{hwsd_meta_data} \alias{hwsd_meta_data} -\title{HWSD meta-data} +\title{HWSD v1.2 (ORNL DAAC) meta-data} \format{ data.frame \describe{ diff --git a/man/ws_download.Rd b/man/ws_download.Rd new file mode 100644 index 0000000..be04539 --- /dev/null +++ b/man/ws_download.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ws_download.R +\name{ws_download} +\alias{ws_download} +\title{Download HWSD v2.0 data} +\usage{ +ws_download(ws_path = file.path(tempdir(), "ws_db"), new_path = FALSE) +} +\arguments{ +\item{ws_path}{the path / directory where to store the HWSD v2.0 database} + +\item{new_path}{update the path, i.e. dowload data to a new local +location (logical, default FALSE)} +} +\value{ +current data path +} +\description{ +Downloads both the database and gridded HWSD v2.0 data products +to a desired output path for subsetting. +} +\details{ +When an existing path is used which is not the temporary directory +an environmental variable WS_PATH will be set. This variable will +override the default temporary directory if it exists. This allows +the gridded data to be stored elsewhere and be forgotten (while using the +{hwsdr} package for HWSD v2.0). + +Should you delete the gridded file, than it can be downloaded again but +the environmental variable should be set again using the new_path = TRUE +flag. +} +\examples{ + +\dontrun{ + + # Download the gridded soil map of + # HWSD v2.0 to the temporary directory + ws_download() + + # download the same data to a specific + # directory (which should exist) + ws_download( + ws_path = "~/my_path" + ) + + # download the same data to a specific + # directory (which should exist) and + # update the environmental variable + ws_download( + ws_path = "~/my_path", + new_path = TRUE + ) +} +} diff --git a/man/ws_subset.Rd b/man/ws_subset.Rd index 084df61..142fc6e 100644 --- a/man/ws_subset.Rd +++ b/man/ws_subset.Rd @@ -8,15 +8,17 @@ ws_subset( location = c(32, -81, 34, -80), site = "HWSD", param = "ALL", + layer = "D1", path = tempdir(), + ws_path = file.path(tempdir(), "ws_db"), internal = TRUE, - rate = 0.1 + rate = 0.1, + version = 1.2 ) } \arguments{ -\item{location}{location of a bounding box c(lat, lon, lat, lon) defined -by a bottom-left and top-right coordinates, a single location (lat, lon) -or a data frame with various locations listed (site, lat, lon)} +\item{location}{location of a bounding box c(lon, lat, lon, lat) defined +by a bottom-left and top-right coordinates, a single location (lon, lat)} \item{site}{sitename for the extracted location} @@ -24,13 +26,24 @@ or a data frame with various locations listed (site, lat, lon)} will download all available soil parameters.Check https://daac.ornl.gov/SOILS/guides/HWSD.html for parameter descriptions.} +\item{layer}{which soil depth layer of HWSD v2.0 to consider, layers are +named D1 to D7 from top to bottom} + \item{path}{path where to download the data to (only applicable to spatial data)} +\item{ws_path}{path to the gridded HWSD v2.0 data, only required/used if +querying v2.0 data} + \item{internal}{do not store the data on disk} \item{rate}{request rate in seconds, determines how long to wait between queries to avoid bouncing because of rate limitations} + +\item{version}{version of HWSD to query (numeric value). By default the +package will query the ORNL DAAC v1.2 via their API. If specifying the +later version (2.0) it will download or require the gridded spatial data +in addition to the included HWSD v2.0 database with soil parameters.} } \value{ Local geotiff data, or a data frame with HWSD soil information @@ -64,6 +77,6 @@ disk. internal = TRUE ) - raster::plot(t_sand) + terra::plot(t_sand) } } diff --git a/tests/testthat/test_hwsd2_downloads.r b/tests/testthat/test_hwsd2_downloads.r new file mode 100644 index 0000000..5b8a533 --- /dev/null +++ b/tests/testthat/test_hwsd2_downloads.r @@ -0,0 +1,33 @@ +context("test hwsd v2 routines") + +test_that("check download to disk.",{ + skip_on_cran() + data <- ws_subset( + site = "HWSD", + location = c(-81, 34), + param = "SAND", + layer = "D1", + version = "2.0" + ) + + expect_type(data, "list") +}) + +test_that("test sf bbox method",{ + skip_on_cran() + a <- sf::st_sf(a = 1:2, + geom = sf::st_sfc( + sf::st_point(c(34, -81)), + sf::st_point(c(32, -80))), + crs = 4326) + + data <- a |> + sf::st_bbox() |> + ws_subset( + param = "SAND", + layer = "D1", + version = "2.0" + ) + + expect_s4_class(data, "SpatRaster") +}) diff --git a/tests/testthat/test_hwsd_downloads.r b/tests/testthat/test_hwsd_downloads.r index eedb3aa..64ff2d3 100644 --- a/tests/testthat/test_hwsd_downloads.r +++ b/tests/testthat/test_hwsd_downloads.r @@ -27,10 +27,8 @@ test_that("check download to disk.",{ expect_true(file.exists(file.path(tempdir(), "HWSD.tif"))) }) - test_that("check point download",{ skip_on_cran() - data <- ws_subset( site = "HWSD", location = c(34, -81), @@ -51,7 +49,6 @@ test_that("check coordinate length",{ internal = TRUE ) ) - }) test_that("faulty param",{ @@ -69,15 +66,14 @@ test_that("faulty param",{ test_that("test sf bbox method",{ skip_on_cran() - library(magrittr) a <- sf::st_sf(a = 1:2, geom = sf::st_sfc( sf::st_point(c(34, -81)), sf::st_point(c(32, -80))), crs = 4326) - data <- a %>% - sf::st_bbox() %>% + data <- a |> + sf::st_bbox() |> ws_subset(param = "T_SAND") expect_s4_class(data, "SpatRaster")