My goal is to write code that will pull all Landsat 8 scenes available for a given month in a given year for the US, add a cloud score band to each image, and if there are multiple images for the same location (which I plan to define using the WRS_PATH and WRS_ROW properties), pull the least cloudy image into a new image collection.

So far, I have written/pulled code to filter the Landsat scenes and add a cloud score band to them. I am stuck with the conditional.

See my code below - any ideas??

// Load a region representing the United States.
var US = ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw')
.filter(ee.Filter.eq('Country', 'United States'));

// SimpleCloudScore, an example of computing a cloud-free composite with L8
// by selecting the least-cloudy pixel from the collection.

// A mapping from a common name to the sensor-specific bands.
var LC8_BANDS = ['B2',   'B3',    'B4',  'B5',  'B6',    'B7',    'B10'];
var STD_NAMES = ['blue', 'green', 'red', 'nir', 'swir1', 'swir2', 'temp'];

// Compute a cloud score.  This expects the input image to have the common
// band names: ["red", "blue", etc], so it can work across sensors.
var cloudScore = function(img) {
  // A helper to apply an expression and linearly rescale the output.
  var rescale = function(img, exp, thresholds) {
    return img.expression(exp, {img: img})
        .subtract(thresholds[0]).divide(thresholds[1] - thresholds[0]);

  // Compute several indicators of cloudyness and take the minimum of them.
  var score = ee.Image(1.0);
  // Clouds are reasonably bright in the blue band.
  score = score.min(rescale(img, 'img.blue', [0.1, 0.3]));

  // Clouds are reasonably bright in all visible bands.
  score = score.min(rescale(img, 'img.red + img.green + img.blue', [0.2, 0.8]));

  // Clouds are reasonably bright in all infrared bands.
  score = score.min(
      rescale(img, 'img.nir + img.swir1 + img.swir2', [0.3, 0.8]));

  // Clouds are reasonably cool in temperature.
  score = score.min(rescale(img, 'img.temp', [300, 290]));

  // However, clouds are not snow.
  var ndsi = img.normalizedDifference(['green', 'swir1']);
  return score.min(rescale(ndsi, 'img', [0.8, 0.6]));

// Filter the TOA collection to a time-range and add the cloudscore band.
var collection = ee.ImageCollection('LC8_L1T_TOA')
    .filterDate('2016-01-01', '2016-01-31')
    .map(function(img) {
      // Invert the cloudscore so 1 is least cloudy, and rename the band.
      var score = cloudScore(img.select(LC8_BANDS, STD_NAMES));
      score = ee.Image(1).subtract(score).select([0], ['cloudscore']);
      return img.addBands(score);

// Check: How many landsat scenes are in this collection?
var count = collection.size();
print('Number of Landsat scenes in collection:', count);

// Create a function that says if two Landsat scenes have been pulled for the same location, selected the scene with the lower cloud score. If only one scene has been pulled, select that. Add all selected scenes to a new ImageCollection.
var conditional = function(image) {
  return ee.Algorithms.If('WRS_PATH'



  • Any particular reason you are filtering the L1T TOA data per-scene instead of using the cloud masked data from the SR dataset which allows you to filter clouds per-pixel? – Kersten Dec 22 '18 at 9:09
  • The cloud score you're computing is per-pixel, not per-image, so you can't select an "image" based on it. If you're just trying to get the least cloudy value in each pixel, then use qualityMosaic() on the cloudscore band. – Noel Gorelick Dec 29 '18 at 18:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.