Hello everyone,
I’m trying to calculate the mean and the median of daily NDVI using the Processing API (I’m aware that there’s the Statistical one, but would like to proceed with just one request, since I’m also fetching weekly max NDVI with this script - not included). The problem I’m facing is that the calcDailyNDVI function only returns arrays filled with 0.
//VERSION=3
function setup() {
return {
input: [{bands: ["B03", "B04", "B08", "SCL", "CLD", "dataMask"], units: "DN"}],
output: [
{id: "meanNDVI", bands: 1, sampleType: "UINT16"},
{id: "NDVI", bands: 1, sampleType: "UINT16"}],
mosaicking: "ORBIT"
};
}
const MIN_INT16 = -32768
const OFFSET = 32767
const FACTOR = 10000
let sampleDates = []
function calcNDVI(sample) {
// Invalid data.
if (!isValid(sample)) {
return MIN_INT16
}
// Cloud detection.
if (isCloud(sample)) {
return -2
}
// Water detection.
if (isWater(sample)) {
return 3
}
if (isWaterCandidate(sample)) {
return 2
}
return index(sample.B08, sample.B04)
}
function preProcessScenes (collections) {
// Sort scenes by dateFrom in ascending order
collections.scenes.orbits.sort(function (s1, s2) {
const date1 = new Date(s1.dateFrom)
const date2 = new Date(s2.dateFrom)
return date1 - date2
})
return collections
}
// Function to calculate daily NDVI
function calcDailyNDVI(samples, scenes) {
let dailyNDVI = {};
samples.forEach((sample, index) => {
const date = scenes[index].date.toISOString().split('T')[0];
const ndvi = calcNDVI(sample);
if (!dailyNDVI[date]) {
dailyNDVI[date] = [];
}
dailyNDVI[date].push(ndvi);
});
return dailyNDVI;
}
function updateOutput(outputs, collections) {
let uniqueDailyDates = new Set()
collections.scenes.forEach(scene => {
uniqueDailyDates.add(scene.date.toISOString().split('T')[0])
})
sampleDates = Array.from(uniqueDailyDates).sort()
outputs.medianNDVI.bands = Math.max(1, sampleDates.length)
outputs.meanNDVI.bands = Math.max(1, sampleDates.length)
}
function updateOutputMetadata(scenes, inputMetadata, outputMetadata){
outputMetadata.userData = {
"dates": [...sampleDates]
}
}
function evaluatePixel(samples, scenes) {
let dailyNDVI = calcDailyNDVI(samples, scenes)
return {
medianNDVI: sampleDates.map(x => {
const ndviValues = dailyNDVI[x];
return ndviValues ? calculateMedian(ndviValues) * FACTOR + OFFSET : 0;
}),
meanNDVI: sampleDates.map(x => {
const ndviValues = dailyNDVI[x];
return ndviValues ? calculateMean(ndviValues) * FACTOR + OFFSET : 0;
})
}
}
function calculateMedian(values) {
if (values.length === 0) {
return undefined;
}
values.sort((a, b) => a - b);
const n = values.length;
if (n % 2 !== 0) {
return values[Math.floor(n / 2)];
} else {
const mid = n / 2;
return (values[mid - 1] + values[mid]) / 2;
}
}
function calculateMean(values) {
if (values.length === 0) {
return undefined;
}
const sum = values.reduce((acc, curr) => acc + curr, 0);
return sum / values.length;
}
Thanks a lot in advance for any help!