4

I would like to use the calculated min/max values of an image region to set the min/max visualization parameters of that image. I can retrieve the actual numbers, but can't use them as variables in the visualization parameters block. I keep getting the error:

Shaded: Layer error: Can't encode object: abs()
Computes the absolute value of the input.
Args: this:input (Number): The input value.

Here's the code I'm using:

var fc = ee.FeatureCollection('TIGER/2018/States')
    .filter(ee.Filter.and(ee.Filter.eq('NAME', 'Utah')));

var DEM = ee.Image('USGS/NED').clip(fc);
var Terrain = ee.Terrain.products(DEM).select('slope');
print(Terrain);

var visPct = Terrain.reduceRegion({reducer: ee.Reducer.percentile([5,95]).setOutputs(['min','max']),
    geometry: fc,
    scale: 10, 
    bestEffort: true
  });

var Min = visPct.getNumber('slope_min');
var Max = visPct.getNumber('slope_max');
print(Min,Max);

var vizParams = {
  min: Min, 
  max: Max, 
  palette: ['blue','green','Yellow','red']
};

Map.centerObject(fc);
Map.addLayer(Terrain, vizParams, 'Shaded');

The only thing that I can figure out is that GEE is trying to display the image before the min/max values are calculated.

1
  • Use getInfo() or evaluate(). Make sure to read serverVSclient
    – Kuik
    Commented Jan 15, 2020 at 0:45

1 Answer 1

4

The Map.addLayer() visualization parameters are expected to be client-side JS objects, but you are providing server-side EE objects (ee.Number). Use the .evaluate() function to convert server-side objects to client-side objects.

Here, I've included the computed min and max values in an ee.Dictionary object and applied the .evaluate() function to it. A client-side dictionary object (dict) is made available within the scope of the anonymous function, where the min and max values can then be referenced and set as visualization parameters for displaying the image to the Map.

Code Editor script

var fc = ee.FeatureCollection('TIGER/2018/States')
  .filter(ee.Filter.eq('NAME', 'Utah'));

var DEM = ee.Image('USGS/NED').clip(fc);
var Terrain = ee.Terrain.products(DEM).select('slope');
print(Terrain);

var visPct = Terrain.reduceRegion({
  reducer: ee.Reducer.percentile([5,95]).setOutputs(['min','max']),
  geometry: fc,
  scale: 10, 
  bestEffort: true
});

// #########################################################
// ### ▼ EDITED ▼ ###
// #########################################################

var minMax = ee.Dictionary({
  minVal: visPct.getNumber('slope_min'),
  maxVal: visPct.getNumber('slope_max')
});

print(minMax);

minMax.evaluate(function(dict) {
  var vizParams = {
    min: dict.minVal, 
    max: dict.maxVal, 
    palette: ['blue','green','Yellow','red']
  };

  Map.centerObject(fc);
  Map.addLayer(Terrain, vizParams, 'Shaded');
});

1
  • Thanks! That worked perfectly. I still need to figure out the server/client side shift. Commented Jan 15, 2020 at 1:55

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