PlanetScope 8bands and NDWI index

Hi! I’m trying to compute the NDWI index with the PlanetScope 8 bands product and I noticed that it gives me always a negative number. I’m using this script

//VERSION=3
//NDWI
function setup() {
  return {
    input: [{
      bands: [
        "Green",
        "NIR",
        "dataMask"
      ]
    }],
    output: {
      bands: 2
    }
  }
}


function evaluatePixel(samples) { 
        let val = (samples.Green-samples.NIR)/(samples.Green+samples.NIR);
	return [val, samples.dataMask]
}

I tried to download the raw bands of NIR and Green and saw that the rage values of NIR is always greater than the range values of Green band, for this the the values are always negative. I checked the images over a period of a few months in the same area but nothing changed, the values are always below zero.

Do you have any suggestions on how to fix this? Thanks

Hi Pablo,

I don’t see anything wrong with the evalscript you are using; can you please provide some more details on the area of interest that you are using and the time period you are requesting. This will help us to troubleshoot your issue.

Hi William,
sure, here is the curl request to one of our geometries, for which we have ordered PlanetScope 8bands images. I deleted the Bearer token and partially masked the collection id. As you will see all the statistics are below zero, for every requested period:

curl -X
POST https://services.sentinel-hub.com/api/v1/statistics -H 'Authorization: Bearer ’
-H ‘Accept: application/json’
-H ‘Content-Type: application/json’
-d ‘{ “input”: { “bounds”: { “geometry”: { “type”: “Polygon”, “coordinates”: [ [ [ -7.065784, 38.827288 ], [ -7.062565, 38.82906 ], [ -7.056471, 38.822457 ], [ -7.059754, 38.820618 ], [ -7.065784, 38.827288 ] ] ] } }, “data”: [ { “dataFilter”: {}, “type”: “byoc-xxxxxx-xxxx-xxxx-xxxxx-5d26179b459f” } ] }, “aggregation”: { “timeRange”: { “from”: “2023-01-20T00:00:00Z”, “to”: “2023-06-20T23:59:59Z” }, “aggregationInterval”: { “of”: “P1D” }, “width”: 589.062, “height”: 685.357, “evalscript”: “//VERSION=3\nfunction setup() {\n return {\n input: [{\n bands: [\n "Green",\n "NIR",\n "dataMask"\n ]\n }],\n output: [\n {\n id: "data",\n bands: 1\n },\n {\n id: "dataMask",\n bands: 1\n }]\n };\n}\n\nfunction evaluatePixel(samples) {\n let index = (samples.Green-samples.NIR)/(samples.Green+samples.NIR);\n return {\n data: [index],\n dataMask: [samples.dataMask]\n };\n}” }, “calculations”: { “default”: {} } }’

Hi Pablo,

It seems that you didn’t specify the SampleType in the evalscript. The default sampleType is UINT8 and only contains whole values 0-255. As NDWI is an index, it’s values range from -1 to 1 including decimal values (FLOAT), therefore, you need to specify FLOAT32 as your sampleType.

//VERSION=3

function setup() {
  return {
    input: ["NIR", "Green"],
    output: { bands: 1, sampleType: "FLOAT32" }
  };
}

function evaluatePixel(sample) {
  return [(sample.Green-sample.NIR)/(sample.Green+sample.NIR)];
}

You can read more about this in the documentation here, and there was also a medium post on the subject by Maxim Lamare.

Hi William,
i tried to add the sampleType to the script, but I still get the negative index statistics in every period. I know that in this geometry there is vegetation, it’s a cultivation with trees, and it’s strage to have all the statistics (mean,min,max) negative (below zero). Even without the setting of sampleType I get the same result.

Do you think it’s possibile to have a negative NDWI index in a geometry where there is vegetation?

curl -X POST https://services.sentinel-hub.com/api/v1/statistics
-H 'Authorization: Bearer ’
-H ‘Accept: application/json’
-H ‘Content-Type: application/json’
-d ‘{
“input”: {
“bounds”: {
“geometry”: {
“type”: “Polygon”,
“coordinates”: [
[
[
-7.06543,
38.827171
],
[
-7.062255,
38.82891
],
[
-7.056719,
38.822491
],
[
-7.059465,
38.820819
],
[
-7.06543,
38.827171
]
]
]
}
},
“data”: [
{
“dataFilter”: {},
“type”: “byoc-xxxxxxx-xxxx-xxxx-xxxx-5d26179b459f”
}
]
},
“aggregation”: {
“timeRange”: {
“from”: “2022-01-20T00:00:00Z”,
“to”: “2022-09-20T23:59:59Z”
},
“aggregationInterval”: {
“of”: “P1D”
},
“width”: 512,
“height”: 610.387,
“evalscript”: “//VERSION=3\nfunction setup() {\n return {\n input: ["NIR", "Green", "dataMask"],\n output: [{ id: ‘data’, bands: 1, sampleType: "FLOAT32" }, { id: ‘dataMask’, bands: 1 }]\n };\n}\n\nfunction evaluatePixel(sample) {\n return { data: [(sample.Green-sample.NIR)/(sample.Green+sample.NIR)], dataMask: [sample.dataMask] };\n}”
},
“calculations”: {
“default”: {}
}
}’

Hi Pablo,

Can you confirm that you are trying to calculate NDWI, in regards to detecting water bodies (this uses the Green and NIR bands), or are you interested in NDWI/NDMI (this uses the Green and SWIR bands) and is used to highlight differences in water content of leaves? The values you are returning indicate you are probably using the former of these.

There is some confusion as both these indices are commonly referred to as NDWI in the literature, so just want to confirm which you are interested in before proceeding.

If you are trying to calculate the latter then this is not possible with Planetscope data as the sensor does not possess a SWIR band.

Hi William,
yes I was interested in NDWI/NDMI, and I saw that PlanetScope do not have the SWIR band, so I thought I can use NDWI as a substitute of the former, but as you pointed out it only detect water bodies. So in this case it’s normal that all the values of the index are negative in an area where there is only trees and bare soil.

Thank you for you help!

OK thanks for the clarification. Apologies for the confusion