When clicking on a GEE map, I would like to get the value of an Image
's (1-band raster) pixel.
I'm using Map.onClick
to extract values from point on a map. According to GEE examples (e.g. https://developers.google.com/earth-engine/tutorial_api_03), xx.reduceRegion(ee.Reducer.mean(), clickpoint, scale)
should work for ImageCollection
objects but does not seem to work for Image
objects.
// Load 1-band image
var dataset = ee.Image('WWF/HydroSHEDS/03VFDEM').select('b1');
print(dataset);
Map.style().set('cursor', 'crosshair');
Map.addLayer(dataset);
// Following is adapted from https://code.earthengine.google.com/?scriptPath=Examples:User+Interface/Ocean+Timeseries+Investigator
// Set a callback function for when the user clicks the map.
var header = ui.Label('Some text', {fontWeight: 'bold', fontSize: '18px'});
var toolPanel = ui.Panel([header], 'flow', {width: '400px'});
Map.onClick(function(coords) {
// Create or update the location label (the second widget in the panel)
var location = 'lon: ' + coords.lon.toFixed(4) + ' ' +
'lat: ' + coords.lat.toFixed(4);
var click_point = ee.Geometry.Point(coords.lon, coords.lat);
var demValue = dataset.reduceRegion(ee.Reducer.first(), click_point, 90);
var demText = 'Habitat suitability: ' + demValue;
// var demText = 'Habitat suitability: ' + demValue.get('b1');
toolPanel.widgets().set(1, ui.Label(location));
toolPanel.widgets().set(2, ui.Label(demText));
// Add a red dot to the map where the user clicked.
Map.layers().set(1, ui.Map.Layer(click_point, {color: 'FF0000'}));
});
// Add the panel to the ui.root.
ui.root.add(toolPanel);
Using demValue
directly or demValue.get('b1')
doesn't change anything.
The resulting panel gives (-86.6746,35.3036 being a random point):
Some text
lon: -86.6746 lat: 35.3036
Habitat suitability:
ee.Dictionary({ "type": "Invocation", "arguments": { "image": {
"type": "Invocation", "arguments": { "input": { "type": "Invocation",
"arguments": { "id": "WWF/HydroSHEDS/03VFDEM" }, "functionName":
"Image.load" }, "bandSelectors": [ "b1" ] }, "functionName":
"Image.select" }, "reducer": { "type": "Invocation", "arguments": {},
"functionName": "Reducer.first" }, "geometry": { "type": "Point",
"coordinates": [ -86.67460937499999, 35.30364788916715 ] }, "scale":
90 }, "functionName": "Image.reduceRegion" })
GEE script: https://code.earthengine.google.com/1204e25cbbdb782d9af4c7944d047bf2
Best Answer
To add to @Rodrigo's answer. You definitely need to bring the data to client side before you can display it on your UI. BUT since you are dealing with UI, you definitely don't want the application to freeze when you click on map. So it might be a better idea to use the evaluate function instead which will run the data fetching process in the background without stopping the UI functions. You can even temporarily set the label as something like loading... An implementation of it within the onClick function could be