Google Earth Engine – Extracting Second Least Cloudy Image at Distinct Path and Row in Landsat

google-earth-enginegoogle-earth-engine-javascript-api

I am trying to extract the second least cloudy image at every distinct path and row in Landsat Google Earth Engine. Below is my code, which is a modified version of Filtering Landsat8 image collection to one scene per row/path and mosaic. I was able to extract the first image using images.first(), but when I tried to get the second image per tile in the collection, there's always this error: EEException: Collection.toList: The value of 'count' must be positive. Got: 0.

Can someone help me resolve this?

The link to the code is here.

//2. Loading L8 image collection (TOA reflectance)
var l8_collection= ee.ImageCollection('LANDSAT/LC08/C01/T1_SR');

//3. Filter by time window (Jan 2015- Dec 2015) for region (private asset)
var x1= l8_collection.filterBounds(asset)
                  .filterDate('2015-01-01', '2015-12-31')
                  .sort('CLOUD_COVER');
print ('L8 2015 image collection:',x1);
print('# images', x1.size()); //446 images

// extract the different rows and paths
var distinctRows = ee.List(x1.distinct(['WRS_ROW']).aggregate_array('WRS_ROW'));
var distinctPaths = ee.List(x1.distinct(['WRS_PATH']).aggregate_array('WRS_PATH'));
print(distinctRows, distinctPaths)

//Extract least cloudy L8 scene in each tile
var imagePerPath = distinctPaths.map(function(path){
  var imagePerRow = distinctRows.map(function(row){
    var images = x1.filter(ee.Filter.and(ee.Filter.eq('WRS_ROW', row), ee.Filter.eq('WRS_PATH', path))).sort('CLOUD_COVER');
        var list = images.toList(images.size())
        var img=ee.Image(list.get(1))
        
        return img
  });
  return imagePerRow;
});
var leastCloudies = ee.ImageCollection.fromImages(imagePerPath.flatten());

// print and add the geometries of the images to the map
print(leastCloudies);
Map.addLayer(ee.FeatureCollection(leastCloudies.map(function(image){return image.geometry()})))

Best Answer

There's probably some path/row combinations which do not exist. In that case images.size() is 0. You could fix that by getting the distinct paths within the map call. Something like this should work:

// extract the different rows and paths
var distinctPaths = ee.List(x1.distinct(['WRS_PATH']).aggregate_array('WRS_PATH'));
print(distinctPaths)

//Extract least cloudy L8 scene in each tile
var imagePerPath = distinctPaths.map(function(path){
  var paths = x1.filter(ee.Filter.eq('WRS_PATH', path))
  var distinctRows = ee.List(paths.distinct(['WRS_ROW']).aggregate_array('WRS_ROW'));
  var imagePerRow = distinctRows.map(function(row){
    var images = paths.filter(ee.Filter.eq('WRS_ROW', row)).sort('CLOUD_COVER');
        var list = images.toList(images.size())
        var img = ee.Image(list.get(1))
        
        return img
  });
  return imagePerRow;
});