Historical flood occurrence
Inspired from Dr. Ate Poortinga’s work in extracting water occurrence from satellite image, I tried to do similar analysis to get historical average of flood occurrence by month. The result from this analysis will be added as a probability information to enhance WFP's VAMPIRE flood alert system (Extreme rainfall-triggering flood) that currently I am working on.
The steps below describe how to extract monthly water occurrence and seasonality water using Google Earth Engine code editor.
Step 1. Define geographic domain
var point = ee.Geometry.Point(111.9124, -6.9454); var rectangle = ee.Geometry.Rectangle(57.0,-13.0,175,57.0); var bbox = ee.Feature(rectangle).geometry(); Map.centerObject(point, 11);
Step 2. Import JRC Global Surface Water and extract permanent water from Seasonality layer
var jrcA = ee.Image('JRC/GSW1_1/GlobalSurfaceWater');
var seasonality = jrcA.select('seasonality').clip(bbox);
var jrcB = ee.ImageCollection("JRC/GSW1_1/MonthlyHistory");
Step 3. Define study period (example: extract January data from 1984 - 2018)
var startYear = 1984;
var endYear = 2018;
var startMonth = 1;
var endMonth = 12;
var startDate = ee.Date.fromYMD(startYear, startMonth,1);
var endDate = ee.Date.fromYMD(endYear, endMonth,31);
var months = endDate.difference(startDate, 'month').divide(12).toInt().add(1);
print('Number of month selected : ', months);
var myjrc = jrcB.filterBounds(bbox);
var myjrc = jrcB.filter(ee.Filter.calendarRange(startYear, endYear, 'year')).filter(ee.Filter.calendarRange(startMonth, endMonth, 'month'));
Step 4. Detect all observation data with water
// Detect observations
var myjrc = myjrc.map(function(img){
// observation is img > 0
var obs = img.gt(0);
return img.addBands(obs.rename('obs').set('system:time_start', img.get('system:time_start')));
});
// Detect all observations with water
var myjrc = myjrc.map(function(img){
// if water
var water = img.select('water').eq(2);
return img.addBands(water.rename('onlywater').set('system:time_start', img.get('system:time_start')));
});
Step 5. Calculate flood occurrence
// Calculate the total amount of observations
var totalObs = ee.Image(ee.ImageCollection(myjrc.select("obs")).sum().toFloat());
// Calculate all observations with water
var totalWater = ee.Image(ee.ImageCollection(myjrc.select("onlywater")).sum().toFloat());
// Calculate the percentage of observations with water
var floodfreq0 = totalWater.divide(totalObs).multiply(100);
// Mask areas that are not water (land)
var landMask = floodfreq0.eq(0).not();
var floodfreq1 = floodfreq0.updateMask(landMask); //Historical water occurrence (permanent water + flood)
// Extract permanent water, threshold >= 82% occurrence
// 82% came from https://www.frontiersin.org/articles/10.3389/fenvs.2019.00191/full
var gte82Mask = floodfreq1.gte(82);
var pw82 = floodfreq1.updateMask(gte82Mask);
// Subtract water (flood) occurrence with permanent water, threshold >= 82% occurrence
var gt82Mask = floodfreq1.gte(82).not();
var floodfreq2 = floodfreq1.updateMask(gt82Mask);
// Extract permanent water, threshold >= 10month/year occurrence
var gte10Mask0 = seasonality.gte(10);
var pw10 = seasonality.updateMask(gte10Mask0);
// Subtract water (flood) occurrence with permanent water, threshold >= 10month/year occurrence
var gte10Mask1 = seasonality.gte(10).mask(1);
gte10Mask1 = gte10Mask1.eq(1).not();
var floodfreq3 = floodfreq1.updateMask(gte10Mask1);
Step 6. Visualisation and add map to canvas
// Seasonal Water - Orange to Red is persistent water for at least 10 month/year
var seasonalityVis = {min: 0.0, max: 12.0, palette: ['f7fbff','deebf7','c6dbef','9ecae1','6baed6','4292c6','2171b5','08519c','08306b','fd8d3c','f03b20','bd0026']};
// Flood Occurrence
var floodViz = {min:0, max:100, palette:['c10000','d742f4','001556','b7d2f7']};
// Permanent Water >=82%
var pw82Viz = {palette:"ff9e00"};
// Permanent Water >=10month
var pw10Viz = {palette:"38f500"};
// Add map to canvas
Map.addLayer(floodfreq3.clip(bbox), floodViz,"FloodFreq without PW >=10month", true);
Map.addLayer(floodfreq2.clip(bbox), floodViz,"FloodFreq without PW >=82%", false);
Map.addLayer(floodfreq1.clip(bbox), floodViz,"FloodFreq", false);
Map.addLayer(pw10.clip(bbox), pw10Viz,"Permanent Water >=10 month/year", false);
Map.addLayer(pw82.clip(bbox), pw82Viz,"Permanent Water >=82% occurrence", false);
Map.addLayer(seasonality.clip(bbox), seasonalityVis, "Seasonal Water", false);
Step 7. Export the result to Google Drive
Export.image.toDrive({
image:floodfreq3,
description:'FF_January_1984_2018',
folder:'GEE',
scale:30,
region: bbox_LKA,
maxPixels:1e12
});
Step 8. Setting legend
// Set position of panel
var legend = ui.Panel({
style: {
position: 'bottom-right',
padding: '8px 15px'
}
});
// Create legend title
var legendTitle = ui.Label({
value: 'Probability of Flood Ocurrence (%)',
style: {
fontWeight: 'bold',
fontSize: '18px',
margin: '0 0 4px 0',
padding: '0'
}
});
// Add the title to the panel
legend.add(legendTitle);
// Create the legend image
var lon = ee.Image.pixelLonLat().select('latitude');
var gradient = lon.multiply((floodViz.max-floodViz.min)/100.0).add(floodViz.min);
var legendImage = gradient.visualize(floodViz);
// Create text on top of legend
var panel = ui.Panel({
widgets: [
ui.Label(floodViz['max'])
],
});
legend.add(panel);
// Create thumbnail from the image
var thumbnail = ui.Thumbnail({
image: legendImage,
params: {bbox:'0,0,10,100', dimensions:'10x200'},
style: {padding: '1px', position: 'bottom-center'}
});
// Add the thumbnail to the legend
legend.add(thumbnail);
// Area text on top of legend
var panel = ui.Panel({
widgets: [
ui.Label(floodViz['min'])
],
});
legend.add(panel);
Map.add(legend);
Figure 1. Google Earth Engine user interface
Full script here