filterScenes filter by month and year

Hi,
I am trying to filter my scenes according to month and year. like this

return scenes.filter(function(scene) {
return scene.date.getFullYear()>=2017 && scene.date.getMonth()==10;
});

but when I try to filter scenes with month in evaluatePixel function I get an error

Cannot read property ‘date’ of undefined let initMonth = scenes[0].date.getMonth();

but it is working smoothly when only use year filtering. I just want to get specific scenes how can I do that ?

Thanks in advance,

Hi @hasanimgecelik,

I have just been testing your code snippet in one of my Evalscripts and it works just fine for me. If you could provide us with the whole Evalscript, we could try to find out where the error is coming from :slight_smile:

Follow this link to the official documentation of the filterScenes function.

Cheers, Max

Hi Max,

My script is like below. You can change the filter option at the end of the script.

//VERSION=3 (auto-converted from 1)
// Minimum difference between the two mean NDVIs
var thresold = 0.25;
// Thresold to dismiss clouds to calculate the mean
var blueThresold = 0.18;
// Minimum mean NDVI to consider for month(s) of last year
var minimunNDVI = 0.7;
// to normalize colormap
var stretchMin = 0;
var stretchMax = 0.8;

function setup() {
return {
input: [{
bands: [
“B02”,
“B03”,
“B04”,
“B05”,
“B08”,
“B12”
]
}],
output: { bands: 3 },
mosaicking: “ORBIT”
}
}

function stretch(val, min, max) {
return (val - min) / (max - min);
}

function NDVI(sample) {
let denom = sample.B08 + sample.B04;
return ((denom != 0) ? (sample.B08 - sample.B04) / denom : 0.0);
}

function NDWI(sample) {
let denom = sample.B03 + sample.B08;
return ((denom != 0) ? (sample.B03 - sample.B08) / denom : -1);
}

function mean(array) {
if (array.length == 0) {
return 1
} else {
var sum = 0;
for (var i = 0; i < array.length; i++) {
sum += parseFloat(array[i]); //don’t forget to add the base
}

    var avg = sum / array.length;
    return avg
}

}

// Manage overlapping years.
// If january is selected and user need 2 months to take
// script needs to take december from last year as second month.
function getNeededDates(sceneMonth, sceneYear, monthsToTake) {
let monthToGet = [];
let yearToGet = [];

for (i = 0; i < monthsToTake; i++) {
    if (sceneMonth - i <= 0) {
        month = 12 - (sceneMonth - i);
        year = sceneYear - 1;
    } else {
        month = sceneMonth - i;
        year = sceneYear;
    }
    monthToGet.push(month);
    yearToGet.push(year);
}

return [monthToGet, yearToGet];

}

function evaluatePixel(samples, scenes) {
let initMonth = scenes[0].date.getMonth();
let initYear = scenes[0].date.getFullYear();

let monthsAndYears = getNeededDates(initMonth, initYear, 3);

let currentYearNDVI = 0;
let currentYearCount = 0;

let previousYearNDVI = 0;
let previousYearCount = 0;
let lastYearMonth0 = [];
let lastYearMonth1 = [];
let lastYearMonth2 = [];

for (i = 0; i < samples.length; i++) {
    if (!(samples[i].B04 == 0) & !(samples[i].B03 == 0)) {
        sceneMonth = scenes[i].date.getMonth();
        sceneYear = scenes[i].date.getFullYear();
        if (monthsAndYears[0].includes(sceneMonth)) {
            if (samples[i].B02 < blueThresold) {
                ndvi = NDVI(samples[i]);
                if (monthsAndYears[1].includes(sceneYear))
                // if current year (last 12 months max)
                {
                    currentYearNDVI = currentYearNDVI + ndvi;
                    currentYearCount++;

                }
                // if year before
                else if (monthsAndYears[1].includes(sceneYear + 1)) {
                    previousYearNDVI = previousYearNDVI + ndvi;

                    if (monthsAndYears[0][0] == sceneMonth) {
                        lastYearMonth0.push(ndvi);
                    } else if (monthsAndYears[0][1] == sceneMonth) {
                        lastYearMonth1.push(ndvi);
                    } else if (monthsAndYears[0][2] == sceneMonth) {
                        lastYearMonth2.push(ndvi);
                    }
                    previousYearCount++;
                }
            }
        }
    }
}

// compute the mean
let avgCurrentYearNDVI = currentYearNDVI / currentYearCount;
let avgPreviousYearNDVI = previousYearNDVI / previousYearCount;

// if ndvi decreases from defined thresold in the same months from previous year
// highlights in red the pixel
// check also if is not water
let difference = avgPreviousYearNDVI - avgCurrentYearNDVI;

if ((NDWI(samples[0]) < 0.5) & (difference >= thresold) & (avgPreviousYearNDVI > minimunNDVI) & (mean(lastYearMonth0) > minimunNDVI) & (mean(lastYearMonth1) > minimunNDVI) & (mean(lastYearMonth2) > minimunNDVI)) {
    // the more the difference is high, the more it is red
    colorMap = [stretch((2.8 * (2 / 3) * 10 * difference * samples[0].B04 + 0.1 * samples[0].B05), stretchMin, stretchMax), stretch((2.8 * samples[0].B03 + 0.15 * samples[0].B08), stretchMin, stretchMax), stretch((2.8 * samples[0].B02), stretchMin, stretchMax)];
}
// else show current image
else {
    colorMap = [stretch((2.8 * samples[0].B04 + 0.1 * samples[0].B05), stretchMin, stretchMax), stretch((2.8 * samples[0].B03 + 0.15 * samples[0].B08), stretchMin, stretchMax), stretch((2.8 * samples[0].B02), stretchMin, stretchMax)];
}
return colorMap;

}

