//VERSION=3 (auto-converted from 1)/*
Author: Karasiak Nicolas
*/// Put 3 to have synthesis of the last 90 daysvarnumberOfMonthsToUse=1;// Thresold to consider pixel as snowvarNDSIthresold=0.2;// In order to dismiss snow from watervarredThresold=0.2;// In order to dismiss cloudsvarblueThresold=0.12;varhighBlueThresold=0.45;varnumberOfTimesForWater=2;// minimum number of times to identify as watervarstretchMin=0;varstretchMax=1;functionsetup(){return{input:[{bands:["B02","B03","B04","B05","B08","B11"]}],output:{bands:3},mosaicking:"ORBIT"}}functionNDSI(sample){return((sample.B03-sample.B11)/(0.01+sample.B03+sample.B11));}functionNDWI(sample){return((sample.B03-sample.B08)/(sample.B03+sample.B08));}functionmedian(values){// from https://stackoverflow.com/questions/45309447/calculating-median-javascriptif(values.length===0)return0;if(values.length===1)returnvalues[0];values.sort(function(a,b){returna-b;});varhalf=Math.floor(values.length/2);returnvalues[half];}functionr(a,b){return(a/b);}functionstretch(val,min,max){return(val-min)/(max-min);}functionindexOfMaxRatio(a,b){ratios=[];for(i=0;i<a.length;i++){ratios.push(r(a[i],b[i]));}if(ratios.length===0){return-1;}varmax=ratios[0];varmaxIndex=0;for(vari=1;i<ratios.length;i++){if(ratios[i]>max){maxIndex=i;max=ratios[i];}}returnmaxIndex;}functionevaluatePixel(samples,scenes){// for snow sceneletsnowyCount=0;letsnowB02=[];letsnowB03=[];letsnowB04=[];// for unsnow sceneletB02=[];letB03=[];letB04=[];letB05=[];letB08=[];// for high blue sceneslethighB02=[];lethighB03=[];lethighB04=[];lethighB05=[];lethighB08=[];// isWaterletisWater=0;// to manage image length between tilesletrealSampleLength=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++;if(samples[i].B02<blueThresold){B02.push(samples[i].B02);B03.push(samples[i].B03);B04.push(samples[i].B04);B05.push(samples[i].B05);B08.push(samples[i].B08);}elseif((samples[i].B02<highBlueThresold)&(samples[i].B02>blueThresold)){highB02.push(samples[i].B02);highB03.push(samples[i].B03);highB04.push(samples[i].B04);highB05.push(samples[i].B05);highB08.push(samples[i].B08);}if((NDSI(samples[i])>NDSIthresold)&(samples[i].B04>redThresold)){snowyCount++;snowB02.push(samples[i].B02);snowB03.push(samples[i].B03);snowB04.push(samples[i].B04);}if((samples[i].B02<blueThresold)&(NDWI(samples[i])>0)){isWater++;}}}if((B02.length>0)){if(isWater>2){bestRatio=indexOfMaxRatio(B02,B08);}else{bestRatio=indexOfMaxRatio(B08,B03);}colorMap=[stretch((2.8*B04[bestRatio]+0.1*B05[bestRatio]),stretchMin,stretchMax),stretch((2.8*B03[bestRatio]+0.15*B08[bestRatio]),stretchMin,stretchMax),stretch((2.8*B02[bestRatio]),stretchMin,stretchMax)];}elseif((highB02.length>0)&(B02.length<1)){if(isWater>2){bestRatio=indexOfMaxRatio(B02,B08);}else{bestRatio=indexOfMaxRatio(highB03,highB02);}colorMap=[stretch((2.8*highB04[bestRatio]+0.1*highB05[bestRatio]),stretchMin,stretchMax),stretch((2.8*highB03[bestRatio]+0.15*highB08[bestRatio]),stretchMin,stretchMax),stretch((2.8*highB02[bestRatio]),stretchMin,stretchMax)];}elseif((snowyCount>0)&(highB02.length<1)&(B02.length<1)){// snowColorMapcolorMap=[1.1*median(snowB04),1.3*median(snowB03),1.1*median(snowB02)];}else{colorMap=[1,0,0];}returncolorMap;}functionpreProcessScenes(collections){collections.scenes.orbits=collections.scenes.orbits.filter(function(orbit){varorbitDateFrom=newDate(orbit.dateFrom)returnorbitDateFrom.getTime()>=(collections.to.getTime()-(numberOfMonthsToUse*31*24*3600*1000));})returncollections}
Monthly composite (31 days before the chosen date), computed with best bands ratio. This script is here for those who want a cloud free image representing the last 31 days.
In order to select the best pixel in a month (and avoid cloud), a selection is made using a ratio :
When blue < 0.12, date is chosen where max ratio of B08 against B02.
If no pixel available above, when blue < 0.45, date is chosen where max ratio of B03 against B02.
If water is detected, date is chosen where max ratio of B02 against B08.