I am trying to find and mosaic the least cloudy Landsat 8 OLI scene per tile, filtered by my region and for the year 2015.

I tried using this post to do so. However, unlike Sentinel 2A, there is no unique tile identifier in L8 tiles. I will have to extract unique combinations of the PATH and ROW properties, which I do not know how to do. My code is below, where i get multiple errors- 1) I am unable to extract distinct combination of path and rows stored in tiles using .distinct() as only one property can be used 2) Even when using only PATH as a property in .distinct(), my error says that I am trying to compile a non-image element in var leastCloudy

But the main question I have is how do i filter the image collection to give me the least cloudy scene per tile in the L8 OLI image collection.

//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')
print ('L8 2015 image collection:',x1);
print('# images', x1.size()); //446 images

var max_x1=x1.max();
var visParams = {bands: ['B4', 'B3', 'B2']}; // Temporally composite the images with a maximum value function.
Map.addLayer(max_x1, visParams, 'max value composite');

// Load Footprint of Landsat WRS-2 grids
var wrs2_descending = ee.FeatureCollection('users/tnccarbonscience/wrs2_descending')
var wrs2_filtered = wrs2_descending.filterBounds(asset);
print('L8 tile info',wrs2_filtered);

var Tiles = ee.List(wrs2_filtered.distinct(["PATH"]).aggregate_array('PATH'));
print("List of unique L8 paths", Tiles);

//Extract least cloudy L8 scene in each tile
var leastCloudyPerPathRow = ee.ImageCollection.fromImages(Tiles.map(function(tile){
var filtCol = x1.filter(ee.Filter.eq("PATH", tile));
var leastCloudy =  ee.Image(filtCol.sort('CLOUDY_PIXEL_PERCENTAGE').first());
return leastCloudy;
print ("Size of least cloudy image collection",leastCloudyPerPathRow.size());
print ("least cloudy image collection",leastCloudyPerPathRow);

1 Answer 1


Yes, it is quite well doable to get the least cloudy image per distinct path and row for landsat.

First we have to get a list of distincts paths and rows to map over:

// 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)

Once we have that, we can map over the different paths and rows and filter the collection on those. With sort and first we can get the least cloudy. But note that tat does not guarantue the image is actually cloud free. Also, landsat SR should be filtered on 'CLOUD_COVER'.

//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)));
    return images.sort('CLOUD_COVER').first();
  return imagePerRow;
var leastCloudies = ee.ImageCollection.fromImages(imagePerPath.flatten());

Then print it in the console or on the map

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


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.