Tmap: tm_tiles in plot mode

Created on 20 Apr 2018  路  11Comments  路  Source: mtennekes/tmap

first, Awesome package!
I was trying out your dev version because I am excited to be able to use basemaps in "plot" mode!

I apologize if this is an unfinished feature and this issue is superfluous.

The help describes tm_basemap as only available in "view" mode. To insert a basemap in "plot" mode,

For plot mode, a tile image can be retrieved by read_osm. tm_tiles draws the tile layer as overlay layer where it follows the plotting order in which this layer is called.

So I was expecting to do

library(sf)
library(tmap)
counties <- sf::st_as_sf(maps::map(database='county',regions='idaho',fill=TRUE,plot=F))
tmap_mode('plot')
CBS_osm2 <- tmaptools::read_osm(counties,raster=TRUE, type="stamen-terrain")
tm_tiles(CBS_osm2)+
tm_shape(counties)+tm_borders()

only the vector is plotted and an warning is given:

Warning message: In is.na(g$server) : is.na() applied to non-(list or vector) of type 'S4'

This gives no warning but doesn't plot a basemap, only the vector

tm_shape(counties)+
  tm_borders(alpha=0.5)+
  tm_tiles(server=leaflet::providers$Stamen.TerrainBackground)

Interestingly, this works exactly as expected:

qtm(CBS_osm2)+
  tm_shape(counties)+tm_borders()

Perhaps there is simply some clarification needed in the documentation

enhancement

Most helpful comment

I use ceramic package and it is working great, tmap is a great package

just an example

library(ceramic)
Sys.setenv(MAPBOX_API_KEY = "get code from mapbox")
map <- st_as_sf(dataset, coords = c("x", "y"), crs = 4326)
background <- cc_location(map)
tm_shape(background)+
 tm_rgb() +

All 11 comments

Actually, it's not a bug, but lacking error handling and documentation. And, some food for discussion (see below).

Currently, tm_basemap and tm_tiles only work in view mode. The argument that they require is a url or name of a tile server. In plot mode, you'll need to explicitly read the tiles from a tile server and get a raster or a SpatialGridDataFrame object, which can indeed be done with read_osm. Such an object can be plot with tm_rgb, which is a shortcut of tm_raster.

So, this one works:
```{r}
tm_shape(CBS_osm2)+
tm_rgb() +
tm_shape(counties)+tm_borders()

which is equivalent to `qtm(CBS_osm2) + ...`

What I would like to achieve is similar syntax for the plot and view mode, which is one of the core principles of tmap. Ideally, this should work, also in plot mode:

```{r}
tm_basemap(leaflet::providers$Stamen.Terrain) +
tm_shape(counties)+tm_borders()

However, this requires on-the-fly downloading of tiles, which can take some time. To prevent over-querrying the tile-server, some caching may be worthwhile.

Another issue is that tmaptools::read_osm relies on OpenStreetMap, which has some downsides. First of all Java is required. Second, more importantly, the set of available tile-serves/shortcuts differ. For instance Stramen Terrain is called "Stamen-Terrain" in OpenStreetMap and "Stamen.Terrain" in leaflet.

Does anyone of you knows a good alternative to OpenStreetMap, of has some time to write code for downloading tiles?

Another thing regarding OSM data and read_osm, is that it relies on osmar for vectorized data, while osmdata is a much better alternative...

In plot mode, you'll need to explicitly read the tiles from a tile server and get a raster or a SpatialGridDataFrame object, which can indeed be done with read_osm.

Maybe you could help me out with this? Is there a way to read tiles from a tile server, other than from OSM? In my case satellite image data from PDOK (Dutch public geoservice) available as WMS, WMTS or TMS.

I would love it if it were easier to get tm_basemap and tm_tiles to work in plot mode.

The advice in the tmap docs is to use read_osm. I installed Java in order to get this working but it is not working for me (read_osm produces a 403 error when trying to download the tiles PNGs from OSM).

The documentation for osmdata says that it is for downloading vector data from OSM, not for raster files, and suggests using the OpenStreetMap package instead. But the last version of this 0.3.3 was released in 2016. It doesn't seem like osmdata is the right package to use to get the tiles that tmap would need.

I don't have enough knowledge to help fix this. Any ideas anyone? Does anyone have basemaps and overlays working in plot mode?

When I do:

tm_shape(shp) + tm_rgb()

I get the error

Error: shp consists of polygons, so it cannot accept tm_raster.

But qtm(shp) works fine - no error message - but no basemap either.

I use ceramic package and it is working great, tmap is a great package

just an example

library(ceramic)
Sys.setenv(MAPBOX_API_KEY = "get code from mapbox")
map <- st_as_sf(dataset, coords = c("x", "y"), crs = 4326)
background <- cc_location(map)
tm_shape(background)+
 tm_rgb() +

When I do read_osm(sf_dataset)

read_osm(sf_dataset, type = "osm")

I get an error:

Error in FUN(X[[i]], ...) : Sorry, parameter type `NA' is ambiguous or not supported.

Also, get the same result when running example code in the help document

@djouallah Can you explain more how you have this working? How does the data you have in map get projected onto your tm_shape object? You can plot the tiles sure, but I don't see how to add the data you actually want to add.

@gregmacfarlane just add another tm_shape(map)

library(sf)
library(dplyr)
library(tmap)
library(ceramic)
library(tmaptools)
Sys.setenv(MAPBOX_API_KEY = xxxxxxxxxx")
map <- st_as_sf(dataset, coords = c("x", "y"), crs = 4326)
background <- cc_location(map)
tm_shape(background)+
 tm_rgb() +
tm_shape(map) +
tm_symbols(col = "color", size = 0.04,shape=19)+

I saw this when you posted this originally @djouallah - and I've finally got around to using it myself.

This works great for me:

library(tmap)
library(ceramic)
library(osmdata)
#> Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright

ctr <- c(-1.25, 53.095)
bfr <- c(1.4e4, 1.7e4)

# other types are "mapbox.light", "mapbox.dark", "mapbox.satellite", "mapbox.streets",
# and in theory "mapbox.satellite-streets"... See:
# https://docs.mapbox.com/api/maps/#mapbox-styles
# https://hypertidy.github.io/ceramic/
ashfield_bg_outdoors <- cc_location(ctr, buffer = bfr, type = "mapbox.outdoors")
#> Preparing to download: 6 tiles at zoom = 11 from 
#> https://api.mapbox.com/v4/mapbox.outdoors/

tm_shape(ashfield_bg_outdoors) +
  tm_rgb() +
  qtm(osmdata::getbb(
    "Ashfield, Nottinghamshire",
    format_out = "sf_polygon"),
    fill = NULL,
    borders = "orange", lwd = 4)

Created on 2020-02-24 by the reprex package (v0.3.0)

My latest preferred solution to this is to use {mapmisc} instead of {ceramic}.

basemap_tiles <- mapmisc::openmap(shp, path = "hyda-base") # the spelling of "hydda" is wrong in the package
basemap <- tm_shape(basemap_tiles) + tm_rgb()

Lots of different map options not just the mapbox ones you get with ceramic.
And totally simple to use.

Just pointing back to a related thread in case anyone else ends up here looking for help with read_osm.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PauGallesClara picture PauGallesClara  路  8Comments

jannes-m picture jannes-m  路  5Comments

Nowosad picture Nowosad  路  4Comments

Nowosad picture Nowosad  路  5Comments

carbonmetrics picture carbonmetrics  路  3Comments