NDVI values within the AOI

Hello everyone, I’m trying to dynamically get the maximum and minimum NDVI values for my Area of Interest (AOI), but the image visualization only returns one color. I want to assign colors dynamically based on the retrieved minimum and maximum values from the function. Here’s my script:

//VERSION=3

function setup() {
  return {
    input: ["B04", "B08", "dataMask"],
    output: [
      { id: "default", bands: 4 },
      { id: "index", bands: 1, sampleType: "FLOAT32" },
      { id: "eobrowserStats", bands: 2, sampleType: "FLOAT32" },
      { id: "dataMask", bands: 1 },
    ],
  };
}

function evaluatePixel(samples) {
  const red = samples.B04;
  const nir = samples.B08;
  const ndvi = (nir - red) / (nir + red);
  const aoiMask = samples.dataMask;

  // Calculate minimum and maximum NDVI values within the AOI
  let minValue = Number.MAX_VALUE;
  let maxValue = Number.MIN_VALUE;
  let countValidPixels = 0; // Count the number of valid pixels within the AOI

  for (let i = 0; i < aoiMask.length; i++) {
    if (aoiMask[i] === 1) {
      const pixelNDVI = ndvi[i];
      if (!isNaN(pixelNDVI)) {
        countValidPixels++;
        minValue = Math.min(minValue, pixelNDVI);
        maxValue = Math.max(maxValue, pixelNDVI);
      }
    }
  }

  // Define color values for minimum (red), maximum (green), and other values (linear interpolation)
  const minColor = [0.67578125, 0.0, 0.15625, samples.dataMask]; // Red
  const maxColor = [0.0, 0.4921875, 0.27734375, samples.dataMask]; // Green

  // Linear interpolation function to calculate colors between minColor and maxColor
  function interpolateColor(value) {
    const t = (value - minValue) / (maxValue - minValue);
    const r = minColor[0] + t * (maxColor[0] - minColor[0]);
    const g = minColor[1] + t * (maxColor[1] - minColor[1]);
    const b = minColor[2] + t * (maxColor[2] - minColor[2]);
    return [r, g, b, samples.dataMask];
  }

  // Assign colors based on the NDVI value
  let imgVals;
  if (countValidPixels > 1) {
    if (!isNaN(ndvi)) {
      if (ndvi >= maxValue) {
        imgVals = maxColor;
      } else if (ndvi <= minValue) {
        imgVals = minColor;
      } else {
        imgVals = interpolateColor(ndvi);
      }
    } else {
      imgVals = [0, 0, 0, samples.dataMask]; // Set to black for NaN values
    }
  } else {
    imgVals = [0, 0, 0, samples.dataMask]; // Set to black when there's only one unique NDVI value in the AOI
  }

  return {
    default: imgVals,
    index: [ndvi],
    eobrowserStats: [ndvi, isCloud(samples) ? 1 : 0],
    dataMask: [samples.dataMask],
  };
}

function isCloud(samples) {
  const red = samples.B04;
  const nir = samples.B08;
  const ndvi = (nir - red) / (nir + red);
  return ndvi < 0; // Assuming negative NDVI values correspond to clouds
}

result:

Hi @noureddine.bassa ,

Based on your description and your script, I guess you are trying to get the maximum and the minimum value of NDVI on a specific timestamp in your AOI, and then interpolate the pixel NDVI value using your self-defined interpolateColor function.

If this is the case, unfortunately, your processing can not be converted into the Evalscript as it only supports pixel-based processing.

I would recommend using the Processing API and the Statistical API together to achieve your processing. Firstly, you could make a statistical request on a specific date over your AOI to obtain the maximum and minimum value of NDVI. Then, in the Processing API request you could insert the maximum and minimum value into your Evalscript and and assign a color based on the pixel value of NDVI.

Below is an example snippet to demonstrate how to insert variables to the Evalscript in python

max_ndvi = 1 # put values obtained from the Statistical API here
min_ndvi =  -1 # put values obtained from the Statistical API here
evalscript = f"""
function evaluatePixel (sample) {{
  const maxNDVI = {max_ndvi};
  const minNDVI = {min_ndvi};
  const ndvi = (sample.B08 - sample.B04) / (sample.B08 + sample.B04);

  const minColor = [0.67578125, 0.0, 0.15625, samples.dataMask];
  const maxColor = [0.0, 0.4921875, 0.27734375, samples.dataMask];
  function interpolateColor(value) {{
    const t = (value - minNDVI) / (maxNDVI - minNDVI);
    const r = minColor[0] + t * (maxColor[0] - minColor[0]);
    const g = minColor[1] + t * (maxColor[1] - minColor[1]);
    const b = minColor[2] + t * (maxColor[2] - minColor[2]);
    return [r, g, b, samples.dataMask];
  }}
  let imgVals;
  if (countValidPixels > 1) {{
    if (!isNaN(ndvi)) {{
      if (ndvi >= maxValue) {{
        imgVals = maxColor;
      }} else if (ndvi <= minValue) {{
        imgVals = minColor;
      }} else {{
        imgVals = interpolateColor(ndvi);
      }}
    }} else {{
      imgVals = [0, 0, 0, samples.dataMask]; // Set to black for NaN values
    }}
  }} else {{
    imgVals = [0, 0, 0, samples.dataMask]; // Set to black when there's only one unique NDVI value in the AOI
  }}
}}
"""

@chung.horng
I am sincerely grateful for your valuable assistance, Sr.

However, I have one more query to explore. I am wondering if there is a method to dynamically retrieve the minimum and maximum values through the Processing API simultaneously. Your insights on this matter would be highly beneficial.

Thank you once again for your support.

Best regards,

Hi @noureddine.bassa ,

As I mentioned in my previous response, the Evalscript only supports pixel-based processing, i.e., there’s no way to obtain statistics such as maximum, minimum, mean, etc. of your area of interest. This can be done with the Statistical API instead.

However, if you’re interested in the maximum/minimum of a pixel in a time series, this can be done with a multi-temporal processing script, e.g., Max NDVI in the past month for every pixel.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.