Nothing
#' Data source is USDA-NRCS Soil Data Access. See package soilDB for more details
#'
#' @title Retrieve soil profile data and convert it to an object of class \sQuote{soil_profile}
#' @description Generate a synthetic soil profile based on the information in SSURGO database
#' @name get_ssurgo_soil_profile
#' @param lonlat Longitude and latitude vector (e.g. c(-93, 42))
#' @param shift simple mechanism for creating an area of interest by displacing the point indicated in
#' lonlat by some amount of distance (e.g. 300 - in meters)
#' @param nmapunit number of mapunits to select (see \code{\link{ssurgo2sp}})
#' @param nsoil number of soils to select (see \code{\link{ssurgo2sp}}). If the
#' number of soils is negative or NA it will fetch all the soils in the mapunit
#' @param xout see \code{\link{ssurgo2sp}}
#' @param soil.bottom see \code{\link{ssurgo2sp}}
#' @param method interpolation method see \code{\link{ssurgo2sp}}
#' @param nlayers number for layer for the new soil profile
#' @param check whether to check for reasonable values using \code{\link{check_apsimx_soil_profile}}.
#' TRUE by default. If \sQuote{fix} is TRUE, it will be applied only after the fix attempt.
#' @param fix whether to fix compatibility between saturation and bulk density (default is FALSE).
#' @param verbose default FALSE. Whether to print messages.
#' @param xargs additional arguments passed to \code{\link{apsimx_soil_profile}} function.
#' @return this function will always return a list. Each element of the list will
#' be an object of class \sQuote{soil_profile}
#' @export
#' @examples
#' \dontrun{
#' require(soilDB)
#' require(sp)
#' require(sf)
#' require(spData)
#' require(ggplot2)
#' ## Soil inforation for a single point
#' sp <- get_ssurgo_soil_profile(lonlat = c(-93, 42))
#' ## The initial attempt throws warnings, so better to use 'fix'
#' sp <- get_ssurgo_soil_profile(lonlat = c(-93, 42), fix = TRUE)
#' plot(sp[[1]])
#' plot(sp[[1]], property = "water")
#' ## Add initial water
#' iwat <- initialwater_parms(Thickness = sp[[1]]$soil$Thickness,
#' InitialValues = sp[[1]]$soil$DUL * 0.8)
#' sp[[1]]$initialwater <- iwat
#' plot(sp[[1]], property = "initialwater")
#' }
#'
#'
get_ssurgo_soil_profile <- function(lonlat, shift = -1,
nmapunit = 1, nsoil = 1,
xout = NULL, soil.bottom = 200,
method = c("constant", "linear"),
nlayers = 10,
check = TRUE,
fix = FALSE,
verbose = FALSE,
xargs = NULL){
if(!requireNamespace("soilDB", quietly = TRUE)){
stop("The soilDB package is required for this function")
return(NULL)
}
if(!requireNamespace("sp", quietly = TRUE)){
stop("The sp package is required for this function")
return(NULL)
}
if(!requireNamespace("sf", quietly = TRUE)){
stop("The sf package is required for this function")
return(NULL)
}
if(!requireNamespace("spData", quietly = TRUE)){
stop("The spData package is required for this function")
return(NULL)
}
if(length(lonlat) != 2 || !is.numeric(lonlat))
stop("lonlat should be a vector with length equal to 2")
lon <- lonlat[1]
lat <- lonlat[2]
## Determine if the location is in the US
if(requireNamespace("maps", quietly = TRUE)){
country <- maps::map.where(x = lon, y = lat)
if(country != "USA" || is.na(country))
stop("These coordinates do not correspond to a location in the USA. \n Did you specify the coordinates correctly?")
}
if(shift <= 0){
spg <- sp::SpatialPoints(cbind(x = lon, y = lat),
proj4string = sp::CRS('+proj=longlat +datum=WGS84'))
}else{
shift <- (shift / 111) * 0.001 ## This is now in degrees
lonlat.mat <- rbind(lonlat, ##root
lonlat + c(shift * 0.75, 0), ## x = 1, y = 0
lonlat + c(shift * 0.75, shift), ## x = 1, y = 1
lonlat + c(0, shift), ## x = 0, y = 1
lonlat) ## back to root
rownames(lonlat.mat) <- NULL
## the previous matrix is a rectangle
pg <- sp::Polygon(lonlat.mat)
spg <- sp::SpatialPolygons(list(sp::Polygons(list(pg), "s1")),
proj4string = sp::CRS("+proj=longlat +datum=WGS84"))
}
if(verbose == FALSE){
res <- suppressWarnings(soilDB::SDA_spatialQuery(spg, what = 'mupolygon', geomIntersection = TRUE))
}else{
res <- soilDB::SDA_spatialQuery(spg, what = 'mupolygon', geomIntersection = TRUE)
}
mu.is <- soilDB::format_SQL_in_statement(res$mukey)
sql <- sprintf("mukey IN %s", mu.is)
if(verbose == FALSE){
fSDA <- suppressWarnings(suppressMessages(soilDB::fetchSDA(sql, duplicates = TRUE)))
}else{
fSDA <- soilDB::fetchSDA(sql, duplicates = TRUE)
}
### Mapunit ### -- this might contain the iacornsr
if(verbose == FALSE){
mapunit <- suppressWarnings(suppressMessages(soilDB::get_mapunit_from_SDA(sql)))
}else{
mapunit <- soilDB::get_mapunit_from_SDA(sql)
}
### Component ###
cmpnt <- fSDA@site
names(cmpnt) <- gsub("_", ".", names(cmpnt), fixed = TRUE)
cmpnt$geomdesc <- cmpnt$geompos
## Retrieve the state from the areasymbol
if(shift <= 0 || length(unique(mapunit$areasymbol)) == 1){
cmpnt$state <- unique(strtrim(mapunit$areasymbol, 2))
}else{
cmpnt$state <- NA
warning("This area includes more than one state.
I have not though about how to get the state in this case. Please submit an issue
with a reproducible example to https://github.com/femiguez/apsimx/issues")
}
### Chorizon ###
chrzns <- fSDA@horizons
names(chrzns) <- gsub("_", ".", names(chrzns), fixed = TRUE)
### Things missing from horizons: hzthk.r, partdensity, wsatiated.r, wfifteenbar.r, wtenthbar.r, wthirdbar.r,
if(sum(grepl("partdensity", names(chrzns))) == 0) chrzns$partdensity <- NA
if(sum(grepl("hzthk", names(chrzns))) == 0) chrzns$hzthk.r <- NA
if(sum(grepl("wsatiated", names(chrzns))) == 0) chrzns$wsatiated.r <- NA
if(sum(grepl("wfifteenbar", names(chrzns))) == 0) chrzns$wfifteenbar.r <- NA
if(sum(grepl("wthirdbar", names(chrzns))) == 0) chrzns$wthirdbar.r <- NA
if(shift <= 0){
spg.sf <- sf::st_as_sf(spg)
spg.sf[["MUKEY"]] <- res$mukey
spg.sf[["AREASYMBOL"]] <- mapunit$areasymbol
mapunit.shp <- spg.sf
}else{
mapunit.shp <- sf::st_as_sf(res)
}
sp0 <- ssurgo2sp(mapunit = mapunit, component = cmpnt,
chorizon = chrzns, mapunit.shp = mapunit.shp,
nmapunit = nmapunit, nsoil = nsoil, xout = xout,
soil.bottom = soil.bottom, method = method, nlayers = nlayers,
verbose = verbose)
ans <- vector("list", length(sp0))
for(i in seq_along(sp0)){
metadata <- attributes(sp0[[i]])
metadata$DataSource <- paste("SSURGO (https://sdmdataaccess.nrcs.usda.gov/) through R package soilDB, R package apsimx function ssurgo2sp. Timestamp",Sys.time())
metadata$names <- NULL; metadata$class <- NULL; metadata$row.names <- NULL;
if(fix){
icheck <- check
check <- FALSE
}
if(!is.null(xargs)){
if(!is.null(xargs$crops)){
crops <- xargs$crops
}
}else{
crops <- c("Maize", "Soybean", "Wheat")
}
asp <- apsimx_soil_profile(nlayers = nlayers,
Thickness = sp0[[i]]$Thickness * 10,
BD = sp0[[i]]$BD,
AirDry = sp0[[i]]$AirDry,
LL15 = sp0[[i]]$LL15,
DUL = sp0[[i]]$DUL,
SAT = sp0[[i]]$SAT,
KS = sp0[[i]]$KS,
Carbon = sp0[[i]]$Carbon,
crop.LL = sp0[[i]]$LL15,
ParticleSizeClay = sp0[[i]]$ParticleSizeClay,
ParticleSizeSilt = sp0[[i]]$ParticleSizeSilt,
ParticleSizeSand = sp0[[i]]$ParticleSizeSand,
soil.bottom = soil.bottom,
metadata = metadata,
check = check,
crops = crops)
if(fix){
asp <- fix_apsimx_soil_profile(asp, verbose = verbose)
if(icheck)
check_apsimx_soil_profile(asp)
}
ans[[i]] <- asp
}
return(ans)
}
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.