//VERSION=3/*
Source: @nkarasiak / www.karasiak.net
Monthly snow report.
Tired of waiting the perfect image with no cloud to show the snow cover ? This monthly snow report is here for you.
This script will find where the snow is persistent within the last 31 days (from chosen date).
In order to well represent the land-cover, the script will store each pertinent date in a list and will represents the median value.
This sentinel-2 script voluntarily color in green the image to better differentiate the snow from the other land-cover.
Script requires multi-temporal processing.
*/// Put 3 to have synthesis of the last 3 monthsvarnumberOfMonthsToUse=1;// Thresold to consider pixel as snowvarNDSIthresold=0.20;// In order to dismiss snow from watervarredThresold=0.2;// In order to dismiss cloudsvarblueThresold=0.18;functionsetup(){return{input:[{bands:["B02","B03","B04","B11"]}],output:{bands:3},mosaicking:"ORBIT"}}functionNDSI(sample){return((sample.B03-sample.B11)/(0.01+sample.B03+sample.B11));}functionmedian(values){// from https://stackoverflow.com/questions/45309447/calculating-median-javascriptif(values.length===0)return0;values.sort(function(a,b){returna-b;});varhalf=Math.floor(values.length/2);if(values.length%2)returnvalues[half];return(values[half-1]+values[half])/2.0;}functionevaluatePixel(samples,scenes){// for snow sceneletsnowyCount=0;letsnowB02=[];letsnowB03=[];letsnowB04=[];// for unsnow sceneletB02=[];letB03=[];letB04=[];// to manage image length between tilesrealSampleLength=0;for(i=0;i<samples.length;i++){// in order to avoid black pixel (the ones between tiles)if((samples[i].B02>0)||(samples[i].B03>0)){realSampleLength++;// found snowif((NDSI(samples[i])>NDSIthresold)&(samples[i].B04>redThresold)){snowyCount++;snowB02.push(samples[i].B02);snowB03.push(samples[i].B03);snowB04.push(samples[i].B04);}// maybe it is snowy but clouds...// so count as snow but not memorizing pixel values.elseif((samples[i].B02>blueThresold)&(samples[i].B04>redThresold)){snowyCount++;}// not snowelseif(samples[i].B02<blueThresold){B02.push(samples[i].B02);B03.push(samples[i].B03);B04.push(samples[i].B04);}}}if((snowB02==0)&(B02.length==0)){// no valid data available : dark green colorcolorMap=[.05,.2,.05];}elseif((snowyCount==realSampleLength)||(B02.length<1)){// snowColorMapcolorMap=[1.1*median(snowB04),1.3*median(snowB03),1.1*median(snowB02)];}elseif(B02.length>=1){// defaultColorMapcolorMap=[1.5*median(B04),2.5*median(B03),1.5*median(B02)];}returncolorMap;}functionpreProcessScenes(collections){varscenes=collections.scenes.orbits;scenes=scenes.sort((s1,s2)=>newDate(s2.dateFrom)-newDate(s1.dateFrom));varlatest_scene=newDate(scenes[0].dateFrom)collections.scenes.orbits=collections.scenes.orbits.filter(function(scene){returnnewDate(scene.dateFrom)>=latest_scene-numberOfMonthsToUse*31*24*3600*1000})returncollections}
Tired of waiting the perfect image with no cloud to show the snow cover? This monthly snow report script is for you.
This code will find where the snow is persistent for the last 30 days (from the chosen date). In order to well represent the land-cover, the script will store each pertinent date in a list and will represent the median value.
As the aim of the script is to represent the snow cover, all the other land-cover are saturated in green in order to easily see the snow.
The limitations are essentially:
a few white rooftops
when no uncloudy pixel is available in the previous 30 days
Thus, it is possible to make the script working with 90 days in order to have a trimonthly synthesis by changing settings to: “numberOfMonthsToUse = 3”.
Author of the script
Nicolas Karasiak
Description of representative images
Persistent snow cover in February 2019 in Corsica
Persistent snow cover in Pyrénées in March 2019
Mer de Glace / Alpes persistent snow cover in the previous 30 days of 24 april 2019.