A SpatVoxel is a terra::SpatRaster in which depth is the layer index
and the cell values are the variable (temperature, oxygen, presence, ...).
Layer names follow the {variable}_depth={value} convention and must be
distinct and ordered shallow to deep. The depth axis is grid-wide: every
cell is sampled at the same set of standard depths.
Details
A voxel may have interior gaps — a cell can be NA at one depth and non-NA at the depths above and below it.
Examples
# Two cells sampled at three standard depths. Build one with as_voxel(),
# which names the layers for you and sorts them shallow to deep.
r <- terra::rast(nrows = 1, ncols = 2, xmin = 0, xmax = 2, ymin = 0, ymax = 1,
nlyrs = 3)
terra::values(r) <- cbind(c(12, 11), c(9, NA), c(6, 5))
v <- as_voxel(r, depths = c(0, 100, 200), varname = "temp")
names(v) # depth lives in the layer name
#> [1] "temp_depth=0" "temp_depth=100" "temp_depth=200"
terra::values(v) # ...and the variable in the cell values
#> temp_depth=0 temp_depth=100 temp_depth=200
#> [1,] 12 9 6
#> [2,] 11 NA 5
# Note cell 2: NA at 100 m, but with values above and below it. A voxel can
# hold that interior gap; a SpatEnvelope cannot.
# It is an ordinary SpatRaster underneath, so terra operations work on it
# unchanged. Re-wrapping with as_voxel() is cheap either way, since the
# constructor is idempotent.
methods::is(v, "SpatRaster")
#> [1] TRUE
terra::nlyr(terra::crop(v, terra::ext(0, 1, 0, 1)))
#> [1] 3
identical(names(as_voxel(v)), names(v))
#> [1] TRUE
# Validity is enforced on construction: every layer name must carry its
# depth, and the layers must run shallow to deep.
bad <- r
names(bad) <- c("a", "b", "c")
try(methods::new("SpatVoxel", bad))
#> Error in validObject(.Object) :
#> invalid class “SpatVoxel” object: every layer name must follow {variable}_depth={value}