--- title: "Using `terra` with `geotargets`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Using `terra` with `geotargets`} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} # With the root.dir option below, # this vignette runs the R code in a temporary directory # so new files are written to temporary storage # and not the user's file space. knitr::opts_knit$set(root.dir = fs::dir_create(tempfile())) knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) if (identical(Sys.getenv("NOT_CRAN", unset = "false"), "false")) { knitr::opts_chunk$set(eval = FALSE) } library(targets) library(geotargets) ``` ```{r setup} library(geotargets) ``` The `geotargets` package extends `targets` to work with geospatial data formats, such as rasters and vectors (e.g., shape files). In particular, `geotargets` aims to support use of the `terra` package, which tend to cause problems if used in targets created with `tar_target()` . If you are new to `targets`, you should start by looking at the [targets manual](https://books.ropensci.org/targets/) to get a handle on the basics. The design of `geotargets` is to specify target factories like so: `tar__`. In this vignette we will demonstrate the use of the `terra` R package, and we will demonstrate how to build raster (`rast`), vector (`vect`), raster collection (`sprc`), and raster dataset (`sds`) targets with: - `tar_terra_rast()` - `tar_terra_vect()` - `tar_terra_sprc()` - `tar_terra_sds()` ## `tar_terra_rast()`: targets with `terra` rasters ```{r} #| label: tar_script_rast #| eval: true #| echo: false targets::tar_script({ # contents of _targets.R: library(targets) library(geotargets) tar_option_set(packages = "terra") geotargets_option_set(gdal_raster_driver = "COG") list( tar_target( tif_file, system.file("ex/elev.tif", package = "terra"), format = "file" ), tar_terra_rast( r, { rast <- rast(tif_file) units(rast) <- "m" rast } ), tar_terra_rast( r_agg, aggregate(r, 2) ) ) }) ``` ```{r} #| label: _targets-rast #| eval: false #| echo: true # contents of _targets.R: library(targets) library(geotargets) tar_option_set(packages = "terra") geotargets_option_set(gdal_raster_driver = "COG") list( tar_target( tif_file, system.file("ex/elev.tif", package = "terra"), format = "file" ), tar_terra_rast( r, { rast <- rast(tif_file) units(rast) <- "m" rast } ), tar_terra_rast( r_agg, aggregate(r, 2) ) ) ``` Above is a basic example showing the use of `tar_terra_rast()` in a targets pipeline. The command for `tar_terra_rast()` can be any function that returns a `SpatRaster` object. In this example, we’ve set the output to a cloud optimized geotiff ("COG"), but any GDAL driver that works with `terra::writeRaster()` should also work here. You can also set this option on a target-by-target basis with the `filetype` argument to `tar_terra_rast()`. Running the pipeline: ```{r} #| label: make-rast #| eval: true #| echo: true tar_make() tar_read(r) tar_read(r_agg) ``` ### Raster metadata You may have noticed that the units for the `r` target above have gone missing. This is due to limitations of `terra` and `targets`---`terra` saves some metadata in "sidecar" aux.json files and `targets` enforces a strict one file per target rule. You can get around this by setting `preserve_metadata = "zip"` in `tar_terra_rast()` to save the output files, including the metadata, as a minimally compressed zip archive. You can also set this for all raster targets with `geotargets_option_set(terra_preserve_metadata = "zip")`. Note: there are likely performance costs associated with this option.\ As an alternative, you can encode information in the layer names by setting `names(r) <-` which are retained even with the default `preserve_metadata = "drop"`. ```{r} #| label: tar_script_rast_metadata #| eval: true #| echo: false targets::tar_script({ # contents of _targets.R: library(targets) library(geotargets) tar_option_set(packages = "terra") geotargets_option_set(gdal_raster_driver = "COG") list( tar_target( tif_file, system.file("ex/elev.tif", package = "terra"), format = "file" ), tar_terra_rast( r, { rast <- rast(tif_file) units(rast) <- "m" rast }, preserve_metadata = "zip" ) ) }) ``` ```{r} #| label: _targets_rast_metadata #| eval: false #| echo: true # contents of _targets.R: library(targets) library(geotargets) tar_option_set(packages = "terra") geotargets_option_set(gdal_raster_driver = "COG") list( tar_target( tif_file, system.file("ex/elev.tif", package = "terra"), format = "file" ), tar_terra_rast( r, { rast <- rast(tif_file) units(rast) <- "m" rast }, preserve_metadata = "zip" ) ) ``` ```{r} #| label: make_rast_metadata #| eval: true #| echo: true tar_make() terra::units(tar_read(r)) ``` ## `tar_terra_vect()`: targets with `terra` vectors For `terra` `SpatVector` objects, use `tar_terra_vect()` in the pipeline. You can set vector specific options with `geotargets_option_set()` or with the `filetype` and `gdal` arguments to individual `tar_terra_vect()` calls. ```{r} #| label: tar_script_vect #| eval: true #| echo: false targets::tar_script({ # contents of _targets.R: library(targets) library(geotargets) geotargets_option_set(gdal_vector_driver = "GeoJSON") list( tar_target( vect_file, system.file("ex", "lux.shp", package = "terra"), format = "file" ), tar_terra_vect( v, terra::vect(vect_file) ), tar_terra_vect( v_proj, terra::project(v, "EPSG:2196") ) ) }) ``` ```{r} #| label: _targets_vect #| eval: false #| echo: true # contents of _targets.R: library(targets) library(geotargets) geotargets_option_set(gdal_vector_driver = "GeoJSON") list( tar_target( vect_file, system.file("ex", "lux.shp", package = "terra"), format = "file" ), tar_terra_vect( v, terra::vect(vect_file) ), tar_terra_vect( v_proj, terra::project(v, "EPSG:2196") ) ) ``` ```{r} #| label: make_vect #| eval: true #| echo: true tar_make() tar_read(v) tar_read(v_proj) ``` ## `tar_terra_sprc()`: targets with `terra` raster collections Targets that produce a `SpatRasterCollection` can be created with `tar_terra_sprc()`. The various rasters in the collection are saved as subdatasets to adhere to `targets` one file per target rule. ```{r} #| label: tar_script_sprc #| eval: true #| echo: false targets::tar_script({ # contents of _targets.R: library(targets) library(geotargets) elev_scale <- function(raster, z = 1, projection = "EPSG:4326") { terra::project( raster * z, projection ) } tar_option_set(packages = "terra") geotargets_option_set(gdal_raster_driver = "GTiff") list( tar_target( elev_file, system.file("ex", "elev.tif", package = "terra"), format = "file" ), tar_target( r, rast(elev_file) ), tar_terra_sprc( raster_elevs, # two rasters, one unaltered, one scaled by factor of 2 and # reprojected to interrupted good homolosine terra::sprc(list( elev_scale(r, 1), elev_scale(r, 2, "+proj=igh") )) ) ) }) ``` ```{r} #| label: _targets_sprc #| eval: false #| echo: true # contents of _targets.R: library(targets) library(geotargets) elev_scale <- function(raster, z = 1, projection = "EPSG:4326") { terra::project( raster * z, projection ) } tar_option_set(packages = "terra") geotargets_option_set(gdal_raster_driver = "GTiff") list( tar_target( elev_file, system.file("ex", "elev.tif", package = "terra"), format = "file" ), tar_target( r, rast(elev_file) ), tar_terra_sprc( raster_elevs, # two rasters, one unaltered, one scaled by factor of 2 and # reprojected to interrupted Goode homolosine terra::sprc(list( elev_scale(r, 1), elev_scale(r, 2, "+proj=igh") )) ) ) ``` ```{r} #| label: make_sprc #| eval: true #| echo: true tar_make() tar_read(raster_elevs) ``` ## `tar_terra_sds()`: targets with `terra` raster datasets A `terra` `SpatRasterDataset` is very similar to a `SpatRasterCollection` except that all sub-datasets must have the same projection and extent ```{r} #| label: tar_script_sds #| eval: true #| echo: false targets::tar_script({ # contents of _targets.R: library(targets) library(geotargets) tar_option_set(packages = "terra") list( tar_target( logo_file, system.file("ex/logo.tif", package="terra"), format = "file" ), tar_terra_sds( raster_dataset, { x <- sds(rast(logo_file), rast(logo_file)/2) names(x) <- c("first", "second") x } ) ) }) ``` ```{r} #| label: _targets_sds #| eval: false #| echo: true # contents of _targets.R: library(targets) library(geotargets) tar_option_set(packages = "terra") list( tar_target( logo_file, system.file("ex/logo.tif", package="terra"), format = "file" ), tar_terra_sds( raster_dataset, { x <- sds(rast(logo_file), rast(logo_file)/2) names(x) <- c("first", "second") x } ) ) ``` ```{r} #| label: make_sds #| echo: true #| eval: true tar_make() tar_read(raster_dataset) ```