Tricks to getting Cloudless Mosaic Working?

Hi there,

Are there any tricks to getting the Sent 2 L2A cloudless mosaic script working on the Sentinel Hub Custom Configuration WMS? Perhaps the date range needs to be set a certain way?

I have copied the script in and set date range as far back as 1 or 2 years but it dosent return a result

Script Used

Alex,

It depends on how you are accessing your data. We have tried setting up the same configuration layer (with Sentinel-2 L2A), displaying it in EO Browser and it works.

However, to display in EO Browser (if this is how you are trying to access the layer) you need to change the script a little. As it is in the repository, it returns UINT16 digital number (reflectance * 10000) values. To display correctly in EO Browser, we should change the SampleType to UINT8:

function setup() {
  return {
    input: [{
      bands: [
        "B04",
        "B03",
        "B02",
        "SCL"
      ],
      units: "DN"
    }],
    output: {
      bands: 3,
      sampleType: SampleType.UINT8
    },
    mosaicking: "ORBIT"
  }
}

Then to return values scaled in the UINT8 range, I would return the following (get reflectance, scale to 0-255, and multiply by 2.5 for a better visualisation):

  return [rValue/10000*255*2.5, gValue/10000*255*2.5, bValue/10000*255*2.5]

Another tip: don’t forget to check the time-range of data being filtered in the evalscript. In the default script the filter fetches 1 year of data:

function filterScenes (scenes, inputMetadata) {
  return scenes.filter(function (scene) {
    return scene.date.getTime()>=(inputMetadata.to.getTime()-12*31*24*3600*1000);
  });
}

Lastly, I would strongly suggest that you test the configuration layer access over a small extent and a short time period (e.g. 1 month) first: fetching years of data consumes a lot of Processing Units! Once you have it working for a small test example, then you can scale up.

Please let me know if you run into any other problems.

Maxim

Hi Maxim, thanks for the prompt reply.

I tried the following in EO Browser under Sent 2 data but got the error “Failed to evaluate script!
SyntaxError: Unexpected token var”

function setup() {
return {
input: [{
bands: [
“B04”,
“B03”,
“B02”,
“SCL”
],
units: “DN”
}],
output: {
bands: 3,
sampleType: SampleType.UINT8
},
mosaicking: “ORBIT”
}
}

function filterScenes (scenes, inputMetadata) {
return scenes.filter(function (scene) {
return scene.date.getTime()>=(inputMetadata.to.getTime()-31243600*1000);
});
}

let rValue = 0
let gVale = 0
let bValue = 0

return [rValue/100002552.5, gValue/100002552.5, bValue/100002552.5]

Maybe you could post a working version linked/setup in EO browser than I could then change if need be?

Ultimately want to get in working as a WMS serivce on Sentinel Hub

Alex

@alex.clark,

I have configured the layer in your dashboard for you to test. If you log in to EO Browser and select the S2L2A-cloudless Theme, you should access the images (layer configured for 2 months of data - you can change that in your dashboard). Just make sure you set a Timespan in your visualisation tab. You can query the CLOUDLESS band of the S2L2A-cloudless configuration using WMS too.

For other users, here is an example link to EO Browser: S2L2A Cloudless mosaic.

Thanks @maxim.lamare thats great, thats working for me and I have edited it sequentially to get it to do what I need.

Plesase excuse my poor coding skills but is this code using the function getDarkest Pixel? I cant find anything calling it, perhaps using the first 1/4 is a more robust approach than going for the darkest pixel?

One thing I would dearly like to be able to do is apply a second date filter at the evlautePixel function stage. So the filterScences function would return all the required dates. But then selectively apply calculations based on a date or date range at the evaluatePixel stage.
i.e. I’m making a “before” cloudless mosaic across 2 weeks, and another 2 week mosaic at an “after” date and subtracting the two images.

Its seems like this should be possible given that the evaluatePixel function has additional arguments “scences” and “inputMetadata” and the Eval2 script documentation aludes to this under the section
Filter scences by time interval

"Combining this with the timeRange set in the body of the request as:

{
“from”: “2019-01-01T00:00:00Z”,
“to”: “2019-06-30T23:59:59Z”
}
we end up only with scenes acquired in January and June 2019. In the evaluatePixel function, we could then e.g., calculate the average NDVI index for each of the months and compare them."

I’m attempting to add a evaluatePixel filter on line 80 of the Sentinel hub configuration you setup but dont have any clear examples to emulate.

Great that it’s working for you!

Please excuse my poor coding skills but is this code using the function getDarkest Pixel? I cant find anything calling it, perhaps using the first 1/4 is a more robust approach than going for the darkest pixel?

Not quite, the script first orders the valid input values from lowest to highest, then returns the value at the first quartile. Tests showed that this method was more robust than using the median. You can read about the process in Pierre Markuse’s blog post.

One thing I would dearly like to be able to do is apply a second date filter at the evlautePixel function stage. So the filterScences function would return all the required dates. But then selectively apply calculations based on a date or date range at the evaluatePixel stage.

It is possible to do that using scenes in the evaluatePixel function. For example, you can collect the dates from the scenes argument:

function evaluatePixel(samples, scenes) {
    // Initialise arrays containing data
    var all_samples = {'B02':[], 'B03':[], 'B04':[]}; 
    var all_dates = []
    
    // Loop over samples (backwards because latest dates are first)
    for (var i = samples.length-1; i >= 0; i--){
        all_dates.push(scenes[i].date);
        all_samples['B02'].push(samples[i].B02);
        all_samples['B03'].push(samples[i].B03);
        all_samples['B04'].push(samples[i].B04);
    }

With the code above, you now have an array of dates (all_dates) and corresponding data for the three bands. Now you can query and manipulate the data as you like in the next lines of the evalscript. Note that the above is just a basic example, but you can do more advanced operations, like filter out clouds per pixel and much more…

If you come up with an interesting script that compares periods for example, it would be great if you shared it with the world via the Custom Scripts Repository :smile: