Graticules are the longitude latitude lines shown on a projected map, and defining and drawing these lines is not easy to automate. The graticule package provides the tools to create and draw these lines by explicit specification by the user. This provides a good compromise between high-level automation and the flexibility to drive the low level details as needed, using base graphics in R.
Please note that this is an evolving topic, across a number of packages in R. There’s no ongoing integration of how best to do this, and some of the commentary in this vignette will be out of date quickly as individual packages do updates. I’ve recorded the exact versions used for this document at the end.
This is an area that needs much more discussion and outlining of needs and experiences.
A simple example uses data from rworldmap to build a map around the state of Victoria in Australia. Victoria uses a local Lambert Conformal Conic projection that was introduced while the shift to GDA94 was implemented, to reduce complications due to working with more than one UTM zone for the state.
library(rgdal)
library(raster)
library(rworldmap)
data(countriesLow)
<- projection(countriesLow)
llproj library(graticule)
<- subset(countriesLow, SOVEREIGNT == "Australia")
map
## VicGrid
<- "+proj=lcc +lat_1=-36 +lat_2=-38 +lat_0=-37 +lon_0=145 +x_0=2500000 +y_0=2500000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
prj
<- spTransform(map, CRS(prj))
pmap #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
#> Warning in spTransform(xSP, CRSobj, ...): NULL source CRS comment, falling back
#> to PROJ string
#> Warning in wkt(obj): CRS object has no comment
## specify exactly where we want meridians and parallels
<- seq(140, 150, length = 5)
lons <- seq(-40, -35, length = 6)
lats ## optionally, specify the extents of the meridians and parallels
## here we push them out a little on each side
<- range(lons) + c(-0.4, 0.4)
xl <- range(lats) + c(-0.4, 0.4)
yl ## build the lines with our precise locations and ranges
<- graticule(lons, lats, proj = prj, xlim = xl, ylim = yl)
grat #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
## build the labels, here they sit exactly on the western and northern extent
## of our line ranges
<- graticule_labels(lons, lats, xline = min(xl), yline = max(yl), proj = prj)
labs #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
## set up a map extent and plot
<- par(mar = rep(0, 4))
op plot(extent(grat) + c(4, 2) * 1e5, asp = 1, type = "n", axes = FALSE, xlab = "", ylab = "")
plot(pmap, add = TRUE)
## the lines are a SpatialLinesDataFrame
plot(grat, add = TRUE, lty = 5, col = rgb(0, 0, 0, 0.8))
## the labels are a SpatialPointsDataFrame, and islon tells us which kind
text(subset(labs, labs$islon), lab = parse(text = labs$lab[labs$islon]), pos = 3)
text(subset(labs, !labs$islon), lab = parse(text = labs$lab[!labs$islon]), pos = 2)
par(op)
Download some sea ice concentration data and plot with a graticule. These passive microwave data are defined on a Polar Stereographic grid on the Hughes ellipsoid (predating WGS84), and there are daily files available since 1978. This is not the prettiest map, but the example is showing how we have control over exactly where the lines are created. We can build the lines anywhere, not necessarily at regular intervals or rounded numbers, and we can over or under extend the parallels relative to the meridians and vice versa.
library(raster)
library(graticule)
library(rgdal)
<- system.file("extdata", "nt_20140320_f17_v01_s.bin", package = "graticule")
tfile <- raster(tfile)
ice #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
<- seq(-180, 160, by = 20)
meridians <- c(-80, -73.77, -68, -55, -45)
parallels <- c(-180, 180)
mlim <- c(-88, -50)
plim <- graticule(lons = meridians, lats = parallels, xlim = mlim, ylim = plim, proj = projection(ice))
grat #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
<- graticule_labels(meridians, parallels, xline = -45, yline = -60, proj = projection(ice))
labs #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
plot(ice, axes = FALSE)
plot(grat, add = TRUE, lty = 3)
text(labs, lab = parse(text= labs$lab), col= c("firebrick", "darkblue")[labs$islon + 1], cex = 0.85)
title(sprintf("Sea ice concentration %s", gsub(".bin", "", basename(tfile))), cex.main = 0.8)
title(sub = projection(ice), cex.sub = 0.6)
Continuing from the sea ice example, build the graticule grid as actual polygons. Necessarily the xlim/ylim
option is ignored since we have not specified sensibly closed polygonal rings where there are under or over laps.
<- graticule(lons = c(meridians, 180), lats = parallels, proj = projection(ice), tiles = TRUE)
polargrid #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
<- project(coordinates(polargrid), projection(ice), inv = TRUE)
centroids <- graticule_labels(meridians, parallels, proj = projection(ice))
labs #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
#labs <- graticule_labels(as.integer(centroids[,1]), as.integer(centroids[,2]), proj = projection(ice))
#labs <- labs[!duplicated(as.data.frame(labs)), ] ## this needs a fix
<- sample(colors(), nrow(polargrid))
cols <- par(mar = rep(0, 4))
op plot(polargrid, col = cols, bg = "black")
text(labs[labs$islon, ], lab = parse(text = labs$lab[labs$islon]), col = "white", cex = 0.9, pos = 3)
par(op)
The rgdal function llgridlines()
will draw a graticule on a map but had a few limitations prior to May 2016 (some of this story is now out of date and has been improved).
Many of these limitations can be worked around, especially by leveraging tools in the raster package but it’s not particularly elegant. Interestingly mapGrid
in oce seems to share some of the same limitations, but I need to explore that more before being sure about the details.
Above we defined longitude and latitude ranges for an area of interest in Australia. We can plot the projected map and put on a llgridlines
graticule. (Note that there’s a fair region around the main land mass of Australia here, due to Heard Island, Macquarie Island and Lord Howe Island driving the bounds of this map.)
plot(pmap)
<- par(xpd = NA)
op llgridlines(pmap)
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
par(op)
We cannot easily modify the lines to be only in our local area, since llgridlines
overrides our inputs with the bounding box of the overall object.
plot(pmap)
<- seq(140, 150, length = 5)
lons <- seq(-40, -35, length = 6)
lats llgridlines(pmap, easts = lons, norths = lats)
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
What we can do is crop the object, or create a new one with the overall extents of our region of interest. This is much closer to what I want but still I need to fiddle to get it just right.
<- par(xpd = NA)
op <- as(extent(range(lons), range(lats)), "SpatialPolygons")
ex projection(ex) <- llproj
<- spTransform(ex, CRS(projection(pmap)))
pex #> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
plot(extent(pex), type = "n", axes = FALSE, xlab = "", ylab = "", asp = 1)
plot(pmap, add = TRUE)
llgridlines(pex, easts = lons, norths = lats)
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in proj4string(obj): Discarded datum Unknown based on GRS80 ellipsoid in
#> Proj4 definition
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded datum Unknown based on GRS80 ellipsoid in Proj4
#> definition
par(op)
How about the polar example? This is not bad, but the default number of vertices is not sufficient and we don’t get a sensible set of meridians.
plot(ice, axes = FALSE)
##llgridlines(ice) does not understand a raster
llgridlines(as(ice, "SpatialPoints"))
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
Try again, we increase the verticular density, but still I can’t get a line at -180/180 and 80S.
plot(ice, axes = FALSE)
llgridlines(as(ice, "SpatialPoints"), easts = c(-180, -120, -60, 0, 60, 120), norths = c(-80, -70, -60, -50), ndiscr = 50)
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
#> Warning in proj4string(obj): CRS object has comment, which is lost in output
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=stere
#> +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m
#> +no_defs +type=crs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
(This is pretty good, needs more exploration.)
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 7.0.0
<- st_as_sf(pmap)
sf_map <- st_graticule(sf_map)
g plot(st_geometry(sf_map))
<- par(xpd = NA)
op plot(st_geometry(g), add = TRUE)
invisible(lapply(seq_len(nrow(g)), function(i) {
if (g$type[i] == "N" && g$x_start[i] - min(g$x_start) < 1000)
text(g[i,"x_start"], g[i,"y_start"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_start[i], pos = 2, cex = .7)
if (g$type[i] == "E" && g$y_start[i] - min(g$y_start) < 1000)
text(g[i,"x_start"], g[i,"y_start"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_start[i] - 90, pos = 1, cex = .7)
if (g$type[i] == "N" && g$x_end[i] - max(g$x_end) > -1000)
text(g[i,"x_end"], g[i,"y_end"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_end[i], pos = 4, cex = .7)
if (g$type[i] == "E" && g$y_end[i] - max(g$y_end) > -1000)
text(g[i,"x_end"], g[i,"y_end"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_end[i] - 90, pos = 3, cex = .7)
}))
par(op)
library(spex)
#>
#> Attaching package: 'spex'
#> The following object is masked _by_ '.GlobalEnv':
#>
#> ice
<- spex(ice)
pex plot(ice, axes = FALSE)
<- st_graticule(st_as_sf(pex))
g plot(st_geometry(g), add = TRUE)
<- par(xpd = NA)
op invisible(lapply(seq_len(nrow(g)), function(i) {
if (g$type[i] == "N" && g$x_start[i] - min(g$x_start) < 1000)
text(g[i,"x_start"], g[i,"y_start"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_start[i], pos = 2, cex = .7)
if (g$type[i] == "E" && g$y_start[i] - min(g$y_start) < 1000)
text(g[i,"x_start"], g[i,"y_start"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_start[i] - 90, pos = 1, cex = .7)
if (g$type[i] == "N" && g$x_end[i] - max(g$x_end) > -1000)
text(g[i,"x_end"], g[i,"y_end"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_end[i], pos = 4, cex = .7)
if (g$type[i] == "E" && g$y_end[i] - max(g$y_end) > -1000)
text(g[i,"x_end"], g[i,"y_end"], labels = parse(text = g[i,"degree_label"]),
srt = g$angle_end[i] - 90, pos = 3, cex = .7)
}))
par(op)
TBD
The oce package has a lot of really neat map projection tools, but it works rather differently from the Spatial and raster tools in R. We need to drive the creation of the plot from the start with mapPlot
, as it sets up the projection metadata for the current plot and handles that for subsequent plotting additions. (My use of oce is inexpert, I’m not across much of the details yet so I may well be off-track with some things here).
Here is our map of Victoria.
library(oce)
## we need to hop the crevasse into another world
<- raster::geom(map, sepNA = TRUE)
pp mapPlot(pp[,"x"], pp[,"y"], projection = projection(pmap), longitudelim = xl, latitudelim = yl, type = "p", grid = FALSE)
mapGrid(longitude = lons, latitude = lats)
## and to prove that all is well in the world
plot(pmap, add = TRUE, col = "grey")
mapGrid(longitude = lons, latitude = lats)
Here is our polar map, this is good I haven’t explore oce enough yet to do it justice. For bonus points we add mapTissot()
, which should be in the basic toolkit of all intrepid R mappers.
<- coordinates(spTransform(xyFromCell(ice, sample(ncell(ice), 1000), spatial = TRUE), CRS(llproj)))
ipts mapPlot(ipts[,1], ipts[,2], projection = projection(ice), type = "n", grid = FALSE)
plot(ice, add = TRUE)
mapGrid(10, 15)
mapTissot()
Also see here for another implementation of the Tissot Indicatrix in R by user whuber on GIS StackExchange. This is available in the dev package tissot.
Efforts could be shared with the sp and rgdal projects to improve the functionality for the llgridlines
and its worker functions gridlines
and gridat
in that central place, and I agree with this. But I have an interest in working with graticules more directly as objects, and potentially stored in relational-table approach built on dplyr, and so I just found it simpler to start from scratch in this package. Also, there is a lot of this functionality spread around the place in sp, raster, maptools, fields, oce and many others. It is time for a new review, analogous to the effort that built sp in ca. 2002.
I tend to use the same terminology as used within Manifold System because it’s so awesome and that’s where I first learnt about most of these concepts. In my experience not many people use the term graticule in this way, so take it from the master himself on page 8 (Snyder, 1987):
To identify the location of points on the Earth, a graticule or network of longitude and latitude lines has been superimposed on the surface. They are commonly referred to as meridians and parallels, respectively.
“Verticular density” is kind of a joke, but I like it. YMMV
::session_info()
devtools#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.0.5 (2021-03-31)
#> os Ubuntu 18.04.5 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language (EN)
#> collate C
#> ctype en_AU.UTF-8
#> tz Etc/UTC
#> date 2021-05-04
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date lib source
#> abind 1.4-5 2016-07-21 [4] CRAN (R 4.0.3)
#> assertthat 0.2.1 2019-03-21 [4] CRAN (R 4.0.3)
#> bslib 0.2.4 2021-01-25 [4] CRAN (R 4.0.3)
#> cachem 1.0.4 2021-02-13 [4] CRAN (R 4.0.4)
#> callr 3.7.0 2021-04-20 [4] CRAN (R 4.0.5)
#> class 7.3-18 2021-01-24 [6] CRAN (R 4.0.3)
#> classInt 0.4-3 2020-04-07 [4] CRAN (R 4.0.3)
#> cli 2.5.0 2021-04-26 [4] CRAN (R 4.0.5)
#> codetools 0.2-18 2020-11-04 [6] CRAN (R 4.0.3)
#> colorspace 2.0-0 2020-11-11 [4] CRAN (R 4.0.3)
#> crayon 1.4.1.9000 2021-04-27 [4] Github (r-lib/crayon@0374453)
#> crsmeta 0.3.0 2020-03-29 [4] CRAN (R 4.0.3)
#> DBI 1.1.1 2021-01-15 [4] CRAN (R 4.0.3)
#> desc 1.3.0 2021-03-05 [4] CRAN (R 4.0.5)
#> devtools 2.4.0 2021-04-07 [4] CRAN (R 4.0.5)
#> digest 0.6.27 2020-10-24 [4] CRAN (R 4.0.3)
#> dotCall64 1.0-1 2021-02-11 [4] CRAN (R 4.0.5)
#> dplyr 1.0.5 2021-03-05 [4] CRAN (R 4.0.5)
#> e1071 1.7-6 2021-03-18 [4] CRAN (R 4.0.5)
#> ellipsis 0.3.1 2020-05-15 [4] CRAN (R 4.0.3)
#> evaluate 0.14 2019-05-28 [4] CRAN (R 4.0.3)
#> fansi 0.4.2 2021-01-15 [4] CRAN (R 4.0.3)
#> fastmap 1.1.0 2021-01-25 [4] CRAN (R 4.0.3)
#> fields 11.6 2020-10-09 [4] CRAN (R 4.0.3)
#> foreign 0.8-81 2020-12-22 [6] CRAN (R 4.0.3)
#> fs 1.5.0 2020-07-31 [4] CRAN (R 4.0.3)
#> generics 0.1.0 2020-10-31 [4] CRAN (R 4.0.3)
#> geometry 0.4.5 2019-12-04 [4] CRAN (R 4.0.3)
#> geosphere 1.5-10 2019-05-26 [4] CRAN (R 4.0.3)
#> glue 1.4.2 2020-08-27 [4] CRAN (R 4.0.3)
#> graticule * 0.1.6 2021-05-04 [1] local
#> gsw * 1.0-5 2017-08-09 [4] CRAN (R 4.0.4)
#> highr 0.9 2021-04-16 [4] CRAN (R 4.0.5)
#> htmltools 0.5.1.1 2021-01-22 [4] CRAN (R 4.0.3)
#> jquerylib 0.1.4 2021-04-26 [4] CRAN (R 4.0.5)
#> jsonlite 1.7.2 2020-12-09 [4] CRAN (R 4.0.3)
#> KernSmooth 2.23-18 2020-10-29 [6] CRAN (R 4.0.3)
#> knitr 1.33 2021-04-24 [4] CRAN (R 4.0.5)
#> lattice 0.20-41 2020-04-02 [6] CRAN (R 4.0.0)
#> lifecycle 1.0.0 2021-02-15 [4] CRAN (R 4.0.4)
#> magic 1.5-9 2018-09-17 [4] CRAN (R 4.0.3)
#> magrittr 2.0.1 2020-11-17 [4] CRAN (R 4.0.3)
#> maps 3.3.0 2018-04-03 [4] CRAN (R 4.0.3)
#> maptools 1.1-1 2021-03-15 [4] CRAN (R 4.0.5)
#> memoise 2.0.0 2021-01-26 [4] CRAN (R 4.0.3)
#> munsell 0.5.0 2018-06-12 [4] CRAN (R 4.0.3)
#> oce * 1.4-0 2021-03-28 [4] CRAN (R 4.0.4)
#> pillar 1.6.0 2021-04-13 [4] CRAN (R 4.0.5)
#> pkgbuild 1.2.0 2020-12-15 [4] CRAN (R 4.0.3)
#> pkgconfig 2.0.3 2019-09-22 [4] CRAN (R 4.0.3)
#> pkgload 1.2.1 2021-04-06 [4] CRAN (R 4.0.5)
#> png 0.1-7 2013-12-03 [4] CRAN (R 4.0.3)
#> prettyunits 1.1.1 2020-01-24 [4] CRAN (R 4.0.3)
#> processx 3.5.1 2021-04-04 [4] CRAN (R 4.0.5)
#> proj4 1.0-10.1 2021-01-26 [4] CRAN (R 4.0.3)
#> proxy 0.4-25 2021-03-05 [4] CRAN (R 4.0.4)
#> ps 1.6.0 2021-02-28 [4] CRAN (R 4.0.5)
#> purrr 0.3.4 2020-04-17 [4] CRAN (R 4.0.3)
#> quadmesh 0.5.0.9001 2021-02-02 [3] local
#> R6 2.5.0 2020-10-28 [4] CRAN (R 4.0.3)
#> raster * 3.4-5 2020-11-14 [4] CRAN (R 4.0.3)
#> Rcpp 1.0.6 2021-01-15 [4] CRAN (R 4.0.3)
#> remotes 2.3.0 2021-04-01 [4] CRAN (R 4.0.5)
#> reproj 0.4.2 2020-04-15 [4] CRAN (R 4.0.3)
#> rgdal * 1.5-23 2021-02-03 [4] CRAN (R 4.0.3)
#> rlang 0.4.10 2020-12-30 [4] CRAN (R 4.0.3)
#> rmarkdown 2.7 2021-02-19 [4] CRAN (R 4.0.5)
#> rprojroot 2.0.2 2020-11-15 [4] CRAN (R 4.0.3)
#> rworldmap * 1.3-6 2016-02-03 [4] CRAN (R 4.0.3)
#> sass 0.3.1 2021-01-24 [4] CRAN (R 4.0.3)
#> scales 1.1.1 2020-05-11 [4] CRAN (R 4.0.3)
#> sessioninfo 1.1.1 2018-11-05 [4] CRAN (R 4.0.3)
#> sf * 0.9-8 2021-03-17 [4] CRAN (R 4.0.5)
#> sp * 1.4-5 2021-01-10 [4] CRAN (R 4.0.3)
#> spam 2.6-0 2020-12-14 [4] CRAN (R 4.0.3)
#> spex * 0.7.1 2020-06-20 [4] CRAN (R 4.0.3)
#> stringi 1.5.3 2020-09-09 [4] CRAN (R 4.0.3)
#> stringr 1.4.0 2019-02-10 [4] CRAN (R 4.0.3)
#> testthat * 3.0.2 2021-02-14 [4] CRAN (R 4.0.5)
#> tibble 3.1.1 2021-04-18 [4] CRAN (R 4.0.5)
#> tidyselect 1.1.0 2020-05-11 [4] CRAN (R 4.0.3)
#> units 0.7-1 2021-03-16 [4] CRAN (R 4.0.5)
#> usethis 2.0.1 2021-02-10 [4] CRAN (R 4.0.3)
#> utf8 1.2.1 2021-03-12 [4] CRAN (R 4.0.4)
#> vctrs 0.3.7 2021-03-29 [4] CRAN (R 4.0.5)
#> withr 2.4.2 2021-04-18 [4] CRAN (R 4.0.5)
#> xfun 0.22 2021-03-11 [4] CRAN (R 4.0.5)
#> yaml 2.2.1 2020-02-01 [4] CRAN (R 4.0.3)
#>
#> [1] /perm_storage/home/data/r_tmp/RtmpnNAUac/Rinst760f469bf5d8
#> [2] /perm_storage/home/data/r_tmp/RtmpH3Sz18/temp_libpathd6a45e7d52d
#> [3] /perm_storage/home/mdsumner/R/x86_64-pc-linux-gnu-library/4.0
#> [4] /usr/local/lib/R/site-library
#> [5] /usr/lib/R/site-library
#> [6] /usr/lib/R/library