[R] [lattice] display a projected map on a layerplot

Tom Roche Tom_Roche at pobox.com
Thu Feb 14 00:32:17 CET 2013


summary: I can display a lon-lat map on a lattice::layerplot, and I
can display a Lambert conformal conic (LCC) map on a spam::image, but
I can't display an LCC map on a lattice::layerplot. Example follows.
What am I doing wrong?

details:

I've been using `lattice` (via `rasterVis`) successfully to display
global atmospheric data, which works well enough (though I am
definitely intrigued by ggplot/ggmap). Particularly, I am able to
overlay my plots with maps, which is essential for the sort of work
I'm doing. However I'm currently unable to use lattice::layerplot for
some regional data projected LCC: the data plots, but I cannot get a
map to overlay. I can do this by cruder means, but would prefer to
know how to do this in lattice/rasterVis or similar (or ggplot/ggmap).
Two nearly-self-contained examples follow.

The data, ozone_lcc.nc, comes with CRAN package=M3 ... except that M3
supplies it as

system.file("extdata/ozone_lcc.ncf", package="M3")

and that extension currently causes problems for CRAN package=raster.
You can either rename that file (and put it some current working
directory), or you can download (270 kB)

https://bitbucket.org/tlroche/mozart-global-to-aqmeii-na/downloads/ozone_lcc.nc

You can then run the following code:

##### start example #####

library("M3")        # http://cran.r-project.org/web/packages/M3/
library("rasterVis") # http://cran.r-project.org/web/packages/rasterVis/

## Use an example file with projection=Lambert conformal conic.
# lcc.file <- system.file("extdata/ozone_lcc.ncf", package="M3")
lcc.file <- "./ozone_lcc.nc" # unfortunate problem with raster::raster
lcc.proj4 <- get.proj.info.M3(lcc.file)
lcc.proj4   # debugging
# [1] "+proj=lcc +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97 +a=6370000 +b=6370000"
# Note +lat_0=40 +lat_1=33 +lat_2=45 for maps::map at projection (below)
lcc.crs <- sp::CRS(lcc.proj4)
lcc.pdf <- "./ozone_lcc.pdf" # for output

## Read in variable with daily ozone.
# o3.raster <- raster::raster(x=lcc.file, varname="O3", crs=lcc.crs)
# ozone_lcc.nc has 4 timesteps, choose 1 at random
o3.raster <- raster::raster(x=lcc.file, varname="O3", crs=lcc.crs, level=1)
o3.raster at crs <- lcc.crs # why does the above assignment not take?
o3.raster # debugging
# class       : RasterLayer 
# band        : 1 
# dimensions  : 112, 148, 16576  (nrow, ncol, ncell)
# resolution  : 1, 1  (x, y)
# extent      : 0.5, 148.5, 0.5, 112.5  (xmin, xmax, ymin, ymax)
# coord. ref. : +proj=lcc +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97 +a=6370000 +b=6370000 
# data source : .../ozone_lcc.nc 
# names       : O3 
# z-value     : 1 
# zvar        : O3 
# level       : 1 

## Get US state boundaries in projection units.
state.map <- maps::map(
  database="state", projection="lambert", par=c(33,45), plot=FALSE)
#                  parameters to lambert: ^^^^^^^^^^^^
#                  see mapproj::mapproject
state.map.shp <-
  maptools::map2SpatialLines(state.map, proj4string=lcc.crs)

pdf(file=lcc.pdf)
rasterVis::levelplot(o3.raster, margin=FALSE
) + latticeExtra::layer(
  sp::sp.lines(state.map.shp, lwd=0.8, col='darkgray'))

dev.off()
# change this as needed to view PDFs on your system
system(sprintf("xpdf %s", lcc.pdf))
# data looks good, but there's no map.

## Try again, with lambert(40,33)
state.map <- maps::map(
  database="state", projection="lambert", par=c(40,33), plot=FALSE)
#                  parameters to lambert: ^^^^^^^^^^^^
#                  see mapproj::mapproject
state.map.shp <-
  maptools::map2SpatialLines(state.map, proj4string=lcc.crs)

pdf(file=lcc.pdf)
rasterVis::levelplot(o3.raster, margin=FALSE
) + latticeExtra::layer(
  sp::sp.lines(state.map.shp, lwd=0.8, col='darkgray'))
# still no map :-(

dev.off()
system(sprintf("xpdf %s", lcc.pdf))

#####   end example #####

The data looks right, in that it greatly resembles the original
example (from which the above is adapted), which follows my .sig.
However the original-example code *does* draw a map, while the code
above does not. How to fix?

TIA, Tom Roche <Tom_Roche at pobox.com> <Roche.Tom at epa.gov>
---------------original example follows to end of post---------------

# Following adapted from what is installed in my
# .../R/x86_64-pc-linux-gnu-library/2.14/m3AqfigExampleScript.r
# (probably by my sysadmin), which also greatly resembles
# https://wiki.epa.gov/amad/index.php/R_packages_developed_in_AMAD
# which is behind a firewall :-(

## EXAMPLE WITH LAMBERT CONIC CONFORMAL FILE.

library("M3")
library("aqfig") # http://cran.r-project.org/web/packages/aqfig/

## Use an example file with LCC projection: either local download ...
lcc.file <- "./ozone_lcc.nc"
## ... or as installed by package=M3:
# lcc.file <- system.file("extdata/ozone_lcc.ncf", package="M3")
## Choose the one that works for you.

##  READ AND PLOT OZONE FROM FILE WITH LCC PROJECTION.

## Read in variable with daily ozone. Note that we can give dates
## rather than date-times, and that will include all time steps
## anytime during those days.  Or, we can give lower and upper bounds
## and all time steps between these will be taken.
o3 <- M3::get.M3.var(
  file=lcc.file, var="O3",
  ldatetime=as.Date("2001-07-01"), udatetime=as.Date("2001-07-04"))

## Get colors and map boundaries for plot.
library("fields")
col.rng <- tim.colors(20)
detach("package:fields")

## Get state boundaries in projetion units.
map.lines <- M3::get.map.lines.M3.proj(file=lcc.file, database="state")

## Set color boundaries so that they incorporate the complete data range.
z.rng <- range(as.vector(o3$data))
## Make a color tile plot of the ozone for the first day (2001-07-01).
image(o3$x.cell.ctr, o3$y.cell.ctr, o3$data[,,1,1],
      col=col.rng, zlim=z.rng,
      xlab="Projection x-coord (km)", ylab="Projection y-coord (km)")

## Put date-time string and chemical name (O3) into a format I can use
## to label the actual figure.
date.str <- format(o3$datetime[1], "%Y-%m-%d")
title(main=bquote(paste(O[3], " on ", .(date.str), sep="")))

## Put the state boundaries on the plot.
lines(map.lines$coords)

## Add color bar to the right of plot to show what colors go with what
## ozone concentraton.  NOTE: AFTER USING vertical.image.legend(), YOU
## WON'T BE ABLE TO ADD NEW FEATURES TO THE PLOT.  Before making a new
## plot, you should open a new device or turn this device off.
vertical.image.legend(zlim=z.rng, col=col.rng)

dev.off() # close the plot if you haven't already



More information about the R-help mailing list