From 50ad08987c22c27ec045eb6c24c2f808a7edafae Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Thu, 14 Mar 2024 22:51:16 -0700 Subject: [PATCH 01/20] Add `tar_stars()` --- DESCRIPTION | 4 +- NAMESPACE | 2 + R/tar-stars.R | 136 ++++++++++++++++ man/tar_stars.Rd | 242 +++++++++++++++++++++++++++++ tests/testthat/_snaps/tar-stars.md | 14 ++ tests/testthat/test-tar-stars.R | 21 +++ 6 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 R/tar-stars.R create mode 100644 man/tar_stars.Rd create mode 100644 tests/testthat/_snaps/tar-stars.md create mode 100644 tests/testthat/test-tar-stars.R diff --git a/DESCRIPTION b/DESCRIPTION index 93fa945..ea712a6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,7 +36,9 @@ Imports: targets, terra Suggests: - testthat (>= 3.0.0) + sf, + stars, + testthat (>= 3.0.0), Depends: R (>= 4.1.0) Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index 4532f2e..6a40473 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,8 +2,10 @@ export(geotargets_option_get) export(geotargets_option_set) +export(tar_stars) export(tar_terra_rast) export(tar_terra_vect) importFrom(rlang,"%||%") importFrom(rlang,arg_match0) +importFrom(rlang,is_installed) importFrom(utils,globalVariables) diff --git a/R/tar-stars.R b/R/tar-stars.R new file mode 100644 index 0000000..e05df5c --- /dev/null +++ b/R/tar-stars.R @@ -0,0 +1,136 @@ +#' Create a stars _stars_ Target +#' +#' Provides a target format for stars objects. +#' +#' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. +#' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] +#' @param ... Additional arguments not yet used +#' +#' @inheritParams targets::tar_target +#' @importFrom rlang %||% arg_match0 is_installed +#' @seealso [targets::tar_target_raw()] +#' @export +#' @examplesIf rlang::is_installed("stars") +#' if (Sys.getenv("TAR_LONG_EXAMPLES") == "true") { +#' targets::tar_dir({ # tar_dir() runs code from a temporary directory. +#' library(geotargets) +#' targets::tar_script({ +#' list( +#' geotargets::tar_stars( +#' stars_example, +#' stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars")) +#' ) +#' ) +#' }) +#' targets::tar_make() +#' x <- targets::tar_read(stars_example) +#' }) +#'} +tar_stars <- function(name, + command, + pattern = NULL, + driver = NULL, + options = NULL, + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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 + driver <- driver %||% geotargets_option_get("gdal.raster.driver") + options <- options %||% geotargets_option_get("gdal.raster.creation_options") + + targets::tar_target_raw( + name = name, + command = command, + pattern = pattern, + packages = packages, + library = library, + format = create_format_stars(driver = driver, options = options, ...), + 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 driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. +#' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] +#' @param ... Additional arguments not yet used +#' @noRd +create_format_stars <- function(driver, options, ...) { + + if (!requireNamespace("sf")) { + stop("package 'sf' is required", call. = FALSE) + } + + if (!requireNamespace("stars")) { + stop("package 'stars' is required", call. = FALSE) + } + + # get list of drivers available for writing depending on what the user's GDAL supports + drv <- sf::st_drivers(what = "raster") + drv <- drv[drv$write, ] + + driver <- driver %||% geotargets_option_get("gdal.raster.driver") + driver <- rlang::arg_match0(driver, drv$name) + + options <- options %||% geotargets_option_get("gdal.raster.creation_options") + + # NOTE: Option getting functions are set in the .write_terra_raster function template + # to resolve issue with body<- not working in some evaluation contexts ({covr}). + # TODO: It should be fine to have driver and options as NULL + .write_stars <- function(object, path) { + stars::write_stars( + object, + path, + driver = geotargets::geotargets_option_get("gdal.raster.driver"), + overwrite = TRUE, + options = geotargets::geotargets_option_get("gdal.raster.creation_options") + ) + } + + body(.write_stars)[[2]][["driver"]] <- driver + body(.write_stars)[[2]][["options"]] <- options + + targets::tar_format( + read = function(path) stars::read_stars(path), + write = .write_stars, + marshal = function(object) object, # Not currently used + unmarshal = function(object) object + ) +} + diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd new file mode 100644 index 0000000..cb0362d --- /dev/null +++ b/man/tar_stars.Rd @@ -0,0 +1,242 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tar-stars.R +\name{tar_stars} +\alias{tar_stars} +\title{Create a stars \emph{stars} Target} +\usage{ +tar_stars( + name, + command, + pattern = NULL, + driver = NULL, + options = NULL, + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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") +) +} +\arguments{ +\item{name}{Symbol, name of the target. A target +name must be a valid name for a symbol in R, and it +must not start with a dot. Subsequent targets +can refer to this name symbolically to induce a dependency relationship: +e.g. \code{tar_target(downstream_target, f(upstream_target))} is a +target named \code{downstream_target} which depends on a target +\code{upstream_target} and a function \code{f()}. In addition, a target's +name determines its random number generator seed. In this way, +each target runs with a reproducible seed so someone else +running the same pipeline should get the same results, +and no two targets in the same pipeline share the same seed. +(Even dynamic branches have different names and thus different seeds.) +You can recover the seed of a completed target +with \code{tar_meta(your_target, seed)} and run \code{\link[targets:tar_seed_set]{tar_seed_set()}} +on the result to locally recreate the target's initial RNG state.} + +\item{command}{R code to run the target.} + +\item{pattern}{Language to define branching for a target. +For example, in a pipeline with numeric vector targets \code{x} and \code{y}, +\code{tar_target(z, x + y, pattern = map(x, y))} implicitly defines +branches of \code{z} that each compute \code{x[1] + y[1]}, \code{x[2] + y[2]}, +and so on. See the user manual for details.} + +\item{driver}{character. File format expressed as GDAL driver names passed to \code{\link[stars:write_stars]{stars::write_stars()}}. See \code{\link[sf:st_drivers]{sf::st_drivers()}}.} + +\item{options}{character. GDAL driver specific datasource creation options passed to \code{\link[stars:write_stars]{stars::write_stars()}}} + +\item{...}{Additional arguments not yet used} + +\item{tidy_eval}{Logical, whether to enable tidy evaluation +when interpreting \code{command} and \code{pattern}. If \code{TRUE}, you can use the +"bang-bang" operator \verb{!!} to programmatically insert +the values of global objects.} + +\item{packages}{Character vector of packages to load right before +the target runs or the output data is reloaded for +downstream targets. Use \code{tar_option_set()} to set packages +globally for all subsequent targets you define.} + +\item{library}{Character vector of library paths to try +when loading \code{packages}.} + +\item{repository}{Character of length 1, remote repository for target +storage. Choices: +\itemize{ +\item \code{"local"}: file system of the local machine. +\item \code{"aws"}: Amazon Web Services (AWS) S3 bucket. Can be configured +with a non-AWS S3 bucket using the \code{endpoint} argument of +\code{\link[targets:tar_resources_aws]{tar_resources_aws()}}, but versioning capabilities may be lost +in doing so. +See the cloud storage section of +\url{https://books.ropensci.org/targets/data.html} +for details for instructions. +\item \code{"gcp"}: Google Cloud Platform storage bucket. +See the cloud storage section of +\url{https://books.ropensci.org/targets/data.html} +for details for instructions. +} + +Note: if \code{repository} is not \code{"local"} and \code{format} is \code{"file"} +then the target should create a single output file. +That output file is uploaded to the cloud and tracked for changes +where it exists in the cloud. The local file is deleted after +the target runs.} + +\item{iteration}{Character of length 1, name of the iteration mode +of the target. Choices: +\itemize{ +\item \code{"vector"}: branching happens with \code{vctrs::vec_slice()} and +aggregation happens with \code{vctrs::vec_c()}. +\item \code{"list"}, branching happens with \verb{[[]]} and aggregation happens with +\code{list()}. +\item \code{"group"}: \code{dplyr::group_by()}-like functionality to branch over +subsets of a non-dynamic data frame. +For \code{iteration = "group"}, the target must not by dynamic +(the \code{pattern} argument of \code{\link[targets:tar_target]{tar_target()}} must be left \code{NULL}). +The target's return value must be a data +frame with a special \code{tar_group} column of consecutive integers +from 1 through the number of groups. Each integer designates a group, +and a branch is created for each collection of rows in a group. +See the \code{\link[targets:tar_group]{tar_group()}} function to see how you can +create the special \code{tar_group} column with \code{dplyr::group_by()}. +}} + +\item{error}{Character of length 1, what to do if the target +stops and throws an error. Options: +\itemize{ +\item \code{"stop"}: the whole pipeline stops and throws an error. +\item \code{"continue"}: the whole pipeline keeps going. +\item \code{"abridge"}: any currently running targets keep running, +but no new targets launch after that. +(Visit \url{https://books.ropensci.org/targets/debugging.html} +to learn how to debug targets using saved workspaces.) +\item \code{"null"}: The errored target continues and returns \code{NULL}. +The data hash is deliberately wrong so the target is not +up to date for the next run of the pipeline. +}} + +\item{memory}{Character of length 1, memory strategy. +If \code{"persistent"}, the target stays in memory +until the end of the pipeline (unless \code{storage} is \code{"worker"}, +in which case \code{targets} unloads the value from memory +right after storing it in order to avoid sending +copious data over a network). +If \code{"transient"}, the target gets unloaded +after every new target completes. +Either way, the target gets automatically loaded into memory +whenever another target needs the value. +For cloud-based dynamic files +(e.g. \code{format = "file"} with \code{repository = "aws"}), +this memory strategy applies to the +temporary local copy of the file: +\code{"persistent"} means it remains until the end of the pipeline +and is then deleted, +and \code{"transient"} means it gets deleted as soon as possible. +The former conserves bandwidth, +and the latter conserves local storage.} + +\item{garbage_collection}{Logical, whether to run \code{base::gc()} +just before the target runs.} + +\item{deployment}{Character of length 1. If \code{deployment} is +\code{"main"}, then the target will run on the central controlling R process. +Otherwise, if \code{deployment} is \code{"worker"} and you set up the pipeline +with distributed/parallel computing, then +the target runs on a parallel worker. For more on distributed/parallel +computing in \code{targets}, please visit +\url{https://books.ropensci.org/targets/crew.html}.} + +\item{priority}{Numeric of length 1 between 0 and 1. Controls which +targets get deployed first when multiple competing targets are ready +simultaneously. Targets with priorities closer to 1 get dispatched earlier +(and polled earlier in \code{\link[targets:tar_make_future]{tar_make_future()}}).} + +\item{resources}{Object returned by \code{tar_resources()} +with optional settings for high-performance computing +functionality, alternative data storage formats, +and other optional capabilities of \code{targets}. +See \code{tar_resources()} for details.} + +\item{storage}{Character of length 1, only relevant to +\code{\link[targets:tar_make_clustermq]{tar_make_clustermq()}} and \code{\link[targets:tar_make_future]{tar_make_future()}}. +Must be one of the following values: +\itemize{ +\item \code{"main"}: the target's return value is sent back to the +host machine and saved/uploaded locally. +\item \code{"worker"}: the worker saves/uploads the value. +\item \code{"none"}: almost never recommended. It is only for +niche situations, e.g. the data needs to be loaded +explicitly from another language. If you do use it, +then the return value of the target is totally ignored +when the target ends, but +each downstream target still attempts to load the data file +(except when \code{retrieval = "none"}). + +If you select \code{storage = "none"}, then +the return value of the target's command is ignored, +and the data is not saved automatically. +As with dynamic files (\code{format = "file"}) it is the +responsibility of the user to write to +the data store from inside the target. + +The distinguishing feature of \code{storage = "none"} +(as opposed to \code{format = "file"}) +is that in the general case, +downstream targets will automatically try to load the data +from the data store as a dependency. As a corollary, \code{storage = "none"} +is completely unnecessary if \code{format} is \code{"file"}. +}} + +\item{retrieval}{Character of length 1, only relevant to +\code{\link[targets:tar_make_clustermq]{tar_make_clustermq()}} and \code{\link[targets:tar_make_future]{tar_make_future()}}. +Must be one of the following values: +\itemize{ +\item \code{"main"}: the target's dependencies are loaded on the host machine +and sent to the worker before the target runs. +\item \code{"worker"}: the worker loads the targets dependencies. +\item \code{"none"}: the dependencies are not loaded at all. +This choice is almost never recommended. It is only for +niche situations, e.g. the data needs to be loaded +explicitly from another language. +}} + +\item{cue}{An optional object from \code{tar_cue()} to customize the +rules that decide whether the target is up to date.} +} +\description{ +Provides a target format for stars objects. +} +\examples{ +\dontshow{if (rlang::is_installed("stars")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +if (Sys.getenv("TAR_LONG_EXAMPLES") == "true") { + targets::tar_dir({ # tar_dir() runs code from a temporary directory. + library(geotargets) + targets::tar_script({ + list( + geotargets::tar_stars( + stars_example, + stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars")) + ) + ) + }) + targets::tar_make() + x <- targets::tar_read(stars_example) + }) +} +\dontshow{\}) # examplesIf} +} +\seealso{ +\code{\link[targets:tar_target_raw]{targets::tar_target_raw()}} +} diff --git a/tests/testthat/_snaps/tar-stars.md b/tests/testthat/_snaps/tar-stars.md new file mode 100644 index 0000000..927ac8f --- /dev/null +++ b/tests/testthat/_snaps/tar-stars.md @@ -0,0 +1,14 @@ +# tar_stars() works + + Code + x + Output + stars object with 2 dimensions and 1 attribute + attribute(s): + Min. 1st Qu. Median Mean 3rd Qu. Max. + test_stars -1 6 12 21.66521 35 88 + dimension(s): + from to offset delta refsys point x/y + x 1 111 288776 89.99 UTM Zone 25, Southern Hem... FALSE [x] + y 1 111 9120761 -89.99 UTM Zone 25, Southern Hem... FALSE [y] + diff --git a/tests/testthat/test-tar-stars.R b/tests/testthat/test-tar-stars.R new file mode 100644 index 0000000..0520f34 --- /dev/null +++ b/tests/testthat/test-tar-stars.R @@ -0,0 +1,21 @@ +# test_that() #Included to make RStudio recognize this file as a test + +skip_if_not_installed("sf") + +skip_if_not_installed("stars") + +targets::tar_test("tar_stars() works", { + geotargets::geotargets_option_set("raster_gdal_creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) + targets::tar_script({ + list(geotargets::tar_stars( + test_stars, + stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars")) + )) + }) + targets::tar_make() + x <- targets::tar_read(test_stars) + expect_s3_class(x, "stars") + expect_snapshot( + x + ) +}) From 0e20c172f574efed855625ec06219c40eade9917 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Fri, 15 Mar 2024 19:46:35 -0700 Subject: [PATCH 02/20] Add `tar_stars_proxy()` --- NAMESPACE | 2 + R/AAAA.R | 2 + R/geotargets-option.R | 20 ++++++- R/geotargets-package.R | 1 + R/tar-stars.R | 94 +++++++++++++++++++++++++----- man/geotargets-options.Rd | 5 +- man/tar_stars.Rd | 27 +++++++++ tests/testthat/_snaps/tar-stars.md | 14 +++++ tests/testthat/test-tar-stars.R | 23 +++++++- 9 files changed, 168 insertions(+), 20 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 6a40473..d7b5995 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,9 +3,11 @@ export(geotargets_option_get) export(geotargets_option_set) export(tar_stars) +export(tar_stars_proxy) export(tar_terra_rast) export(tar_terra_vect) importFrom(rlang,"%||%") importFrom(rlang,arg_match0) +importFrom(rlang,check_installed) importFrom(rlang,is_installed) importFrom(utils,globalVariables) diff --git a/R/AAAA.R b/R/AAAA.R index 4b046dd..57b0d07 100644 --- a/R/AAAA.R +++ b/R/AAAA.R @@ -10,4 +10,6 @@ geotargets_env <- function() { geotargets.env$geotargets.gdal.vector.creation_options <- geotargets_option_get("gdal.vector.creation_options") geotargets.env$geotargets.gdal.vector.driver <- geotargets_option_get("gdal.vector.driver") + + geotargets.env$geotargets.stars.proxy <- geotargets_option_get("stars.proxy") } diff --git a/R/geotargets-option.R b/R/geotargets-option.R index 5e52b88..c5aeb03 100644 --- a/R/geotargets-option.R +++ b/R/geotargets-option.R @@ -16,12 +16,15 @@ #' #' - `"geotargets.gdal.vector.creation_options"` - character. Set the GDAL layer creation options used when writing vector files to target store (default: `"ENCODING=UTF-8"`). You may specify multiple values e.g. `c("WRITE_BBOX=YES", "COORDINATE_PRECISION=10")`. Each GDAL driver supports a unique set of creation options. For example, with the default `"GeoJSON"` driver: #' +#' - `"geotargets.stars.proxy"` - logical. Control the object type read from a _stars_ target via `tar_stars()` with [stars::read_stars()]. Value `FALSE` (default) returns `stars` object; if `TRUE` a `stars_proxy` is returned. + #' Each option can be overridden with a system environment variable. Options include: #' #' - `GEOTARGETS_GDAL_RASTER_DRIVER` #' - `GEOTARGETS_GDAL_RASTER_CREATION_OPTIONS` #' - `GEOTARGETS_GDAL_VECTOR_DRIVER` #' - `GEOTARGETS_GDAL_VECTOR_CREATION_OPTIONS` +#' - `GEOTARGETS_STARS_PROXY` #' #' When specifying options that support multiple values using a system environment variable, the separate options should be delimited with a semicolon (";"). For example: `"COMPRESS=DEFLATE;TFW=YES"`. #' @@ -32,7 +35,11 @@ geotargets_option_get <- function(option_name) { option_name <- geotargets_repair_option_name(option_name) option_value <- geotargets_env()[[option_name]] - get_option <- function(option_name, option_value, name){ + if (length(option_value) == 0) { + option_value <- NULL + } + + get_option <- function(option_name, option_value, name) { getOption(option_name, default = option_value %||% name) } @@ -68,6 +75,13 @@ geotargets_option_get <- function(option_name) { ) } + get_geotargets_stars_proxy <- function(option_name, option_value) { + as.logical(Sys.getenv( + x = "GEOTARGETS_STARS_PROXY", + unset = get_option(option_name, option_value, FALSE) + )) + } + switch(option_name, "geotargets.gdal.raster.creation_options" = get_geotargets_gdal_raster_creation_options(option_name, option_value), @@ -76,7 +90,9 @@ geotargets_option_get <- function(option_name) { "geotargets.gdal.vector.creation_options" = get_geotargets_gdal_vector_creation_options(option_name, option_value), "geotargets.gdal.vector.driver" = - get_geotargets_gdal_vector_driver(option_name, option_value) + get_geotargets_gdal_vector_driver(option_name, option_value), + "geotargets.stars.proxy" = + get_geotargets_stars_proxy(option_name, option_value) ) } diff --git a/R/geotargets-package.R b/R/geotargets-package.R index b20dd73..0e00ac4 100644 --- a/R/geotargets-package.R +++ b/R/geotargets-package.R @@ -7,6 +7,7 @@ NULL # clear CRAN checks spotting floating global variables #' @importFrom utils globalVariables +#' @importFrom rlang %||% arg_match0 is_installed check_installed utils::globalVariables( c( "packages" diff --git a/R/tar-stars.R b/R/tar-stars.R index e05df5c..1e568e1 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -2,12 +2,12 @@ #' #' Provides a target format for stars objects. #' +#' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target an object of class `stars_proxy`. Otherwise, the object is class `stars`. #' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. #' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] #' @param ... Additional arguments not yet used #' #' @inheritParams targets::tar_target -#' @importFrom rlang %||% arg_match0 is_installed #' @seealso [targets::tar_target_raw()] #' @export #' @examplesIf rlang::is_installed("stars") @@ -29,6 +29,7 @@ tar_stars <- function(name, command, pattern = NULL, + proxy = FALSE, driver = NULL, options = NULL, ..., @@ -47,6 +48,74 @@ tar_stars <- function(name, retrieval = targets::tar_option_get("retrieval"), cue = targets::tar_option_get("cue")) { + rlang::check_installed("stars") + + 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 + driver <- driver %||% geotargets_option_get("gdal.raster.driver") + options <- options %||% geotargets_option_get("gdal.raster.creation_options") + + targets::tar_target_raw( + name = name, + command = command, + pattern = pattern, + packages = packages, + library = library, + format = create_format_stars(driver = driver, options = options, proxy = proxy, ...), + repository = repository, + iteration = iteration, + error = error, + memory = memory, + garbage_collection = garbage_collection, + deployment = deployment, + priority = priority, + resources = resources, + storage = storage, + retrieval = retrieval, + cue = cue + ) +} + +#' @export +#' @rdname tar_stars +tar_stars_proxy <- function(name, + command, + pattern = NULL, + driver = NULL, + options = NULL, + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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")) { + + rlang::check_installed("stars") + name <- targets::tar_deparse_language(substitute(name)) envir <- targets::tar_option_get("envir") @@ -73,7 +142,7 @@ tar_stars <- function(name, pattern = pattern, packages = packages, library = library, - format = create_format_stars(driver = driver, options = options, ...), + format = create_format_stars(driver = driver, options = options, proxy = TRUE, ...), repository = repository, iteration = iteration, error = error, @@ -87,19 +156,13 @@ tar_stars <- function(name, cue = cue ) } + + #' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. #' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] #' @param ... Additional arguments not yet used #' @noRd -create_format_stars <- function(driver, options, ...) { - - if (!requireNamespace("sf")) { - stop("package 'sf' is required", call. = FALSE) - } - - if (!requireNamespace("stars")) { - stop("package 'stars' is required", call. = FALSE) - } +create_format_stars <- function(driver, options, proxy, ...) { # get list of drivers available for writing depending on what the user's GDAL supports drv <- sf::st_drivers(what = "raster") @@ -110,7 +173,12 @@ create_format_stars <- function(driver, options, ...) { options <- options %||% geotargets_option_get("gdal.raster.creation_options") - # NOTE: Option getting functions are set in the .write_terra_raster function template + .read_stars <- function(path) { + stars::read_stars(path, proxy = geotargets::geotargets_option_get("stars.proxy")) + } + body(.read_stars)[[2]][["proxy"]] <- proxy + + # NOTE: Option getting functions are set in the .write_stars function template # to resolve issue with body<- not working in some evaluation contexts ({covr}). # TODO: It should be fine to have driver and options as NULL .write_stars <- function(object, path) { @@ -127,7 +195,7 @@ create_format_stars <- function(driver, options, ...) { body(.write_stars)[[2]][["options"]] <- options targets::tar_format( - read = function(path) stars::read_stars(path), + read = .read_stars, write = .write_stars, marshal = function(object) object, # Not currently used unmarshal = function(object) object diff --git a/man/geotargets-options.Rd b/man/geotargets-options.Rd index e1cda96..7be07ab 100644 --- a/man/geotargets-options.Rd +++ b/man/geotargets-options.Rd @@ -24,14 +24,15 @@ Get or set behavior for geospatial data target stores using geotargets-specific \item \code{"geotargets.gdal.raster.creation_options"} - character. Set the GDAL creation options used when writing raster files to target store (default: \code{""}). You may specify multiple values e.g. \code{c("COMPRESS=DEFLATE", "TFW=YES")}. Each GDAL driver supports a unique set of creation options. For example, with the default \code{"GTiff"} driver: \url{https://gdal.org/drivers/raster/gtiff.html#creation-options} \item \code{"geotargets.gdal.vector.driver"} - character. Length 1. Set the file type used for vector data in target store (default: \code{"GeoJSON"}). \item \code{"geotargets.gdal.vector.creation_options"} - character. Set the GDAL layer creation options used when writing vector files to target store (default: \code{"ENCODING=UTF-8"}). You may specify multiple values e.g. \code{c("WRITE_BBOX=YES", "COORDINATE_PRECISION=10")}. Each GDAL driver supports a unique set of creation options. For example, with the default \code{"GeoJSON"} driver: \url{https://gdal.org/drivers/vector/geojson.html#layer-creation-options} -} - +\item \code{"geotargets.stars.proxy"} - logical. Control the object type read from a \emph{stars} target via \code{tar_stars()} with \code{\link[stars:read_stars]{stars::read_stars()}}. Value \code{FALSE} (default) returns \code{stars} object; if \code{TRUE} a \code{stars_proxy} is returned. Each option can be overridden with a system environment variable. Options include: \itemize{ \item \code{GEOTARGETS_GDAL_RASTER_DRIVER} \item \code{GEOTARGETS_GDAL_RASTER_CREATION_OPTIONS} \item \code{GEOTARGETS_GDAL_VECTOR_DRIVER} \item \code{GEOTARGETS_GDAL_VECTOR_CREATION_OPTIONS} +\item \code{GEOTARGETS_STARS_PROXY} +} } When specifying options that support multiple values using a system environment variable, the separate options should be delimited with a semicolon (";"). For example: \code{"COMPRESS=DEFLATE;TFW=YES"}. diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd index cb0362d..ed53cdb 100644 --- a/man/tar_stars.Rd +++ b/man/tar_stars.Rd @@ -2,9 +2,34 @@ % Please edit documentation in R/tar-stars.R \name{tar_stars} \alias{tar_stars} +\alias{tar_stars_proxy} \title{Create a stars \emph{stars} Target} \usage{ tar_stars( + name, + command, + pattern = NULL, + proxy = FALSE, + driver = NULL, + options = NULL, + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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") +) + +tar_stars_proxy( name, command, pattern = NULL, @@ -52,6 +77,8 @@ For example, in a pipeline with numeric vector targets \code{x} and \code{y}, branches of \code{z} that each compute \code{x[1] + y[1]}, \code{x[2] + y[2]}, and so on. See the user manual for details.} +\item{proxy}{logical. Passed to \code{\link[stars:read_stars]{stars::read_stars()}}. If \code{TRUE} the target an object of class \code{stars_proxy}. Otherwise, the object is class \code{stars}.} + \item{driver}{character. File format expressed as GDAL driver names passed to \code{\link[stars:write_stars]{stars::write_stars()}}. See \code{\link[sf:st_drivers]{sf::st_drivers()}}.} \item{options}{character. GDAL driver specific datasource creation options passed to \code{\link[stars:write_stars]{stars::write_stars()}}} diff --git a/tests/testthat/_snaps/tar-stars.md b/tests/testthat/_snaps/tar-stars.md index 927ac8f..42c33c9 100644 --- a/tests/testthat/_snaps/tar-stars.md +++ b/tests/testthat/_snaps/tar-stars.md @@ -12,3 +12,17 @@ x 1 111 288776 89.99 UTM Zone 25, Southern Hem... FALSE [x] y 1 111 9120761 -89.99 UTM Zone 25, Southern Hem... FALSE [y] +# tar_stars_proxy() works + + Code + x + Output + stars_proxy object with 1 attribute in 1 file(s): + $test_stars_proxy + [1] "[...]/test_stars_proxy" + + dimension(s): + from to offset delta refsys point x/y + x 1 111 288776 89.99 UTM Zone 25, Southern Hem... FALSE [x] + y 1 111 9120761 -89.99 UTM Zone 25, Southern Hem... FALSE [y] + diff --git a/tests/testthat/test-tar-stars.R b/tests/testthat/test-tar-stars.R index 0520f34..7c5366d 100644 --- a/tests/testthat/test-tar-stars.R +++ b/tests/testthat/test-tar-stars.R @@ -1,11 +1,9 @@ # test_that() #Included to make RStudio recognize this file as a test -skip_if_not_installed("sf") - skip_if_not_installed("stars") targets::tar_test("tar_stars() works", { - geotargets::geotargets_option_set("raster_gdal_creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) + geotargets::geotargets_option_set("gdal.raster.creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) targets::tar_script({ list(geotargets::tar_stars( test_stars, @@ -19,3 +17,22 @@ targets::tar_test("tar_stars() works", { x ) }) + + +targets::tar_test("tar_stars_proxy() works", { + geotargets::geotargets_option_set("gdal.raster.creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) + geotargets::geotargets_option_set("stars.proxy", TRUE) # needed for {covr} only + targets::tar_script({ + list(geotargets::tar_stars_proxy( + test_stars_proxy, + stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars"), proxy = TRUE) + )) + }) + targets::tar_make() + x <- targets::tar_read(test_stars_proxy) + expect_s3_class(x, "stars_proxy") + expect_snapshot( + x + ) + geotargets::geotargets_option_set("stars.proxy", FALSE) # go back to default +}) From 980c291b1c00bfeea87b9b39d992cd781e94a510 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Fri, 15 Mar 2024 20:44:40 -0700 Subject: [PATCH 03/20] fix typo in test-tar-terra.R - noticed while writing stars tests --- tests/testthat/test-tar-terra.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-tar-terra.R b/tests/testthat/test-tar-terra.R index 5c9d587..0ea9c24 100644 --- a/tests/testthat/test-tar-terra.R +++ b/tests/testthat/test-tar-terra.R @@ -1,6 +1,6 @@ # test_that() #Included to make RStudio recognize this file as a test targets::tar_test("tar_terra_rast() works", { - geotargets::geotargets_option_set("raster_gdal_creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) + geotargets::geotargets_option_set("gdal.raster.creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) targets::tar_script({ list( geotargets::tar_terra_rast( From 78bdee5347f99818837669bac4aa75e69911f6f4 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Fri, 15 Mar 2024 21:00:06 -0700 Subject: [PATCH 04/20] rlang importFrom is now in geotargets-package.R --- R/tar-terra-rast.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/tar-terra-rast.R b/R/tar-terra-rast.R index de18c69..777a1eb 100644 --- a/R/tar-terra-rast.R +++ b/R/tar-terra-rast.R @@ -7,7 +7,6 @@ #' @param ... Additional arguments not yet used #' #' @inheritParams targets::tar_target -#' @importFrom rlang %||% arg_match0 #' @seealso [targets::tar_target_raw()] #' @export #' @examples From bcd64a748fe7f4f2adc6b60df4150cfd2b64887b Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Fri, 15 Mar 2024 21:21:42 -0700 Subject: [PATCH 05/20] clean up unneeded addition --- R/geotargets-option.R | 4 ---- 1 file changed, 4 deletions(-) diff --git a/R/geotargets-option.R b/R/geotargets-option.R index c5aeb03..49d1d03 100644 --- a/R/geotargets-option.R +++ b/R/geotargets-option.R @@ -35,10 +35,6 @@ geotargets_option_get <- function(option_name) { option_name <- geotargets_repair_option_name(option_name) option_value <- geotargets_env()[[option_name]] - if (length(option_value) == 0) { - option_value <- NULL - } - get_option <- function(option_name, option_value, name) { getOption(option_name, default = option_value %||% name) } From f74fe91d48f6c6fdab5ffb13e6895bfb555c9a6c Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Sat, 16 Mar 2024 00:50:37 -0700 Subject: [PATCH 06/20] tar_stars: Add support for storage of arbitrary multidimensional arrays --- R/geotargets-option.R | 10 +++- R/tar-stars.R | 95 ++++++++++++++++++++++++++++-- man/tar_stars.Rd | 30 +++++++++- tests/testthat/_snaps/tar-stars.md | 14 +++++ tests/testthat/test-tar-stars.R | 23 +++++++- 5 files changed, 164 insertions(+), 8 deletions(-) diff --git a/R/geotargets-option.R b/R/geotargets-option.R index 49d1d03..9b2c8b2 100644 --- a/R/geotargets-option.R +++ b/R/geotargets-option.R @@ -42,8 +42,11 @@ geotargets_option_get <- function(option_name) { get_geotargets_gdal_raster_creation_options <- function(option_name, option_value) { gdal_creation_options <- Sys.getenv( x = "GEOTARGETS_GDAL_RASTER_CREATION_OPTIONS", - unset = get_option(option_name, option_value, "") + unset = "" ) + if (gdal_creation_options == "") { + gdal_creation_options <- get_option(option_name, option_value, "") + } the_option <- strsplit(gdal_creation_options, ";")[[1]] the_option } @@ -58,8 +61,11 @@ geotargets_option_get <- function(option_name) { get_geotargets_gdal_vector_creation_options <- function(option_name, option_value) { gdal_creation_options <- Sys.getenv( x = "GEOTARGETS_GDAL_VECTOR_CREATION_OPTIONS", - unset = get_option(option_name, option_value, "ENCODING=UTF-8") + unset = "" ) + if (gdal_creation_options == "") { + gdal_creation_options <- get_option(option_name, option_value, "ENCODING=UTF-8") + } the_options <- strsplit(gdal_creation_options, ";")[[1]] the_options } diff --git a/R/tar-stars.R b/R/tar-stars.R index 1e568e1..282daba 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -3,7 +3,8 @@ #' Provides a target format for stars objects. #' #' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target an object of class `stars_proxy`. Otherwise, the object is class `stars`. -#' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. +#' @param mdim logical. Use the [Multidimensional Raster Data Model](https://gdal.org/user/multidim_raster_data_model.html) via [stars::write_mdim()]? Default: `FALSE`. Only supported for some drivers, e.g. `"HDF5"`, `"netCDF"`, `"Zarr"`. +#' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()] or [stars::write_mdim()] See [sf::st_drivers()]. #' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] #' @param ... Additional arguments not yet used #' @@ -30,6 +31,7 @@ tar_stars <- function(name, command, pattern = NULL, proxy = FALSE, + mdim = FALSE, driver = NULL, options = NULL, ..., @@ -76,7 +78,7 @@ tar_stars <- function(name, pattern = pattern, packages = packages, library = library, - format = create_format_stars(driver = driver, options = options, proxy = proxy, ...), + format = create_format_stars(driver = driver, options = options, proxy = proxy, mdim = mdim, ...), repository = repository, iteration = iteration, error = error, @@ -96,6 +98,7 @@ tar_stars <- function(name, tar_stars_proxy <- function(name, command, pattern = NULL, + mdim = FALSE, driver = NULL, options = NULL, ..., @@ -142,7 +145,7 @@ tar_stars_proxy <- function(name, pattern = pattern, packages = packages, library = library, - format = create_format_stars(driver = driver, options = options, proxy = TRUE, ...), + format = create_format_stars(driver = driver, options = options, proxy = TRUE, mdim = mdim, ...), repository = repository, iteration = iteration, error = error, @@ -158,11 +161,80 @@ tar_stars_proxy <- function(name, } +#' @export +#' @rdname tar_stars +tar_stars_proxy <- function(name, + command, + pattern = NULL, + mdim = FALSE, + driver = NULL, + options = NULL, + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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")) { + + rlang::check_installed("stars") + + 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 + driver <- driver %||% geotargets_option_get("gdal.raster.driver") + options <- options %||% geotargets_option_get("gdal.raster.creation_options") + + targets::tar_target_raw( + name = name, + command = command, + pattern = pattern, + packages = packages, + library = library, + format = create_format_stars(driver = driver, options = options, proxy = TRUE, mdim = mdim, ...), + 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 driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. #' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] +#' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target an object of class `stars_proxy`. Otherwise, the object is class `stars`. +#' @param mdim logical. Use the [Multidimensional Raster Data Model](https://gdal.org/user/multidim_raster_data_model.html) via [stars::write_mdim()]? Default: `FALSE`. Only supported for some drivers, e.g. `"netCDF"` or `"Zarr"`. #' @param ... Additional arguments not yet used #' @noRd -create_format_stars <- function(driver, options, proxy, ...) { +create_format_stars <- function(driver, options, proxy, mdim, ...) { # get list of drivers available for writing depending on what the user's GDAL supports drv <- sf::st_drivers(what = "raster") @@ -191,6 +263,21 @@ create_format_stars <- function(driver, options, proxy, ...) { ) } + # TODO: should multidimensional array use the same options as 2D? + .write_stars_mdim <- function(object, path) { + stars::write_mdim( + object, + path, + driver = geotargets::geotargets_option_get("gdal.raster.driver"), + overwrite = TRUE, + options = geotargets::geotargets_option_get("gdal.raster.creation_options") + ) + } + + if (isTRUE(mdim)) { + .write_stars <- .write_stars_mdim + } + body(.write_stars)[[2]][["driver"]] <- driver body(.write_stars)[[2]][["options"]] <- options diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd index ed53cdb..9edd02e 100644 --- a/man/tar_stars.Rd +++ b/man/tar_stars.Rd @@ -10,6 +10,7 @@ tar_stars( command, pattern = NULL, proxy = FALSE, + mdim = FALSE, driver = NULL, options = NULL, ..., @@ -33,6 +34,31 @@ tar_stars_proxy( name, command, pattern = NULL, + mdim = FALSE, + driver = NULL, + options = NULL, + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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") +) + +tar_stars_proxy( + name, + command, + pattern = NULL, + mdim = FALSE, driver = NULL, options = NULL, ..., @@ -79,7 +105,9 @@ and so on. See the user manual for details.} \item{proxy}{logical. Passed to \code{\link[stars:read_stars]{stars::read_stars()}}. If \code{TRUE} the target an object of class \code{stars_proxy}. Otherwise, the object is class \code{stars}.} -\item{driver}{character. File format expressed as GDAL driver names passed to \code{\link[stars:write_stars]{stars::write_stars()}}. See \code{\link[sf:st_drivers]{sf::st_drivers()}}.} +\item{mdim}{logical. Use the \href{https://gdal.org/user/multidim_raster_data_model.html}{Multidimensional Raster Data Model} via \code{\link[stars:mdim]{stars::write_mdim()}}? Default: \code{FALSE}. Only supported for some drivers, e.g. \code{"HDF5"}, \code{"netCDF"}, \code{"Zarr"}.} + +\item{driver}{character. File format expressed as GDAL driver names passed to \code{\link[stars:write_stars]{stars::write_stars()}} or \code{\link[stars:mdim]{stars::write_mdim()}} See \code{\link[sf:st_drivers]{sf::st_drivers()}}.} \item{options}{character. GDAL driver specific datasource creation options passed to \code{\link[stars:write_stars]{stars::write_stars()}}} diff --git a/tests/testthat/_snaps/tar-stars.md b/tests/testthat/_snaps/tar-stars.md index 42c33c9..9904189 100644 --- a/tests/testthat/_snaps/tar-stars.md +++ b/tests/testthat/_snaps/tar-stars.md @@ -26,3 +26,17 @@ x 1 111 288776 89.99 UTM Zone 25, Southern Hem... FALSE [x] y 1 111 9120761 -89.99 UTM Zone 25, Southern Hem... FALSE [y] +# tar_stars(mdim=TRUE) works + + Code + x + Output + stars object with 2 dimensions and 1 attribute + attribute(s): + Min. 1st Qu. Median Mean 3rd Qu. Max. + test_stars_mdim 0.03524588 0.3224987 0.3772574 0.4289465 0.511113 0.9204841 + dimension(s): + from to offset delta x/y + x 1 2 0 1 [x] + y 1 5 5 -1 [y] + diff --git a/tests/testthat/test-tar-stars.R b/tests/testthat/test-tar-stars.R index 7c5366d..3eecb03 100644 --- a/tests/testthat/test-tar-stars.R +++ b/tests/testthat/test-tar-stars.R @@ -18,7 +18,6 @@ targets::tar_test("tar_stars() works", { ) }) - targets::tar_test("tar_stars_proxy() works", { geotargets::geotargets_option_set("gdal.raster.creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) geotargets::geotargets_option_set("stars.proxy", TRUE) # needed for {covr} only @@ -36,3 +35,25 @@ targets::tar_test("tar_stars_proxy() works", { ) geotargets::geotargets_option_set("stars.proxy", FALSE) # go back to default }) + + +targets::tar_test("tar_stars(mdim=TRUE) works", { + targets::tar_script({ + geotargets::geotargets_option_set("gdal.raster.driver", "netCDF") + list(geotargets::tar_stars(test_stars_mdim, { + set.seed(135) + m <- matrix(runif(10), 2, 5) + names(dim(m)) <- c("stations", "time") + times <- as.Date("2022-05-01") + 1:5 + pts <- sf::st_as_sfc(c("POINT(0 1)", "POINT(3 5)")) + s <- stars::st_as_stars(list(Precipitation = m)) |> + stars::st_set_dimensions(1, values = pts) |> + stars::st_set_dimensions(2, values = times) + }, driver = "netCDF", mdim = TRUE)) + }) + + targets::tar_make() + x <- targets::tar_read(test_stars_mdim) + expect_s3_class(x, "stars") + expect_snapshot(x) +}) From 948a2e6fedff8466428f417e8c37c6804b665a50 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Mon, 18 Mar 2024 21:21:03 -0700 Subject: [PATCH 07/20] Better tar_format function building following #34, #43 - substitute in options, read/write functions following #43 - add support for reading netCDF via `stars::read_ncdf()` using #43 - consolidate option getter usage for #34 --- DESCRIPTION | 1 + R/tar-stars.R | 118 ++++++++++++++--------------- man/tar_stars.Rd | 21 +++-- tests/testthat/_snaps/tar-stars.md | 24 ++++-- tests/testthat/test-tar-stars.R | 24 +++++- 5 files changed, 114 insertions(+), 74 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index ea712a6..f0f9356 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -38,6 +38,7 @@ Imports: Suggests: sf, stars, + ncmeta, testthat (>= 3.0.0), Depends: R (>= 4.1.0) diff --git a/R/tar-stars.R b/R/tar-stars.R index 282daba..692d5de 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -2,10 +2,11 @@ #' #' Provides a target format for stars objects. #' -#' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target an object of class `stars_proxy`. Otherwise, the object is class `stars`. -#' @param mdim logical. Use the [Multidimensional Raster Data Model](https://gdal.org/user/multidim_raster_data_model.html) via [stars::write_mdim()]? Default: `FALSE`. Only supported for some drivers, e.g. `"HDF5"`, `"netCDF"`, `"Zarr"`. -#' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()] or [stars::write_mdim()] See [sf::st_drivers()]. +#' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. #' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] +#' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target an object of class `stars_proxy`. Otherwise, the object is class `stars`. +#' @param mdim logical. Use the [Multidimensional Raster Data Model](https://gdal.org/user/multidim_raster_data_model.html) via [stars::write_mdim()]? Default: `FALSE`. Only supported for some drivers, e.g. `"netCDF"` or `"Zarr"`. +#' @param ncdf logical. Use the NetCDF library directly to read data via [stars::read_ncdf()]? Default: `FALSE`. Only supported for `driver="netCDF"`. #' @param ... Additional arguments not yet used #' #' @inheritParams targets::tar_target @@ -32,8 +33,9 @@ tar_stars <- function(name, pattern = NULL, proxy = FALSE, mdim = FALSE, - driver = NULL, - options = NULL, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation_options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -68,17 +70,20 @@ tar_stars <- function(name, tidy_eval = tidy_eval ) - # if not specified by user, pull the corresponding geotargets option - driver <- driver %||% geotargets_option_get("gdal.raster.driver") - options <- options %||% geotargets_option_get("gdal.raster.creation_options") - targets::tar_target_raw( name = name, command = command, pattern = pattern, packages = packages, library = library, - format = create_format_stars(driver = driver, options = options, proxy = proxy, mdim = mdim, ...), + format = create_format_stars( + driver = driver, + options = options, + proxy = proxy, + mdim = mdim, + ncdf = ncdf, + ... + ), repository = repository, iteration = iteration, error = error, @@ -99,8 +104,9 @@ tar_stars_proxy <- function(name, command, pattern = NULL, mdim = FALSE, - driver = NULL, - options = NULL, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation_options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -135,17 +141,20 @@ tar_stars_proxy <- function(name, tidy_eval = tidy_eval ) - # if not specified by user, pull the corresponding geotargets option - driver <- driver %||% geotargets_option_get("gdal.raster.driver") - options <- options %||% geotargets_option_get("gdal.raster.creation_options") - targets::tar_target_raw( name = name, command = command, pattern = pattern, packages = packages, library = library, - format = create_format_stars(driver = driver, options = options, proxy = TRUE, mdim = mdim, ...), + format = create_format_stars( + driver = driver, + options = options, + proxy = TRUE, + mdim = mdim, + ncdf = ncdf, + ... + ), repository = repository, iteration = iteration, error = error, @@ -167,8 +176,9 @@ tar_stars_proxy <- function(name, command, pattern = NULL, mdim = FALSE, - driver = NULL, - options = NULL, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation_options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -203,17 +213,20 @@ tar_stars_proxy <- function(name, tidy_eval = tidy_eval ) - # if not specified by user, pull the corresponding geotargets option - driver <- driver %||% geotargets_option_get("gdal.raster.driver") - options <- options %||% geotargets_option_get("gdal.raster.creation_options") - targets::tar_target_raw( name = name, command = command, pattern = pattern, packages = packages, library = library, - format = create_format_stars(driver = driver, options = options, proxy = TRUE, mdim = mdim, ...), + format = create_format_stars( + driver = driver, + options = options, + proxy = TRUE, + mdim = mdim, + ncdf = ncdf, + ... + ), repository = repository, iteration = iteration, error = error, @@ -228,58 +241,43 @@ tar_stars_proxy <- function(name, ) } -#' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. -#' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] -#' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target an object of class `stars_proxy`. Otherwise, the object is class `stars`. -#' @param mdim logical. Use the [Multidimensional Raster Data Model](https://gdal.org/user/multidim_raster_data_model.html) via [stars::write_mdim()]? Default: `FALSE`. Only supported for some drivers, e.g. `"netCDF"` or `"Zarr"`. -#' @param ... Additional arguments not yet used -#' @noRd -create_format_stars <- function(driver, options, proxy, mdim, ...) { +create_format_stars <- function(driver, options, proxy, mdim, ncdf, ...) { # get list of drivers available for writing depending on what the user's GDAL supports drv <- sf::st_drivers(what = "raster") drv <- drv[drv$write, ] - driver <- driver %||% geotargets_option_get("gdal.raster.driver") driver <- rlang::arg_match0(driver, drv$name) - options <- options %||% geotargets_option_get("gdal.raster.creation_options") + READ_FUN <- "stars::read_stars" + WRITE_FUN <- "stars::write_stars" - .read_stars <- function(path) { - stars::read_stars(path, proxy = geotargets::geotargets_option_get("stars.proxy")) + if (mdim) { + READ_FUN <- "stars::read_mdim" + WRITE_FUN <- "stars::write_mdim" } - body(.read_stars)[[2]][["proxy"]] <- proxy - # NOTE: Option getting functions are set in the .write_stars function template - # to resolve issue with body<- not working in some evaluation contexts ({covr}). - # TODO: It should be fine to have driver and options as NULL - .write_stars <- function(object, path) { - stars::write_stars( - object, - path, - driver = geotargets::geotargets_option_get("gdal.raster.driver"), - overwrite = TRUE, - options = geotargets::geotargets_option_get("gdal.raster.creation_options") - ) + if (ncdf && requireNamespace("ncmeta")) { + READ_FUN <- "stars::read_ncdf" } - # TODO: should multidimensional array use the same options as 2D? - .write_stars_mdim <- function(object, path) { - stars::write_mdim( + .read_stars <- eval(substitute(function(path) { + FUN(path, proxy = proxy) + }, list(FUN = str2lang(READ_FUN), + proxy = proxy))) + + # TODO: should multidimensional array use the same `options` as 2D? + .write_stars <- eval(substitute(function(object, path) { + FUN( object, path, - driver = geotargets::geotargets_option_get("gdal.raster.driver"), + driver = driver, overwrite = TRUE, - options = geotargets::geotargets_option_get("gdal.raster.creation_options") + options = options ) - } - - if (isTRUE(mdim)) { - .write_stars <- .write_stars_mdim - } - - body(.write_stars)[[2]][["driver"]] <- driver - body(.write_stars)[[2]][["options"]] <- options + }, list(FUN = str2lang(WRITE_FUN), + driver = driver, + options = options))) targets::tar_format( read = .read_stars, diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd index 9edd02e..feefaf2 100644 --- a/man/tar_stars.Rd +++ b/man/tar_stars.Rd @@ -11,8 +11,9 @@ tar_stars( pattern = NULL, proxy = FALSE, mdim = FALSE, - driver = NULL, - options = NULL, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation_options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -35,8 +36,9 @@ tar_stars_proxy( command, pattern = NULL, mdim = FALSE, - driver = NULL, - options = NULL, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation_options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -59,8 +61,9 @@ tar_stars_proxy( command, pattern = NULL, mdim = FALSE, - driver = NULL, - options = NULL, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation_options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -105,9 +108,11 @@ and so on. See the user manual for details.} \item{proxy}{logical. Passed to \code{\link[stars:read_stars]{stars::read_stars()}}. If \code{TRUE} the target an object of class \code{stars_proxy}. Otherwise, the object is class \code{stars}.} -\item{mdim}{logical. Use the \href{https://gdal.org/user/multidim_raster_data_model.html}{Multidimensional Raster Data Model} via \code{\link[stars:mdim]{stars::write_mdim()}}? Default: \code{FALSE}. Only supported for some drivers, e.g. \code{"HDF5"}, \code{"netCDF"}, \code{"Zarr"}.} +\item{mdim}{logical. Use the \href{https://gdal.org/user/multidim_raster_data_model.html}{Multidimensional Raster Data Model} via \code{\link[stars:mdim]{stars::write_mdim()}}? Default: \code{FALSE}. Only supported for some drivers, e.g. \code{"netCDF"} or \code{"Zarr"}.} -\item{driver}{character. File format expressed as GDAL driver names passed to \code{\link[stars:write_stars]{stars::write_stars()}} or \code{\link[stars:mdim]{stars::write_mdim()}} See \code{\link[sf:st_drivers]{sf::st_drivers()}}.} +\item{ncdf}{logical. Use the NetCDF library directly to read data via \code{\link[stars:read_ncdf]{stars::read_ncdf()}}? Default: \code{FALSE}. Only supported for \code{driver="netCDF"}.} + +\item{driver}{character. File format expressed as GDAL driver names passed to \code{\link[stars:write_stars]{stars::write_stars()}}. See \code{\link[sf:st_drivers]{sf::st_drivers()}}.} \item{options}{character. GDAL driver specific datasource creation options passed to \code{\link[stars:write_stars]{stars::write_stars()}}} diff --git a/tests/testthat/_snaps/tar-stars.md b/tests/testthat/_snaps/tar-stars.md index 9904189..c0ccff9 100644 --- a/tests/testthat/_snaps/tar-stars.md +++ b/tests/testthat/_snaps/tar-stars.md @@ -33,10 +33,24 @@ Output stars object with 2 dimensions and 1 attribute attribute(s): - Min. 1st Qu. Median Mean 3rd Qu. Max. - test_stars_mdim 0.03524588 0.3224987 0.3772574 0.4289465 0.511113 0.9204841 + Min. 1st Qu. Median Mean 3rd Qu. Max. + Precipitation 0.03524588 0.3224987 0.3772574 0.4289465 0.511113 0.9204841 dimension(s): - from to offset delta x/y - x 1 2 0 1 [x] - y 1 5 5 -1 [y] + from to offset delta refsys point values + stations 1 2 NA NA NA TRUE POINT (0 1), POINT (3 5) + time 1 5 2022-05-02 1 days Date NA NULL + +# tar_stars(mdim=TRUE, ncdf=TRUE) works + + Code + x + Output + stars object with 2 dimensions and 1 attribute + attribute(s): + Min. 1st Qu. Median Mean 3rd Qu. Max. + Precipitation 0.03524588 0.3224987 0.3772574 0.4289465 0.511113 0.9204841 + dimension(s): + from to offset delta x/y + stations 1 2 0.5 1 [x] + time 1 5 2022-05-02 UTC 1 days [y] diff --git a/tests/testthat/test-tar-stars.R b/tests/testthat/test-tar-stars.R index 3eecb03..9cf59d6 100644 --- a/tests/testthat/test-tar-stars.R +++ b/tests/testthat/test-tar-stars.R @@ -20,7 +20,6 @@ targets::tar_test("tar_stars() works", { targets::tar_test("tar_stars_proxy() works", { geotargets::geotargets_option_set("gdal.raster.creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) - geotargets::geotargets_option_set("stars.proxy", TRUE) # needed for {covr} only targets::tar_script({ list(geotargets::tar_stars_proxy( test_stars_proxy, @@ -57,3 +56,26 @@ targets::tar_test("tar_stars(mdim=TRUE) works", { expect_s3_class(x, "stars") expect_snapshot(x) }) + + +targets::tar_test("tar_stars(mdim=TRUE, ncdf=TRUE) works", { + targets::tar_script({ + list(geotargets::tar_stars(test_stars_mdim_ncdf, { + set.seed(135) + m <- matrix(runif(10), 2, 5) + names(dim(m)) <- c("stations", "time") + times <- as.Date("2022-05-01") + 1:5 + pts <- sf::st_as_sfc(c("POINT(0 1)", "POINT(3 5)")) + s <- stars::st_as_stars(list(Precipitation = m)) |> + stars::st_set_dimensions(1, values = pts) |> + stars::st_set_dimensions(2, values = times) + s + }, driver = "netCDF", mdim = TRUE, ncdf = TRUE)) + }) + + targets::tar_make() + # warnings related to no CRS + suppressWarnings({x <- targets::tar_read(test_stars_mdim_ncdf)}) + expect_s3_class(x, "stars") + expect_snapshot(x) +}) From 29ff1f73b6b1280d74dec46fc90eb3a054e56c74 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Sat, 27 Apr 2024 07:18:27 -0700 Subject: [PATCH 08/20] Update tar-stars.R --- R/tar-stars.R | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/R/tar-stars.R b/R/tar-stars.R index 692d5de..468bfe2 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -35,7 +35,7 @@ tar_stars <- function(name, mdim = FALSE, ncdf = FALSE, driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation_options"), + options = geotargets_option_get("gdal.raster.creation.options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -106,7 +106,7 @@ tar_stars_proxy <- function(name, mdim = FALSE, ncdf = FALSE, driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation_options"), + options = geotargets_option_get("gdal.raster.creation.options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -178,7 +178,7 @@ tar_stars_proxy <- function(name, mdim = FALSE, ncdf = FALSE, driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation_options"), + options = geotargets_option_get("gdal.raster.creation.options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -243,6 +243,9 @@ tar_stars_proxy <- function(name, create_format_stars <- function(driver, options, proxy, mdim, ncdf, ...) { + driver <- driver %||% "GTiff" + options <- options %||% character(0) + # get list of drivers available for writing depending on what the user's GDAL supports drv <- sf::st_drivers(what = "raster") drv <- drv[drv$write, ] From a1be44c68860f1c5b31409e5945dbeffa6dc0d58 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Sat, 27 Apr 2024 07:59:08 -0700 Subject: [PATCH 09/20] Docs --- man/tar_stars.Rd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd index feefaf2..0667a13 100644 --- a/man/tar_stars.Rd +++ b/man/tar_stars.Rd @@ -13,7 +13,7 @@ tar_stars( mdim = FALSE, ncdf = FALSE, driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation_options"), + options = geotargets_option_get("gdal.raster.creation.options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -38,7 +38,7 @@ tar_stars_proxy( mdim = FALSE, ncdf = FALSE, driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation_options"), + options = geotargets_option_get("gdal.raster.creation.options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), @@ -63,7 +63,7 @@ tar_stars_proxy( mdim = FALSE, ncdf = FALSE, driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation_options"), + options = geotargets_option_get("gdal.raster.creation.options"), ..., tidy_eval = targets::tar_option_get("tidy_eval"), packages = targets::tar_option_get("packages"), From fb2b99a91b7819e8f2bd3c79f9372a5f3ee8c2b6 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Sat, 27 Apr 2024 08:27:07 -0700 Subject: [PATCH 10/20] cleanup duplicate --- R/tar-stars.R | 72 --------------------------------------------------- 1 file changed, 72 deletions(-) diff --git a/R/tar-stars.R b/R/tar-stars.R index 468bfe2..7991065 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -98,78 +98,6 @@ tar_stars <- function(name, ) } -#' @export -#' @rdname tar_stars -tar_stars_proxy <- function(name, - command, - pattern = NULL, - mdim = FALSE, - ncdf = FALSE, - driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation.options"), - ..., - tidy_eval = targets::tar_option_get("tidy_eval"), - packages = targets::tar_option_get("packages"), - 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")) { - - rlang::check_installed("stars") - - 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 - ) - - targets::tar_target_raw( - name = name, - command = command, - pattern = pattern, - packages = packages, - library = library, - format = create_format_stars( - driver = driver, - options = options, - proxy = TRUE, - mdim = mdim, - ncdf = ncdf, - ... - ), - repository = repository, - iteration = iteration, - error = error, - memory = memory, - garbage_collection = garbage_collection, - deployment = deployment, - priority = priority, - resources = resources, - storage = storage, - retrieval = retrieval, - cue = cue - ) -} - - #' @export #' @rdname tar_stars tar_stars_proxy <- function(name, From a1841bd59fe96ff266d7bae60c3c8d0f4df2ad59 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Mon, 29 Apr 2024 21:23:35 -0700 Subject: [PATCH 11/20] Update R/tar-stars.R Co-authored-by: Eric R. Scott --- R/tar-stars.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/tar-stars.R b/R/tar-stars.R index 7991065..6dfbed5 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -4,7 +4,7 @@ #' #' @param driver character. File format expressed as GDAL driver names passed to [stars::write_stars()]. See [sf::st_drivers()]. #' @param options character. GDAL driver specific datasource creation options passed to [stars::write_stars()] -#' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target an object of class `stars_proxy`. Otherwise, the object is class `stars`. +#' @param proxy logical. Passed to [stars::read_stars()]. If `TRUE` the target will be read as an object of class `stars_proxy`. Otherwise, the object is class `stars`. #' @param mdim logical. Use the [Multidimensional Raster Data Model](https://gdal.org/user/multidim_raster_data_model.html) via [stars::write_mdim()]? Default: `FALSE`. Only supported for some drivers, e.g. `"netCDF"` or `"Zarr"`. #' @param ncdf logical. Use the NetCDF library directly to read data via [stars::read_ncdf()]? Default: `FALSE`. Only supported for `driver="netCDF"`. #' @param ... Additional arguments not yet used From 6cfaa2030d9f4540eb2bd44c9a8fa19bc923838f Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Mon, 29 Apr 2024 21:24:35 -0700 Subject: [PATCH 12/20] Docs --- man/tar_stars.Rd | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd index 0667a13..cab7958 100644 --- a/man/tar_stars.Rd +++ b/man/tar_stars.Rd @@ -31,31 +31,6 @@ tar_stars( cue = targets::tar_option_get("cue") ) -tar_stars_proxy( - name, - command, - pattern = NULL, - mdim = FALSE, - ncdf = FALSE, - driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation.options"), - ..., - tidy_eval = targets::tar_option_get("tidy_eval"), - packages = targets::tar_option_get("packages"), - 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") -) - tar_stars_proxy( name, command, @@ -106,7 +81,7 @@ For example, in a pipeline with numeric vector targets \code{x} and \code{y}, branches of \code{z} that each compute \code{x[1] + y[1]}, \code{x[2] + y[2]}, and so on. See the user manual for details.} -\item{proxy}{logical. Passed to \code{\link[stars:read_stars]{stars::read_stars()}}. If \code{TRUE} the target an object of class \code{stars_proxy}. Otherwise, the object is class \code{stars}.} +\item{proxy}{logical. Passed to \code{\link[stars:read_stars]{stars::read_stars()}}. If \code{TRUE} the target will be read as an object of class \code{stars_proxy}. Otherwise, the object is class \code{stars}.} \item{mdim}{logical. Use the \href{https://gdal.org/user/multidim_raster_data_model.html}{Multidimensional Raster Data Model} via \code{\link[stars:mdim]{stars::write_mdim()}}? Default: \code{FALSE}. Only supported for some drivers, e.g. \code{"netCDF"} or \code{"Zarr"}.} From 443f88f515a755ac25f08dfeab1ad0a6256ab7bc Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Mon, 29 Apr 2024 21:46:22 -0700 Subject: [PATCH 13/20] tar_stars cleanup --- NAMESPACE | 1 + R/tar-stars.R | 162 ++++++++++++++++++++++---------- man/tar_stars.Rd | 27 ++++++ tests/testthat/test-tar-stars.R | 11 +-- 4 files changed, 147 insertions(+), 54 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 9975293..ee16a36 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,6 +4,7 @@ export(geotargets_option_get) export(geotargets_option_set) export(tar_stars) export(tar_stars_proxy) +export(tar_stars_raw) export(tar_terra_rast) export(tar_terra_sprc) export(tar_terra_vect) diff --git a/R/tar-stars.R b/R/tar-stars.R index 6dfbed5..dd305be 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -70,20 +70,17 @@ tar_stars <- function(name, tidy_eval = tidy_eval ) - targets::tar_target_raw( + tar_stars_raw( name = name, command = command, pattern = pattern, + proxy = proxy, + mdim = mdim, + ncdf = ncdf, + driver = driver, + options = options, packages = packages, library = library, - format = create_format_stars( - driver = driver, - options = options, - proxy = proxy, - mdim = mdim, - ncdf = ncdf, - ... - ), repository = repository, iteration = iteration, error = error, @@ -123,7 +120,7 @@ tar_stars_proxy <- function(name, retrieval = targets::tar_option_get("retrieval"), cue = targets::tar_option_get("cue")) { - rlang::check_installed("stars") + check_pkg_installed("stars") name <- targets::tar_deparse_language(substitute(name)) @@ -141,20 +138,18 @@ tar_stars_proxy <- function(name, tidy_eval = tidy_eval ) - targets::tar_target_raw( + tar_stars_raw( name = name, command = command, pattern = pattern, + proxy = TRUE, + mdim = mdim, + ncdf = ncdf, + driver = driver, + options = options, + ..., packages = packages, library = library, - format = create_format_stars( - driver = driver, - options = options, - proxy = TRUE, - mdim = mdim, - ncdf = ncdf, - ... - ), repository = repository, iteration = iteration, error = error, @@ -169,52 +164,123 @@ tar_stars_proxy <- function(name, ) } -create_format_stars <- function(driver, options, proxy, mdim, ncdf, ...) { + +#' tar_stars method with no tidy eval etc. +#' @noRd +tar_stars_raw <- function(name, + command, + pattern = NULL, + proxy, + mdim = FALSE, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation.options"), + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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")) { driver <- driver %||% "GTiff" options <- options %||% character(0) - # get list of drivers available for writing depending on what the user's GDAL supports + # get drivers available for writing (depends on user's GDAL build) drv <- sf::st_drivers(what = "raster") drv <- drv[drv$write, ] driver <- rlang::arg_match0(driver, drv$name) - READ_FUN <- "stars::read_stars" - WRITE_FUN <- "stars::write_stars" + .read_stars <- eval(substitute( + function(path) { - if (mdim) { - READ_FUN <- "stars::read_mdim" - WRITE_FUN <- "stars::write_mdim" - } + ## TODO: it appears envvar custom resources do not work in read function? + READ_FUN <- stars::read_stars + # mdim <- as.logical(Sys.getenv("GEOTARGETS_GDAL_RASTER_MDIM", unset = FALSE)) + print(mdim) + if (mdim) { + READ_FUN <- stars::read_mdim + } - if (ncdf && requireNamespace("ncmeta")) { - READ_FUN <- "stars::read_ncdf" - } + # ncdf <- as.logical(Sys.getenv("GEOTARGETS_USE_NCMETA", unset = FALSE)) + print(ncdf) + if (ncdf && requireNamespace("ncmeta")) { + READ_FUN <- stars::read_ncdf + } + + # proxy <- as.logical(Sys.getenv("GEOTARGETS_PROXY", unset = FALSE)) + print(proxy) + READ_FUN(path, proxy = proxy) - .read_stars <- eval(substitute(function(path) { - FUN(path, proxy = proxy) - }, list(FUN = str2lang(READ_FUN), - proxy = proxy))) + }, list(ncdf = ncdf, mdim = mdim, proxy = proxy))) # TODO: should multidimensional array use the same `options` as 2D? - .write_stars <- eval(substitute(function(object, path) { - FUN( + .write_stars <- function(object, path) { + + WRITE_FUN <- stars::write_stars + + mdim <- as.logical(Sys.getenv("GEOTARGETS_GDAL_RASTER_MDIM", + unset = FALSE)) + if (mdim) { + WRITE_FUN <- stars::write_mdim + } + + dr <- Sys.getenv("GEOTARGETS_GDAL_RASTER_DRIVER") + + # stars requires character(0), not "", for no options set + co <- Sys.getenv("GEOTARGETS_GDAL_RASTER_CREATION_OPTIONS") + co2 <- strsplit(co, ";")[[1]] + + WRITE_FUN( object, path, - driver = driver, overwrite = TRUE, - options = options + driver = dr, + options = co ) - }, list(FUN = str2lang(WRITE_FUN), - driver = driver, - options = options))) - - targets::tar_format( - read = .read_stars, - write = .write_stars, - marshal = function(object) object, # Not currently used - unmarshal = function(object) object + } + + targets::tar_target_raw( + name = name, + command = command, + pattern = pattern, + packages = packages, + library = library, + format = targets::tar_format( + read = .read_stars, + write = .write_stars, + marshal = function(object) object, # Not currently used + unmarshal = function(object) object + ), + repository = repository, + iteration = iteration, + error = error, + memory = memory, + garbage_collection = garbage_collection, + deployment = deployment, + priority = priority, + resources = targets::tar_resources( + custom_format = targets::tar_resources_custom_format( + #these envvars are used in read and write functions of format + envvars = c("GEOTARGETS_GDAL_RASTER_DRIVER" = driver, + "GEOTARGETS_GDAL_RASTER_CREATION_OPTIONS" = + paste0(options, collapse = ";"), + "GEOTARGETS_GDAL_RASTER_MDIM" = mdim, + "GEOTARGETS_PROXY" = proxy, + "GEOTARGETS_USE_NCMETA" = ncdf) + ) + ), + storage = storage, + retrieval = retrieval, + cue = cue ) } - diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd index cab7958..78cb94d 100644 --- a/man/tar_stars.Rd +++ b/man/tar_stars.Rd @@ -3,6 +3,7 @@ \name{tar_stars} \alias{tar_stars} \alias{tar_stars_proxy} +\alias{tar_stars_raw} \title{Create a stars \emph{stars} Target} \usage{ tar_stars( @@ -55,6 +56,32 @@ tar_stars_proxy( retrieval = targets::tar_option_get("retrieval"), cue = targets::tar_option_get("cue") ) + +tar_stars_raw( + name, + command, + pattern = NULL, + proxy, + mdim = FALSE, + ncdf = FALSE, + driver = geotargets_option_get("gdal.raster.driver"), + options = geotargets_option_get("gdal.raster.creation.options"), + ..., + tidy_eval = targets::tar_option_get("tidy_eval"), + packages = targets::tar_option_get("packages"), + 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") +) } \arguments{ \item{name}{Symbol, name of the target. A target diff --git a/tests/testthat/test-tar-stars.R b/tests/testthat/test-tar-stars.R index 9cf59d6..266d58f 100644 --- a/tests/testthat/test-tar-stars.R +++ b/tests/testthat/test-tar-stars.R @@ -3,7 +3,7 @@ skip_if_not_installed("stars") targets::tar_test("tar_stars() works", { - geotargets::geotargets_option_set("gdal.raster.creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) + geotargets::geotargets_option_set(gdal_raster_creation_options = c("COMPRESS=DEFLATE", "TFW=YES")) targets::tar_script({ list(geotargets::tar_stars( test_stars, @@ -19,11 +19,11 @@ targets::tar_test("tar_stars() works", { }) targets::tar_test("tar_stars_proxy() works", { - geotargets::geotargets_option_set("gdal.raster.creation_options", c("COMPRESS=DEFLATE", "TFW=YES")) + geotargets::geotargets_option_set(gdal_raster_creation_options = c("COMPRESS=DEFLATE", "TFW=YES")) targets::tar_script({ list(geotargets::tar_stars_proxy( test_stars_proxy, - stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars"), proxy = TRUE) + stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars")) )) }) targets::tar_make() @@ -32,13 +32,12 @@ targets::tar_test("tar_stars_proxy() works", { expect_snapshot( x ) - geotargets::geotargets_option_set("stars.proxy", FALSE) # go back to default }) targets::tar_test("tar_stars(mdim=TRUE) works", { targets::tar_script({ - geotargets::geotargets_option_set("gdal.raster.driver", "netCDF") + geotargets::geotargets_option_set(gdal_raster_driver = "netCDF") list(geotargets::tar_stars(test_stars_mdim, { set.seed(135) m <- matrix(runif(10), 2, 5) @@ -48,7 +47,7 @@ targets::tar_test("tar_stars(mdim=TRUE) works", { s <- stars::st_as_stars(list(Precipitation = m)) |> stars::st_set_dimensions(1, values = pts) |> stars::st_set_dimensions(2, values = times) - }, driver = "netCDF", mdim = TRUE)) + }, mdim = TRUE)) }) targets::tar_make() From 4a062b985799e82b6a36f03574c7e13cd10db431 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Thu, 2 May 2024 20:29:53 -0700 Subject: [PATCH 14/20] tar_stars: more cleanup after merge --- DESCRIPTION | 3 ++- NAMESPACE | 1 - R/tar-stars.R | 3 --- man/tar_stars.Rd | 27 --------------------------- 4 files changed, 2 insertions(+), 32 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 86d19e6..d35a899 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,10 +36,11 @@ Imports: rlang, cli Suggests: + crew, + terra, sf, stars, ncmeta, - terra, testthat (>= 3.0.0), withr Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index ee16a36..9975293 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,7 +4,6 @@ export(geotargets_option_get) export(geotargets_option_set) export(tar_stars) export(tar_stars_proxy) -export(tar_stars_raw) export(tar_terra_rast) export(tar_terra_sprc) export(tar_terra_vect) diff --git a/R/tar-stars.R b/R/tar-stars.R index dd305be..27a3fce 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -206,19 +206,16 @@ tar_stars_raw <- function(name, ## TODO: it appears envvar custom resources do not work in read function? READ_FUN <- stars::read_stars # mdim <- as.logical(Sys.getenv("GEOTARGETS_GDAL_RASTER_MDIM", unset = FALSE)) - print(mdim) if (mdim) { READ_FUN <- stars::read_mdim } # ncdf <- as.logical(Sys.getenv("GEOTARGETS_USE_NCMETA", unset = FALSE)) - print(ncdf) if (ncdf && requireNamespace("ncmeta")) { READ_FUN <- stars::read_ncdf } # proxy <- as.logical(Sys.getenv("GEOTARGETS_PROXY", unset = FALSE)) - print(proxy) READ_FUN(path, proxy = proxy) }, list(ncdf = ncdf, mdim = mdim, proxy = proxy))) diff --git a/man/tar_stars.Rd b/man/tar_stars.Rd index 78cb94d..cab7958 100644 --- a/man/tar_stars.Rd +++ b/man/tar_stars.Rd @@ -3,7 +3,6 @@ \name{tar_stars} \alias{tar_stars} \alias{tar_stars_proxy} -\alias{tar_stars_raw} \title{Create a stars \emph{stars} Target} \usage{ tar_stars( @@ -56,32 +55,6 @@ tar_stars_proxy( retrieval = targets::tar_option_get("retrieval"), cue = targets::tar_option_get("cue") ) - -tar_stars_raw( - name, - command, - pattern = NULL, - proxy, - mdim = FALSE, - ncdf = FALSE, - driver = geotargets_option_get("gdal.raster.driver"), - options = geotargets_option_get("gdal.raster.creation.options"), - ..., - tidy_eval = targets::tar_option_get("tidy_eval"), - packages = targets::tar_option_get("packages"), - 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") -) } \arguments{ \item{name}{Symbol, name of the target. A target From eee3fac4ee702f953c1d12df8a3908c585681d09 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Thu, 2 May 2024 20:52:44 -0700 Subject: [PATCH 15/20] update NAMESPACE --- NAMESPACE | 3 --- R/geotargets-package.R | 2 +- R/tar-stars.R | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 9975293..503044a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,7 +8,4 @@ export(tar_terra_rast) export(tar_terra_sprc) export(tar_terra_vect) importFrom(rlang,"%||%") -importFrom(rlang,arg_match0) -importFrom(rlang,check_installed) -importFrom(rlang,is_installed) importFrom(utils,globalVariables) diff --git a/R/geotargets-package.R b/R/geotargets-package.R index 0e00ac4..878833d 100644 --- a/R/geotargets-package.R +++ b/R/geotargets-package.R @@ -7,7 +7,7 @@ NULL # clear CRAN checks spotting floating global variables #' @importFrom utils globalVariables -#' @importFrom rlang %||% arg_match0 is_installed check_installed +#' @importFrom rlang %||% utils::globalVariables( c( "packages" diff --git a/R/tar-stars.R b/R/tar-stars.R index 27a3fce..a46b834 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -52,7 +52,7 @@ tar_stars <- function(name, retrieval = targets::tar_option_get("retrieval"), cue = targets::tar_option_get("cue")) { - rlang::check_installed("stars") + check_pkg_installed("stars") name <- targets::tar_deparse_language(substitute(name)) From dbd73432b4bbf72f11cecde3eecac1753d514add Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Thu, 2 May 2024 20:57:53 -0700 Subject: [PATCH 16/20] Update README --- README.Rmd | 76 +++++++++++++++++++++++--------- README.md | 126 +++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 162 insertions(+), 40 deletions(-) diff --git a/README.Rmd b/README.Rmd index ee8145b..04807bd 100644 --- a/README.Rmd +++ b/README.Rmd @@ -24,7 +24,7 @@ knitr::opts_chunk$set( `geotargets` extends targets to work with geospatial data formats, such as rasters and vectors (e.g., shapefiles). -A relatively common gotcha moment when using popular libraries like `terra` with targets is running into erros with read and write. Due to the limitations that come with the underlying C++ implementation in the `terra` library, there are specific ways to write and read these objects. See `?terra` for details. `geotargets` helps handle these write and read steps, so you don't have to worry about them and can use targets as you are used to. +A relatively common gotcha moment when using popular libraries like `terra` with targets is running into errors with read and write. Due to the limitations that come with the underlying C++ implementation in the `terra` library, there are specific ways to write and read these objects. See `?terra` for details. `geotargets` helps handle these write and read steps, so you don't have to worry about them and can use targets as you are used to. In essence, if you've ever come across the error: @@ -55,33 +55,39 @@ install.packages("geotargets", repos = c("https://njtierney.r-universe.dev", "ht # Examples -Below we show three examples of target factories: +Below we show four examples of target factories: - `tar_terra_rast()` - `tar_terra_vect()` - `tar_terra_sprc()` +- `tar_stars()` -You would use these in place of `tar_target()` in your targets pipeline, when you are doing work with terra raster or terra vector data. +You would use these in place of `tar_target()` in your targets pipeline, when you are doing work with objects from the terra or stars packages such as SpatRaster, SpatVector, SpatRasterCollection, stars, or stars_proxy. -It is a bit tricky to implement targets workflows in a README, but if you would like to see and download working examples for yourself, see the repo, [demo-geotargets](https://github.com/njtierney/demo-geotargets). +If you would like to see and download working examples for yourself, see the repo, [demo-geotargets](https://github.com/njtierney/demo-geotargets). ## `tar_terra_rast()`: targets with terra rasters ```{r} #| label: tar-terra-rast -#| eval: false library(targets) + tar_dir({ # tar_dir() runs code from a temporary directory. tar_script({ - library(targets) library(geotargets) + + get_elev <- function() { + terra::rast(system.file("ex", "elev.tif", package = "terra")) + } + list( tar_terra_rast( terra_rast_example, - system.file("ex/elev.tif", package = "terra") |> terra::rast() + get_elev() ) ) }) + tar_make() x <- tar_read(terra_rast_example) x @@ -93,18 +99,16 @@ tar_dir({ # tar_dir() runs code from a temporary directory. ```{r} #| label: tar-terra-vect -#| eval: false tar_dir({ # tar_dir() runs code from a temporary directory. tar_script({ library(geotargets) + lux_area <- function(projection = "EPSG:4326") { - terra::project( - terra::vect(system.file("ex", "lux.shp", - package = "terra" - )), - projection - ) + terra::project(terra::vect(system.file("ex", "lux.shp", + package = "terra")), + projection) } + list( tar_terra_vect( terra_vect_example, @@ -112,6 +116,7 @@ tar_dir({ # tar_dir() runs code from a temporary directory. ) ) }) + tar_make() x <- tar_read(terra_vect_example) x @@ -123,21 +128,23 @@ tar_dir({ # tar_dir() runs code from a temporary directory. ```{r} #| label: tar-terra-sprc -#| eval: false -targets::tar_dir({ # tar_dir() runs code from a temporary directory. - library(geotargets) - targets::tar_script({ +tar_dir({ # tar_dir() runs code from a temporary directory. + tar_script({ + + library(geotargets) + elev_scale <- function(z = 1, projection = "EPSG:4326") { terra::project( terra::rast(system.file("ex", "elev.tif", package = "terra")) * z, projection ) } + list( tar_terra_sprc( raster_elevs, # two rasters, one unaltered, one scaled by factor of 2 and - # reprojected to interrupted good homolosine + # reprojected to interrupted goode homolosine command = terra::sprc(list( elev_scale(1), elev_scale(2, "+proj=igh") @@ -145,11 +152,38 @@ targets::tar_dir({ # tar_dir() runs code from a temporary directory. ) ) }) - targets::tar_make() - x <- targets::tar_read(raster_elevs) + + tar_make() + x <- tar_read(raster_elevs) + x }) ``` + + +## `tar_stars()`: targets with stars objects + +```{r} +#| label: tar-stars +tar_dir({ # tar_dir() runs code from a temporary directory. + tar_script({ + library(geotargets) + + list( + tar_stars( + test_stars, + stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars")) + ) + ) + }) + + tar_make() + x <- tar_read(test_stars) + x +}) +``` + + ## Code of Conduct Please note that the geotargets project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. diff --git a/README.md b/README.md index c916954..eab2ba8 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ coverage](https://codecov.io/gh/njtierney/geotargets/branch/master/graph/badge.s as rasters and vectors (e.g., shapefiles). A relatively common gotcha moment when using popular libraries like -`terra` with targets is running into erros with read and write. Due to +`terra` with targets is running into errors with read and write. Due to the limitations that come with the underlying C++ implementation in the `terra` library, there are specific ways to write and read these objects. See `?terra` for details. `geotargets` helps handle these write @@ -55,17 +55,19 @@ breaking ways. # Examples -Below we show three examples of target factories: +Below we show four examples of target factories: - `tar_terra_rast()` - `tar_terra_vect()` - `tar_terra_sprc()` +- `tar_stars()` You would use these in place of `tar_target()` in your targets pipeline, -when you are doing work with terra raster or terra vector data. +when you are doing work with objects from the terra or stars packages +such as SpatRaster, SpatVector, SpatRasterCollection, stars, or +stars_proxy. -It is a bit tricky to implement targets workflows in a README, but if -you would like to see and download working examples for yourself, see +If you would like to see and download working examples for yourself, see the repo, [demo-geotargets](https://github.com/njtierney/demo-geotargets). @@ -73,21 +75,39 @@ the repo, ``` r library(targets) + tar_dir({ # tar_dir() runs code from a temporary directory. tar_script({ - library(targets) library(geotargets) + + get_elev <- function() { + terra::rast(system.file("ex", "elev.tif", package = "terra")) + } + list( tar_terra_rast( terra_rast_example, - system.file("ex/elev.tif", package = "terra") |> terra::rast() + get_elev() ) ) }) + tar_make() x <- tar_read(terra_rast_example) x }) +#> ▶ dispatched target terra_rast_example +#> ● completed target terra_rast_example [0.007 seconds] +#> ▶ ended pipeline [0.15 seconds] +#> class : SpatRaster +#> dimensions : 90, 95, 1 (nrow, ncol, nlyr) +#> resolution : 0.008333333, 0.008333333 (x, y) +#> extent : 5.741667, 6.533333, 49.44167, 50.19167 (xmin, xmax, ymin, ymax) +#> coord. ref. : lon/lat WGS 84 (EPSG:4326) +#> source : terra_rast_example +#> name : elevation +#> min value : 141 +#> max value : 547 ``` ## `tar_terra_vect()`: targets with terra vectors @@ -96,14 +116,13 @@ tar_dir({ # tar_dir() runs code from a temporary directory. tar_dir({ # tar_dir() runs code from a temporary directory. tar_script({ library(geotargets) + lux_area <- function(projection = "EPSG:4326") { - terra::project( - terra::vect(system.file("ex", "lux.shp", - package = "terra" - )), - projection - ) + terra::project(terra::vect(system.file("ex", "lux.shp", + package = "terra")), + projection) } + list( tar_terra_vect( terra_vect_example, @@ -111,29 +130,47 @@ tar_dir({ # tar_dir() runs code from a temporary directory. ) ) }) + tar_make() x <- tar_read(terra_vect_example) x }) +#> ▶ dispatched target terra_vect_example +#> ● completed target terra_vect_example [0.027 seconds] +#> ▶ ended pipeline [0.127 seconds] +#> class : SpatVector +#> geometry : polygons +#> dimensions : 12, 6 (geometries, attributes) +#> extent : 5.74414, 6.528252, 49.44781, 50.18162 (xmin, xmax, ymin, ymax) +#> source : terra_vect_example +#> coord. ref. : lon/lat WGS 84 (EPSG:4326) +#> names : ID_1 NAME_1 ID_2 NAME_2 AREA POP +#> type : +#> values : 1 Diekirch 1 Clervaux 312 18081 +#> 1 Diekirch 2 Diekirch 218 32543 +#> 1 Diekirch 3 Redange 259 18664 ``` ## `tar_terra_sprc()`: targets with terra raster collections ``` r -targets::tar_dir({ # tar_dir() runs code from a temporary directory. - library(geotargets) - targets::tar_script({ +tar_dir({ # tar_dir() runs code from a temporary directory. + tar_script({ + + library(geotargets) + elev_scale <- function(z = 1, projection = "EPSG:4326") { terra::project( terra::rast(system.file("ex", "elev.tif", package = "terra")) * z, projection ) } + list( tar_terra_sprc( raster_elevs, # two rasters, one unaltered, one scaled by factor of 2 and - # reprojected to interrupted good homolosine + # reprojected to interrupted goode homolosine command = terra::sprc(list( elev_scale(1), elev_scale(2, "+proj=igh") @@ -141,9 +178,60 @@ targets::tar_dir({ # tar_dir() runs code from a temporary directory. ) ) }) - targets::tar_make() - x <- targets::tar_read(raster_elevs) + + tar_make() + x <- tar_read(raster_elevs) + x +}) +#> ▶ dispatched target raster_elevs +#> ● completed target raster_elevs [0.14 seconds] +#> ▶ ended pipeline [0.29 seconds] +#> Warning message: +#> [rast] skipped sub-datasets (see 'describe(sds=TRUE)'): +#> /tmp/RtmpZRJR3w/targets_788293366c7ea/_targets/scratch/raster_elevs +#> class : SpatRasterCollection +#> length : 2 +#> nrow : 90, 115 +#> ncol : 95, 114 +#> nlyr : 1, 1 +#> extent : 5.741667, 1558890, 49.44167, 5556741 (xmin, xmax, ymin, ymax) +#> crs (first) : lon/lat WGS 84 (EPSG:4326) +#> names : raster_elevs, raster_elevs +``` + +## `tar_stars()`: targets with stars objects + +``` r +tar_dir({ # tar_dir() runs code from a temporary directory. + tar_script({ + library(geotargets) + + list( + tar_stars( + test_stars, + stars::read_stars(system.file("tif", "olinda_dem_utm25s.tif", package = "stars")) + ) + ) + }) + + tar_make() + x <- tar_read(test_stars) + x }) +#> ▶ dispatched target test_stars +#> ● completed target test_stars [0.033 seconds] +#> ▶ ended pipeline [0.123 seconds] +#> Warning message: +#> In CPL_write_gdal(mat, file, driver, options, type, dims, from, : +#> GDAL Message 6: creation option '' is not formatted with the key=value format +#> stars object with 2 dimensions and 1 attribute +#> attribute(s): +#> Min. 1st Qu. Median Mean 3rd Qu. Max. +#> test_stars -1 6 12 21.66521 35 88 +#> dimension(s): +#> from to offset delta refsys point x/y +#> x 1 111 288776 89.99 UTM Zone 25, Southern Hem... FALSE [x] +#> y 1 111 9120761 -89.99 UTM Zone 25, Southern Hem... FALSE [y] ``` ## Code of Conduct From 946e06bb7bf1a3be8ca3c3226741f3c748b8067a Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Sat, 11 May 2024 07:52:32 -0700 Subject: [PATCH 17/20] Update R/tar-stars.R Co-authored-by: Eric R. Scott --- R/tar-stars.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/tar-stars.R b/R/tar-stars.R index a46b834..0a19087 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -265,7 +265,7 @@ tar_stars_raw <- function(name, garbage_collection = garbage_collection, deployment = deployment, priority = priority, - resources = targets::tar_resources( + resources = utils::modifyList(targets::tar_resources( custom_format = targets::tar_resources_custom_format( #these envvars are used in read and write functions of format envvars = c("GEOTARGETS_GDAL_RASTER_DRIVER" = driver, @@ -275,7 +275,7 @@ tar_stars_raw <- function(name, "GEOTARGETS_PROXY" = proxy, "GEOTARGETS_USE_NCMETA" = ncdf) ) - ), + ), resources) storage = storage, retrieval = retrieval, cue = cue From a757a456a9a5c605aa39f173e92afb01f9800fe1 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Sat, 11 May 2024 07:58:45 -0700 Subject: [PATCH 18/20] Update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index d88cc57..1511d4c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,5 +2,6 @@ * Created `tar_terra_rast()` and `tar_terra_vect()` for targets that create `SpatRaster` and `SpatVector` objects, respectively * Created `tar_terra_sprc()` that creates a `SpatRasterCollection` object. +* Created `tar_stars()` and `tar_stars_proxy()` that create `stars` and `stars_proxy` objects, respectively. * `geotargets_options_get()` and `geotargets_options_set()` can be used to set and get options specific to `geotargets`. * `geotargets` now requires `targets` version 1.7.0 or higher From 2f269204089a52ffdfef075eb83126225959cb19 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Sat, 11 May 2024 08:00:00 -0700 Subject: [PATCH 19/20] comma --- R/tar-stars.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/tar-stars.R b/R/tar-stars.R index 0a19087..ad89856 100644 --- a/R/tar-stars.R +++ b/R/tar-stars.R @@ -275,7 +275,7 @@ tar_stars_raw <- function(name, "GEOTARGETS_PROXY" = proxy, "GEOTARGETS_USE_NCMETA" = ncdf) ) - ), resources) + ), resources), storage = storage, retrieval = retrieval, cue = cue From bc2208666612b84f86405ba4c37206353634a86e Mon Sep 17 00:00:00 2001 From: Eric Scott Date: Wed, 29 May 2024 10:11:27 -0700 Subject: [PATCH 20/20] document() --- NAMESPACE | 1 + 1 file changed, 1 insertion(+) diff --git a/NAMESPACE b/NAMESPACE index 503044a..807ca5c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,4 +8,5 @@ export(tar_terra_rast) export(tar_terra_sprc) export(tar_terra_vect) importFrom(rlang,"%||%") +importFrom(rlang,arg_match0) importFrom(utils,globalVariables)