Title: | Helper Tools in Creating or Handling GeoPackage Files |
---|---|
Description: | The aim of this R package is to provide helper tools in creating or handling GeoPackage files, in order to complement other R spatial packages or GDAL. The package has no dependencies on other spatial packages and is not tied to any particular package by design. |
Authors: | Floris Vanderhaeghe [aut, cre] , Research Institute for Nature and Forest [cph], Eli Pousson [ctb] |
Maintainer: | Floris Vanderhaeghe <[email protected]> |
License: | GPL (>= 3) |
Version: | 0.0.0.900 |
Built: | 2024-11-04 05:34:43 UTC |
Source: | https://github.com/r-spatial/rgeopackage |
Overwrites all timestamps (column last_change
) of the
gpkg_contents
table in an existing GeoPackage file.
If the optional table gpkg_metadata_reference
is present, does the
same with its timestamp
column.
As such the function assists in making a binary-reproducible GeoPackage file.
amend_timestamp(dsn, timestamp = Sys.time(), verbose = TRUE)
amend_timestamp(dsn, timestamp = Sys.time(), verbose = TRUE)
dsn |
the path to the GeoPackage file (*.gpkg) |
timestamp |
a |
verbose |
Logical. For each relevant table, prints a message with the number of affected rows. |
Internally the timestamp is converted to a specific ISO 8601 format that is required by the GeoPackage standard.
NULL
is returned invisibly.
Directly editing a GeoPackage is not advised; whenever possible use
preset_timestamp()
since it goes via GDAL.
However amend_timestamp()
is especially useful when a
GeoPackage file also contains a timestamp in the optional table
gpkg_metadata_reference
, as GDAL does not control that timestamp
as of writing (for GDAL 3.1.3).
See a corresponding issue
in the GDAL source repository.
Floris Vanderhaeghe, https://github.com/florisvdh
Other functions to control the GeoPackage timestamp(s):
preset_timestamp
,
sf::st_write
library(sf) library(openssl) md5sum <- function(x) paste(md5(file(x))) # Using existing geopackage with vector layer: filepath <- system.file("gpkg/b_pump.gpkg", package = "sf") (md5_original <- md5sum(filepath)) sf_layer <- read_sf(system.file("gpkg/b_pump.gpkg", package = "sf")) # A rewrite changes the checksum: filepath_notimeset <- file.path(tempdir(), "b_pump_notimeset.gpkg") # write 1: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset1 <- md5sum(filepath_notimeset)) # write 2: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset2 <- md5sum(filepath_notimeset)) # compare: md5_notimeset1 == md5_notimeset2 # Setting a fixed date filepath_timeset <- file.path(tempdir(), "b_pump_timeset.gpkg") (fixed_date <- as.Date("2020-12-25")) # write 1 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_date) md5_timeset1 <- md5sum(filepath_timeset) # write 2 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_date) md5_timeset2 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset1, md5_timeset2) # Setting a fixed time (fixed_time <- as.POSIXct("2020-12-25 12:00:00", tz = "CET")) # write 3 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_time) md5_timeset3 <- md5sum(filepath_timeset) # write 4 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_time) md5_timeset4 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset3, md5_timeset4) # Also works for GPKG 2D gridded coverage (with stars): library(stars) library(dplyr) filepath_stars <- file.path(tempdir(), "stars_2d.gpkg") stars_2d <- system.file("tif/L7_ETMs.tif", package = "stars") %>% read_stars() %>% slice(band, 1) # write 1: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") amend_timestamp(filepath_stars, fixed_time) md5_stars1 <- md5sum(filepath_stars) # write 2: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") amend_timestamp(filepath_stars, fixed_time) md5_stars2 <- md5sum(filepath_stars) # compare: all.equal(md5_stars1, md5_stars2)
library(sf) library(openssl) md5sum <- function(x) paste(md5(file(x))) # Using existing geopackage with vector layer: filepath <- system.file("gpkg/b_pump.gpkg", package = "sf") (md5_original <- md5sum(filepath)) sf_layer <- read_sf(system.file("gpkg/b_pump.gpkg", package = "sf")) # A rewrite changes the checksum: filepath_notimeset <- file.path(tempdir(), "b_pump_notimeset.gpkg") # write 1: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset1 <- md5sum(filepath_notimeset)) # write 2: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset2 <- md5sum(filepath_notimeset)) # compare: md5_notimeset1 == md5_notimeset2 # Setting a fixed date filepath_timeset <- file.path(tempdir(), "b_pump_timeset.gpkg") (fixed_date <- as.Date("2020-12-25")) # write 1 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_date) md5_timeset1 <- md5sum(filepath_timeset) # write 2 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_date) md5_timeset2 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset1, md5_timeset2) # Setting a fixed time (fixed_time <- as.POSIXct("2020-12-25 12:00:00", tz = "CET")) # write 3 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_time) md5_timeset3 <- md5sum(filepath_timeset) # write 4 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) amend_timestamp(filepath_timeset, fixed_time) md5_timeset4 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset3, md5_timeset4) # Also works for GPKG 2D gridded coverage (with stars): library(stars) library(dplyr) filepath_stars <- file.path(tempdir(), "stars_2d.gpkg") stars_2d <- system.file("tif/L7_ETMs.tif", package = "stars") %>% read_stars() %>% slice(band, 1) # write 1: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") amend_timestamp(filepath_stars, fixed_time) md5_stars1 <- md5sum(filepath_stars) # write 2: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") amend_timestamp(filepath_stars, fixed_time) md5_stars2 <- md5sum(filepath_stars) # compare: all.equal(md5_stars1, md5_stars2)
Presets the timestamp for usage by GDAL by setting the environment variable
OGR_CURRENT_DATE
.
After this, newly written GeoPackage files
created by the GDAL vector or raster driver (e.g. through
sf::st_write()
or stars::write_stars()
)
will carry this timestamp.
As such preset_timestamp()
assists in making a binary-reproducible
GeoPackage file.
unset_timestamp()
removes OGR_CURRENT_DATE
from the
environment.
preset_timestamp(timestamp) unset_timestamp()
preset_timestamp(timestamp) unset_timestamp()
timestamp |
a |
The function converts the timestamp to a very specific ISO 8601 format
that is required by the GeoPackage standard, including conversion to UTC.
Cf. Requirement 15 in
version 1.3.
GDAL uses the timestamp to set the last_change
column of the
gpkg_contents
table in newly written GeoPackage files.
The timestamp set by preset_timestamp()
is adopted by GDAL during
the entire session, unless unset_timestamp()
is called.
Previous value of environment variable OGR_CURRENT_DATE
is returned
invisibly.
Floris Vanderhaeghe, https://github.com/florisvdh
Other functions to control the GeoPackage timestamp(s):
amend_timestamp
,
sf::st_write
library(sf) library(openssl) md5sum <- function(x) paste(md5(file(x))) # Using existing geopackage with vector layer: filepath <- system.file("gpkg/b_pump.gpkg", package = "sf") (md5_original <- md5sum(filepath)) sf_layer <- read_sf(system.file("gpkg/b_pump.gpkg", package = "sf")) # A rewrite changes the checksum: filepath_notimeset <- file.path(tempdir(), "b_pump_notimeset.gpkg") # write 1: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset1 <- md5sum(filepath_notimeset)) # write 2: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset2 <- md5sum(filepath_notimeset)) # compare: md5_notimeset1 == md5_notimeset2 # Setting a fixed date filepath_timeset <- file.path(tempdir(), "b_pump_timeset.gpkg") (fixed_date <- as.Date("2020-12-25")) preset_timestamp(fixed_date) # write 1 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset1 <- md5sum(filepath_timeset) # write 2 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset2 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset1, md5_timeset2) # Setting a fixed time (fixed_time <- as.POSIXct("2020-12-25 12:00:00", tz = "CET")) preset_timestamp(fixed_time) # write 3 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset3 <- md5sum(filepath_timeset) # write 4 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset4 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset3, md5_timeset4) # Also works for GPKG 2D gridded coverage (with stars): library(stars) library(dplyr) filepath_stars <- file.path(tempdir(), "stars_2d.gpkg") (fixed_time <- as.POSIXct("2010-02-14 12:00:00", tz = "CET")) preset_timestamp(fixed_time) stars_2d <- system.file("tif/L7_ETMs.tif", package = "stars") %>% read_stars() %>% slice(band, 1) # write 1: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") md5_stars1 <- md5sum(filepath_stars) # write 2: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") md5_stars2 <- md5sum(filepath_stars) # compare: all.equal(md5_stars1, md5_stars2)
library(sf) library(openssl) md5sum <- function(x) paste(md5(file(x))) # Using existing geopackage with vector layer: filepath <- system.file("gpkg/b_pump.gpkg", package = "sf") (md5_original <- md5sum(filepath)) sf_layer <- read_sf(system.file("gpkg/b_pump.gpkg", package = "sf")) # A rewrite changes the checksum: filepath_notimeset <- file.path(tempdir(), "b_pump_notimeset.gpkg") # write 1: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset1 <- md5sum(filepath_notimeset)) # write 2: st_write(sf_layer, dsn = filepath_notimeset, delete_dsn = TRUE) (md5_notimeset2 <- md5sum(filepath_notimeset)) # compare: md5_notimeset1 == md5_notimeset2 # Setting a fixed date filepath_timeset <- file.path(tempdir(), "b_pump_timeset.gpkg") (fixed_date <- as.Date("2020-12-25")) preset_timestamp(fixed_date) # write 1 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset1 <- md5sum(filepath_timeset) # write 2 (date): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset2 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset1, md5_timeset2) # Setting a fixed time (fixed_time <- as.POSIXct("2020-12-25 12:00:00", tz = "CET")) preset_timestamp(fixed_time) # write 3 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset3 <- md5sum(filepath_timeset) # write 4 (time): st_write(sf_layer, dsn = filepath_timeset, delete_dsn = TRUE) md5_timeset4 <- md5sum(filepath_timeset) # compare: all.equal(md5_timeset3, md5_timeset4) # Also works for GPKG 2D gridded coverage (with stars): library(stars) library(dplyr) filepath_stars <- file.path(tempdir(), "stars_2d.gpkg") (fixed_time <- as.POSIXct("2010-02-14 12:00:00", tz = "CET")) preset_timestamp(fixed_time) stars_2d <- system.file("tif/L7_ETMs.tif", package = "stars") %>% read_stars() %>% slice(band, 1) # write 1: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") md5_stars1 <- md5sum(filepath_stars) # write 2: stars_2d %>% write_stars(filepath_stars, driver = "GPKG") md5_stars2 <- md5sum(filepath_stars) # compare: all.equal(md5_stars1, md5_stars2)