It is quite difficult to debug this Custom script thing, I know. It’s not a trivial thing though if you imagine that the script is executed for each individual pixel for each individual scene, in your case for a tile of 512x512 px and 3 months of data cca 4 million times… And you get an error if one of these 4 million executions fails…
That being said, we do have some ideas on how to make it easier.
Trying to make your script work I changed:
return scenes.filter(function (scene, inputMetadata)
to
return scenes.filter(function (scene)
var current_year = dateFormatYear(inputMetadata.to.getTime());
var current_month = dateFormatMonth(inputMetadata.to.getTime());
to
var current_year = dateFormatYear(inputMetadata.to);
var current_month = dateFormatMonth(inputMetadata.to);
(as dateFormatYear expects a Date type, not Time type)
allowedDates.push(current_year-i+'-'+mm);
to
allowedDates.push(current_year-i+'-'+current_month);
(as mm is not defined in this function)
var current_year = dateFormatYear(inputMetadata.to.getTime());
to
var current_year = dateFormatYear(scenes[0].date);
In evaluatePixel function inputMetadata are unfortunately not accessible. This is somehow a fail on our side, not assuming it will be needed. We are aware of it and will be added in one of the next version of EVALSCRIPT.
As scenes are ordered in a descending order (PRIORITY=mostRecent parameter, which is default), you can take the date of the first scene and get a same result.
This script now works, I just hope it produces the results you want.
I noticed you replaced “max ndvi” with “average ndvi”, which IMHO is not the best choice. Whenever there are clouds over the field, this will result in very low NDVI, impacting your average, even though it has nothing to do with the field itself.
Script:
function setup (dss) {
// get all bands for display and analysis
setInputComponents([dss.B04,dss.B08]);
// return as RGB
setOutputComponentCount(3);
}
//you should reduce number of scenes you are processing as much as possible here to speed up the processing
function filterScenes (scenes, inputMetadata) {
return scenes.filter(function (scene) {
var number_of_points_average = 3;
var current_year = dateFormatYear(inputMetadata.to);
var current_month = dateFormatMonth(inputMetadata.to);
// set months for the analysis
//var allowedDates = ["2016-12","2017-12","2018-12"];
var allowedDates = [];
for (var i=0;i<=number_of_points_average;i++) {
allowedDates.push(current_year-i+'-'+current_month);
}
// format scene date timestamp to match allowed dates
var sceneDateStr = dateFormatYearMonth(scene.date);
if (allowedDates.indexOf(sceneDateStr)!= -1) return true;
else return false;
});
}
function dateFormatYear(d){
var yyyy = d.getFullYear();
var result = yyyy;
return result;
}
function dateFormatMonth(d){
var mm = d.getMonth()+1;
if(mm<10){mm='0'+mm}
var result = mm;
return result;
}
function dateFormatYearMonth(d){
var mm = dateFormatMonth(d);
var yyyy = dateFormatYear(d);
var result = yyyy+'-'+mm;
return result;
}
function calcNDVI(sample) {
var denom = sample.B04+sample.B08;
var result = ((denom!=0) ? (sample.B08-sample.B04) / denom : false);
if (result === false) {return false}
var min_ndvi = 0.1;
return ((result > min_ndvi) ? result : false);
}
function evaluatePixel(samples,scenes) {
/*var ndvi_max = [];
ndvi_max["2016"] = null;
ndvi_max["2017"] = null;
ndvi_max["2018"] = null;*/
/*past_ndvi_sum = 0;
past_ndvi_number = 0;
current_ndvi_sum = 0;
current_ndvi_number = 0;*/
var number_of_points_average = 3;
var current_year = dateFormatYear(scenes[0].date);
var ndvi_sum = [];
var ndvi_count = [];
for (var i=0;i<=number_of_points_average;i++) {
ndvi_sum[current_year-i] = 0
ndvi_count[current_year-i] = 0
}
for (var i=0;i<samples.length;i++) {
var ndvi = calcNDVI(samples[i]);
//if there is no pixel at the location (e.g. at borders of scenes), we skip it
if (ndvi===false) continue;
var year = dateFormatYear(scenes[i].date);
ndvi_sum[year] += ndvi ;
ndvi_count[year]++ ;
}
var past_ndvi_average = 0 ;
var past_ndvi_average_count = 0;
for (var i=1;i<=number_of_points_average;i++) {
if (ndvi_sum[current_year-i] > 0) {
past_ndvi_average += ndvi_sum[current_year-i] ;
past_ndvi_average_count++ ;
}
}
past_ndvi_average = (past_ndvi_average_count > 0) ? past_ndvi_average / past_ndvi_average_count : 0
current_ndvi_average = (ndvi_count[current_year] > 0) ? ndvi_sum[current_year] / ndvi_count[current_year] : 0
//now we calculate average NDVI of first two years and compare it with the last year
//var ndvi_avg = (ndvi_max["2016"]+ndvi_max["2017"])/2;
//we visualise on the scale going from red (much less) to yellow (same) to green (much more)
//all ndvis should be between -1 and 1 but let's cap it to [0,1] so that we can better predict what is happening
/*if (ndvi_avg<0) ndvi_avg=0;
if (ndvi_avg>1) ndvi_avg=1;
if (ndvi_max["2018"]<0) ndvi_max["2018"]=0;
if (ndvi_max["2018"]>1) ndvi_max["2018"]=1;*/
/*if (past_ndvi_average<0) past_ndvi_average=0;
if (past_ndvi_average>1) past_ndvi_average=1;
if (current_ndvi_average<0) current_ndvi_average=0;
if (current_ndvi_average>1) current_ndvi_average=1*/
var val = current_ndvi_average - past_ndvi_average
if (val<-1) val=-1;
if (val>1) val=1;
/*var val=0;
if ((ndvi_max["2018"]+ndvi_avg)!=0)
{
val = (ndvi_max["2018"]-ndvi_avg)/(ndvi_max["2018"]+ndvi_avg);
}*/
return colorBlend(val,
[-1, 0, 1],
[
[1,0,0],
[1,1,1],
[0,1,0]
]);
}
Link: