Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRS cache and updated CRS print method #103

Merged
merged 10 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: sp
Version: 1.4-5
Version: 1.4-6
Title: Classes and Methods for Spatial Data
Authors@R: c(person("Edzer", "Pebesma", role = c("aut", "cre"),
email = "edzer.pebesma@uni-muenster.de"),
Expand All @@ -16,7 +16,7 @@ Authors@R: c(person("Edzer", "Pebesma", role = c("aut", "cre"),
person("Joseph", "O'Rourke", role = "ctb"))
Depends: R (>= 3.0.0), methods
Imports: utils, stats, graphics, grDevices, lattice, grid
Suggests: RColorBrewer, rgdal (>= 1.2-3), rgeos (>= 0.3-13), gstat, maptools, deldir
Suggests: RColorBrewer, rgdal (>= 1.2-3), rgeos (>= 0.3-13), gstat, maptools, deldir, knitr, rmarkdown
Description: Classes and methods for spatial
data; the classes document where the spatial location information
resides, for 2D or 3D data. Utility functions are provided, e.g. for
Expand Down Expand Up @@ -44,3 +44,5 @@ Collate: bpy.colors.R AAA.R Class-CRS.R CRS-methods.R
recenter.R dms.R gridlines.R spdists.R rbind.R flipSGDF.R
chfids.R loadmeuse.R compassRose.R surfaceArea.R spOptions.R
subset.R disaggregate.R sp_spat1.R merge.R aggregate.R
VignetteBuilder: knitr

4 changes: 4 additions & 0 deletions R/AAA.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ assign("col.regions", bpy.colors(), envir = .spOptions)
assign("thin_PROJ6_warnings", FALSE, envir=.spOptions)
assign("PROJ6_warnings_count", 0L, envir=.spOptions)

#.sp_CRS_cache <- new.env(FALSE, globalenv())
#assign("CRS_CACHE", list(), envir=.sp_CRS_cache)
.sp_CRS_cache <- new.env(hash=TRUE, globalenv())

.onLoad <- function(lib, pkg) {
load_stuff()
}
Expand Down
59 changes: 49 additions & 10 deletions R/CRS-methods.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2003-20 by Barry Rowlingson and Roger Bivand
# Copyright (c) 2003-21 by Barry Rowlingson and Roger Bivand

if (!is.R()) {
strsplit <- function(a,b) {
Expand Down Expand Up @@ -35,15 +35,42 @@ setMethod("rebuild_CRS", signature(obj = "CRS"),
stopifnot(is.logical(get_source_if_boundcrs))
stopifnot(length(get_source_if_boundcrs) == 1L)
stopifnot(is.character(projargs))
# CRS_CACHE <- get("CRS_CACHE", envir=.sp_CRS_cache)
input_projargs <- projargs
if (!is.na(input_projargs)) {
res <- .sp_CRS_cache[[input_projargs]]
if (!is.null(res)) {
return(res)
}
}
if (doCheckCRSArgs && requireNamespace("rgdal", quietly = TRUE)) {
if (packageVersion("rgdal") >= "1.5.1" && !rgdal::new_proj_and_gdal()) {
if (is.na(projargs) && !is.null(SRS_string)) {
if (substring(SRS_string, 1, 4) == "EPSG") {
pa0 <- strsplit(SRS_string, ":")[[1]]
projargs <- paste0("+init=epsg:", pa0[2])
}
}
}
}
if (!is.na(projargs)) {
if (length(grep("^[ ]*\\+", projargs)) == 0) {
if (is.null(SRS_string)) {
if (doCheckCRSArgs &&
requireNamespace("rgdal", quietly = TRUE)) {
if (packageVersion("rgdal") >= "1.5.1" &&
rgdal::new_proj_and_gdal()) {
SRS_string <- projargs
projargs <- NA_character_
if (packageVersion("rgdal") >= "1.5.1") {
if (rgdal::new_proj_and_gdal()) {
SRS_string <- projargs
projargs <- NA_character_
} else {
if (substring(projargs, 1, 4) == "EPSG") {
pa0 <- strsplit(projargs, ":")[[1]]
projargs <- paste0("+init=epsg:", pa0[2])
} else {
stop("Cannot revert", projargs,
"to +init=epsg:")
}
}
}
}
} else {
Expand Down Expand Up @@ -96,15 +123,21 @@ setMethod("rebuild_CRS", signature(obj = "CRS"),
uprojargs <- res[[2]]
comm <- res[[3]]
} else { #stop("rgdal version mismatch")
res <- rgdal::checkCRSArgs(uprojargs)
if (!res[[1]]) stop(res[[2]])
uprojargs <- res[[2]]
if (!is.na(uprojargs)) {
res <- rgdal::checkCRSArgs(uprojargs)
if (!res[[1]]) stop(res[[2]])
uprojargs <- res[[2]]
}
}
} else stop("rgdal version mismatch")
}
}
res <- new("CRS", projargs=uprojargs)
if (!is.null(comm)) comment(res) <- comm
if (!is.na(slot(res, "projargs"))) .sp_CRS_cache[[input_projargs]] <- res
# CRS_CACHE[[input_projargs]] <- res
# assign("CRS_CACHE", CRS_CACHE, envir=.sp_CRS_cache)

res
}
if (!isGeneric("wkt"))
Expand Down Expand Up @@ -137,9 +170,15 @@ setMethod("wkt", signature(obj = "CRS"),

"print.CRS" <- function(x, ...)
{
cat("Coordinate Reference System:\n")
pst <- paste(strwrap(x@projargs), collapse="\n")
if (nchar(pst) < 40) cat(paste("CRS arguments:", pst, "\n"))
else cat(paste("CRS arguments:\n", pst, "\n"))
if (nchar(pst) < 40) cat(paste("Deprecated Proj.4 representation:", pst, "\n"))
else cat(paste("Deprecated Proj.4 representation:\n", pst, "\n"))
wkt <- wkt(x)
if (!is.null(wkt)) {
cat("WKT2 2019 representation:\n")
cat(wkt, "\n")
}
invisible(pst)
}

Expand Down
2 changes: 1 addition & 1 deletion R/projected.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ setMethod("proj4string", signature(obj = "Spatial"),
if (get("rgdal_show_exportToProj4_warnings",
envir=.spOptions)) {
if (!get("thin_PROJ6_warnings", envir=.spOptions)) {
warning("CRS object has comment, which is lost in output")
warning("CRS object has comment, which is lost in output; in tests, see\nhttps://cran.r-project.org/web/packages/sp/vignettes/CRS_warnings.html")
} else {
if (get("PROJ6_warnings_count",
envir=.spOptions) == 0L) {
Expand Down
2 changes: 1 addition & 1 deletion inst/NEWS.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
\itemize{
\item update sp gallery, see \url{https://edzer.github.io/sp/}
\item move \code{methods} from Imports: to Depends:
\item improve base plot methods for \code{SpatialGridDataFrame} and \code{SpatialPixelsDataFrame} objects, see \url{https://www.r-spatial.org/r/2016/03/08/plotting-spatial-grids.html} for examples
\item improve base plot methods for \code{SpatialGridDataFrame} and \code{SpatialPixelsDataFrame} objects, see \url{https://r-spatial.org/r/2016/03/08/plotting-spatial-grids.html} for examples
\item improve the graticule \code{labels} methods, see \code{?gridlines}
\item fix hole assignment for triangles, reported in \url{https://stat.ethz.ch/pipermail/r-sig-geo/2016-March/024214.html}
\item \code{as.SpatialPolygons.GridTopology} drops rownames of coordinates generated, but keeps coordinate (column) names from the \code{cellcentre.offset} slot of the grid
Expand Down
2 changes: 1 addition & 1 deletion inst/include/sp.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#endif
/* remember to touch local_stubs.c */

#define SP_VERSION "1.4-5"
#define SP_VERSION "1.4-6"

#include <R.h>
/* RSB 091203 */
Expand Down
8 changes: 7 additions & 1 deletion man/CRS-class.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Objects can be created by calls of the form \code{CRS("projargs")}, where "proja

\section{Methods}{
\describe{
\item{show}{\code{signature(object = "CRS")}: print projection arguments in object }
\item{show}{\code{signature(object = "CRS")}: print deprecated Proj.4 projection arguments and WKT2 2019 representation if available }
\item{wkt}{\code{signature(object = "CRS")}: return WKT comment on object}
\item{rebuild_CRS}{rebuild a CRS object, usually used to add a WKT comment with PROJ >= 6 and GDAL >= 3}
}
Expand Down Expand Up @@ -88,6 +88,12 @@ if (run) {
if (run) {
print(CRSargs(CRS("+init=epsg:28992")))
}
if (run) {
print(CRSargs(CRS("EPSG:28992")))
}
if (run) {
print(CRSargs(CRS(SRS_string="EPSG:28992")))
}
if (run) {
o <- try(CRS(SRS_string="ESRI:102760"))
if (!inherits(o, "try-error")) print(CRSargs(o))
Expand Down
2 changes: 1 addition & 1 deletion man/SpatialGridDataFrame-class.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ value such as \code{1/6} to specify relative size; default \code{lcm(2.8)}}
and \code{\link{SpatialPixelsDataFrame-class} which holds possibly incomplete
grids }

Plotting gridded data with sp: \url{https://www.r-spatial.org/r/2016/03/08/plotting-spatial-grids.html}
Plotting gridded data with sp: \url{https://r-spatial.org/r/2016/03/08/plotting-spatial-grids.html}
}
\examples{
data(meuse.grid) # only the non-missing valued cells
Expand Down
2 changes: 1 addition & 1 deletion src/sp.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#endif
/* remember to touch local_stubs.c */

#define SP_VERSION "1.4-5"
#define SP_VERSION "1.4-6"

#include <R.h>
/* RSB 091203 */
Expand Down
27 changes: 23 additions & 4 deletions tests/fail1.Rout.save
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

R version 4.0.2 (2020-06-22) -- "Taking Off Again"
Copyright (C) 2020 The R Foundation for Statistical Computing
R version 4.0.4 (2021-02-15) -- "Lost Library Book"
Copyright (C) 2021 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
Expand Down Expand Up @@ -213,11 +213,30 @@ y 50.955770 0.0003318105 112
Error in CRS("+proj=latlon +ellps=WGS84") :
northings must follow eastings: +proj=latlon +ellps=WGS84
> try(CRS("+proj=lonlat +ellps=WGS84"))
CRS arguments: +proj=longlat +ellps=WGS84 +no_defs
Coordinate Reference System:
Deprecated Proj.4 representation: +proj=longlat +ellps=WGS84 +no_defs
WKT2 2019 representation:
GEOGCRS["unknown",
DATUM["Unknown based on WGS84 ellipsoid",
ELLIPSOID["WGS 84",6378137,298.257223563,
LENGTHUNIT["metre",1],
ID["EPSG",7030]]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433],
ID["EPSG",8901]],
CS[ellipsoidal,2],
AXIS["longitude",east,
ORDER[1],
ANGLEUNIT["degree",0.0174532925199433,
ID["EPSG",9122]]],
AXIS["latitude",north,
ORDER[2],
ANGLEUNIT["degree",0.0174532925199433,
ID["EPSG",9122]]]]
Warning message:
In CRS("+proj=lonlat +ellps=WGS84") :
'lonlat' changed to 'longlat': +proj=longlat +ellps=WGS84
>
> proc.time()
user system elapsed
0.585 0.045 0.630
0.500 0.042 0.536
64 changes: 64 additions & 0 deletions vignettes/CRS_warnings.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: "Testing packages using CRS objects"
author: "Roger Bivand"
output:
html_document:
toc: true
toc_float:
collapsed: false
smooth_scroll: false
toc_depth: 2
vignette: >
%\VignetteIndexEntry{Testing packages using CRS objects}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---

## Introduction

As has been explained in https://CRAN.R-project.org/package=rgdal/vignettes/CRS_projections_transformations.html, coordinate reference systems are represented differently when PROJ < 6 and PROJ >= 6.

To alert interactive users to the possibility that their workflows might be degraded unless they take the representational changes into account, the **sp** `proj4string()` method issues warnings if a `"CRS"` object does not have an accompanying `WKT2 2019` representation (stored in a `comment` attached to the `"CRS"` object). This is because `proj4string()` only returns the PROJ 4 representation, not the accompanying `WKT2 2019` representation if any, so may constitute a loss of information. See also https://stat.ethz.ch/pipermail/r-sig-geo/2020-May/028125.html for further discussion.

In general, it is good practice to replace all use in packages of `proj4string()` with `slot(, "proj4string")` and its assignment form by the assignment form of `slot()`; when `sp::proj4string()` is not called, many of the warnings are suppressed anyway.

On attaching **rgdal**:


```{r, echo=FALSE}
run <- FALSE
if (requireNamespace("rgdal", quietly=TRUE)) run <- TRUE
```


```{r, eval=run}
library(rgdal)
```
a package startup message is displayed if PROJ >= 6 and GDAL >= 3, including the important information that:

> To mute warnings of possible GDAL/OSR exportToProj4() degradation, use options("rgdal_show_exportToProj4_warnings"="none") before loading rgdal.

In **sp** 1.4 and **rgdal** 1.5, the default option value is `"all"`, in **sp** >= 1.5 and **rgdal** >= 1.6, the default will be flipped to `"none"`.

## Testing

Both CRAN checks and use of checks by end users may trigger spurious errors, if the versions of PROJ and GDAL differ from those on the development platform. Since the `WKT2 2019` representation is only generated on systems with PROJ >= 6 (and GDAL >= 3), warnings should not be expected when the same code is run on platforms with older versions of PROJ and GDAL. There are many such platforms, including RHEL and CentOS systems, as well as Ubuntu 18 and others. Think of a large lab with a cluster runnning such a system version, and that those installing software may wish to run `R CMD check` or just your test suite to confirm that things are as they should be. They will be dismayed to find that tests fail, but will not be able to find out whether this matters for them.

Consequently, it is best either not to check warnings that perform differently when run under different versions of upstream external software (PROJ and GDAL), or to condition on the software versions with different expectations depending on the version.

To mute warnings in all settings, add the option above early in any relevant test file.

Fine-grained control may be obtained using `rgdal::rgdal_extSoftVersion()`:

```{r, eval=run}
rgdal::rgdal_extSoftVersion()
```
and its shorter version, testing only PROJ >= 6 (and GDAL >= 3):

```{r, eval=run}
rgdal::new_proj_and_gdal()
```
Using this test, a warning might be expected if recent PROJ and GDAL are used, and before the warning default is flipped in **sp** > 1.4 and **rgdal** > 1.5.

In **sf**, use `sf::sf_extSoftVersion()` to determine versions if necessary.