2

I am trying to extract the min and max values of an NDVI time series and print those values to the console, so I could then subtract those values to determine the seasonal stability of an area. Most of the questions and answers in this forum explain how to reduce a collection to a Max NDVI composite image. I just want the values. I know I can download the CSV and get the values from there, but I am wishing to do this programmatically in Google Earth Engine.

Note: in the code below, the bounds are filtered by a polygon which I couldn't figure out how to attach. Creating any sample polygon should work to run the code.

//This approach starts with a collection of L8 TOA images and filters them by cloud cover 
  // Note: - CC is calculated only over the ROI (ie. not whole image CC score).
  //       - the simpleCloudScore algorithm only works with TOA images.

// --------------Set Location and Filter by Date and Cloud-------------------//

var MAX_LIST_SIZE = 100;

var L8_TOA = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA")

    .filterDate('2013-12-25', '2016-12-25')
    .filter(ee.Filter.eq('WRS_PATH', 41))
    .filter(ee.Filter.eq('WRS_ROW', 36)); 
var count = L8_TOA.size();

var c = L8_TOA.filterBounds(geometry);        

var withCloudiness = c.map(function(image) {
  var cloud = ee.Algorithms.Landsat.simpleCloudScore(image).select('cloud');
  var cloudiness = cloud.reduceRegion({
    reducer: 'mean', 
    geometry: geometry,                        
    scale: 30,  });
  return image.set(cloudiness);});

// Here is where the computed cloud score threshold is set!
var filteredCollection = withCloudiness.filter(ee.Filter.lt('cloud', 5));

// print('L8 TOA Filtered Collection, by date and cloud',filteredCollection);

//---------------------------Add NDVI Band--------------------------------//

// Create an NDVI band  
var addNDVI = function(filteredCollection) {
var nir = filteredCollection.select('B5');
var red = filteredCollection.select('B4');
var ndvi = filteredCollection.normalizedDifference(['B5', 'B4']).rename('NDVI');
return filteredCollection.addBands(ndvi);};

// Add the NDVI band to each image in the collection

var withNDVI = filteredCollection.map(addNDVI);

// print('L8 Filtered Collection with NDVI band',withNDVI)

// Filter collection to only include NDVI Band

var NDVI_bands = withNDVI.select('NDVI');

print('L8 Collection with cloud filtering added', NDVI_bands)

//--------------------------Create Map and Chart-----------------------------//

// Create an image time series chart, average it over the ROI

var chart = ui.Chart.image.series({
  imageCollection: NDVI_bands,
  region: geometry,
  reducer: ee.Reducer.mean(),
  scale: 200});

// Add the chart to the map.

chart.style().set({
  position: 'bottom-right',
  width: '400px',
  height: '200px'});
Map.add(chart);

// Outline and center the map around coordinates.

var BakersfieldLayer = ui.Map.Layer(boundary, {color: 'FF0000'}, 'Bakersfield');
Map.layers().add(BakersfieldLayer);
Map.setCenter(-118.72, 35.4, 9);

// Create a label on the map.
var label = ui.Label('Click a point on the chart to show the image for that date.');
Map.add(label);

// When the chart is clicked, update the map and label.

chart.onClick(function(xValue, yValue, seriesName) {
  if (!xValue) return;

// Show the image for the clicked date.

  var equalDate = ee.Filter.equals('system:time_start', xValue);
  var image = ee.Image(L8_TOA.filter(equalDate).first());
  var l8Layer = ui.Map.Layer(image, {gamma: 1.3, min: 0, max: 0.3,});
  Map.layers().reset([l8Layer, BakersfieldLayer]);
  
// Show a label with the date on the map.

  label.setValue((new Date(xValue)).toUTCString());});

  // Predefine the chart titles.

var title = {
  title: 'Bakersfield site',
  hAxis: {title: 'Date'},
  vAxis: {title: 'NDVI'},};

print(Chart.image.series(NDVI_bands, geometry, ee.Reducer.mean(), 200).setOptions(title));
3

It seems you actually forgot to calculate the max and min values. Adding:

var NDVI_mean = NDVI_bands.mean();

var stats = NDVI_mean.reduceRegion({
  reducer: ee.Reducer.max().combine({
  reducer2: ee.Reducer.min(),
  sharedInputs: true
}),
  geometry: geometry,
  scale: 200,
  maxPixels: 1e13
});
  
print('Maximum NDVI',stats.getNumber('NDVI_max'));
print('Minimum NDVI',stats.getNumber('NDVI_min'));

Should do the trick.

EDIT :

I was calculating the geographic max of a temporal mean, rather than the temporal max of a geographic mean.

Here's the solution:

var stats = NDVI_bands.map(function(image) {
  
    var imgStats = image.reduceRegion({
      reducer: ee.Reducer.mean(),
      geometry: geometry,
      scale: 200,
      maxPixels: 1e13
    });
    
    return ee.Image.constant(imgStats.getNumber('NDVI')).toFloat();
    
});

print(stats);

var maxImg = stats.max();
var maxValue = maxImg.reduceRegion(ee.Reducer.max(),geometry,200).getNumber('constant');
print('Maximum NDVI:',maxValue);

var minImg = stats.min();
var minValue = minImg.reduceRegion(ee.Reducer.min(),geometry,200).getNumber('constant');
print ('Minimum NDVI:',minValue);

print('NDVI difference:',maxValue.subtract(minValue));
4
  • Thank you, Madeleine. This calculates the min and max of any any pixel in the time-series, but not the min and max of the mean value in the time series, which is strange since it looks like you did reduce the region of the mean value (i.e., var stats = NDVI_mean.reduceRegion). The values I'm concerned with should match what is in the chart.
    – Shannon
    Dec 3 '20 at 18:14
  • Also, if I want to get the difference of those two values (i.e., to gauge seasonal stability) "var diff = NDVI_max.subtract(NDVI_min);" does not work. Should I use some other expression?
    – Shannon
    Dec 3 '20 at 18:24
  • Ok I see what you mean, I was actually calculating the geographic max on a temporal mean, when what you wanted was a temporal max on a geographic mean. The second one is much trickier but I managed to figure it out. It's messy but it works. Will add edit to answer. Dec 3 '20 at 22:36
  • Hey there! Did it work? If so could you accept the answer? Thanks! Feb 4 at 20:43
3

To print the minimum and maximum values of an image to the console, you simply need to use reducer: ee.Reducer.min().combine(ee.Reducer.max(), '', true) .

The following is an example which calculates the minimum and maximum values of an elevation raster for a given box extent.

//  Create box extent
var geometry = ee.Geometry.Rectangle({
  coords: [94.8,18.3,99.1,22.8],
  proj: 'EPSG:4326',
  geodesic: false
  });
  
//  Center map viewer
Map.centerObject(geometry,7);

//  Load elevation data
var elev = ee.Image("USGS/SRTMGL1_003").clip(geometry);

//  Retrieve min/max values
var MinMax = elev.reduceRegion({
  reducer: ee.Reducer.min().combine(ee.Reducer.max(), '', true),
  geometry: geometry,
  maxPixels: 1e13 // is required if geometry extent is large
});

//  Print to console
print(MinMax);
//  Visualize map (manual)
var elevViz = {min: -12, max: 2664, palette: ['000000', 'FFFFFF']};
Map.addLayer(elev, elevViz, 'SRTM elevation');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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