Search code examples
pythongoogle-earth-engine

Google Earth Engine Geometry constructor problem on python API


I have a table with coordinates and dates loaded as an Asset. With the javascript API I was able to sample a collection per date and respective coordinate using the function below applied to the asset:

var extract_pts = test.map(function(feat){
  // Get date from each pts feature and convert to date object
  var date = ee.Date.parse('YYYY-MM-dd HH:mm:ss', feat.get('date'));
  // Create range to filter image before or after 10-15 minutes
  var start = date.advance(-10, 'minute');
  var end = date.advance(20, 'minute');
  
  // Filter using the date ranges and get first image
  var filtered_img = filtered.filterDate(start, end).first();

  var training = ee.Algorithms.If(
    filtered_img, 
    filtered_img.sample({
      region: feat.geometry(),
      scale: 2000,
      geometries: true
    }).set('isNull', false),
    ee.Image(0).selfMask().set('isNull', true)
  ); // if there is data, flag isNull = false; else, flags true
 
  return training;

In the code editor, everything worked fine.

Then, I tried reproducing it with the Python API through google colab. So, I imported the Asset as an ee.FeatureCollection and have re-written the function as follows:

def extract_values(feat):
  # get the date and convert to an ee object
  date = ee.Date.parse('YYYY-MM-dd HH:mm:ss', feat.get('date'))

  # sample on an interval
  start =  date.advance(-10, 'minute')
  end = date.advance(20, 'minute')

  # sample first available image
  filtered_img = filtered.filterDate(start, end).first()

  # checking if there are available data in the time range of interest
  # in case the isn't, it will flag isNull as True
  training_samps = (ee.Algorithms.If(
      filtered_img,
      filtered_img.sample({
          'region': feat.geometry(),
          'scale': 2000,
          'geometries': True
      }).set('isNull', False),
      ee.Image(0).selfMask().set('isNull', True)
  ))

  return training_samps

And when I apply it to the Asset with map(), I get: EEException: Invalid GeoJSON geometry.

I checked if the Asset is being read correctly with: relatos_asset.limit(1).geometry().coordinates().getInfo() which returns the lon, lat correctly:

[-51.18999851064491, -22.990001338101475]

and relatos_asset.limit(1).geometry().getInfo() that returns:

{'coordinates': [-51.18999851064491, -22.990001338101475], 'type': 'Point'}

I even tried using the Geometry Point constructor inside the sample function with the geometry().coordinates() but I got the same Exception.

Can anyone help?


Solution

  • To anyone with the same problem, I found the solution in this thread of the GEE Developers Google Group.

    The Python API does not take dictionaries as arguments into functions. Adding ** in front of the dictionary worked for me:

    training_samps = (ee.Algorithms.If(
          filtered_img,
          filtered_img.sample(**{
              'region': feat.geometry(),
              'scale': 2000,
              'geometries': True
          }).set('isNull', False),
          ee.Image(0).selfMask().set('isNull', True)
      ))