Search code examples
javascriptgoogle-earth-enginesentinel2

Converting an imageCollection into a dictionary with unique label values


I am trying to write a function which will create a dictionary from an image collection using Sentinel 2 data which will contain label/value pairs where the label comes from the MGRS_TILE property of the image and the value will contain a list of all the images with the same MGRS_TILE id. The label values must be distinct.I want the output to be like this: {'label' : 'tileid1', 'values':[ image1, image2 ...] 'label' : 'tileid2', 'values':[ image3, image4 ...]}

Below is my code: interestImageCollection is my filtered imageCollection object tileIDS is a ee.List type object containg all of the distinct tile ids and field is the name of the image property of my interest which in this case is 'MGRS_TILE'.

var build_selectZT = function(interestImageCollection, tileIDS, field){

  //this line returns a list which contains the unique tile ids thanks to the keys function
  //var field_list = ee.Dictionary(interestImageCollection.aggregate_histogram(field)).keys();

  //.map must always return something
  var a = tileIDS.map(function(tileId) {
    var partialList=ee.List([]);
    var partialImage = interestImageCollection.map(function(image){
      return ee.Algorithms.If(ee.Image(image).get(field)==tileId, image, null);
    });
    partialList.add(partialImage);
    return ee.Dictionary({'label': tileId, 'value': partialList});
  }).getInfo();
  return a;
};

Unfortunately the above function gives me this result: {'label' : 'tileid1', 'values':[], 'label' : 'tileid2', 'values':[]}


Solution

  • I think you can use filter function instead of using if. And if you need it in list form then you could change it to list using toList function.

    var build_selectZT = function(interestImageCollection, tileIDS, field){
      //.map must always return something
      var a = tileIDS.map(function(tileId) {
        var partialList=ee.List([]);
        // get subset of image collection where images have specific tileId
        var subsetCollection = interestImageCollection.filter(ee.Filter.eq(field, tileId));
        // convert the collection to list
        var partialImage = subsetCollection.toList(subsetCollection.size())
        partialList.add(partialImage);
        return ee.Dictionary({'label': tileId, 'value': partialList});
      }).getInfo();
      return a;
    };
    

    BUT this would actually give you a list of dictionaries

    [{'label':'id1','value':[image1]},{'label':'id2','value':[image2,image3]......}]
    

    If you want to use ee.Algorithms.If like you did in your code then your error is in the "ee.Image(image).get(field)==tileId" part. as .get(field) is returning a server side object, you can't use == to equate it to something, since it is an string type you need to use compareTo instead. However, it returns 0 if the strings are same and since 0 is treated as false, you can return image when condition is false.

    return ee.Algorithms.If(ee.String(ee.Image(image).get(field)).compareTo(tileId), null, image);
    

    I still think this is a bad way as you'll get an array full of null in values like

    [{'label':'id1','value':[image1, null, null, null, .....]},{'label':'id2','value':[null,image2,image3, null,....]......}]