1

I am trying to plot an earth engine image using Python and the Folium package as described in the Python docs for Earth Engine. I tried running the example code given and I can't seem get the image to show up when saving as an HTML and opening in the browser. The getMapID() method always returns a token as empty string as in: mapID['token'] = ''. Does anyone know a way to get Earth Engine map tiles to show up on a Folium interactive map?

I also tried using the folium_gee functions by mccarthyryanc and ran into the same issues, the basemap shows up but not the tiles.

# Import libraries.
import ee
import folium

# Initialize the Earth Engine library.
ee.Initialize()

# Define a method for displaying Earth Engine image tiles to folium map.
def add_ee_layer(self, eeImageObject, visParams, name):
  mapID = ee.Image(eeImageObject).getMapId(visParams)
  folium.raster_layers.TileLayer(
    tiles = "https://earthengine.googleapis.com/map/"+mapID['mapid']+
      "/{z}/{x}/{y}?token="+mapID['token'],
    attr = "Map Data © Google Earth Engine",
    name = name,
    overlay = True,
    control = True
  ).add_to(self)

# Add EE drawing method to folium.
folium.Map.add_ee_layer = add_ee_layer

# Fetch an elevation model.
dem = ee.Image('USGS/SRTMGL1_003')

# Set visualization parameters.
visParams = {'min':0, 'max':3000, 'palette':['225ea8','41b6c4','a1dab4','ffffcc']}

# Create a folium map object.
myMap = folium.Map(location=[20, 0], zoom_start=3, height=500)

# Add the elevation model to the map object.
myMap.add_ee_layer(dem, visParams, 'DEM')

# Add a layer control panel to the map.
myMap.add_child(folium.LayerControl())

# Display the map.
myMap.save("myMap.html")

2 Answers 2

2

Please note that the current recommended method for defining the tiles argument is as follows:

# Define a method for displaying Earth Engine image tiles to folium map.
def add_ee_layer(self, eeImageObject, visParams, name):
  map_id_dict = ee.Image(eeImageObject).getMapId(visParams)
  folium.raster_layers.TileLayer(
    tiles = map_id_dict['tile_fetcher'].url_format,
    attr = "Map Data &copy; <a href='https://earthengine.google.com/'>Google Earth Engine</a>",
    name = name,
    overlay = True,
    control = True
  ).add_to(self)

I see you found a workaround, but does this resolve your issue as well?

1
  • 1
    PS: the Developer Guide is being updated to reflect the change. Nov 18, 2019 at 21:27
1

Turns out the URL format is a little different than what is posted in the docs currently. The code above gives a url string of:

https://earthengine.googleapis.com/map/projects/earthengine-legacy/maps/<Map Id>/{z}/{x}/{y}?token=

Which I believe from this post is depreciated and the url no longer needs the token. If instead you use the command:

ee.data.getTileUrl(image.getMapId({visParams}), 8014,4817, 37)

You get something like:

https://earthengine.googleapis.com/v1alpha/projects/earthengine-legacy/maps/<Map Id #>/tiles/37/8014/4817

where the (x,y,z) values are arbitrary, if you then replace "37/8014/4817" with "{z}/{x}/{y}" to get:

https://earthengine.googleapis.com/v1alpha/projects/earthengine-legacy/maps/<Map Id #>/tiles/{z}/{x}/{y}

is a valid URL and can plot with folium's TileLayer class. This definition of adding a layer to the folium map worked for me.

def add_ee_layer(self, eeImageObject, visParams, name):
  tiles = ee.data.getTileUrl(eeImageObject.getMapId(visParams), 8014, 4817, 37)
  tiles = tiles[:-12] + "{z}/{x}/{y}"
  folium.raster_layers.TileLayer(
    tiles = tiles,
    attr = "Map Data © Google Earth Engine",
    name = name,
    overlay = True,
    control = True
  ).add_to(self)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.