function filterScenes(scenes, inputMetadata) {

return scenes.filter(function(scene) {
return scene.date.getMonth()==10;
//return scene.date.getFullYear()>=2017;
});
}

Hi @hasanimgecelik,

We checked your script and it works fine if the time range you specify in the request payload coincides with the specified return scene.date.getMonth() or return scene.date.getFullYear() calls you use in the filterScenes function.

Can you confirm that you are requesting images from a time range that covers 2017 or the month of November (or combined)? If the data you request is not containing these dates, the filterScenes function cannot filter and you get an error message.

Hope that helps the troubleshooting :slight_smile:

Hi Max,

You are right when I use year filter when I use script with

  return scenes.filter(function(scene) {
    return scene.date.getFullYear()>=2017;
  });

and make a request like below

http://services.sentinel-hub.com/ogc/fis/{{TOKEN}}?LAYER=ANOMALY_ANALYSIS_V2&TIME=2018-10-08/2020-10-08&RESOLUTION=20&CRS=EPSG:3857&geometry=%20POLYGON%20((4338379.70798844%204435662.11596043,4338513.06873841%204436071.9281716,4338658.2293544%204436000.30395004,4338668.02546959%204435995.56617812,4338658.2293544%204435965.46744128,4338534.77603911%204435585.75691806,4338379.70798844%204435662.11596043))

I get an answer from server.

with the same request when I change the script to this

  return scenes.filter(function(scene) {
    return scene.date.getMonth()=="10";
  });

I get an error but I know there is data at [“2020-10-04”,“2019-10-30”,“2019-10-20”,“2019-10-25”…“2018-10-10”]

Hi @hasanimgecelik,

If you are looking for data from October you’d have to use:

 return scenes.filter(function(scene) {
    return scene.date.getMonth()=="9";
  });

because it is a zero-based indexing system where the index of 0 refers to January and accordingly October would be at index 9.

Cheers, Max

Hi Max,
İ tried the month with 9 but I still get the same error I mentioned before.

Hi @hasanimgecelik,

Your script works completely fine for me. Could you provide the rest of your request so that we can figure out why you are still receiving the error message?

Cheers, Max

Hi Max,
Below I give you full request. It still doesn’t work when I try to filter by month.
I am getting the same error.

https://services.sentinel-hub.com/ogc/fis/e95318f4-e465-4aa4-927b-d42426bf3aa0?LAYER=ANOMALY&geometry=POLYGON((4332578.056858547%204425747.42719139%2C4332578.0532000335%204425747.993574083%2C4332578.156061227%204425748.550550127%2C4332578.361775667%204425749.078266253%2C4332578.663010715%204425749.55791215%2C4332579.04902892%204425749.972390965%2C4332579.506070762%204425750.306928694%2C4332580.017845101%204425750.549600834%2C4332580.566109865%204425750.691757395%2C4332581.131322297%204425750.72833124%2C4332829.417455499%204425743.296945397%2C4332830.019049712%204425743.217541668%2C4332830.592358605%204425743.018701373%2C4332831.113926164%204425742.708559744%2C4332831.562413291%204425742.299805726%2C4332831.919470853%204425741.809162836%2C4332832.170490418%204425741.256704939%2C4332832.305201919%204425740.665034962%2C4332869.441984338%204425439.163443645%2C4332869.457570826%204425438.593122129%2C4332869.364904228%204425438.030163459%2C4332869.167336085%204425437.494928557%2C4332868.872011987%204425437.006775669%2C4332868.489613136%204425436.583360165%2C4332868.033970032%204425436.239996032%2C4332867.52156225%204425435.989101963%2C4332866.970922417%204425435.839752236%2C4332866.4019659255%204425435.797348482%2C4332611.749618756%204425441.105455184%2C4332611.134531251%204425441.1823307155%2C4332610.548373257%204425441.383977166%2C4332610.016169973%204425441.701785517%2C4332609.560643077%204425442.12218739%2C4332609.201240659%204425442.627234305%2C4332608.953306903%204425443.19536399%2C4332608.827426998%204425443.802320934%2C4332578.056858547%204425747.42719139))&srs=EPSG%3A3857&time=2020-10-07&RESX=10&RESY=10

Hi @hasanimgecelik,

I have been able to reproduce your error now. I falsely assumed that you were trying to request image data and not statistical information via a feature info service (FIS) request! I have been testing the return statement return scene.date.getMonth()==9; with API requests and there it worked out just fine.

The problem is that FIS requests are not designed to work with multitemporal scripts like the one you provided, because it uses the mosaicking type SIMPLE and there is no date information available (See your error message and script line reference).
The purpose of FIS is to run a non-temporal script on each available date inside a specified time range. FIS will create a request for each specific time point inside your time range.

Would it be possible to send a FIS request for the whole time range and then filter out the demanded dates from the response?
You could also consider getting a list of available datasets via our Catalog API, then select the ones you want to receive statistics for and send FIS requests for each of the dates in a loop.

Cheers, Max