3

I want to create a select menu which lists all datasets in an ImageCollection. When the user selects an item, the referenced dataset should be displayed in the map. Here's a static example that works and illustrates my approach so far...

Step 1 - Acquire L8 scenes for region of interest and create a list of what should be the label-value pairs for the select menu:

var roi = ee.Geometry.Rectangle(113, 53.5, 114, 54); 
Map.centerObject(roi);
Map.addLayer(roi);

var landsatCollection = ee.ImageCollection("LANDSAT/LC08/C01/T1_TOA")
    .filterBounds(roi);

var sat_scene_dict = landsatCollection.map(function(sat_scene) {
  var dict = {
    value: sat_scene.id(),
    label: sat_scene.get('DATE_ACQUIRED'), 
  };
  return ee.Feature(sat_scene.geometry(), dict);
});

Step 2 - Initialize select items and populate with values

var imageSelect = ui.Select({
  items: [ // Replace this part with labels/value from the list of scenes
    {label: '2013-06-16', value: 'LC08_128022_20130616'},
    {label: '2015-05-21', value: 'LC08_128023_20150521'}
  ], 
  onChange: function(value) {
    var selected_scene = 
        landsatCollection.filter(ee.Filter.eq('system:index', value));
    Map.addLayer(selected_scene, {bands: ['B3', 'B2', 'B1']}, 'Selected scene');
  }
});

So, the whole problem is about how to populate the 'items' of ui.Select with label-value pairs from the list of scenes. As soon as I put any form of sat_scene_dict to items I get errors in in the form of The argument provided to ui.List.reset() must be an array.. I have tried to convert the sat_scene_dict to a list of dictionaries as in the static version but keep getting errors that map must return features or images.

1 Answer 1

4

The problem is that sat_scene_dict is a FeatureCollection (i.e. a remote not-yet-computed collection of features), not an array.

To initialize a ui.Select drop-down, you need a plain old JavaScript array, which you can get using the getInfo() method on FeatureCollection:

var features = sat_scene_dict.getInfo()['features'];
var select_items = []
for (var i = 0; i < features.length; i++) {
  select_items.push({
    label: features[i]['properties']['label'],
    value: features[i]['properties']['value']
  })
}

var imageSelect = ui.Select({
  items: select_items,
  onChange: function(value) {
    var selected_scene = 
        landsatCollection.filter(ee.Filter.eq('system:index', value));
    Map.addLayer(selected_scene, {bands: ['B3', 'B2', 'B1']}, 'Selected scene');
  }
});

getInfo() causes the FeatureCollection to be computed (aka materialized) and stored in a plain JavaScript object, from which you can extract whatever data you need.

Note: The print command is very useful for debugging these intermediate data types, e.g. print(features).

2
  • i got the error: Argument 1 of Node.appendChild does not implement interface Node. If i delete the ['features'] in line 1 the error disappear but the select_items is now empty. What can i do? Commented Feb 27, 2019 at 20:49
  • 1
    I'd suggest calling print(sat_scene_dict) to make sure it is indeed a FeatureCollection or ImageCollection before trying to extract features from it.
    – Newtonx
    Commented Feb 28, 2019 at 16:44

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.