Search code examples
javascriptgoogle-earth-engine

Is there a way to be sure that the mosiaic you're creating with help of Googles Earth Engine is complete?


As stated in the heading - we're trying to use the data out of the mosaic for a project but the data will only make sense when the mosaic is actually completed. So if the area we choose is too big, the satellite might not get over the spot in the span of a day which would make the result incomplete. So is there a way to only get the results of 100% complete mosaics?

Here is the code we're using:

// Difference in days between start and finish
var diff = finish.difference(start, 'day');

// Make a list of all dates
var range = ee.List.sequence(0, diff.subtract(1)).map(function(day){return start.advance(day,'day')});

// Funtion for iteraton over the range of dates
var day_mosaics = function(date, newlist) {
  // Cast
  date = ee.Date(date);
  newlist = ee.List(newlist);

  // Filter collection between date and the next day
  var filtered = collection.filterDate(date, date.advance(1,'day'));

  // Make the mosaic and clip to aoi
  var clipped = ee.Image(filtered.mosaic().clip(aoi)).setMulti({'system:time_start': date});

  var footprint = ee.Feature(clipped.get('system:footprint'));

  // Add the mosaic to a list only if the collection has images
  return ee.List(ee.Algorithms.If(footprint.area().eq(aoi.area()), newlist.add(clipped), newlist));
};

// Iterate over the range to make a new list, and then cast the list to an imagecollection
var mosaic = ee.ImageCollection(ee.List(range.iterate(day_mosaics, ee.List([]))));
print(mosaic);

Solution

  • You've already got the idea of looking at the footprint, but it would be more accurate to

    • use the mask pixels instead of the footprint geometry, in case there are any holes in the image, and
    • instead of counting the valid areas, find out if there are any invalid areas.
    var missingPixels = image
      .mask()  // Get the mask data as an image
      .reduce(ee.Reducer.min()) // Take the least coverage across all bands
      .expression('1 - b(0)')  // Invert the value
      .rename(['missing_pixels']);  // Give the result a better name
    
    // Sum up missing pixel indications; if nonzero, some are missing. Pick a scale that is good enough for your purposes.
    var noMissingPixels = missingPixels.reduceRegion({
      geometry: aoi,
      reducer: ee.Reducer.sum(),
      scale: 100
    }).getNumber('missing_pixels').eq(0);
    print(noMissingPixels);
    

    https://code.earthengine.google.com/2dff320b7ab68e27e3acbd96efa23e4b

    Additional advice: iterate() to collect a list result is inefficient and should be avoided whenever practical. When you want to process a collection and discard some elements, you can use map() with the dropNulls parameter set to true, and return null for any element you don't want to keep:

    var day_mosaics = function(date) {
      ... regular code goes here, but no 'newlist' ...
    
      return ee.Algorithms.If(noMissingPixels, clipped, null);
    };
    
    var mosaic = ee.ImageCollection(range.map(day_mosaics, true));
    

    This will work well with very large collections whereas building a list may run out of memory.