SophiaL
SophiaL

Reputation: 71

Write RasterStack and preserve metadata in R

I would like to write a RasterStack object and preserve names and metadata of the individual layers. How to preserve names is explained here. Is there a way to preserve metadata of individual layers when writing a RasterStack object? Here is replicable code:

# load library
library(raster)

# create example rasters
ras_1 <- raster(nrows=180, ncols=360, xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=, vals=1)
ras_2 <- raster(nrows=180, ncols=360, xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=, vals=2)
ras_3 <- raster(nrows=180, ncols=360, xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=, vals=3)

# assign names
names(ras_1) <- "raster_A"
names(ras_2) <- "raster_B"
names(ras_3) <- "raster_C"

# assign metadata
metadata(ras_1) <- list("metadata_raster_A")
metadata(ras_2) <- list("metadata_raster_B")
metadata(ras_3) <- list("metadata_raster_C")

# check
ras_1
ras_2
ras_3
metadata(ras_1)
metadata(ras_2)
metadata(ras_3)

# create and check stack
raster_stack <- stack(ras_1,
                      ras_2,
                      ras_3)
raster_stack
raster_stack[[1]]
metadata(raster_stack[[1]])

# write raster stack to disk
setwd("~")

# load library
library(terra)
# create rast object
raster_stack_terr <- rast(raster_stack)
# write raster stack
terra::writeRaster(raster_stack_terr, "raster_stack_terr_test.tif")

# load and check raster stack
raster_stack_check <- stack("raster_stack_terr_test.tif")
raster_stack_check
raster_stack_check[[1]]
names(raster_stack_check[[1]])
metadata(raster_stack_check[[1]])

Use terra to preseve names according to the 3rd answer from here.

When opening the RasterStack from disk, the metadata is not preserved. See console output:

> metadata(raster_stack_check[[1]])
list()

How to preserve metadata of individual layers when writing and re-loading a RasterStack object? Thanks!

Upvotes: 1

Views: 735

Answers (1)

dimfalk
dimfalk

Reputation: 1413

It does not seem like {terra} offers an equivalent to raster::metadata(). However, from my perspective, the use cases would be limited here, because you would only be able to store structured information in corresponding format-specific tags (at least, this is my understanding) when writing to disk.

TIFF files (c.f. here) seem to offer the following tags:

TIFFTAG_DOCUMENTNAME
TIFFTAG_IMAGEDESCRIPTION
TIFFTAG_SOFTWARE
TIFFTAG_DATETIME
TIFFTAG_ARTIST
TIFFTAG_HOSTCOMPUTER
TIFFTAG_COPYRIGHT
TIFFTAG_XRESOLUTION
TIFFTAG_YRESOLUTION
TIFFTAG_RESOLUTIONUNIT

ESRI-Grids, on the other hand, do not offer any possibilities to store metadata except for the known header and maybe the filename as far as I know.

If you only wanted to store certain metadata with your raster object, you might as well make use of attr(r, "meta") <- "foobar". However, I don't see how this (random) information can be stored in specific formats and restored afterwards.

You already noticed names() when using {terra}, but there is also time() to be mentioned. Maybe this already suits your needs, since you did not specify what exactly you intend to store.

# set up a raster stack with three layers
library(terra)
#> terra 1.6.17

# create raster
r <- rast(nrows = 10, ncols = 10)
values(r) <- rnorm(100)

# set metadata
names(r) <- "foo"
time(r) <- as.Date("2000-01-01")
attr(r, "meta") <- "bar"

# inspect
r
#> class       : SpatRaster 
#> dimensions  : 10, 10, 1  (nrow, ncol, nlyr)
#> resolution  : 36, 18  (x, y)
#> extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 
#> source      : memory 
#> name        :       foo 
#> min value   : -2.503790 
#> max value   :  1.998731 
#> time (days) : 2000-01-01

# write to disk
writeRaster(r, "sample.tif", overwrite = TRUE)

# read from disk
r2 <- rast("sample.tif")
r2
#> class       : SpatRaster 
#> dimensions  : 10, 10, 1  (nrow, ncol, nlyr)
#> resolution  : 36, 18  (x, y)
#> extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : sample.tif 
#> name        :       foo 
#> min value   : -2.503790 
#> max value   :  1.998731 
#> time (days) : 2000-01-01

# try to access attributes
attr(r2, "meta")
#> NULL

As expected, data stored as attribute has been lost whereas information provided via names() and time() was sustained.

Upvotes: 3

Related Questions