diff --git a/sentinel-2/barren_soil/README.md b/sentinel-2/barren_soil/README.md index 6c60f16a..2fef430e 100644 --- a/sentinel-2/barren_soil/README.md +++ b/sentinel-2/barren_soil/README.md @@ -5,6 +5,11 @@ grand_parent: Sentinel layout: script permalink: /sentinel-2/barren_soil/ nav_exclude: true +scripts: +- - Visualization + - script.js +- - Updated version + - updated_script.js examples: - zoom: '13' lat: '45.98008' @@ -31,6 +36,8 @@ The bare soil index for Sentinel-2: **BSI = ((B11 + B04) - (B08 + B02)) / ((B11 + B04) + (B08 + B02))** +The **Updated version** tab (`updated_script.js`) is an Evalscript V3 rewrite that keeps the same colour scheme but adds two extra outputs - `index` and `eobrowserStats` (the BSI scaled to 0-1, where 1 = definitely bare soil and 0 = not bare soil) - so EO Browser shows the value at a pixel and can build Statistical Info and temporal charts. It also masks clouds and water (and other non-soil classes) via the Scene Classification Layer, following the same palette approach as the [kNDVI script](/sentinel-2/kndvi/). Updated-version contributor: András Zlinszky. + ## Author of the script Monja Sebela diff --git a/sentinel-2/barren_soil/updated_script.js b/sentinel-2/barren_soil/updated_script.js new file mode 100644 index 00000000..af424219 --- /dev/null +++ b/sentinel-2/barren_soil/updated_script.js @@ -0,0 +1,58 @@ +//VERSION=3 +// Barren soil (Bare Soil Index) - Evalscript V3 multi-output update of the original +// single-output script by Monja Sebela. This "Updated version" created by András Zlinszky (Sinergise) and AI: +// * adds `index` and `eobrowserStats` outputs (the BSI scaled to 0..1) so EO Browser +// shows the value at a pixel and builds Statistical Info / temporal charts; +// * masks clouds, water (and other non-soil classes) via the Scene Classification +// Layer, using the same palette approach as the kNDVI script +// (https://custom-scripts.sentinel-hub.com/custom-scripts/sentinel-2/kndvi/); +// * keeps the original colour scheme for land pixels. +// +// BSI = ((B11 + B04) - (B08 + B02)) / ((B11 + B04) + (B08 + B02)) + +function setup() { + return { + input: ["B02", "B04", "B08", "B11", "SCL", "dataMask"], + output: [ + { id: "default", bands: 3 }, + { id: "index", bands: 1, sampleType: "FLOAT32" }, + { id: "eobrowserStats", bands: 1, sampleType: "FLOAT32" }, + { id: "dataMask", bands: 1 }, + ], + }; +} + +// SCL classes to mask out (recoloured, and excluded from the index): no-data, defective, +// shadows, water, clouds, cirrus and snow. Same palette as the kNDVI script. +const cloud_palette = { + 0: [0, 0, 0], // No Data - black + 1: [1, 0, 0.016], // Saturated / defective - red + 2: [0.525, 0.525, 0.525], // Dark area / topographic shadows - dark grey + 3: [0.467, 0.298, 0.043], // Cloud shadows - dark brown + 6: [0, 0, 1], // Water - blue + 7: [0.506, 0.506, 0.506], // Unclassified - grey + 8: [0.753, 0.753, 0.753], // Cloud medium probability - grey + 9: [0.949, 0.949, 0.949], // Cloud high probability - white + 10: [0.733, 0.773, 0.925], // Thin cirrus - pale blue + 11: [0.325, 1, 0.98], // Snow / ice - bright cyan +}; + +function evaluatePixel(s) { + let bsi = (s.B11 + s.B04 - (s.B08 + s.B02)) / (s.B11 + s.B04 + s.B08 + s.B02); + let val = 2.5 * bsi; // unscaled value that drives the original colour scheme + let masked = Object.keys(cloud_palette).includes(s.SCL.toString()); + + // Default visualization: original colours on land, palette colours on masked classes. + let color = masked ? cloud_palette[s.SCL] : [2.5 * val, s.B08, s.B11]; + + // Index scaled to [0, 1]: 1 = definitely bare soil, 0 = not bare soil at all. + // NaN on masked pixels so they are excluded from the index readout and statistics. + let index = masked ? NaN : Math.max(0, Math.min(1, val)); + + return { + default: color, + index: [index], + eobrowserStats: [index], + dataMask: [s.dataMask], + }; +}