Skip to content

Commit

Permalink
Merge pull request #21 from njtierney/filetype_terra_vect
Browse files Browse the repository at this point in the history
Add filetype argument to `tar_terra_vect()`
  • Loading branch information
Aariq authored Mar 15, 2024
2 parents b16bea4 + 1b902e1 commit f24dd74
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 84 deletions.
10 changes: 6 additions & 4 deletions R/tar-terra-rast.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#' Create a terra _SpatRaster_ Target
#' Create a terra _SpatRaster_ target
#'
#' Creates a target for a terra _SpatRaster_ object.
#' Provides a target format for [terra::SpatRaster-class] objects.
#'
#' @param filetype character. File format expressed as GDAL driver names passed to `terra::writeRaster()`
#' @param gdal character. GDAL driver specific datasource creation options passed to `terra::writeRaster()`
#' @param filetype character. File format expressed as GDAL driver names passed
#' to [terra::writeRaster()]
#' @param gdal character. GDAL driver specific datasource creation options
#' passed to [terra::writeRaster()]
#' @param ... Additional arguments not yet used
#'
#' @inheritParams targets::tar_target
Expand Down
215 changes: 149 additions & 66 deletions R/tar-terra-vect.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
#' Targets format for terra vectors
#' Create a terra _SpatVector_ target
#'
#' Provides targets format for `terra::vect` objects
#' Provides a target format for [terra::SpatVector-class] objects.
#'
#' @param filetype character. File format expressed as GDAL driver names passed
#' to [terra::writeVector()]. See 'Note' for more details
#' @param gdal character. GDAL driver specific datasource creation options
#' passed to [terra::writeVector()].
#' @param ... Additional arguments not yet used
#' @inheritParams targets::tar_target
#'
#' @note Although you may pass any supported GDAL vector driver to the
#' `filetype` argument, not all formats are guaranteed to work with
#' `geotargets`. At the moment, we have tested `GeoJSON` and `ESRI Shapefile`
#' which both appear to work generally.
#' @export
#' @examples
#' if (Sys.getenv("TAR_LONG_EXAMPLES") == "true") {
Expand All @@ -29,68 +38,142 @@
#' })
#' }
tar_terra_vect <- function(name,
command,
pattern = NULL,
packages = targets::tar_option_get("packages"),
tidy_eval = targets::tar_option_get("tidy_eval"),
library = targets::tar_option_get("library"),
repository = targets::tar_option_get("repository"),
iteration = targets::tar_option_get("iteration"),
error = targets::tar_option_get("error"),
memory = targets::tar_option_get("memory"),
garbage_collection = targets::tar_option_get("garbage_collection"),
deployment = targets::tar_option_get("deployment"),
priority = targets::tar_option_get("priority"),
resources = targets::tar_option_get("resources"),
storage = targets::tar_option_get("storage"),
retrieval = targets::tar_option_get("retrieval"),
cue = targets::tar_option_get("cue")) {
name <- targets::tar_deparse_language(substitute(name))

envir <- targets::tar_option_get("envir")

command <- targets::tar_tidy_eval(
expr = as.expression(substitute(command)),
envir = envir,
tidy_eval = tidy_eval
)
pattern <- targets::tar_tidy_eval(
expr = as.expression(substitute(pattern)),
envir = envir,
tidy_eval = tidy_eval
)

format_terra_shapefile_zip <- targets::tar_format(
read = function(path) terra::vect(paste0("/vsizip/{", path, "}")),
write = function(object, path) {
terra::writeVector(
x = object,
filename = paste0(path, ".shz"),
filetype = "ESRI Shapefile"
)
file.rename(paste0(path, ".shz"), path)
},
marshal = function(object) terra::wrap(object),
unmarshal = function(object) terra::unwrap(object)
)

targets::tar_target_raw(
name = name,
command = command,
pattern = pattern,
packages = packages,
library = library,
format = format_terra_shapefile_zip,
repository = repository,
iteration = iteration,
error = error,
memory = memory,
garbage_collection = garbage_collection,
deployment = deployment,
priority = priority,
resources = resources,
storage = storage,
retrieval = retrieval,
cue = cue
)
command,
pattern = NULL,
filetype = NULL,
gdal = NULL,
...,
packages = targets::tar_option_get("packages"),
tidy_eval = targets::tar_option_get("tidy_eval"),
library = targets::tar_option_get("library"),
repository = targets::tar_option_get("repository"),
iteration = targets::tar_option_get("iteration"),
error = targets::tar_option_get("error"),
memory = targets::tar_option_get("memory"),
garbage_collection = targets::tar_option_get("garbage_collection"),
deployment = targets::tar_option_get("deployment"),
priority = targets::tar_option_get("priority"),
resources = targets::tar_option_get("resources"),
storage = targets::tar_option_get("storage"),
retrieval = targets::tar_option_get("retrieval"),
cue = targets::tar_option_get("cue")) {
name <- targets::tar_deparse_language(substitute(name))

envir <- targets::tar_option_get("envir")

command <- targets::tar_tidy_eval(
expr = as.expression(substitute(command)),
envir = envir,
tidy_eval = tidy_eval
)
pattern <- targets::tar_tidy_eval(
expr = as.expression(substitute(pattern)),
envir = envir,
tidy_eval = tidy_eval
)

# if not specified by user, pull the corresponding geotargets option
filetype <- filetype %||% geotargets_option_get("gdal.vector.driver")
gdal <- gdal %||% geotargets_option_get("gdal.vector.creation_options")

format <- ifelse(
test = filetype == "ESRI Shapefile",
#special handling of ESRI shapefiles because the output is a dir of multiple files.
yes = create_format_terra_vect_shz(options = gdal, ...),
no = create_format_terra_vect(filetype, options = gdal, ...)
)

targets::tar_target_raw(
name = name,
command = command,
pattern = pattern,
packages = packages,
library = library,
format = format,
repository = repository,
iteration = iteration,
error = error,
memory = memory,
garbage_collection = garbage_collection,
deployment = deployment,
priority = priority,
resources = resources,
storage = storage,
retrieval = retrieval,
cue = cue
)
}


