TransWikia.com

Converting results of reduceRegion in GEE to something that can be passed as visualization parameter

Geographic Information Systems Asked by majemc on December 9, 2020

I’m trying to dynamically set my visualization parameters based on the range of pixel values in my layer of interest. This seems like something that should be easy to do, since visualizing any given dataset requires you to understand the range of values that you’re working with, and yet until recently, the only way I could figure out how to do this was by printing out the 1st and 99th percentile pixel values (obtained using reduceRegion), and then setting that by hand as my min and max in my visualization parameters.

Now, I’m using .getInfo() to convert the results of my reduceRegion percentile function to numbers that can be passed to my viz params. However, GEE warns against using .getInfo(), and indeed it is working very slowly and crashing my webpage fairly frequently. Does anyone have a superior solution to dynamically set viz params based on the range of pixel values in a band that doesn’t involve calling .getInfo()?

Here’s my code, which works, but slowly and sometimes crashes.

// Load an input region: CA
var ca_counties = ee.FeatureCollection('TIGER/2016/Counties').filter(ee.Filter.eq('STATEFP', '06'));
var ca = ca_counties.union(); //making into one state instead of many counties

//Loading AOD data
var start_date = '2019-03-01';
var end_date = '2019-07-01';
var aod = ee.ImageCollection("MODIS/006/MCD19A2_GRANULES");

       
function get_state_mean(image_collection, band, state_borders, start_date, end_date) {
  var aod_state = ee.ImageCollection(image_collection)
        .filterDate(ee.String(start_date), ee.String(end_date))
        .select(ee.String(band))
        .reduce(ee.Reducer.mean())
        .clip(ee.FeatureCollection(state_borders))
  return aod_state;
}

// Get statewide mean AOD by pixel
var aod_ca = get_state_mean(aod, 'Optical_Depth_047', ca, start_date, end_date);

// Get scale (in meters) information from Optical Depth band
var aod_scale = aod_ca.projection().nominalScale();
print('Optical_Depth_047_mean', aod_scale); // ee.Number


//Getting viz parameters--min and max
var percentClip = aod_ca.reduceRegion({
  reducer: ee.Reducer.percentile([1, 99]),
  geometry:ca,
  scale: aod_scale,
  maxPixels: 3e7
});
var keys = percentClip.keys();

var palette = ['#00abff','#95bd00','e5e700','#cc2900','#a400c3'];
var viz = {palette: palette, 
  min: ee.Number(percentClip.get(keys.get(0))).getInfo(), // <<< THE QUESTIONABLE PART
  max: ee.Number(percentClip.get(keys.get(1))).getInfo()  // <<< THE QUESTIONABLE PART
}

Map.addLayer(aod_ca, viz, 'ca aod');

One Answer

Two things:

  • Use .evaluate() with a callback instead of .getInfo(). This means the page will not freeze while the computation is happening.
  • Use one such call, not two. Right now, you're requesting basically the same computation twice; fitting it into one computation will take half the time.
// Renaming the band will make for predictable output keys
var percentClip = aod_ca.rename('v').reduceRegion({
  reducer: ee.Reducer.percentile([1, 99]),
  geometry:ca,
  scale: aod_scale,
  maxPixels: 3e7
});

print('Computing visualization...');
percentClip.evaluate(function (percentClipLocal, error) {
  if (error) {
    // Report a computation failure
    print(error);
    return;
  }

  print(percentClipLocal);
  var palette = ['#00abff','#95bd00','e5e700','#cc2900','#a400c3'];
  var viz = {
    palette: palette, 
    // This uses JavaScript object manipulation, not EE methods, because it's a local value.
    min: percentClipLocal['v_p1'],
    max: percentClipLocal['v_p99'],
  };
  
  Map.addLayer(aod_ca, viz, 'ca aod');
});

Notice that I renamed the band of the image, so the reducer outputs will have nice short predictable names — this is a much better idea than picking dictionary keys by index.

Correct answer by Kevin Reid on December 9, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP