where could we get such a landscape GIS layer - r

Here, I found a landscape GIS layer is really attractive, especially for presenting species/samples distributions. I would like to know if it can be reached in R or any other resources?
The GIS layer were used in Fig 1. in this article (http://onlinelibrary.wiley.com/doi/10.1111/j.1469-8137.2010.03479.x/full).
This Fig 1 image is here:
http://onlinelibrary.wiley.com/store/10.1111/j.1469-8137.2010.03479.x/asset/image_t/NPH_3479_f1_thumb.gif?v=1&t=gsk5sbhs&s=e5e2e4bbb194f799f7ab9bec85a416e295405784
I have ever tried to submit this question in R-sig-geo. But, I failed. I expect to get some helps/directions here.
Thanks a lots for any directions.
Best wishes,

It is very possible to download this file and read it in with R, configure it to have the correct geo-coordinates so that overplotting works easily, and showing the image with the right colour scheme and so on. But, automating getting all of the data you need is not so easy.
You need the colour table from the GIF file so that you can plot the correct set of RGB values for each pixel (the information is in the file, but I'm not sure if this can be obtained directly with R, I will check - it certainly can be with GDAL, but extracting those values in an automated way depends on various tools being available).
UPDATE: It turns out that the raster package gets hold of the colour information correctly and plots it, see below.
You also need the geo-spatial information, i.e. the coordinates of a reference pixel (say, the top left pixel corner), and the scale (the geographic width and height of the pixels) and this information is not stored in the file. Also, the coordinate system of the file is not in the file, and very likely not provided explicitly with the image data.
If the colours and the coordinate system were stored with the file, then it would all be easy and something like the following would be enough.
(Note this worked for me once, but then I think subsequent requests are blocked by the server, so try to only download the file one time).
u <- "http://onlinelibrary.wiley.com/store/10.1111/j.1469-8137.2010.03479.x/asset/image_n/NPH_3479_f1.gif?v=1&t=gskxvi17&s=0f13fa9dae78bd6837aeee594065c6ca112864d2"
imfile <- paste(tempfile(), ".gif", sep = "")
download.file(u, imfile, mode = "wb")
library(raster) ## rgdal also required for this file format
library(rgdal)
im <- raster(imfile)
plot(im)
This looks fine but now see that there is no "real-world" coordinate system, this is just an axis from pixel 1 to the number in the X dimension (and same for Y).
axis(1, pos = 2)
So, still we need manually work to discover appropriate reference coordinates for the image - and guesses here can work fine, but still they are only guesses and you may end up creating a lot of pain for something seemingly simple.
If plot points interactively is enough for you, then you might use locator in conjunction with points and lines and text, and related plotting functions.

Feng,
if I read the Google docs correctly, you can modify the labels and displayed features with the extra parameters style and element.
I did not include custom parameters for these in the RgoogleMaps package, however, you can easily pass ANY addition parameters via the path argument !
If you read the help file for GetMap carefully, you will note the following example:
note that since the path string is just appended to the URL you can "abuse" the path argument to pass anything to the query, e.g. the style parameter:
#The following example displays a map of Brooklyn where local roads have been changed to bright green and the residential areas have been changed to black:
## Not run: GetMap(center='Brooklyn', zoom=12, maptype = "roadmap", path = "&style=feature:road.local|element:geometry|hue:0x00ff00|saturation:100&style=feature:landscape|element:geometry|lightness:-100", sensor='false', destfile = "MyTile4.png", RETURNIMAGE = FALSE);
Hope this helps,
Markus Loecher

If you just want data like this image, then there are packages to access imagery directly, again utilizing the tools in sp and rgdal. This example is close using gmap in the dismo package.
library(dismo)
e <- extent(-7, 5, 38, 44)
gm <- gmap(e, type = "terrain")
plot(gm)
Note that while we specify the extents in "longlat" the image comes back in its native (Google) Mercator.
print(gm)
See ?gmap for more options on transforming your own data to match the image's projection, or the broader function set in raster, rgdal and sp for other options. There are other imagery providers that might be preferable, and quite a few options in the R suite of contributed packages.

Related

How to rasterize a single layer of a ggplot?

Matplotlib allows to rasterize individual elements of a plot and save it as a mixed pixel/vector graphic (.pdf) (see e.g. this answer). How can the same achieved in R with ggplot2?
The following is a toy problem in which I would like to rasterize only the geom_point layer.
set.seed(1)
x <- rlnorm(10000,4)
y <- 1+rpois(length(x),lambda=x/10+1/x)
z <- sample(letters[1:2],length(x), replace=TRUE)
p <- ggplot(data.frame(x,y,z),aes(x=x,y=y)) +
facet_wrap("z") +
geom_point(size=0.1,alpha=0.1) +
scale_x_log10()+scale_y_log10() +
geom_smooth(method="gam",formula = y ~ s(x, bs = "cs"))
print(p)
ggsave("out.pdf", p)
When saved as .pdf as is, Adobe reader DC needs ~1s to render the figure. Below you can see a .png version:
Of course, it is often possible to avoid the problem by not plotting raw data
Thanks to the ggrastr package by Viktor Petukhov & Evan Biederstedt, it is now possible to rasterize individual layers. However, currently (2018-08-13), only geom_point and geom_tile are supported. and work by Teun van den Brand it is now possible to rasterize any individual ggplot layer by wrapping it in ggrastr::rasterise():
# install.packages('devtools')
# remotes::install_github('VPetukhov/ggrastr')
df %>% ggplot(aes(x=x, y=y)) +
# this layer will be rasterized:
ggrastr::rasterise(geom_point(size=0.1, alpha=0.1)) +
# this one will still be "vector":
geom_smooth()
Previously, only a few geoms were supported:
To use it, you had to replace geom_point by ggrastr::geom_point_rast.
For example:
# install.packages('devtools')
# devtools::install_github('VPetukhov/ggrastr')
library(ggplot2)
set.seed(1)
x <- rlnorm(10000, 4)
y <- 1+rpois(length(x), lambda = x/10+1/x)
z <- sample(letters[1:2], length(x), replace = TRUE)
ggplot(data.frame(x, y, z), aes(x=x, y=y)) +
facet_wrap("z") +
ggrastr::geom_point_rast(size=0.1, alpha=0.1) +
scale_x_log10() + scale_y_log10() +
geom_smooth(method="gam", formula = y ~ s(x, bs = "cs"))
ggsave("out.pdf")
This yields a pdf that contains only the geom_point layer as raster and everything else as vector graphic. Overall the figure looks as the one in the question, but zooming in reveals the difference:
Compare this to an all-raster graphic:
I think you've set yourself up to not have this question answered. You write:
I expect an answer to provide an extension to ggplot2 that allows to export plots with rasterized layers with minimal changes to to existing plotting commands, i.e. as wrapper for geom_... commands or as an additional parameter to these or a ggsave command that expects a list of unevaluated parts of a plot command (every second to be rasterized), not a hacky workaround as provided in the linked question.
This is a major development effort that could easily require several weeks or more of effort by a highly skilled developer. It's unlikely anybody will do this just because of a Stack Overflow question. In lieu of a functioning implementation, I'll describe here how one could implement what you're asking for and why it's rather challenging.
The players
Let's start with the key players we'll be dealing with. At the highest level sits the ggplot2 library. It takes data frames and turns them into figures. ggplot2 itself doesn't know anything about low-level drawing, though. It only deals with lines, polygons, text, etc., which it hands off to the grid library in the form of graphics objects (grobs).
The grid library itself is a fairly high-level library. It also doesn't know much about low-level drawing. It primarily deals with lines, polygons, text, etc., which it hands off to an R graphics device. The device does the actual drawing.
There are many different R graphics devices. Enter ?Devices in an R command line to see an incomplete list. There are vector-graphics devices, such as pdf, postscript, or svg, raster devices such as png, jpeg, or tiff, and interactive devices such as X11 or quartz. Obviously, rasterization as a concept only makes sense for vector-graphics devices, since raster devices raster everything anyways. Importantly, neither ggplot2 nor grid know or care which graphics device you're currently drawing on. They deal with graphical objects that can be drawn on any device.
Ideal high-level interface
The high-level interface should consist of an option rasterize in the layer() function of ggplot2. In this way, one could simply write, e.g., geom_point(rasterize = TRUE) to rasterize the points layer. This would work transparently for all geoms and stats, since they all call layer().
Possible implementations
I see four possible routes of implementation, ordered from most impossible to least.
1. Ideally, the layer() function would simply hand off the rasterize option to the grid library, which would hand it off to the graphics device to tell it which parts of the plot to rasterize. This approach would require major changes in the graphics device API. I don't see this happening. Not in my lifetime, at least.
2. Alternatively, one could write a new grob type that can take any arbitrary grob and rasterize it on demand when the grob is drawn on a graphics device. This approach would not require changes in the graphics device API, but it would require detailed knowledge of the low-level implementation of the grid library. It would also possibly make interactive viewing of such figures very slow.
3. A slightly simpler alternative to 2. would be to rasterize the arbitrary grob only once, on grob construction, and then reuse whenever that grob is drawn. This would be quite a bit faster on interactive graphics devices but the drawing would get distorted if the aspect ratio is changed interactively. Nevertheless, since the primary use of this functionality would be to generate pdf output (I assume), this option might be sufficient.
4. Finally, rasterization could also happen in the layer() function, and that function could simply place a regular raster grob into the grob tree. That solution is similar to the technique described here. Technically, it's not much different from 3. Either way, one needs to write code to rasterize a grob tree and then replace it by a raster grob.
Technical hurdles
To rasterize parts of the grob tree, we'd have to send them to an R raster graphics device to render. However, there isn't one that renders to memory. So, one would have to render to a temporary file (e.g., using png()), and then read the file back in. That's possible but ugly. It also depends on functionality (such as png()) that isn't guaranteed to be available on every R installation.
Second, to render parts of the grob tree separately from the overall rendering, we'll have to open a new graphics device in addition to the one currently open. That's possible but can lead to unexpected bugs. I'm dealing with such bugs all the time, see e.g. here or here for issues related to code using this technique. Whoever implements the rasterization functionality would have to deal with such issues.
Finally, we'll have to get the rasterization code accepted into the ggplot2 library, since we need to replace the layer() function and I don't think there's a way to do that from a separate package. Given how hackish the rasterization solutions are going to be (see previous two paragraphs), that may be a tall order.

Google Maps vs. ggplot2/MarMap

Below is a JavaScript page I have created that allows me add and freely move markers on the map. From this map I can figure out the regions I am interested in.
Basically what I want to do is show the same map using ggplot2/MarMap with coastline indicators + bathymetry data. I am really just interested in getting bathymetry data per GPS location, basically getting negative/positive elevation per Lat+Long, so I was thinking if I can plot it then I should be able to export data to a Database. I am also interested in coastline data, so I want to know how close I am (Lat/Long) to coastline, so with plot data I was also going to augment in DB.
Here is the R script that I am using:
library(marmap);
library(ggplot2);
a_lon1 = -79.89836596313478;
a_lon2 = -79.97179329675288;
a_lat1 = 32.76506070891712;
a_lat2 = 32.803624214389615;
dat <- getNOAA.bathy(a_lon1,a_lon2,a_lat1,a_lat2, keep=FALSE);
autoplot(dat, geom=c("r", "c"), colour="white", size=0.1) + scale_fill_etopo();
Here is the output of above R script:
Questions:
Why do both images not match?
In google-maps I am using zoom value 13. How does that translate in ggplot2/MarMap?
Is it possible to zoom in ggplot2/MarMap into a (Lat/Long)-(Lat/Long) region?
Is it possible to plot what I am asking for?
I don't know how you got this result. When I use your script, I get an error since the area your are trying to fetch from the ETOPO1 database using getNOAA.bathy() is too small. However, adding resolution=1 (this gives the highest possible resolution for the ETOPO1 database), here is what I get:
To answer your questions:
Why do both images not match?
Probably because getNOAA.bathy() returned an error and the object dat you're using has been created before, using another set of coordinates
In google-maps I am using zoom value 13. How does that translate in ggplot2/MarMap?
I have no clue!
Is it possible to zoom in ggplot2/MarMap into a (Lat/Long)-(Lat/Long) region?
I urge you to take a look at section 4 of the marmap-DataAnalysis vignette. This section is dedicated to working with big files. You will find there that you can zoom in any area of a bathy object by using (for instance) the subsetBathy() function that will allow you to click on a map to define the desired area
Is it possible to plot what I am asking for? Yes, but it would be much easier to use base graphics and not ggplot2. Once again, you should read the package vignettes.
Finally, regarding the coastline data, you can use the dist2isobath() function to compute the distance between any gps point and any isobath, including the coastline. Guess where you can learn more about this function and how to use it...

Wrong output size when plotting over an image in R

My goal is to read an image file in either the PNG or JPEG format and plot various data over said image and save it to disk.
I also want the image to take up all available space in the produced plot, no axes or labels or anything. I'm a bit concerned that this might be relevant to my problem.
Code example
Below is my current code that currently only tries to output the same image as you put in. Later I plan on plotting data points corresponding to coordinates over the image. I've used some sample code found here in order to remove the axes and be able to have the image in the background of the plot.
library(jpeg)
library(grid)
img <- readJPEG(system.file("img", "Rlogo.jpg", package="jpeg"),native=TRUE)
jpeg(filename = "Rlogo-2.jpg", width=100,height=76, quality = 100,res=299)
op<-par(mar=rep(0,4))
plot(0:100,type="n", axes="FALSE",ann="FALSE")
lim <- par()
rasterImage(img, lim$usr[1], lim$usr[3], lim$usr[2], lim$usr[4])
dev.off()
Example output
This is an example output of my above code in a comparison with the original image:
The image to the left is the original and the right one is the modified one. As you can see it seems as if the image I read and plot somehow is smaller than the original image and when saved to the original dimensions it appears blurred.
I've been pulling my hair over this one for hours and I don't seem to get anywhere. This is my first attempt to plot data over images and I'm aware of my lack of knowledge about how R represents images and I've mostly been using the basic graphics to do relatively simple plots before.
I'm currently considering doing this in Python instead but I'm afraid that'll come back and bite me when it comes to the actual plotting of the data.
I run R version 3.1.0 on x86_64 running Windows 7.
Just to summarize, since you already found the culprit, there are two issues present here:
Firstly, the blurring appears to be caused by the jpeg device on Windows. There is no such problem on Ubuntu Linux and it disappears if you use the Cairo-device instead, as you did already discover. Cairo-devices are great for pdf:s too since they embed all the fonts etc. making the figure look the same across platforms.
Secondly, R adds 4% extra margin to the x and y axes by default to prevent graphics from being chopped off near the edge of the plot area. It can be corrected by setting xaxs="i" and yaxs="i".
par(mfrow=1:2)
plot(1:5, 1:5) # Left
plot(1:5, 1:5, xaxs="i", yaxs="i") # Right
In your case the difference is subtle but still would cause everything to be slightly misaligned.

How to save a pdf in R with a lot of points

So I have to save a pdf plot with a lot of points in it. That is not a problem. The problem is that when I open it. It takes forever to plot all those points. How can I save this pdf in such a way that it doesn't have to draw point by point when someone opens it. I'm OK if the quality of the picture goes down a bit.
Here's a sample. I don't think this would crash your computer but be careful with the parameter length if you have an old machine. I am using many more points than that in my real problem by the way.
pdf("lots of points.pdf")
x <- seq(0,100, length = 100000)
y <- 0.00001 * x
plot(x, y)
dev.off()
I had a similar problem and there is a sound solution. The drawback is that this solution is not generic and does not involve programming (always bad).
For draft purposes, png or any other graphic format may be sufficient, but for presentation purposes this is often not the case. So the way to go is to combine vector graphics for fonts, axis etc and bitmap for your zillions of points:
1) save as pdf (huge and nasty)
2) load into illustrator or likewise ( must have layers )
3) separate points from all other stuff by dragging other stuff to new layer - save as A
4) delete other stuff and export points only as bitmap (png, jpg) and save as B
5) load B into A; scale and move B to exact overlap; delete vector points layer, and export as slender pdf.
done. takes you 30 minutes.
As said this has nothing to do with programming, but there is simply no way around the fact that as vector graphics each and every point (even those that are not visible, since covered by others) are single elements and its a pain handling pdfs with thousands of elements.
So there is need for postprocessing. I know ImageMagick can do alot, but AFAIK the above cant be done by an algorithm.
The only programming way to (partly) solve this is to eliminate those points that will not display because the are covered by others. But thats beyond me.
Only go this way if you really and desperately need extreme scalability, otherwise go with #Ben and #inform and use a bitmap --in whatever container you need it (png,pdf,bmp,jpg,tif, even eps).

