[GIS] Mapping simple function to print date and time stamp on Google Earth Engine Python API

datetimegoogle-earth-enginegoogle-earth-engine-python-api

I am new to the Google Earth Engine Python API, and I am trying to create functions that when mapped over a collection will print some metadata (e.g. time stamp, band names) but I always get the same error:

EEException: ValueNode is empty

Here is the code:

import ee
ee.Authenticate()
ee.Initialize()

# Getting the Sentinel 1 image over the study site
collection = ee.ImageCollection('COPERNICUS/S1_GRD').filterBounds(ee.Geometry.Point(121.1737372,24)).filterDate('2019-01-01','2019-01-30')
collectionList = collection.toList(collection.size())
sentinel1 = ee.Image(collectionList.get(1)).select('VH')

##Function to print the dates of a collection
def printDate(image):
  date = ee.Date(image.get('system:time_start'))
  print('Time stamp:'+str(date.format('Y-M-d').getInfo()))

collection.map(printDate)

def collectionBands(img):
  bands = img.bandNames()
  print('band names:'+str(bands.getInfo()))

collection.map(collectionBands)

Best Answer

From the JavaScript docs (it's essentially identical to the Python docs, but easier to get to, as it's there in the code editor):

ImageCollection.map(algorithm, dropNulls)

[...]

algorithm (Function): The operation to map over the images or features of the collection. A JavaScript function that receives an image or features and returns one. The function is called only once and the result is captured as a description, so it cannot perform imperative operations or rely on external state.

[...]

This is a bit cryptical, but it implies that it doesn't make sense to print inside the function you pass to .map(). The function is called only once, no matter how many images you have in the collection. In addition to this, you'll get an error if you call .getInfo() inside that function, and the function must return an ee.Feature or ee.Image.

Here's how you could get the dates and band names printed:

collection = ee.ImageCollection('COPERNICUS/S1_GRD') \
    .filterBounds(ee.Geometry.Point(121.1737372,24)) \
    .filterDate('2019-01-01','2019-01-30')

dates = ee.List(collection \
    .aggregate_array('system:time_start')) \
    .map(lambda time_start: 
         ee.Date(time_start).format('Y-MM-dd')
    ) \
    .getInfo()

band_names = collection \
    .map(lambda image: 
         image.set('bandNames', image.bandNames())
   ) \
    .aggregate_array('bandNames') \
    .getInfo()

for date in dates:
    print(date)

for band_name in band_names:
    print(band_name)