How to have a tiff file where each pixel is composed of 3 bands

for the below posted evalscript, i want to have a tiff files where each pixel is composed of 3 bands [averages, numOfCloudyPixels, numOfCloudFreePixels]
is that possible using sentnelhub api?

Note

 i also posted below my attempts to return five bands. i would truly appreciate it if  
 tell whether it is correct or not please?

 `//VERSION=3
  // Script to extract a time series of NDVI values using 
  // Sentinel 2 Level 2A data and  metadata file.
  
  function setup() {
	return {
	  input: [{
		bands: ["B04", "B08", "CLD"],
		units: "DN"
	  }],
	  output: [
	{
	  id: "default",
	  bands: 3,
	  sampleType: "FLOAT32",
	  nodataValue: NaN,
	},
  ],
	  mosaicking: Mosaicking.ORBIT
	}
  }

  function updateOutput(output, collection) {
	output.default.bands = collection.scenes.length
  }

  const cloudFreeSamples = new Array();
  const cloudySamples = new Array();

  function samplesParser(samples) {
	samples.forEach((sample) => {
	  if (sample.CLD > 0) {
		cloudySamples.push(sample);
	  } else {
		cloudFreeSamples.push(sample);
	  }
	});
	return [cloudySamples, cloudFreeSamples];
  }

  calcAverage(samples) {
	let sum = 0;
	for(let i = 0;i < samples.length; i++) {
	  sum += samples[i];
	}
	let avg = sum / samples.length;
	return [avg];
  }
  calcNDVIForCloudFreeSamples(samples) {
	const ndvis = new Array(samples.length).fill(NaN);
	samples.forEach((sample, index) => {
	  ndvis[index] = (sample.B08 - sample.B04) / (sample.B08 + sample.B04) ;
	});
	return ndvis;
  }
  function evaluatePixel(samples) {
	if (samples.length < 1) return [NaN];
	const parsedSamples = samplesParser(samples);
	const ndvis = calcNDVIForCloudFreeSamples(parsedSamples[1]);
	const averages = calcAverage(ndvis);
	const numOfCloudyPixels = parsedSamples[0].length;
	const numOfCloudFreePixels = parsedSamples[1].length;
	return [averages, numOfCloudyPixels, numOfCloudFreePixels];
  }`

attempts:

`//VERSION=3
  // Script to extract a time series of NDVI values using 
  // Sentinel 2 Level 2A data and  metadata file.
  
  function setup() {
	return {
	  input: [{
		bands: ["B04", "B08", "CLD"],
		units: "DN"
	  }],
	  output: [
		{
		  id: "averages",
		  bands: 1,
		  sampleType: "FLOAT32",
		  nodataValue: NaN,
		},
		{
		  id: "numOfCloudFreePixels",
		  bands: 1,
		  sampleType: "FLOAT32",
		  nodataValue: NaN,
		},
		{
		  id: "numOfCloudyPixels",
		  bands: 1,
		  sampleType: "FLOAT32",
		  nodataValue: NaN,
		},
		{
		  id: "percentageOfCloudFree",
		  bands: 1,
		  sampleType: "FLOAT32",
		  nodataValue: NaN,
		},
		{
		  id: "percentageOfCloudy",
		  bands: 1,
		  sampleType: "FLOAT32",
		  nodataValue: NaN,
		},
	  ],
	  mosaicking: Mosaicking.ORBIT
	}
  }

  function updateOutput(output, collection) {
	output.default.bands = collection.scenes.length
  }

  const cloudFreeSamples = new Array();
  const cloudySamples = new Array();

  function samplesParser(samples) {
	samples.forEach((sample) => {
	  if (sample.CLD > 0) {
		cloudySamples.push(sample);
	  } else {
		cloudFreeSamples.push(sample);
	  }
	});
	return [cloudySamples, cloudFreeSamples];
  }

  function calcAverage(samples) {
	let sum = 0;
	for(let i = 0;i < samples.length; i++) {
	  sum += samples[i];
	}
	let avg = sum / samples.length;
	return [avg];
  }
  function calcNDVIForCloudFreeSamples(samples) {
	const ndvis = new Array(samples.length).fill(NaN);
	samples.forEach((sample, index) => {
	  ndvis[index] = (sample.B08 - sample.B04) / (sample.B08 + sample.B04) ;
	});
	return ndvis;
  }
  function calcPercentage(total, incidences) {
	return ((incidence / total) * 100);
  }
  function evaluatePixel(samples) {
	if (samples.length < 1) return [NaN];
	const parsedSamples = samplesParser(samples);
	const ndvis = calcNDVIForCloudFreeSamples(parsedSamples[1]);
	const averages = calcAverage(ndvis);
	const numOfCloudyPixels = parsedSamples[0].length;
	const numOfCloudFreePixels = parsedSamples[1].length;
	const totalNumOfPixels = numOfCloudyPixels + numOfCloudFreePixels;
	const percentageOfCloudy = calcPercentage(totalNumOfPixels, numOfCloudyPixels);
	const percentageOfCloudFree = calcPercentage(totalNumOfPixels, numOfCloudFreePixels);

	// return [averages, numOfCloudFreePixels, numOfCloudyPixels, percentageOfCloudFree, percentageOfCloudy];
	return {
	  averages: averages,
	  numOfCloudFreePixels: numOfCloudFreePixels,
	  numOfCloudyPixels: numOfCloudyPixels,
	  percentageOfCloudFree: percentageOfCloudFree,
	  percentageOfCloudy: percentageOfCloudy,
	}
  }

I see you are almost there!

This documentation page will help you understand the structure of Evalscripts better, particularly looking at the output section: to return a tiff with 5 bands, simply specify the number of bands in the setup function:

function setup() {
	return {
	  input: [{
		bands: ["B04", "B08", "CLD"],
		units: "DN"
	  }],
	  output: [
	{
	  id: "default",
	  bands: 5,
	  sampleType: "FLOAT32",
	  nodataValue: NaN,
	},
  ],
	  mosaicking: Mosaicking.ORBIT
	}
  }

and then in evaluatePixel, you can do what you tried in your second script:

return [averages, numOfCloudFreePixels, numOfCloudyPixels, percentageOfCloudFree, percentageOfCloudy];

In return, you will get a tiff with 5 bands. You can adapt to do the same for 3 bands, etc…

Based on the above, in the body of your request you would set the response to:

"responses": [
      {
        "identifier": "default",
        "format": {
          "type": "image/tiff"
        }
      }
    ]

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