Skip to contents

Some functions return a list of terra::SpatRaster objects rather than a single raster. The geotargets package can serialize individual SpatRaster objects, but not a list that contains several of them. tar_terra_nested() fills this gap by recursively finding and serializing every spatial object inside an arbitrary R structure.

A natural example is bssdm::mess(), which calculates Multivariate Environmental Similarity Surfaces. With full = TRUE it returns a MessResult list of four SpatRaster layers: mess, mess_by_variable, mod, and mos.

This vignette keeps things lightweight: rather than downloading global climate data via geodata, it builds a small synthetic three-variable raster so the example runs in a fraction of a second and requires no network access.

library(targets)
library(bssdm)

tar_dir({

  # tar_dir() runs the pipeline in a temporary directory.

  tar_script({

    library(targets)
    library(geotargets)
    library(terra)
    library(bssdm)
    library(targets.utils)

    # Build a small synthetic climate raster and compute MESS against a
    # sample of reference cells. Everything is generated in-memory, so no
    # data is downloaded.
    make_mess <- function() {

      set.seed(4172)

      r <- rast(
        nrows = 20, ncols = 20, nlyrs = 3,
        xmin = 0, xmax = 10, ymin = 0, ymax = 10
      )
      names(r) <- c("bio1", "bio12", "bio5")
      values(r) <- cbind(
        runif(ncell(r), 5, 25),      # mean temperature
        runif(ncell(r), 200, 2000),  # annual precipitation
        runif(ncell(r), 20, 40)      # max temperature
      )

      # Reference values drawn from a random sample of cells
      ref <- spatSample(
        r, size = 30, method = "random",
        as.df = TRUE, na.rm = TRUE
      )

      # mess() returns a MessResult: a list of several SpatRasters
      mess(r, ref, full = TRUE)
    }

    list(
      # tar_terra_nested() handles the list of rasters that tar_target()
      # alone could not serialize.
      tar_terra_nested(
        mess_result,
        make_mess()
      )
    )
  })

  tar_make()

  # Read the target back: the MessResult list is reconstructed, with each
  # SpatRaster restored from its own file on disk.
  x <- tar_read(mess_result)
  print(class(x))
  print(names(x))
  x$mess
  
  # Plot the MESS result
  plot(x)

})
#> terra 1.9.34
#> + mess_result dispatched
#>  mess_result completed [159ms, 4.32 kB]
#>  ended pipeline [380ms, 1 completed, 0 skipped]
#> [1] "MessResult" "list"      
#> [1] "mess"             "mess_by_variable" "mod"              "mos"
#> [plot mode] fit legend/component: Some legend items or map compoments do not
#> fit well, and are therefore rescaled.
#>  Set the tmap option `component.autoscale = FALSE` to disable rescaling.

The reconstructed object retains its original MessResult class and all four SpatRaster layers, each transparently restored from disk. The same approach works for any function that returns spatial objects nested inside lists, data frames, or other R structures.