How to set the display border of a raster :: plot?

Summary

How to limit the display of R raster::plot boundaries of the Raster * object? Why am I asking:

I'm a newbie R who should

  • convert non-projected (lon-lat) global spatial data from ASCII to netCDF (allowed)
  • "regrid" it: i.e. limit the data to the area, project it and reduce the scale (reduce the size of the gridcells), it (basically solved)

Unfortunately, in scientific work, mainly QA data transformations, such as visual inspection. Step 1 above looks good. But, although step 2 now looks much better, I really want to draw only the borders (or extents ) of the registered RasterLayer . I have R code driven by bash scripts in a public git repository ( here ) that does the conversion step and displays the converted output, apparently correctly . However, my attempts to construct regression output using raster::plot not entirely correct (see the first 3 pages of output here ).

How to fix?

more details

background

I need to take some data (global marine emissions inventory (EI)), combine it with other data (mostly other EI) and enter them into the model. The model wants to consume netCDF, and it wants the netCDF above the spatial domain to be slightly larger than the adjacent US (CONUS). Borders of this image AQMEII-NA domain are the boundaries of the area. (Note that the part, but only part of the domain, is oceanic.) The model also wants the netCDF to project in a certain way ( LCC at 12 -km). I see this as two independent problems:

  • convert global EI from its own ASCII format to netCDF
  • "regrid" netCDF from global / non-projected to a smaller (thinner) projected subdomain.

I am trying to solve these problems with the code that I archived into this public git repository . If you clone this git repository and then configure / run the bash driver GEIA_to_netCDF.sh as described for the "first example" in README (and assuming your R is configured accordingly, especially with packages = raster , ncdf4 ), it will output netCDF and a graph (using fields::image.plot ) that are output to PDF , which should look like this: GEIA global marine emissions . The output distribution looks right, so problem 1 seems to be resolved.

Problem

The solution to problem 2 (like the "second example" in README ) seems to require R package = raster . My bash driver regrid_GEIA_netCDF.sh calls regrid.global.to.AQMEII.r (both in the repository ), which works without errors and displays a PDF file of its output. GEIA_N2O_oceanic_regrid.pdf contains 4 pages corresponding to the 4 code blocks at the end of regrid.global.to.AQMEII.r . Only the first 3 pages are important here (the fourth page tries to use fields::image.plot and has big problems).

Page = 1/4 is obtained from the simple raster::plot of the wrld_simpl output, as well as the projected version of the CONUS map from wrld_simpl :

 plot(out.raster) plot(map.us.proj, add=TRUE) 

Unfortunately, the output looks global or almost like this: raster :: plot bounds problem But the desired domain to which the output was processed is much smaller: AQMEII-NA domain . So, I have 3 questions (1 main question, 2 observations):

  • Does the image displayed by raster::plot show by default only the RasterLayer extents specified in its arguments?
  • If so, what happened to my reggae? (below)
  • If not (i.e. if raster::plot defaults to display more than the extents of its RasterLayer ), how can raster::plot display only extents of this RasterLayer ?

The code is in regrid.global.to.AQMEII.r ( here ), which apparently returns the correct result:

 out.crs <- '+proj=lcc +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97 +x_0=-2556000 +y_0=-1728000' 

