Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Workaround for Google Earth Engine Python API and no support for `ee.mapclient` in Python 3

So I was using Google Earth Engine and working through some of the example code in their repo. I am using Python 3.6. Looks like Google will not support the mapping functionality in Python 3 through their ee.mapclient() anymore. I was wondering if anyone has found a suitable workaround? Let me outline the problem.

I tried to load the ee.mapclient to plot a map.

import ee
import ee.mapclient
ee.Initialize()

But I got an error:

ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-13-6d4860410653> in <module>()
      1 import ee
----> 2 import ee.mapclient
      3 ee.Initialize()

/media/krishnab/lakshmi/anaconda3/envs/pMining/lib/python3.6/site-packages/ee/mapclient.py in <module>()
     29 
     30 import collections
---> 31 import cStringIO
     32 import functools
     33 import math

ModuleNotFoundError: No module named 'cStringIO'

The cStringIO problem is easy enough to resolve as per: python 3.4.0 email package install: ImportError: No module named 'cStringIO'

So I went to post an issue on the Google Earth Engine Repo, but found a preexisting issue:

https://github.com/google/earthengine-api/issues/16

In the issue the developers acknowledge the problem, but indicate that they will not fix it due to limitations with the underlying Tk package.

Here is a quote from the issue:

We have not been actively maintaining the mapclient object, because it depends on Tk, a graphical user interface toolkit, which behaves differently on different machines. Could you describe your use case that requires mapclient? We may be able to suggest an alternative approach.

The google developers offered to submit a workaround, but so far no workaround has been posted.

Hence, I was wondering if anyone else had found a suitable workaround in Python3.6 for this problem?

By way of a genuine code example, I can offer the code below from the Google examples repo:

import datetime
import ee
import ee.mapclient

ee.Initialize()
ee.mapclient.centerMap(-95.738, 18.453, 9)

# Filter the LE7 collection to a single date.
collection = (ee.ImageCollection('LE7_L1T')
              .filterDate(datetime.datetime(2002, 11, 8),
                          datetime.datetime(2002, 11, 9)))
image = collection.mosaic().select('B3', 'B2', 'B1')

# Display the image normally.
ee.mapclient.addToMap(image, {'gain': '1.6, 1.4, 1.1'}, 'Land')

# Add and stretch the water.  Once where the elevation is masked,
# and again where the elevation is zero.
elev = ee.Image('srtm90_v4')
mask1 = elev.mask().eq(0).And(image.mask())
mask2 = elev.eq(0).And(image.mask())
ee.mapclient.addToMap(
    image.mask(mask1), {'gain': 6.0, 'bias': -200}, 'Water: Masked')
ee.mapclient.addToMap(
    image.mask(mask2), {'gain': 6.0, 'bias': -200}, 'Water: Elev 0')
like image 911
krishnab Avatar asked Oct 26 '17 17:10

krishnab


People also ask

Does Google Earth Engine Support Python?

In addition to the web-based IDE Google Earth Engine also provides a Python API that can be used on your local machine without the need to utilize a browser, although the capabilities of this API are reduced compared to the Code Editor/IDE.

Is there an API for Google Earth?

The Earth Engine API is available in Python and JavaScript, making it easy to harness the power of Google's cloud for your own geospatial analysis.

What code language does Google Earth Engine use?

The Google Earth Engine uses the programming language JavaScript. Similarly to other programming languages, there is support online - you can google JavaScript and Earth Engine tutorials.


1 Answers

Not sure if there is still an issue with import ee.mapclient in Python 3 but here is a work around using the folium package that can have similar methods to the ee.mapclient. However, this was will render the result in your web browser and not as a popup window (unless using a Jupyter notebook, then you can just call the folium map object to render).

import ee
import folium
import datetime
import webbrowser

ee.Initialize()

class eeMapHack(object):
    def __init__(self,center=[0, 0],zoom=3):
        self._map = folium.Map(location=center,zoom_start=zoom)
        return

    def addToMap(self,img,vizParams,name):
         map_id = ee.Image(img.visualize(**vizParams)).getMapId()
         tile_url_template = "https://earthengine.googleapis.com/map/{mapid}/{{z}}/{{x}}/{{y}}?token={token}"
         mapurl = tile_url_template.format(**map_id)
         folium.WmsTileLayer(mapurl,name=name).add_to(self._map)

         return

    def addLayerControl(self):
         self._map.add_child(folium.map.LayerControl())
         return


# initialize map object
eeMap = eeMapHack(center=[18.453,-95.738],zoom=9)

# Filter the LE7 collection to a single date.
collection = (ee.ImageCollection('LE7_L1T')
          .filterDate(datetime.datetime(2002, 11, 8),
                      datetime.datetime(2002, 11, 9)))
image = collection.mosaic().select('B3', 'B2', 'B1')
eeMap.addToMap(image, {'gain': '1.6, 1.4, 1.1'}, 'Land')

# Add and stretch the water.  Once where the elevation is masked,
# and again where the elevation is zero.
elev = ee.Image('srtm90_v4')
mask1 = elev.mask().eq(0).And(image.mask())
mask2 = elev.eq(0).And(image.mask())

eeMap.addToMap(image.mask(mask1), {'gain': 6.0, 'bias': -200}, 'Water: Masked')
eeMap.addToMap(image.mask(mask2), {'gain': 6.0, 'bias': -200}, 'Water: Elev 0')

# add layer control to map
eeMap.addLayerControl()

outHtml = 'map.html' # temporary file path, change if needed
eeMap._map.save(outHtml)

webbrowser.open('file://'+outHtml) 

You should get an interactive web map in your browser with your analysis results that looks like this:

like image 120
Kel Markert Avatar answered Sep 20 '22 23:09

Kel Markert