-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add flash drought example for Soil Water Content (#334)
* Add initial flash drought script * Add raw file * add flash drought * add flash drought * right links on index page * Add superscript to SWC units * Add improved formatting, align whitespace * Refactor to remove map --------- Co-authored-by: anne <[email protected]>
- Loading branch information
1 parent
65721e0
commit 5f05c28
Showing
5 changed files
with
181 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+298 KB
...ables/soil-water-content/soil-water-content-flash-drought/fig/flash_drought.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions
30
planetary-variables/soil-water-content/soil-water-content-flash-drought/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
--- | ||
title: Flash Drought | ||
grand_parent: Planetary Variables | ||
parent: Soil Water Content | ||
layout: script | ||
nav_exclude: false | ||
scripts: | ||
- [Visualization, script.js] | ||
- [Raw Values, raw.js] | ||
--- | ||
## General description | ||
Droughts that are formed in just a few weeks are called flash droughts. We have published a [series of blog posts](https://www.planet.com/pulse/drying-up-in-a-flash-what-satellite-data-can-tell-us-about-flash-drought-risks-and-the-regions-we-should-be-watching/) about this fast-emerging and increasingly impactful climate phenomenon. This custom script uses the same principles as described in the blogs and can be used to highlight areas with potential flash droughts. | ||
|
||
## Method | ||
Based on the work of Eswar et al. (2018), we developed a methodology that highlights areas that reach a certain threshold for dryness and changes in SWC over a 28-day period. Specific thresholds for dryness and changes in SWC are set; by default, areas are highlighted where the 14-days backward average SWC was under 0.15 m<sup>3</sup>/m<sup>3</sup> and the average decrease in the 14-days backward average SWC was above 0.12 m<sup>3</sup>/m<sup>3</sup> compared to 28 days ago. Visualizing the areas that meet those criteria over time show these rapidly drying regions in red, and as conditions continue to change, they fade away. | ||
|
||
## Description of representative images | ||
[One of the blog posts](https://www.planet.com/pulse/flash-drought-hotspots-southwestern-united-states/) describes the flash drought in Southwestern United States in 2023. The example below shows the flash drought in a part of the Southwest on 22 April 2023. | ||
![Flash Drought Southwestern U.S.A. 22 April 2023](fig/flash_drought.png) | ||
|
||
## Usage of the script | ||
The amount of days to calculate the backward average is 14, but can be changed by setting *nDaysBackwardAverage*. By default, the backward average SWC value is compared to the backward average SWC value of 28 days ago, which can be changed by setting *nDaysPrevious*. If you have a collection with SWC data, the first day on which this flash drought script can be applied is day 42 (*nDaysBackwardAverage + nDaysPrevious*). Be also aware that you set the timespan correctly in the EO Browser or Requests Builder (the difference between the start and end date must be at least *nDaysBackwardAverage + nDaysPrevious*), otherwise *no data* will be returned. | ||
|
||
## Useful links | ||
- [Drying Up in a Flash: What Satellite Data Can Tell Us About Flash Drought Risks and the Regions We Should Be Watching](https://www.planet.com/pulse/drying-up-in-a-flash-what-satellite-data-can-tell-us-about-flash-drought-risks-and-the-regions-we-should-be-watching/) | ||
- [Flash Drought Hotspots: Southwestern United States](https://www.planet.com/pulse/flash-drought-hotspots-southwestern-united-states/) | ||
- [Flash Drought Hotspots: Iberian Peninsula](https://www.planet.com/pulse/flash-drought-hotspots-iberian-peninsula/) | ||
|
||
## References | ||
Eswar R., Das N.N., Poulsen C., Behrangi A., Swigart J., Svoboda M., Entekhabi D., Yueh S., Doorn B., Entin J. (2018). SMAP Soil Moisture Change as an Indicator of Drought Conditions. Remote Sensing, 10(5), 788. [https://doi.org/10.3390/rs10050788](https://doi.org/10.3390/rs10050788) |
72 changes: 72 additions & 0 deletions
72
planetary-variables/soil-water-content/soil-water-content-flash-drought/raw.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
//VERSION=3 | ||
|
||
const nDaysBackwardAverage = 14; // The number of days that is used to calculate the swc backward average | ||
const nDaysPrevious = 28; // The number of days to look back to compare the current value with the previous value | ||
const scaleFactor = 1000; // The scale factor for the SWC values | ||
const droughtThreshold = 0.15; // The SWC value under which conditions are considered drought-like | ||
const differenceThreshold = -0.12; // Threshold signifying a rapid drop in SWC from the previous average value | ||
|
||
function setup() { | ||
return { | ||
input: ["SWC", "dataMask"], | ||
output: { bands: 1 }, | ||
mosaicking: "ORBIT", | ||
}; | ||
} | ||
|
||
const daysToLoad = nDaysBackwardAverage + nDaysPrevious; // The number of days looking back to load data for | ||
|
||
function preProcessScenes(collections) { | ||
const millisecondsBack = daysToLoad * 24 * 3600 * 1000; | ||
|
||
collections.scenes.orbits = collections.scenes.orbits.filter(function ( | ||
orbit | ||
) { | ||
const orbitDateFrom = new Date(orbit.dateFrom); | ||
return ( | ||
orbitDateFrom.getTime() >= collections.to.getTime() - millisecondsBack | ||
); | ||
}); | ||
return collections; | ||
} | ||
|
||
function getMeanSWCValue(samples) { | ||
// Get the sum of all SWC values | ||
let validDateCount = 0; | ||
let sum = 0; | ||
for (let i = 0; i < samples.length; i++) { | ||
if (samples[i].dataMask) { | ||
sum += samples[i].swc; | ||
validDateCount += 1; | ||
} | ||
} | ||
|
||
// Calculate the mean SWC value | ||
let meanSWCValue = NaN; | ||
if (validDateCount > 0) { | ||
meanSWCValue = sum / validDateCount; | ||
} | ||
|
||
return meanSWCValue; | ||
} | ||
|
||
function evaluatePixel(samples) { | ||
// When there are no dates, return no data | ||
if (samples.length == 0) return [NaN]; | ||
// When the search interval of the request body is too short to perform the calculation, return no data | ||
if (samples.length < daysToLoad) return [NaN]; | ||
|
||
// Extract samples for the two time periods | ||
const initialSamples = samples.slice(0, nDaysBackwardAverage) | ||
const previousSamples = samples.slice(nDaysPrevious, nDaysBackwardAverage + nDaysPrevious) | ||
|
||
// Calculate mean SWC value | ||
const meanSWC = getMeanSWCValue(initialSamples); | ||
const meanSWCPrevious = getMeanSWCValue(previousSamples); | ||
|
||
const swcDifference = meanSWC - meanSWCPrevious; | ||
const isFlashDrought = | ||
meanSWC < droughtThreshold && swcDifference < differenceThreshold ? 1 : 0; | ||
|
||
return [isFlashDrought]; | ||
} |
77 changes: 77 additions & 0 deletions
77
planetary-variables/soil-water-content/soil-water-content-flash-drought/script.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
//VERSION=3 | ||
|
||
const nDaysBackwardAverage = 14; // The number of days that is used to calculate the swc backward average | ||
const nDaysPrevious = 28; // The number of days to look back to compare the current value with the previous value | ||
const scaleFactor = 1000; // The scale factor for the SWC values | ||
const droughtThreshold = 0.15; // The SWC value under which conditions are considered drought-like | ||
const differenceThreshold = -0.12; // Threshold signifying a rapid drop in SWC from the previous average value | ||
|
||
function setup() { | ||
return { | ||
input: ["SWC", "dataMask"], | ||
output: { bands: 4 }, | ||
mosaicking: "ORBIT", | ||
}; | ||
} | ||
|
||
const daysToLoad = nDaysBackwardAverage + nDaysPrevious; // The number of days looking back to load data for | ||
|
||
function preProcessScenes(collections) { | ||
const millisecondsBack = daysToLoad * 24 * 3600 * 1000; | ||
|
||
collections.scenes.orbits = collections.scenes.orbits.filter(function ( | ||
orbit | ||
) { | ||
const orbitDateFrom = new Date(orbit.dateFrom); | ||
return ( | ||
orbitDateFrom.getTime() >= collections.to.getTime() - millisecondsBack | ||
); | ||
}); | ||
return collections; | ||
} | ||
|
||
function getMeanSWCValue(samples) { | ||
// Get the sum of all SWC values | ||
let validDateCount = 0; | ||
let sum = 0; | ||
for (let i = 0; i < samples.length; i++) { | ||
if (samples[i].dataMask) { | ||
sum += samples[i].swc; | ||
validDateCount += 1; | ||
} | ||
} | ||
|
||
// Calculate the mean SWC value | ||
let meanSWCValue = NaN; | ||
if (validDateCount > 0) { | ||
meanSWCValue = sum / validDateCount; | ||
} | ||
|
||
return meanSWCValue; | ||
} | ||
|
||
function evaluatePixel(samples) { | ||
// When there are no dates, return no data | ||
if (samples.length == 0) return [NaN, NaN, NaN, 0]; | ||
// When the search interval of the request body is too short to perform the calculation, return no data | ||
if (samples.length < daysToLoad) return [NaN, NaN, NaN, 0]; | ||
|
||
// Extract samples for the two time periods | ||
const initialSamples = samples.slice(0, nDaysBackwardAverage) | ||
const previousSamples = samples.slice(nDaysPrevious, nDaysBackwardAverage + nDaysPrevious) | ||
|
||
// Calculate mean SWC value | ||
const meanSWC = getMeanSWCValue(initialSamples); | ||
const meanSWCPrevious = getMeanSWCValue(previousSamples); | ||
|
||
const swcDifference = meanSWC - meanSWCPrevious; | ||
const isFlashDrought = | ||
meanSWC < droughtThreshold && swcDifference < differenceThreshold ? 1 : 0; | ||
|
||
let opacity = 0; | ||
if (isFlashDrought) { | ||
opacity = 1; | ||
} | ||
|
||
return [isFlashDrought, 0, 0, opacity]; | ||
} |