Not receiving NDVI value in Statistical API

Hi guys,

I am trying to use a custom script in statistical api. It seems the aggregation is taking the right dates but I got "NaN"in the most dates. Could you help me to figure out what I am doing wrong?
It should give me the s2 ndvi if no clouds and s1 ndvi if so.

//VERSION=3
function setup() {
  return {
    input: [
      // Sepcify input bands using the id of datasource set in the payload under data parameter
      {datasource: 's2', bands: ['B04', 'B08', 'SCL', 'dataMask']},
      {datasource: 's1', bands: ['VV', 'VH', 'dataMask']}
    ],
    output: [
      {
        id: 'ndvi',
        bands: 1
      },
      {
        id: 'dataMask',
        bands: 1
      }],
    mosaicking: 'SIMPLE'
  };
}

function evaluatePixel(samples) {
  var s1 = samples.s1[0]
  var s2 = samples.s2[0]



  // Use the S2-L2A classification to identify clouds
  if ([7, 8, 9, 10].includes(s2.SCL)) {
    // If clouds are present use S1 NDVI
    let s1_ndvi = calc_s1_ndvi(s1.VV, s1.VH) // Calculate S1 NDVI
let validNDVIMask = 1;
  if (!isFinite(s1_ndvi)) {
    validNDVIMask = 0;
  }

    return {
      ndvi: [s1_ndvi], dataMask: [samples.s2[0].dataMask * samples.s1[0].dataMask * validNDVIMask]
  }
  } else {
    // Otherwise use s2 NDVI
    let ndvi = index(s2.B08, s2.B04) // Calculate S2 NDVI
let validNDVIMask = 1;
  if (!isFinite(ndvi)) {
    validNDVIMask = 0;
  }
    return {
      ndvi: [ndvi], dataMask: [samples.s2[0].dataMask * samples.s1[0].dataMask * validNDVIMask]

  }
  }
}

function calc_s1_ndvi(sigmaVV, sigmaVH) {
  // Convert sigma0 to Decibels
  let vh_Db = toDb(sigmaVH)
  let vv_Db = toDb(sigmaVV)
  // Calculate NRPB (Filgueiras et al. (2019), eq. 4)
  let NRPB = (vh_Db - vv_Db) / (vh_Db + vv_Db)
  // Calculate NDVI_nc with approach A3 (Filgueiras et al. (2019), eq. 14)
  let NDVInc = 2.572 - 0.05047 * vh_Db + 0.176 * vv_Db + 3.422 * NRPB
  return NDVInc
}

function toDb(linear) {
  // Convert the linear backscatter to DB (Filgueiras et al. (2019), eq. 3)
  return 10 * Math.LN10 * linear
}
{
  \"input\": {
    \"bounds\": {
      \"geometry\": {
        \"type\": \"Polygon\",
        \"coordinates\": [
            [
            [
                -57.51975291377155,-14.205968661454873
              ],
              [
                -57.518731982092056,-14.221243309719119
              ],
              [
                -57.52433747328446,-14.220981893817928
              ],
              [
                -57.52538171878425,-14.205814285762376
              ],
              [
                -57.51975291377155,-14.205968661454873
              ]
          ]
          ]
      },
      \"properties\": {
        \"crs\": \"http://www.opengis.net/def/crs/EPSG/0/4326\"
        }
    },
    \"data\": [
      {
        \"dataFilter\": {
            \"mosaickingOrder\": \"leastRecent\"
        },
        \"id\": \"s2\",
        \"type\": \"sentinel-2-l2a\"
      },
      {
        \"dataFilter\": {
          \"resolution\": \"HIGH\",
          \"acquisitionMode\": \"IW\",
          \"polarization\": \"DV\"
        },
        \"processing\": {
          \"backCoeff\": \"GAMMA0_TERRAIN\",
          \"orthorectify\": \"true\"
          
        },
        \"id\": \"s1\",
        \"type\": \"sentinel-1-grd\"
      }
    ]
  },
  \"aggregation\": {
    \"timeRange\": {
      \"from\": \"2022-12-21T00:00:00Z\",
      \"to\": \"2023-01-23T23:59:59Z\"
    },
    \"aggregationInterval\": {
      \"of\": \"P1D\"
    },
    \"resx\": 0.00009,
    \"resy\": 0.00009,
    \"evalscript\": \"$evalscript\"
  },
  \"calculations\": {
    \"default\": {}
  }
}

What I receive:

{
"data": [
{
"interval": {
"from": "2022-12-21T00:00:00Z",
"to": "2022-12-23T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2022-12-25T00:00:00Z",
"to": "2022-12-27T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": -0.38824281096458435,
"max": 4.252981185913086,
"mean": 1.292178402528126,
"stDev": 0.5258252083396445,
"sampleCount": 12654,
"noDataCount": 1911
}
}
}
}
}
},
{
"interval": {
"from": "2022-12-27T00:00:00Z",
"to": "2022-12-29T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2022-12-29T00:00:00Z",
"to": "2022-12-31T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2022-12-31T00:00:00Z",
"to": "2023-01-02T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-04T00:00:00Z",
"to": "2023-01-06T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-06T00:00:00Z",
"to": "2023-01-08T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": 0.43648046255111694,
"max": 0.8741295337677002,
"mean": 0.7873053286125081,
"stDev": 0.06790011249613606,
"sampleCount": 12654,
"noDataCount": 1911
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-08T00:00:00Z",
"to": "2023-01-10T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-10T00:00:00Z",
"to": "2023-01-12T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-14T00:00:00Z",
"to": "2023-01-16T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-16T00:00:00Z",
"to": "2023-01-18T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-18T00:00:00Z",
"to": "2023-01-20T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": -0.6149955987930298,
"max": 4.806635856628418,
"mean": 1.3176422709378766,
"stDev": 0.5970834167301392,
"sampleCount": 12654,
"noDataCount": 1911
}
}
}
}
}
},
{
"interval": {
"from": "2023-01-20T00:00:00Z",
"to": "2023-01-22T00:00:00Z"
},
"outputs": {
"ndvi": {
"bands": {
"B0": {
"stats": {
"min": "NaN",
"max": "NaN",
"mean": "NaN",
"stDev": "NaN",
"sampleCount": 12654,
"noDataCount": 12654
}
}
}
}
}
}
],
"status": "OK"
}

Thanks a lot!

Hi @ofgnxx ,

In your evalscript the dataMask is set to [samples.s2[0].dataMask * samples.s1[0].dataMask * validNDVIMask], meaning that you are masking pixels where 1. there is no S2 data OR 2. there is no S1 data OR 3. there is an invalid ndvi value.

As the S1 data has only 3 acquisitions (18th Jan, 6th Jan, 25th Dec) over your AOI during the input time range (you can check the data availability using Catalog API), all data on other acquisition dates are masked and you get NaN (no samples to compute statistics) in the output.

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