Using R for extracing data from colour image

I have a scanned map from which i would like to extract the data into form of Long Lat and the corresponding value. Can anyone please tell me about how i can extract the data from the map. Is there any packages in R that would enable me to extract data from the scanned map. Unfortunately, i cannot find the person who made this map.
Thanks you very much for your time and help.
Take a look at OCR. I doubt you'll find anything for R, since R is primarily a statistical programming language.
You're better off with something like opencv
Once you find the appropriate OCR package, you will need to identify the x and y positions of your characters which you can then use to classify them as being on the x or y axis of your map.
This is not trivial, but good luck
Try this:
Read in the image file using the raster package
Use the locator() function to click on all the lat-long intersection points.
Use the locator data plus the lat-long data to create a table of lat-long to raster x-y coordinates
Fit a radial (x,y)->(r,theta) transformation to the data. You'll be assuming the projected latitude lines are circular which they seem to be very close to but not exact from some overlaying I tried earlier.
To sample from your image at a lat-long point, invert the transformation.
The next hard problem is trying to get from an image sample to the value of the thing being mapped. Maybe take a 5x5 grid of pixels and average, leaving out any gray pixels. Its even harder than that because some of the colours look like they are made from combining pixels of two different colours to make a new shade. Is this the best image you have?
I'm wondering what top-secret information has been blanked out from the top left corner. If it did say what the projection was that would help enormously.
Note you may be able to do a lot of the process online with mapwarper:
http://mapwarper.net
but I'm not sure if it can handle your map's projection.

Resources