Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b933e4b
chore: update .gitignore
brownag Sep 27, 2025
4f1b2e5
fix: tempfiles in `wbt_source()` should be relative to tempdir not wo…
brownag Oct 10, 2025
28724e2
version bump
brownag Oct 10, 2025
9f576b0
Update NEWS.md
brownag Oct 10, 2025
53f9df0
Update inst/CITATION
brownag Oct 10, 2025
8a85456
fix: `wbt_source()` pass `tmpdir` for `dsn` construction
brownag Oct 10, 2025
f481a1c
fix: `wbt_source()` handle terra::sources output
brownag Oct 10, 2025
0304890
fix: `wbt_source()` handle terra::sources output (2)
brownag Oct 10, 2025
95f8af5
spellcheck
brownag Oct 10, 2025
26be95a
fix: handling of various object input types
brownag Oct 10, 2025
0c71c8b
for code review
brownag Oct 10, 2025
1561b08
wbt_source: be explicit about use of first source
brownag Oct 10, 2025
940288f
fix: wbt_source: raster source with user-specified `dsn` or `layer`
brownag Oct 11, 2025
11b27a0
fix: wbt_source: verbosity of multiple source files message
brownag Oct 11, 2025
a5ac102
feat: add STATSGO2 shapefile dataset for DEM.tif extent and `sample_s…
brownag Oct 11, 2025
1786c8a
test: wbt_source: basic behaviors for vector and raster data sources
brownag Oct 11, 2025
c51bf21
fix: wbt_source: writing to shapefile or geotiff when data source typ…
brownag Oct 11, 2025
f33368b
fix: wbt_source: nzchar source
brownag Oct 11, 2025
9f810c0
fix: wbt_source: quiet namespace check
brownag Oct 11, 2025
cd54dbb
test: wbt_source: regex extension pattern
brownag Oct 11, 2025
4471edb
test: wbt_source: raster in memory and spatvectorproxy
brownag Oct 11, 2025
939f9bf
test: wbt_source: use gpkg as alternative non-wbt data source type
brownag Oct 11, 2025
8f57a75
test: wbt_source: sources with multiple layers
brownag Oct 11, 2025
aea2d75
call.=F
brownag Oct 11, 2025
14dfd99
fix: wbt_source: no need to specify `layer` for output `dsn`
brownag Oct 11, 2025
e90968b
test: wbt_source: suppress upstream warnings
brownag Oct 11, 2025
629da64
test: wbt_source: use in memory spatraster
brownag Oct 11, 2025
7578cca
fix: wbt_source: short circuit for common single-layer geotiff case
brownag Oct 11, 2025
58365d9
Update NEWS.md
brownag Oct 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ whiteboxR.Rproj
*.shx
*.prj
*.dbf
*.cpg
*.tif
settings.json
__MACOSX
Expand Down
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
Package: whitebox
Type: Package
Title: 'WhiteboxTools' R Frontend
Version: 2.4.1
Version: 2.4.2
Description: An R frontend for the 'WhiteboxTools' library, which is an advanced geospatial data analysis platform developed by Prof. John Lindsay at the University of Guelph's Geomorphometry and Hydrogeomatics Research Group. 'WhiteboxTools' can be used to perform common geographical information systems (GIS) analysis operations, such as cost-distance analysis, distance buffering, and raster reclassification. Remote sensing and image processing tasks include image enhancement (e.g. panchromatic sharpening, contrast adjustments), image mosaicing, numerous filtering operations, simple classification (k-means), and common image transformations. 'WhiteboxTools' also contains advanced tooling for spatial hydrological analysis (e.g. flow-accumulation, watershed delineation, stream network analysis, sink removal), terrain analysis (e.g. common terrain indices such as slope, curvatures, wetness index, hillshading; hypsometric analysis; multi-scale topographic position analysis), and LiDAR data processing. Suggested citation: Lindsay (2016) <doi:10.1016/j.cageo.2016.07.003>.
Authors@R: c(person("Qiusheng", "Wu", email = "giswqs@gmail.com", role = c("aut")),
person("Andrew", "Brown", email = "brown.andrewg@gmail.com", role = c("ctb", "cre")))
person("Andrew", "Brown", email = "brown.andrewg@gmail.com", role = c("aut", "cre"), comment=c(ORCID="0000-0002-4565-533X")))
Maintainer: Andrew Brown <brown.andrewg@gmail.com>
License: MIT + file LICENSE
SystemRequirements: WhiteboxTools (https://github.com/jblindsay/whitebox-tools/releases/latest)
Encoding: UTF-8
Language: en-US
RoxygenNote: 7.3.2
RoxygenNote: 7.3.3
Roxygen: list(markdown = TRUE)
URL: https://whiteboxr.gishub.org/, https://github.com/opengeos/whiteboxR
BugReports: https://github.com/opengeos/whiteboxR/issues
Expand Down
14 changes: 14 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# whitebox 2.4.2

* `wbt_source()`: now accepts `tmpdir` argument which defaults to `tempdir()` (not `getwd()` or `wbt_wd()`) that is used for storing the intermediate shapefiles needed for WhiteboxTools

* Also, the pattern for temporary file names is now customizable via `pattern` argument

* Bug fixes for `wbt_source()`:

* No longer writes temporary intermediate shapefiles to the working directory when passed a non-shapefile vector data source.

* The temporary directory is used by default, unless new `tmpdir` argument is specified. This could be a breaking change if you were relying on the temporary files to be present in the WhiteboxTools working directory. Specify `tmpdir` in call to `wbt_source()` to make old behavior explicit.

* Properly uses `layer` argument for data sources (e.g. GPKG) that may contain multiple vector layers of interest (thanks to @mps9506 for reporting; #132)

# whitebox 2.4.1

* Rebuilt `wbttools` and `wbttoolparameters` with WhiteboxTools v2.4.0
Expand Down
160 changes: 119 additions & 41 deletions R/wbt_source.R
Original file line number Diff line number Diff line change
@@ -1,52 +1,116 @@
#' Initialize an R object containing spatial data for use by WhiteboxTools
#'
#' @param x A terra SpatVector or sf object, or a path to a file that can be read as a SpatVectorProxy
#' @param x A terra SpatVector or sf object (in memory) or a path to a file that
#' can be read as a SpatVectorProxy. Or a memory or file-based SpatRaster.
#' SpatRaster object. When `x` has multiple layers/bands, the first layer is
#' used by default; use the \code{layer} argument to select a specific
#' layer/band.
Comment thread
brownag marked this conversation as resolved.
Outdated
#' @param dsn Data source path / file name
#' @param layer Data layer
#' @param force Force write of vector data to file? Default: FALSE (only write if file does not exist)
#' @param ... Additional arguments passed to `terra::writeVector()` or `sf::st_write()`
#' @param layer Data layer. For vectors, `layer` is interpreted as a layer
#' name (character); for rasters, `layer` is interpreted as a band index or
#' name (integer OR character)
#' @param tmpdir Directory to write temporary ESRI Shapefiles for vector input
#' in memory or otherwise not already in shapefile. Default: `tempdir()`
#' @param pattern Character vector giving the initial part of the temporary file
#' name
#' @param force Force write of vector data to file? Default: FALSE (only write
#' if file does not exist and new file is needed)
#' @param verbose Print information about data source and contents?
#' @return An R object with attributes `wbt_dsn` and `wbt_layer` set as needed to support reading and writing R objects from file by WhiteboxTools.
#' @param ... Additional arguments passed to `terra::writeVector()` or
#' `sf::st_write()`, or `terra::writeRaster` (for rasters).
#' @return An R object (SpatRaster, SpatVector, SpatVectorProxy, sf) with
#' attributes `wbt_dsn` and `wbt_layer` set as needed to support reading and
#' writing R objects from file by WhiteboxTools.
#' @keywords General
#' @export
wbt_source <- function(x,
dsn = NULL,
layer = NULL,
force = FALSE,
tmpdir = tempdir(),
pattern = "wbt",
verbose = wbt_verbose(),
...) {
Comment thread
brownag marked this conversation as resolved.

if (!requireNamespace("terra")) {
stop("package `terra` is required to convert vector sources to `wbt()`-compatible SpatVectorProxy", call. = FALSE)
if (length(layer) > 1) {
stop("argument `layer` must have length 1 or 0 (NULL)", call. = FALSE)
}

.check_pkg_ns <- function(pkg) {
if (!requireNamespace(pkg)) {
Comment thread
brownag marked this conversation as resolved.
Outdated
stop("package `", pkg, "` is required to convert to `wbt()`-compatible data sources", call. = FALSE)
}
}

if (is.character(x)) {
if (file.exists(x)) {
# convert to shapefile if needed
if (!grepl("\\.shp$", x)) {
xp <- paste0(basename(x), "_", basename(tempfile()), ".shp")
fp <- file.path(tempdir(), xp)
.check_pkg_ns("terra")

if (!requireNamespace("terra")) {
stop("package `terra` is required to convert non-Shapefile vector sources to Shapefile")
}
# convert to shapefile if needed
x2 <- try(terra::vect(x, layer = ifelse(is.null(layer), "", layer), proxy = TRUE), silent = TRUE)
fp <- file.path(tmpdir, paste0(basename(x), "_", basename(tempfile(pattern = pattern))))
if (!inherits(x2, 'try-error') && !grepl("\\.shp$", x, ignore.case = TRUE)) {
fp <- paste0(fp, ".shp")

x2 <- terra::vect(x, layer = ifelse(is.null(layer), "", layer))
if (terra::writeVector(x2, fp)) {
if (terra::writeVector(terra::query(x2), fp)) {
x <- fp
} else {
stop("Failed to convert `x` (", x, ") to Shapefile.")
}
Comment thread
brownag marked this conversation as resolved.
Outdated
} else if (inherits(x2, 'try-error')) {
if (!grepl("\\.tiff?$", x, ignore.case = TRUE) || length(layer) > 0) {
# try reading a raster file and writing to geotiff
fp <- paste0(fp, ".tif")
if (length(layer) > 0) {
x2 <- terra::rast(x, lyrs = layer[1])
Comment thread
brownag marked this conversation as resolved.
} else {
x2 <- terra::rast(x)
}
if (terra::writeRaster(x2, fp)) {
x <- fp
} else {
stop("Failed to convert `x` (", x, ") to GeoTIFF")
}
Comment thread
brownag marked this conversation as resolved.
Outdated
}
x <- terra::rast(x)
Comment thread
brownag marked this conversation as resolved.
}

if (!inherits(x, 'SpatRaster')) {
# a SpatVectorProxy allows us to get some basic info without loading the whole file
x <- terra::vect(x, proxy = TRUE)
}

if (is.character(x) && !file.exists(x)) {
stop("File (", x, ") does not exist")
Comment thread
brownag marked this conversation as resolved.
Outdated
}

if (!inherits(x, c("SpatRaster", "SpatVectorProxy"))) {
stop("Unhandled input object type")
Comment thread
brownag marked this conversation as resolved.
Outdated
}

# a SpatVectorProxy allows us to get some basic info without loading the whole file
x <- terra::vect(x, proxy = TRUE)
attr(x, 'wbt_dsn') <- terra::sources(x)
Comment thread
brownag marked this conversation as resolved.
Outdated
attr(x, 'wbt_layer') <- layer
return(x)
}
}
Comment thread
brownag marked this conversation as resolved.

ext <- ".shp"
if (inherits(x, c('SpatRaster', 'RasterLayer',
'RasterStack', 'RasterBrick'))) {
.check_pkg_ns("terra")
if (!inherits(x, 'SpatRaster')) {
x <- terra::rast(x)
}
ext <- ".tif"
src <- terra::sources(x)
if (length(src) > 0 && any(nzchar(src))) {
if (length(src) > 1) {
message("Object 'x' has multiple source files; using first non-empty source path")
}
dsn <- src[which(nzchar(src))[1]]
}
}

# NULL dsn (TODO: GDAL-supported dsn not supported by WBT)
if (is.null(dsn)) {
# if (gpkg) {
Expand All @@ -57,35 +121,49 @@ wbt_source <- function(x,
# only supported vector format is the ESRI Shapefile.
# TODO: dbf limitations? use alternate wbt/gdal common format?
if (!is.null(layer)) {
bn <- layer
} else bn <- "file"
wd <- wbt_wd()
if (wd == "")
wd <- getwd()
ext <- ".shp"
if (inherits(x, 'SpatRaster') ||
inherits(x, 'RasterLayer') ||
inherits(x, 'RasterStack') ||
inherits(x, 'RasterBrick')) {
ext <- ".tif"
bn <- paste0(pattern, "_", layer)
Comment thread
brownag marked this conversation as resolved.
} else {
bn <- pattern
}
dsn <- tempfile(pattern = bn, tmpdir = wd, fileext = ext)
dsn <- tempfile(pattern = bn, tmpdir = tmpdir, fileext = ext)
# }
}

if (!file.exists(dsn) || force) {
# convert less common types to core types
if (inherits(x, 'sfc') || inherits(x, 'Spatial')) {
x <- sf::st_as_sf(x)
}

# write to file/db
if (inherits(x, 'SpatVector')) {
terra::writeVector(x, filename = dsn, layer = layer, ...)
} else if (inherits(x, 'sf')) {
sf::st_write(x, dsn = dsn, layer = layer, quiet = !verbose, ...)
} else if (inherits(x, 'SpatRaster')) {
terra::writeRaster(x, filename = dsn)
# write to file/db
if (inherits(x, c('SpatVector', 'SpatVectorProxy', 'SpatRaster'))) {
.check_pkg_ns("terra")
if (inherits(x, 'SpatVectorProxy')) {
x <- terra::query(x)
}
if (inherits(x, 'SpatVector')) {
terra::writeVector(x,
filename = dsn,
layer = layer,
overwrite = force,
...)
} else if (inherits(x, 'SpatRaster')) {
Comment thread
brownag marked this conversation as resolved.
terra::writeRaster(x, filename = dsn, overwrite = force, ...)
}
} else {
.check_pkg_ns("sf")

# convert less common types to core types
if (inherits(x, 'sfc') || inherits(x, 'Spatial')) {
x <- sf::st_as_sf(x)
}

if (inherits(x, 'sf')) {
sf::st_write(
x,
dsn = dsn,
layer = layer,
quiet = !verbose,
delete_dsn = force,
Comment thread
brownag marked this conversation as resolved.
...
)
Comment thread
brownag marked this conversation as resolved.
}
}
}
Comment thread
brownag marked this conversation as resolved.

Expand Down
6 changes: 3 additions & 3 deletions inst/CITATION
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ bibentry(
bibtype = "Manual",
title = "'whitebox': 'WhiteboxTools' R Frontend",
author = "Qiusheng Wu, Andrew Brown",
note = "R package version 2.2.0",
note = "R package version 2.4.2",
url = "https://CRAN.R-project.org/package=whitebox",
year = "2022",
textVersion = "Wu, Q., Brown, A. (2022). whitebox: 'WhiteboxTools' R Frontend. R package version 2.2.0. <https://CRAN.R-project.org/package=whitebox>"
year = "2025",
textVersion = "Wu, Q., Brown, A. (2025). whitebox: 'WhiteboxTools' R Frontend. R package version 2.4.2. <https://CRAN.R-project.org/package=whitebox>"
)

bibentry(
Expand Down
16 changes: 2 additions & 14 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ BACKTRACE
BreachDepressions
Breakline
CMD
CRS
CamelCase
Ceil
Centre
Centroid
Christoph
ClassificationError
Colour
Expand Down Expand Up @@ -52,6 +50,7 @@ François
Frontend
GAT
GDAL
GPKG
GeoKey
GeoPackage
GeoTIFF
Expand All @@ -77,7 +76,6 @@ InPlaceAdd
InPlaceSubtract
InverseMultiQuadric
Isobasins
JSON
JandR
Jens
Jenson
Expand Down Expand Up @@ -108,6 +106,7 @@ NDI
NoData
Northness
Num
ORCID
OSAVI
OptionList
POLYLINE
Expand Down Expand Up @@ -136,7 +135,6 @@ Rasterizes
Reclass
Reinitializes
RemoveSpurs
Rescale
Rgb
Robinne
Rosenfeld
Expand Down Expand Up @@ -206,7 +204,6 @@ cageo
centerlines
centred
centres
centroid
cls
codecov
colour
Expand All @@ -219,7 +216,6 @@ darboux
decorrelation
depressionless
dev
differencing
dinf
directionality
doi
Expand Down Expand Up @@ -282,7 +278,6 @@ lengthed
lidar
liu
lq
macOS
magrittr
medoid
meso
Expand All @@ -303,12 +298,10 @@ neighbouring
neighbours
nn
nodata
normals
num
nw
olympic
parallelepiped
parallelize
parsable
pearson
planchon
Expand All @@ -318,21 +311,17 @@ pre
pts
quant
quartic
quartile
ransac
raster's
rasters
rbf
reclass
repo
rgb
rgdal
sca
scattergram
se
shapetype
sibson
sigmoid
sigmoidal
silverman
sinh
Expand All @@ -358,7 +347,6 @@ vals
viewshed
viewsheds
viridi
viridis
wang
watershedding
wb
Expand Down
Loading
Loading