Note that CRS seems to match the output domain definition specified here here . (Once on the linked page, scroll the map.)

 out.raster <- projectRaster( from=in.raster, to=template.raster, method='bilinear', crs=out.crs, overwrite=TRUE, progress='window', format='CDF', # args from writeRaster NAflag=-999.0, # match emi_n2o:missing_value,_FillValue (TODO: copy) varname=data.var.name, varunit='ton N2O-N/yr', longname='N2O emissions', xname='COL', yname='ROW', filename=out.fp) out.raster # made with CRS #> class : RasterLayer #> dimensions : 299, 459, 137241 (nrow, ncol, ncell) #> resolution : 53369.55, 56883.69 (x, y) #> extent : -14802449, 9694173, -6258782, 10749443 (xmin, xmax, ymin, ymax) # ??? why still proj=longlat ??? #> coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0 #> data source : /home/rtd/code/R/GEIA_to_netCDF/GEIA_N2O_oceanic_regrid.nc #> names : N2O.emissions #> zvar : emi_n2o 

But, as already noted, the regression output ( out.raster ) shows that it is lon-lat in its CRS: I'm not sure why this is, or if it implies that out.raster is global in extents.

I also tried to limit the plot itself in two ways:

Firstly, I tried to add extents to the plot, i.e.

 plot(out.raster, ext=template.raster) plot(map.us.proj, add=TRUE) 

which creates the page <2/4 PDF . Unfortunately, this does not change the output at all: AFAICS, it is completely identical to the page = 1/4 (see above).

Secondly, I tried using raster::crop to bind the most corrected netCDF before building it using the same RasterLayer object ( template.raster ) that I used to bind regression:

 template.raster.extent <- extent(template.raster) out.raster.crop <- # overwrite the uncropped file crop(out.raster, template.raster.extent, filename=out.fp, overwrite=TRUE) ... plot(out.raster.crop) plot(map.us.proj, add=TRUE) 

which generates a page = 3/4 pdf . Unfortunately, this also seems to be completely identical to page = 1/4 (see above).

(If you're interested, page 4 of the PDF was generated using fields::image.plot , which has another problem described here if StackOverflow doesn't hit the link.)

Your help to this newbie R is appreciated!

+4
source share
1 answer

Summary

My question

 How to limit display of an R `raster::plot` to the bounds of a `Raster*` object? 

was based on my misdiagnosis of the problem. The solution was to correctly set the boundaries (or extent ) of the underlying Raster* data object (i.e., the data source for the graph), and especially

  • to get the boundaries of the template object (used to create the data object) by querying its main file (do not make any assumptions!)
  • to get the CRS of the template object by requesting its main file (do not make any assumptions!)
  • set borders and CRS for the template object directly

But

  • do not try to just set the permission to extent ; for me at least that hangs
  • there is another minor limited issue with the raster::plot map; at least regarding the map i use with fields::image.plot

more details

The answer to this question is actually the answer to another question: how to set the extent of the Raster* object correctly? because the raster::plot problem basically disappeared as soon as I correctly set the size of the object I wanted to build. (With one minor exception, see below.) It may have been what Robert J. Haymans, raster main developer, tried to post to this post , but if so, I did not perceive it at the time.

I solved the problem after receiving two offers, which in themselves were not what I needed, but which put me on the right track. In this case, this path led to R package M3 , which is useful for processing input and output of CMAQ and WRF data. Suggestions were

  • Use project.lonlat.to.M3 for reference.
  • The plot problem may be related to the assumption of a production model (CMAQ) of spherical projection.

The second sentence seemed plausible since I knew that I was getting and installing CRS using +ellps=WGS84 . (See R's detailed commentary on this repository , in particular regrid.global.to.AQMEII.r .) So I decided to study this.

I knew that the first sentence would only work with difficulty (since it only projects points), but looked at the M3 doc to be sure. The following features in his ToC immediately caught my eye:

  • get.proj.info.M3 , which not only returned the spherical line PROJ.4 from the template file, but also without false east and north directions, which, as I thought, I needed to provide:

     # use package=M3 to get CRS from template file out.crs <- get.proj.info.M3(template.in.fp) cat(sprintf('out.crs=%s\n', out.crs)) # debugging # out.crs=+proj=lcc +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97 +a=6370000 +b=6370000 
  • get.grid.info.M3 , which can, with a little effort, return the borders / size of the template file:

     extents.info <- get.grid.info.M3(template.in.fp) extents.xmin <- extents.info$x.orig extents.xmax <- max( get.coord.for.dimension( file=template.in.fp, dimension="col", position="upper", units="m")$coords) extents.ymin <- extents.info$y.orig extents.ymax <- max( get.coord.for.dimension( file=template.in.fp, dimension="row", position="upper", units="m")$coords) template.extents <- extent(extents.xmin, extents.xmax, extents.ymin, extents.ymax) 

You can then set these borders on the Raster* template Raster*

 template.in.raster <- raster(template.in.fp, ...) template.raster <- projectExtent(template.in.raster, crs=out.crs) template.raster@extent <- template.extents 

and use the template to change the input Raster*

 out.raster <- projectRaster( # give a template with extents--fast, but gotta calculate extents from=in.raster, to=template.raster, crs=out.crs, # give a resolution instead of a template? no, that hangs # from=in.raster, res=grid.res, crs=out.crs, method='bilinear', overwrite=TRUE, format='CDF', # args from writeRaster NAflag=-999.0, # match emi_n2o:missing_value,_FillValue (TODO: copy) varname=data.var.name, varunit='ton N2O-N/yr', longname='N2O emissions', xname='COL', yname='ROW', filename=out.fp) # above fails to set CRS, so out.raster@crs <- CRS(out.crs) 

(As mentioned above, the re-installation of the template took only 7 seconds, but the re-completion by setting the grid resolution did not complete after 2 hours when I killed the task.) After that, raster::plot

 map.us.unproj <- wrld_simpl[wrld_simpl$ISO3 %in% c('CAN', 'MEX', 'USA'),] map.us.proj <- spTransform(map.us.unproj, CRS(out.crs)) # projected ... pdf(file=pdf.fp, width=5.5, height=4.25) ... plot(out.raster, # remaining args from image.plot main=title, sub=subtitle, xlab='', ylab='', axes=F, col=colors(100), axis.args=list(at=quantiles, labels=quantiles.formatted)) # add a projected CONUS map plot(map.us.proj, add=TRUE) 

was almost as expected, with one exception: excess north-south plot extents with raster :: plot the map goes beyond the data to the north and south (although not to the east and west), which leads to the fact that the image does not closely resemble published domain images, for example this . I wonder when I draw with fields::image.plot as

 # see code in # https://github.com/TomRoche/GEIA_to_netCDF/blob/master/plotLayersForTimestep.r plot.raster( raster=out.raster, title=title, subtitle=subtitle, q.vec=probabilities.vec, colors, map.cmaq ) 

I do not get this problem: fields :: image.plot after problem fixed . Therefore, I will probably use fields::image.plot to display, at least for now.

+3
source

Source: https://habr.com/ru/post/1441190/


All Articles