NDVI difference between two dates Visualization EO Browser Raw Values
//VERSION=3
// Script to extract NDVI difference between the latest acquisition and the acquisition 10-day prior to the latest within a specified time range
// Returns visualized RGB values
function setup () {
return {
input : [{
bands : [ " B04 " , " B08 " , " SCL " , " dataMask " ],
units : " DN "
}],
output : { bands : 4 },
mosaicking : Mosaicking . ORBIT
}
}
function evaluatePixel ( samples ) {
// ndvi difference
let latest = samples [ 0 ];
let prior = samples [ 1 ];
let dataMask = latest . dataMask * prior . dataMask ;
const diff = dataMask === 1 ? index ( latest . B08 , latest . B04 ) - index ( prior . B08 , prior . B04 ) : NaN ;
// visualisation
const ramps = [
[ - 2 , 0x8e0152 ],
[ - 1 , 0xc51b7d ],
[ - 0.5 , 0xde77ae ],
[ 0 , 0xf7f7f7 ],
[ 0.5 , 0x7fbc41 ],
[ 1 , 0x4d9221 ],
[ 2 , 0x276419 ]
]
const visualizer = new ColorRampVisualizer ( ramps );
let imgVals = visualizer . process ( diff );
imgVals . push ( dataMask )
return imgVals
}
function preProcessScenes ( collections ) {
// sort from most recent to least recent
collections . scenes . orbits = collections . scenes . orbits . sort (
( s1 , s2 ) => new Date ( s2 . dateFrom ) - new Date ( s1 . dateFrom )
);
let scenes = collections . scenes . orbits ;
let latest ;
let closest ;
latest = closest = scenes [ 0 ];
// timestamp of 10-day prior to latest acquisition
let target = new Date ( new Date ( latest . dateFrom ). getTime () - 10 * 24 * 3600 * 1000 );
// find closet timestamp to the target
let diff = Number . POSITIVE_INFINITY ;
for ( let i = 1 ; i < scenes . length ; i ++ ) {
current = new Date ( scenes [ i ]. dateFrom );
if ( Math . abs ( current - target ) >= diff ) { break ; }
diff = Math . abs ( current - target );
closest = scenes [ i ];
}
// filter collections to keep the latest acquisition and the closest acquisitions to the target
collections . scenes . orbits = collections . scenes . orbits . filter ( function ( orbit ) {
var orbitDateFrom = orbit . dateFrom ;
return [ latest . dateFrom , closest . dateFrom ]. includes ( orbitDateFrom );
})
return collections
}
//VERSION=3
// Script to extract NDVI difference between the latest acquisition and the acquisition 10-day prior to the latest within a specified time range
// To be used on EO Browser. Makes statistics work in EOB
function setup () {
return {
input : [{
bands : [ " B04 " , " B08 " , " SCL " , " dataMask " ],
units : " DN "
}],
output : [
{ id : " default " , bands : 4 },
{ id : " index " , bands : 1 , sampleType : " FLOAT32 " },
{ id : " eobrowserStats " , bands : 2 , sampleType : " FLOAT32 " },
{ id : " dataMask " , bands : 1 }
],
mosaicking : Mosaicking . ORBIT
}
}
function evaluatePixel ( samples ) {
// ndvi difference
let latest = samples [ 0 ];
let prior = samples [ 1 ];
let dataMask = latest . dataMask * prior . dataMask ;
const diff = dataMask === 1 ? index ( latest . B08 , latest . B04 ) - index ( prior . B08 , prior . B04 ) : NaN ;
// visualisation
const ramps = [
[ - 2 , 0x8e0152 ],
[ - 1 , 0xc51b7d ],
[ - 0.5 , 0xde77ae ],
[ 0 , 0xf7f7f7 ],
[ 0.5 , 0x7fbc41 ],
[ 1 , 0x4d9221 ],
[ 2 , 0x276419 ]
]
const visualizer = new ColorRampVisualizer ( ramps );
let imgVals = visualizer . process ( diff );
imgVals . push ( dataMask )
return {
default : imgVals ,
index : [ diff ],
eobrowserStats : [ diff , isCloud ( samples . SCL ) ? 1 : 0 ],
dataMask : [ dataMask ]
};
}
function preProcessScenes ( collections ) {
// sort from most recent to least recent
collections . scenes . orbits = collections . scenes . orbits . sort (
( s1 , s2 ) => new Date ( s2 . dateFrom ) - new Date ( s1 . dateFrom )
);
let scenes = collections . scenes . orbits ;
let latest ;
let closest ;
latest = closest = scenes [ 0 ];
// timestamp of 10-day prior to latest acquisition
let target = new Date ( new Date ( latest . dateFrom ). getTime () - 10 * 24 * 3600 * 1000 );
// find closet timestamp to the target
let diff = Number . POSITIVE_INFINITY ;
for ( let i = 1 ; i < scenes . length ; i ++ ) {
current = new Date ( scenes [ i ]. dateFrom );
if ( Math . abs ( current - target ) >= diff ) { break ; }
diff = Math . abs ( current - target );
closest = scenes [ i ];
}
// filter collections to keep the latest acquisition and the closest acquisitions to the target
collections . scenes . orbits = collections . scenes . orbits . filter ( function ( orbit ) {
var orbitDateFrom = orbit . dateFrom ;
return [ latest . dateFrom , closest . dateFrom ]. includes ( orbitDateFrom );
})
return collections
}
function isCloud ( scl ) {
if ( scl == 3 ) { // SC_CLOUD_SHADOW
return false ;
} else if ( scl == 9 ) { // SC_CLOUD_HIGH_PROBA
return true ;
} else if ( scl == 8 ) { // SC_CLOUD_MEDIUM_PROBA
return true ;
} else if ( scl == 7 ) { // SC_CLOUD_LOW_PROBA
return false ;
} else if ( scl == 10 ) { // SC_THIN_CIRRUS
return true ;
} else if ( scl == 11 ) { // SC_SNOW_ICE
return false ;
} else if ( scl == 1 ) { // SC_SATURATED_DEFECTIVE
return false ;
} else if ( scl == 2 ) { // SC_DARK_FEATURE_SHADOW
return false ;
}
return false ;
}
//VERSION=3
// Script to extract NDVI difference between the latest acquisition and the acquisition 10-day prior to the latest within a specified time range
// Returns raw (Float32) values
function setup () {
return {
input : [{
bands : [ " B04 " , " B08 " , " SCL " , " dataMask " ],
units : " DN "
}],
output : {
bands : 1 ,
sampleType : SampleType . FLOAT32
},
mosaicking : Mosaicking . ORBIT
}
}
function evaluatePixel ( samples ) {
// ndvi difference
let latest = samples [ 0 ];
let prior = samples [ 1 ];
let combinedMask = latest . dataMask * prior . dataMask ;
const diff = combinedMask === 1 ? index ( latest . B08 , latest . B04 ) - index ( prior . B08 , prior . B04 ) : NaN ;
return [ diff ];
}
function preProcessScenes ( collections ) {
// sort from most recent to least recent
collections . scenes . orbits = collections . scenes . orbits . sort (
( s1 , s2 ) => new Date ( s2 . dateFrom ) - new Date ( s1 . dateFrom )
);
let scenes = collections . scenes . orbits ;
let latest ;
let closest ;
latest = closest = scenes [ 0 ];
// timestamp of 10-day prior to latest acquisition
let target = new Date ( new Date ( latest . dateFrom ). getTime () - 10 * 24 * 3600 * 1000 );
// find closet timestamp to the target
let diff = Number . POSITIVE_INFINITY ;
for ( let i = 1 ; i < scenes . length ; i ++ ) {
current = new Date ( scenes [ i ]. dateFrom );
if ( Math . abs ( current - target ) >= diff ) { break ;}
diff = Math . abs ( current - target );
closest = scenes [ i ];
}
collections . scenes . orbits = [ latest , closest ];
return collections
}
Show full evalscript Evaluate and Visualize General description This script aims to obtain the diffence of NDVI between the latest acquisition and the acquisition 10-day prior to the latest on within a specified time period. Multi-temporal analysis is common in the Earth Observation field. Here we take NDVI as an example and demonstrate how to calculate the difference of NDVI between two acquisitions using mosaicking: ORBIT
and preProcessScenes
in one single request.
To implement multi-temporal analysis in the Evalscript, we apply ORBIT
mosaicking to query daily mosaic in the specified time period. Then, by using the optional preProcessScenes
function, we find out the acquisition acquired on the date closest to the date 10-day prior to the latest acquisition and filter the out the other unused acquisitions to save Processing Units. Last but not least, in the evaluatePixel
function we initialise a combined mask to ensure the difference of NDVI between two acquisitions exists only if there is data on both dates.
Note : The example script is used to obtain the raw value of NDVI difference. For visualisation purpose, please follow the EO Browser link in the Evaluate and visualize section. The visualisation script contains 4 outputs: default, index, eobrowserStats and dataMask. The default layer is a visualisation layer to visualise NDVI difference in EO Browser. The index layer is the actual value of the NDVI difference. The eobrowserStats and the dataMask layer is configured to activate statistical features on EO Browser. Please see the FAQ for more details.
Author of the script Chung-Xiang Hong
Description of representative images The following image shows the NDVI difference between the latest acquisition and the acquisition 10-day prior to the latest one during the time period from 29th of June, 2023 to 29th July, 2023.