//VERSION=3 (auto-converted from 2)//NOTE: This Custom script requires Sentinel Hub API v.2 to operate properly. It is however possible to use some parts of it already now.functionsetup(){return{input:[{bands:["B01","B02","B03","B04","B05","B06","B07","B08","B8A","B11","B12","AOT","CLD","SNW","SCL","viewZenithMean","viewAzimuthMean","sunZenithAngles","sunAzimuthAngles"]}],output:[{id:"quality_aot",sampleType:"UINT16",bands:1},{id:"B11",sampleType:"UINT16",bands:1},{id:"B01",sampleType:"UINT16",bands:1},{id:"B12",sampleType:"UINT16",bands:1},{id:"quality_cloud_confidence",sampleType:"UINT8",bands:1},{id:"B02",sampleType:"UINT16",bands:1},{id:"valid_obs",sampleType:"UINT8",bands:1},{id:"B03",sampleType:"UINT16",bands:1},{id:"B04",sampleType:"UINT16",bands:1},{id:"B05",sampleType:"UINT16",bands:1},{id:"B06",sampleType:"UINT16",bands:1},{id:"B07",sampleType:"UINT16",bands:1},{id:"view_azimuth_mean",sampleType:"UINT16",bands:1},{id:"B08",sampleType:"UINT16",bands:1},{id:"sun_zenith",sampleType:"UINT16",bands:1},{id:"B8A",sampleType:"UINT16",bands:1},{id:"source_index",sampleType:"INT16",bands:1},{id:"view_zenith_mean",sampleType:"UINT16",bands:1},{id:"sun_azimuth",sampleType:"UINT16",bands:1},{id:"quality_snow_confidence",sampleType:"UINT8",bands:1},{id:"medoid_mos",sampleType:"UINT16",bands:1},{id:"quality_scene_classification",sampleType:"UINT8",bands:1}],mosaicking:"TILE"}}functionevaluatePixel(samples,scenes){varfilteredSamples=filterByOrbitId(samples,scenes);varbest=selectRepresentativeSample(filteredSamples);if(best===undefined){return{B01:[0],B02:[0],B03:[0],B04:[0],B05:[0],B06:[0],B07:[0],B08:[0],B8A:[0],B11:[0],B12:[0],source_index:[65535],quality_aot:[0],quality_cloud_confidence:[0],quality_snow_confidence:[0],quality_scene_classification:[0],view_zenith_mean:[32768],view_azimuth_mean:[32768],sun_zenith:[32768],sun_azimuth:[32768],medoid_mos:[65535],valid_obs:[0]};}else{varbestSample=best.sample;varmos;varsampleIndex=samples.indexOf(bestSample);if(isNaN(best.mos)){mos=65535;}else{mos=best.mos*10000;}return{B01:[bestSample.B01*10000],B02:[bestSample.B02*10000],B03:[bestSample.B03*10000],B04:[bestSample.B04*10000],B05:[bestSample.B05*10000],B06:[bestSample.B06*10000],B07:[bestSample.B07*10000],B08:[bestSample.B08*10000],B8A:[bestSample.B8A*10000],B11:[bestSample.B11*10000],B12:[bestSample.B12*10000],source_index:[sampleIndex],quality_aot:[bestSample.AOT*10000],quality_cloud_confidence:[bestSample.CLD],quality_snow_confidence:[bestSample.SNW],quality_scene_classification:[bestSample.SCL],view_zenith_mean:[bestSample.viewZenithMean*100],view_azimuth_mean:[bestSample.viewAzimuthMean*100],sun_zenith:[bestSample.sunZenithAngles*100],sun_azimuth:[bestSample.sunAzimuthAngles*100],medoid_mos:[mos],valid_obs:[best.valid_obs]};}}// UtilsfunctiontoUInt16(value){returnMath.max(0,Math.min(value*10000,65535));}functionfilterByOrbitId(samples,scenes){varorbitId=-1;returnsamples.map(function(sample,i){return{s:sample,orbitId:scenes[i].orbitId,tileId:scenes[i].tileId};}).filter(e=>e.s.SCL>0).sort(function(a,b){if(a.orbitId<b.orbitId)return1;if(a.orbitId>b.orbitId)return-1;if(a.tileId<b.tileId)return1;if(a.tileId>b.tileId)return-1;return0;}).filter(function(e){if(e.orbitId!==orbitId){orbitId=e.orbitId;returntrue;}else{returnfalse;}}).map(e=>e.s);}// MosaicconstminSamplesForMedoid=4;functionselectRepresentativeSample(samples){varn=samples.length;varvalidSamples=samples.filter(validate);varvalidSamplesNum=validSamples.length;if(validSamplesNum==0){returnundefined;}if(validSamplesNum==1){return{sample:validSamples[0],mos:NaN,valid_obs:1};}if(validSamplesNum>=minSamplesForMedoid){returnperformMedoid(validSamples);}else{returnperformStc(validSamples);}}functionperformMedoid(samples){varmedoid=computeMedoidIndex(samples);return{sample:samples[medoid.index],mos:medoid.spread,valid_obs:samples.length};}functionperformStc(samples){varbestSample=samples[0];for(vari=1;i<samples.length;i++){bestSample=computeStc(samples[i],bestSample);}return{sample:bestSample,mos:NaN,valid_obs:samples.length};}// Validatefunctionvalidate(sample){returnvalidateSCL(sample.SCL)&&validateViewZenithMean(sample.viewZenithMean);}functionvalidateSCL(scl){returnscl==2||scl==4||scl==5||scl==6||scl==11;}functionvalidateViewZenithMean(vzm){returnvzm<11;}functionvalidateSamples(samples){returnsamples.every(validateSample);}functionvalidateSample(sample){return!isNaN(sample)&&isFinite(sample);}// STCfunctioncomputeNdvi(sample){return(sample.B08-sample.B04)/(sample.B08+sample.B04);}functioncomputeVisualBandsSum(sample){returnsample.B02+sample.B03+sample.B04;}functioncomputeSWIRMean(sample){return(sample.B11+sample.B12)/2;}functioncomputeNdwi(sample){return(sample.B03-sample.B08)/(sample.B03+sample.B08);}functioncomputeStc(sampleA,sampleB){varkeySwitch=sampleA.SCL*100+sampleB.SCL;switch(keySwitch){//Vegetationcase404:varndviSampleA=computeNdvi(sampleA);varndviSampleB=computeNdvi(sampleB);if(ndviSampleA>ndviSampleB&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{if(ndviSampleA<ndviSampleB&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{returnsampleB;}}break;case405:case504:if(computeVisualBandsSum(sampleA)<computeVisualBandsSum(sampleB)&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{returnsampleB;}break;case400:case401:case402:case403:case406:case407:case408:case409:case410:case411:returnsampleA;break;case4:case104:case204:case304:case604:case704:case804:case904:case1004:case1104:returnsampleB;break;//BARE_SOIL_DESERTcase505:if(computeVisualBandsSum(sampleA)<computeVisualBandsSum(sampleB)&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{returnsampleB;}break;case500:case501:case502:case503:case506:case507:case508:case509:case510:case511:returnsampleA;break;case5:case105:case205:case305:case605:case705:case805:case905:case1005:case1105:returnsampleB;break;//SNOW_ICEcase1111:if(computeVisualBandsSum(sampleA)>computeVisualBandsSum(sampleB)&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{returnsampleB;}break;case1100:case1101:case1102:case1103:case1106:case1107:case1108:case1109:case1110:returnsampleA;break;case11:case111:case211:case311:case611:case711:case811:case911:case1011:returnsampleB;break;//Watercase606:if((computeNdwi(sampleA)>computeNdwi(sampleB)||computeSWIRMean(sampleA)<computeSWIRMean(sampleB))&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{returnsampleB;}break;case600:case601:case602:case603:case607:case608:case609:case610:returnsampleA;break;case6:case106:case206:case306:case706:case806:case906:case1006:returnsampleB;break;//DARK_FEATURE_SHADOWcase202:if(computeVisualBandsSum(sampleA)>computeVisualBandsSum(sampleB)&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{returnsampleB;}break;case200:case201:case203:case207:case208:case209:case210:returnsampleA;break;case2:case102:case302:case702:case802:case902:case1002:returnsampleB;break;//CLOUD_SHADOWcase303:if(computeVisualBandsSum(sampleA)>computeVisualBandsSum(sampleB)&&sampleA.CLD<=sampleB.CLD){returnsampleA;}else{returnsampleB;}break;case300:case301:case307:case308:case309:case310:returnsampleA;break;case3:case103:case703:case803:case903:case1003:returnsampleB;break;//CLOUD_LOW_PROBAcase707:if(computeVisualBandsSum(sampleA)<computeVisualBandsSum(sampleB)){returnsampleA;}else{returnsampleB;}break;case700:case701:case708:case709:case710:returnsampleA;break;case7:case107:case807:case907:case1007:returnsampleB;break;//THIN_CIRRUScase1010:if(computeVisualBandsSum(sampleA)<computeVisualBandsSum(sampleB)){returnsampleA;}else{returnsampleB;}break;case1000:case1001:case1008:case1009:returnsampleA;break;case10:case110:case810:case910:returnsampleB;break;//CLOUD_MEDIUM_PROBAcase808:if(computeVisualBandsSum(sampleA)<computeVisualBandsSum(sampleB)){returnsampleA;}else{returnsampleB;}break;case800:case801:case809:returnsampleA;break;case8:case108:case908:returnsampleB;break;//CLOUD_HIGH_PROBAcase909:if(computeVisualBandsSum(sampleA)<computeVisualBandsSum(sampleB)){returnsampleA;}else{returnsampleB;}break;case900:case901:returnsampleA;break;case9:case109:returnsampleB;break;//SATURATED_DEFECTIVEcase101:if(computeVisualBandsSum(sampleA)<computeVisualBandsSum(sampleB)){returnsampleA;}else{returnsampleB;}break;case100:returnsampleA;break;case1:returnsampleB;break;default:returnundefined;}}// Medoidfunctiondistance(a,b){varret=0;ret+=Math.pow(a.B02-b.B02,2);ret+=Math.pow(a.B03-b.B03,2);ret+=Math.pow(a.B04-b.B04,2);ret+=Math.pow(a.B06-b.B06,2);ret+=Math.pow(a.B08-b.B08,2);ret+=Math.pow(a.B11-b.B11,2);ret+=Math.pow(a.B12-b.B12,2);returnMath.sqrt(ret);}functioncomputeMedoidIndex(samples){varn=samples.length;vard=createDistanceMatrix(samples);vardistanceRow;vardistanceSum;vardistanceSumMin=Number.POSITIVE_INFINITY;varmedoidIndex=-1;for(varj=0;j<n;j++){distanceRow=d[j];distanceSum=0.0;for(vari=0;i<n;i++){distanceSum+=distanceRow[i];}if(distanceSum<distanceSumMin){distanceSumMin=distanceSum;medoidIndex=j;}}return{index:medoidIndex,spread:distanceSumMin/n};}functioncreateDistanceMatrix(samples){varn=samples.length;vard=createArray(n,n);for(vari=0;i<n;i++){vara=samples[i];for(varj=i+1;j<n;j++){varb=samples[j]d[i][j]=d[j][i]=distance(a,b);}d[i][i]=0;}returnd;}functioncreateArray(length){vararr=newArray(length||0),i=length;if(arguments.length>1){varargs=Array.prototype.slice.call(arguments,1);while(i--)arr[length-1-i]=createArray.apply(this,args);}returnarr;}
General description
Sentinel-2 Global Mosaic script is used within S2GM project to select best pixel within the chosen temporal period (10-daily, monthly, quarterly, annual).
Script requires Sentinel Hub API v.2 to run as a whole due to multi-part result. Parts of it can however be used at this point already.