Skip to main content

Is it possible return more than 4 chanels in evalscript?


for example i want to return an ndvi visualization on the first 3 channels [c1,c2,c3] and use the 4th chanel and transparent and the 5th channel maybe as the actual pixel value at a given location? so my return code would look like this

return[c1,c2,c3,c4,c5].

Hi,

This is possible (see this example), however, this does not make sense in your case. Visualisations generally use values between 0-255 (UINT8) and the actual NDVI pixel value consists of values -1.0-1.0 requiring FLOAT32. You cannot mix Sample Types in a single raster. For more information about SampleTypes I recommend reading this Medium post written by my colleague @maxim.lamare

In your case, it makes sense to return two outputs in your evalscript:

//VERSION=3
function setup( ){
return{

input: [{
bands:["B04", "B08"],
}],
output: [{
id: "default",
bands: 1,
sampleType: SampleType.FLOAT32},
{
id: "ndvi_image",
bands: 3,
sampleType: SampleType.AUTO}
]
}
}


function evaluatePixel(sample) {
let ndvi = (sample.B08 - sample.B04) / (sample.B08 + sample.B04)

if (ndvi<-0.5) image = [0.05,0.05,0.05]
else if (ndvi<-0.2) image = [0.75,0.75,0.75]
else if (ndvi<-0.1) image = [0.86,0.86,0.86]
else if (ndvi<0) image = [0.92,0.92,0.92]
else if (ndvi<0.025) image = [1,0.98,0.8]
else if (ndvi<0.05) image = [0.93,0.91,0.71]
else if (ndvi<0.075) image = [0.87,0.85,0.61]
else if (ndvi<0.1) image = [0.8,0.78,0.51]
else if (ndvi<0.125) image = [0.74,0.72,0.42]
else if (ndvi<0.15) image = [0.69,0.76,0.38]
else if (ndvi<0.175) image = [0.64,0.8,0.35]
else if (ndvi<0.2) image = [0.57,0.75,0.32]
else if (ndvi<0.25) image = [0.5,0.7,0.28]
else if (ndvi<0.3) image = [0.44,0.64,0.25]
else if (ndvi<0.35) image = [0.38,0.59,0.21]
else if (ndvi<0.4) image = [0.31,0.54,0.18]
else if (ndvi<0.45) image = [0.25,0.49,0.14]
else if (ndvi<0.5) image = [0.19,0.43,0.11]
else if (ndvi<0.55) image = [0.13,0.38,0.07]
else if (ndvi<0.6) image = [0.06,0.33,0.04]
else image = [0,0.27,0]

return {
default: [ ndvi ],
ndvi_image: image
}

The full example for this can be found here.

Hope that these examples clear things up for you 👍


Hi,Thank you for the response. If i get it correctly, this example would only work with a process request and not OGC. Would this be correct?


Correct, this won’t work with OGC as this doesn’t support multiple outputs.


If you wanted to display the visualisation and the actual values, you would need to create two seperate OGC Layers.


Hi,, thank you!

Do you have an example on how to implement this?
Do I need to set up 2 instances and then return one for the value and the other for the visualization?


Hi,

Yes, you will need a visualisation instance and a raw values instance.

To explain this let’s look at the below example:

//VERSION=3
function setup() {
return {
input: :{
bands: :
"B04",
"B08",
"dataMask"
]
}],
output: {
bands: 4
}
}
}


function evaluatePixel(sample) {
let val = (sample.B08 - sample.B04) / (sample.B08 + sample.B04);
let imgVals = null;

if (val<-1.1) imgVals = =0,0,0];
else if (val<-0.2) imgVals = =0.75,0.75,0.75];
else if (val<-0.1) imgVals = =0.86,0.86,0.86];
else if (val<0) imgVals = =1,1,0.88];
else if (val<0.025) imgVals = =1,0.98,0.8];
else if (val<0.05) imgVals = =0.93,0.91,0.71];
else if (val<0.075) imgVals = =0.87,0.85,0.61];
else if (val<0.1) imgVals = =0.8,0.78,0.51];
else if (val<0.125) imgVals = =0.74,0.72,0.42];
else if (val<0.15) imgVals = =0.69,0.76,0.38];
else if (val<0.175) imgVals = =0.64,0.8,0.35];
else if (val<0.2) imgVals = =0.57,0.75,0.32];
else if (val<0.25) imgVals = =0.5,0.7,0.28];
else if (val<0.3) imgVals = =0.44,0.64,0.25];
else if (val<0.35) imgVals = =0.38,0.59,0.21];
else if (val<0.4) imgVals = =0.31,0.54,0.18];
else if (val<0.45) imgVals = =0.25,0.49,0.14];
else if (val<0.5) imgVals = =0.19,0.43,0.11];
else if (val<0.55) imgVals = =0.13,0.38,0.07];
else if (val<0.6) imgVals = =0.06,0.33,0.04];
else imgVals = =0,0.27,0];


imgVals.push(sample.dataMask)

return imgVals
}

This evalscript in its current form is returning a visualisation of NDVI from the Sentinel-2 L2A data collection. The visualisation is populated in the imgVals array. However, if you wanted the raw NDVI values you would return the val array instead. Therefore, you just need to change the evalscript to return either the visualisation or actual values.

But also bear in mind if returning the actual values, you will need to change the output image format to GeoTIFF format and the SampleType to FLOAT32.


Hi,

Thank you for this example. Our problem is a bit more complex. We want to return the visualisation as the overal map/layer that users see on our application but when they click on any given pixel on this map, we want them to see the actual ndvi value pop-up and not the rescassification color values (as is the case now). I am not sure if this makes it a bit more clear? That is why we thought we could include the real pixel value as a chanel and display it to users but it is not possible at the moment. We are exploring further options and any suggestions here would be super great!


Hi,

The feature you are trying to create is the same as the functionality in the EO Browser application then? This implements Statistical API which you can use to do this.

There are also several previous threads in the forum you can use to help you: [1] [2]

I think the first one will be most useful to you.


Hi,

Not exactly, the feature we want to create is a layer from SH let’s say an NDVI composite and then enable with a popup (that we have in place) query the layer and see the pixel value once clicked.

Currently when we set the evalscript we see that we can return only the value and not visualization or the other way around; return the composite visualization and once clicked the output values displayed on our pop-up are the RGB bands.

So we do not think that the Statistical API is what would solve this issue.


Reply