Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Cloud Statistics

//VERSION=3
function setup() {
  return {
  // The script can be adapted for S2L1C by removing the "SCL" band
    input: ["CLM", "SCL", "dataMask"],
    output: { bands: 4 },
    mosaicking: "ORBIT"
  };
}

function isNotCloudy(smp) {
  // Check if cloud using s2cloudless and scene classification
  let clm = smp.CLM;
  let scl = smp.SCL;

  if (clm == 1){
    // s2cloudless
    return false;
  } else if (scl == 1 || scl == 3 || scl == 8 || scl == 9 || scl == 10){
    // saturated/defective, cloud shadow, cloud medium probability,
    // cloud high probability, cirrus
    return false;
  } else {
    return true;
  }
}

function evaluatePixel(samples) {
  var noOfClearPx = 0;
  var noOfSamples = 0;

  // Loop over available samples (images)
  for (i=0;i<samples.length;i++)
  {
	//If there is no value available, we avoid further count
    if (!samples[i].dataMask) continue;
     noOfSamples++;

    //Criteria for cloudless pixel
    if (
      isNotCloudy(samples[i])
     ) noOfClearPx++;
  }

  //transparent if there is no data
  if (noOfSamples==0) return [0,0,0,0];

  // Ratio of non-cloudy pixels
  var avg = noOfClearPx / noOfSamples;

  // Color scheme for visualisation
  var color= colorBlend(avg,
   [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 ],
   [
    [0/255,0,0/255],        //  -> 0 = #000000
    [141/255,0/255,0/255],   //  -> .1 = #8D0000
    [219/255,36/255,36/255],  //  -> .2 = #DB2424
    [236/255,125/255,0/255],  //  -> .3 = #EC7D00
    [236/255,199/255,0/255], //  -> .4 = #ECC700
    [111/255,161/255,32/255], //  -> .5 = #6FA120
    [75/255,126/255,39/255], //  -> .6 = #4B7E27
    [72/255,168/255,146/255], //  -> .7 = #48A892
    [63/255,142/255,185/255],  //  -> .8 = #3F8EB9
    [133/255,78/255,144/255],   //  -> .9 = #854EA4
    [85/255,34/255,115/255]         //  -> 1.0 = #552273
   ]);

  return[color[0],color[1],color[2],1];
}

Evaluate and Visualize

General description of the script

For a given time-range, this script counts the number of Sentinel-2 L2A cloud-free pixels based on the s2cloudless algorithm and the Sen2Cor scene classification (SCL) data. The SCL categories used to detect clouds in the current version of the script are:

  • saturated/defective
  • cloud shadow
  • cloud medium probability
  • cloud high probability
  • cirrus.

The categories can be easily modified to fit users’ needs. Furthermore, the SCL band can be removed from the script for compatibility with Sentinel-2 L1C images.

The script returns the ratio of cloud-free pixels against the total number of pixels over the time period.

Description of representative images

The cloud statistics over the north of Spain for July 2020. The map shows a higher occurence of clouds along the North coastline (Asturias) than inland. Processed by Sentinel Hub.

clouds

Above is an example output from the Cloud Statistics script: for each Sentinel-2 pixel, the values represent the ratio of cloud-free images over a given time period to the total number of images for the same period. Therefore, a value of 1 (represented in purple) means that 100% of the images in the time-series were cloud-free, and a value of 0 (in black) signifies that there are no cloud-free images available.

Note: users are free to improve this page and modify any part of the script.