1

I need to view imagery from a collection as separate layers. Since I have to do this for several sites and the number of images in the collection therefore varies, I tried to apply a for loop to solve this.

My working code without for loop looks like this:

// Load a landsat image and select three bands for Mount Spurr

// HSV-based Pan-Sharpening of Landsat 7 TOA images.
var panSharpenL8 = function(image) {
  var rgb = image.select('B3', 'B2', 'B1');
  var pan = image.select('B8');
  // Convert to HSV, swap in the pan band, and convert back to RGB.
  var huesat = rgb.rgbToHsv().select('hue', 'saturation');
  var upres = ee.Image.cat(huesat, pan).hsvToRgb();
  return image.addBands(upres);
};


var dataset = ee.ImageCollection('LANDSAT/LE07/C01/T1_TOA')
                  .filterDate('2004-04-01', '2006-06-30')
                  .sort('system:time_start')
                  .map(panSharpenL8)


// short form
var Image_filtered = dataset.filterBounds(geometry_Mount_Spurr)
.filterMetadata('CLOUD_COVER','less_than',10)
print(Image_filtered.size())

var listOfImages = Image_filtered.toList(Image_filtered.size());
print('List:',listOfImages);

var img1 = ee.Image(listOfImages.get(0));
var img2 = ee.Image(listOfImages.get(1));
var img3 = ee.Image(listOfImages.get(2));
var img4 = ee.Image(listOfImages.get(3));
var img5 = ee.Image(listOfImages.get(4));
var img6 = ee.Image(listOfImages.get(5));
var img7 = ee.Image(listOfImages.get(6));
var img8 = ee.Image(listOfImages.get(7));
var img9 = ee.Image(listOfImages.get(8));
var img10 = ee.Image(listOfImages.get(9));
var img11 = ee.Image(listOfImages.get(10));
var img12 = ee.Image(listOfImages.get(11));
var img13 = ee.Image(listOfImages.get(12));
var img14 = ee.Image(listOfImages.get(13));
var img15 = ee.Image(listOfImages.get(14));
var img16 = ee.Image(listOfImages.get(15));
var img17 = ee.Image(listOfImages.get(16));
var img18 = ee.Image(listOfImages.get(17));

// add pansharpened bands

Map.addLayer(img1, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img2, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img3, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img4, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img5, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img6, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img7, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img8, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img9, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img10, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img11, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img12, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img13, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img14, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img15, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img16, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img17, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
Map.addLayer(img18, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');



//Map.addLayer(Image_filtered, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');

As you can see, there are many Map.addLayer expressions. I wish to not copy and paste the lines to add each image to the Map, so I built an ee.List and looped like this:

var listOfImages = ee.List(Image_filtered);
print('List:',listOfImages);

var len = listOfImages.length;

for (var i=0; i < len; i++) {
  var img = ee.Image(listOfImages.get(i));
  Map.addLayer(img, {bands:['red','green','blue'], max: 0.3}, 'Pansharpened');
}

However, it does not add layers to the map and does not result in an error message.

How do I solve the problem?

1 Answer 1

0

The listOfImages variable is a server-side ee.List object and has no length property (length is a property of a client-side JS list object), so when you use it to define the len variable it produces a function, which likely results in a null value when you try to use it to bound the for loop.

What you need to do is use .size() on the listOfImages variable and then convert the result to a client-side object for bounding the for loop. Use the .evaluate() method to safely convert server-side objects to client-side objects.

// Get the size of the image list (this is a server side ee.Number object).
var len = listOfImages.size();

// Call `.evaluate()` on `len` to convert it from server-side object to a
// client-side object available within the scope of the anonymous function as `l`.
len.evaluate(function(l) {
  for (var i=0; i < l; i++) {
    var img = ee.Image(listOfImages.get(i));
    Map.addLayer(img, {bands:['red','green','blue'], max: 0.3}, 'Img-'+i.toString());
  } 
});

Please see the Client vs. Server section of the Developer Guide for more information.

3
  • Thank you so much! You solved my problem! If I am right, the problem was, that I tried to execute the for loop on the client-side, but the object to iterate on was server-side... However, I am wondering, why ee.List.length() is listed in the google earth engine Docs!
    – MMartin
    Commented Jan 21, 2020 at 13:47
  • I'm glad it worked for you! Your assessment of the problem is correct: mixing server-side objects with client-side operations. You are right about .length() being a method of ee.List objects. What I intended to say was "property" instead of "method". Your use of .length is intended for client-side JS objects - it fetches the "length" property of the object through dot notation, but an ee.List object has no such property (at least not accessible through JS object dot notation). I've updated my answer to clarify this. Commented Jan 21, 2020 at 16:17
  • Ok, this makes it more clear, thanks!
    – MMartin
    Commented Jan 21, 2020 at 16:58

Your Answer

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

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