#' @param filetype File format expressed as GDAL driver names passed to
#' `terra::writeVector()`
#' @param options GDAL driver specific datasource creation options passed to
#' `terra::writeVector()`
#' @param ... Additional arguments not yet used
#' @noRd
create_format_terra_vect <- function(filetype, options, ...) {

if (!requireNamespace("terra")) {
stop("package 'terra' is required", call. = FALSE)
}

# get list of drivers available for writing depending on what the user's GDAL supports
drv <- terra::gdal(drivers = TRUE)
drv <- drv[drv$type == "vector" & grepl("write", drv$can), ]

if (is.null(filetype)) {
filetype <- "GeoJSON"
}

filetype <- match.arg(filetype, drv$name)

.write_terra_vector <- function(object, path) {
terra::writeVector(
object,
path,
filetype = NULL,
overwrite = TRUE,
options = NULL
)
}
body(.write_terra_vector)[[2]][["filetype"]] <- filetype
body(.write_terra_vector)[[2]][["options"]] <- options

targets::tar_format(
read = function(path) terra::vect(path),
write = .write_terra_vector,
marshal = function(object) terra::wrap(object),
unmarshal = function(object) terra::unwrap(object)
)
}

#' Special handling for ESRI Shapefiles
#' @param options GDAL driver specific datasource creation options passed to
#' `terra::writeVector()`
#' @param ... Additional arguments not yet used
#' @noRd
create_format_terra_vect_shz <- function(options, ...) {

if (!requireNamespace("terra")) {
stop("package 'terra' is required", call. = FALSE)
}

.write_terra_vector <- function(object, path) {
terra::writeVector(
x = object,
filename = paste0(path, ".shz"),
filetype = "ESRI Shapefile",
overwrite = TRUE,
options = NULL
)
file.rename(paste0(path, ".shz"), path)
}
body(.write_terra_vector)[[2]][["options"]] <- options

targets::tar_format(
read = function(path) terra::vect(paste0("/vsizip/{", path, "}")),
write = .write_terra_vector,
marshal = function(object) terra::wrap(object),
unmarshal = function(object) terra::unwrap(object)
)
}
10 changes: 6 additions & 4 deletions man/tar_terra_rast.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 19 additions & 2 deletions man/tar_terra_vect.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion tests/testthat/_snaps/tar-terra.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,24 @@
geometry : polygons
dimensions : 12, 6 (geometries, attributes)
extent : 5.74414, 6.528252, 49.44781, 50.18162 (xmin, xmax, ymin, ymax)
source : test_terra_vect} (test_terra_vect)
source : test_terra_vect
coord. ref. : lon/lat WGS 84 (EPSG:4326)
names : ID_1 NAME_1 ID_2 NAME_2 AREA POP
type : <num> <chr> <num> <chr> <num> <int>
values : 1 Diekirch 1 Clervaux 312 18081
1 Diekirch 2 Diekirch 218 32543
1 Diekirch 3 Redange 259 18664

---

Code
y
Output
class : SpatVector
geometry : polygons
dimensions : 12, 6 (geometries, attributes)
extent : 5.74414, 6.528252, 49.44781, 50.18162 (xmin, xmax, ymin, ymax)
source : test_terra_vect_shz} (test_terra_vect_shz)
coord. ref. : lon/lat WGS 84 (EPSG:4326)
names : ID_1 NAME_1 ID_2 NAME_2 AREA POP
type : <num> <chr> <num> <chr> <num> <int>
Expand Down
3 changes: 0 additions & 3 deletions tests/testthat/test-tar-shapefile.R

This file was deleted.

15 changes: 11 additions & 4 deletions tests/testthat/test-tar-terra.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ targets::tar_test("tar_terra_rast() works", {
list(
geotargets::tar_terra_rast(
test_terra_rast,
system.file("ex/elev.tif", package = "terra") |> terra::rast()
terra::rast(system.file("ex/elev.tif", package = "terra"))
)
)
})
Expand All @@ -31,13 +31,20 @@ targets::tar_test("tar_terra_vect() works", {
geotargets::tar_terra_vect(
test_terra_vect,
lux_area()
),
geotargets::tar_terra_vect(
test_terra_vect_shz,
lux_area(),
filetype = "ESRI Shapefile"
)
)
})
targets::tar_make()
x <- targets::tar_read(test_terra_vect)
y <- targets::tar_read(test_terra_vect_shz)
expect_s4_class(x, "SpatVector")
expect_snapshot(
x
)
expect_s4_class(y, "SpatVector")
expect_snapshot(x)
expect_snapshot(y)
expect_equal(terra::values(x), terra::values(y))
})

0 comments on commit f24dd74

Please sign in to comment.