2

The below code calculates the number of days with heavy precipitation with dates. However I don't know how can I compute the number of consecutive days from the final result. For instance, I want to know that how many consecutive days experienced heavy rainfall.

Code link: https://code.earthengine.google.com/0b25766495d1f1a355fbaf3973b97012

Map.centerObject(table);
Map.addLayer(table);

var temporalCollection = function(collection, start, count, interval, units){
  
  var sequence = ee.List.sequence(0, ee.Number(count).subtract(1));
  var originDate = ee.Date(start);
  
  return ee.ImageCollection(sequence.map(function(i){
    
    var startDate = originDate.advance(ee.Number(interval).multiply(i), units);
    var endDate = originDate.advance(ee.Number(interval).multiply(ee.Number(i).add(1)),units);
    
    return collection
    .filterDate(startDate, endDate).mean()
    .set('system:time_start', startDate.millis())
    .set('system:time_end', endDate.millis());
    
  }));
  
};

var startYear = '2020'; 
var endYear = '2021';

var pr = function(img){
  return img.select('precipitationCal').clip(table).multiply(24)
  .copyProperties(img,['system:time_start','system:time_end']);
};

var precipitationGPM = ee.ImageCollection("NASA/GPM_L3/IMERG_V06")
.filterDate(startYear, endYear)
.filterBounds(table)
.map(pr);


var prDaily = temporalCollection(precipitationGPM, startYear, 365, 1, 'days')
.filter(ee.Filter.calendarRange(6,8,'month'))
.map(function(img){
  
  var pday = img.multiply(24.0);
  
  var pMean = pday.reduceRegion({
    reducer: ee.Reducer.mean(),
    scale: 1000,
    geometry: table
  }).getNumber('precipitationCal');
  
  return pday
  .set('pMean',pMean)
  .copyProperties(img,['system:time_start','system:time_end']);
});


print(prDaily);


// extreme evemts analysis
// pr >= 10 mm/day as heavy rainfall
// pr >= 20 mm/day as very heavy rainfall



var heavyRain = prDaily
.filterMetadata('pMean','greater_than', 9.9)



print('Heavy Rainy Days:'+startYear, heavyRain.size());


//----------------------------------------------------------------

// put all dates in a list
var dates = ee.List(heavyRain.aggregate_array("system:time_start"))
    .map(function(d) { return ee.Date(d)});

// print a list with dates
print(dates);
2

1 Answer 1

2

For applying Gorelick's approach (Runs with Arrays) to precipitation values different of 0, you only have to try with 1 values generated with the specified threshold (9.9 in your case) for daily precipitation sequence. So, you only need to change a few lines in original Gorelick's code: prepending a 0 to the difference array and mask wetRunStarts and wetRunLengths (I also renamed the variables for an obvious reason) with 1 instead 0.

As you didn't generate a daily precipitation sequence based in the threshold, you need one. It is easily obtained with following function:

var prDaily_lst = prDaily.toList(prDaily.size());

var precipitation = prDaily_lst.map(function (ele) {
  
  return ee.Algorithms.If(ee.Number.parse(ee.Image(ele).get('pMean')).gt(9.9), 1, 0);
  
}); 

You also need a dates sequence for pairing them with wetRunStarts list resulting of adapting Gorelick's code. It looks as follows.

var dates = prDaily.aggregate_array("system:time_start");

var dates = dates.map(function(date){
  return ee.Date(date).format().slice(0,10);
  });

Complete code looks as follows:

Map.centerObject(table);
Map.addLayer(table);

var temporalCollection = function(collection, start, count, interval, units){
  
  var sequence = ee.List.sequence(0, ee.Number(count).subtract(1));
  var originDate = ee.Date(start);
  
  return ee.ImageCollection(sequence.map(function(i){
    
    var startDate = originDate.advance(ee.Number(interval).multiply(i), units);
    var endDate = originDate.advance(ee.Number(interval).multiply(ee.Number(i).add(1)),units);
    
    return collection
    .filterDate(startDate, endDate).mean()
    .set('system:time_start', startDate.millis())
    .set('system:time_end', endDate.millis());
    
  }));
  
};

var startYear = '2020'; 
var endYear = '2021';

var pr = function(img){
  return img.select('precipitationCal').clip(table).multiply(24)
  .copyProperties(img,['system:time_start','system:time_end']);
};

var precipitationGPM = ee.ImageCollection("NASA/GPM_L3/IMERG_V06")
  .filterDate(startYear, endYear)
  .filterBounds(table)
  .map(pr);

var prDaily = temporalCollection(precipitationGPM, startYear, 365, 1, 'days')
  .filter(ee.Filter.calendarRange(6,8,'month'))
  .map(function(img){
  
    var pday = img.multiply(24.0);
  
    var pMean = pday.reduceRegion({
      reducer: ee.Reducer.mean(),
      scale: 1000,
      geometry: table
    }).getNumber('precipitationCal');
  
  return pday
    .set('pMean',pMean)
    .copyProperties(img,['system:time_start','system:time_end']);
});

print("prDaily", prDaily);

// extreme evemts analysis
// pr >= 10 mm/day as heavy rainfall
// pr >= 20 mm/day as very heavy rainfall

var heavyRain = prDaily
  .filterMetadata('pMean','greater_than', 9.9);

//print('Heavy Rainy Days:' + startYear, heavyRain.size());

var prDaily_lst = prDaily.toList(prDaily.size());

var precipitation = prDaily_lst.map(function (ele) {
  
  return ee.Algorithms.If(ee.Number.parse(ee.Image(ele).get('pMean')).gt(9.9), 1, 0);
  
});

print('precipitation', precipitation);

//----------------------------------------------------------------

// put all dates in a list
var dates = prDaily.aggregate_array("system:time_start");

var dates = dates.map(function(date){
  return ee.Date(date).format().slice(0,10);
  });

// print a list with dates
print("dates", dates);

// We're only working with a single axis: #0
var axis = 0;

// computes the foward difference of an array.
var forwardDifference = function(array) {
  var left = array.slice(axis, 0, -1);
  var right = array.slice(axis, 1);
  return left.subtract(right);
};

var precipitation = ee.Array(precipitation);

var difference = forwardDifference(precipitation);
difference = ee.Array.cat([[0], difference], axis);   // Prepend a 0 to the difference array.

//print("difference", difference);

var length1 = precipitation.length().get([0]);   // How long is the data array?
var indexList = ee.List.sequence(0, length1.subtract(1));  // A list of sequential numbers.

var runStarts = ee.Array(indexList).mask(difference.neq(0));
var runLengths = forwardDifference(ee.Array.cat([runStarts, [length1]], 0)).multiply(-1);

var runValues = precipitation.mask(difference.neq(0));

var wetRunStarts = runStarts.mask(runValues.eq(1));
var wetRunLengths = runLengths.mask(runValues.eq(1));

var datesWetRunStarts = wetRunStarts.toList().map(function (ele) {
  
  return dates.get(ele);
  
});

print("wetRunStarts", wetRunStarts);
print("datesWetRunStarts", datesWetRunStarts);
print("wetRunLengths", wetRunLengths);

var maxIndex = wetRunLengths.argmax();

print(wetRunStarts.get(maxIndex).format("The first day of the longest wet run is day: %d"));
print(wetRunLengths.get(maxIndex).format("The length of the longest run of wet days is: %d days")); 

After running above code in GEE code editor, I got result of following image.

enter image description here

All printed results were corroborated carefully and they were as expected.

Editing Note:

For setting a range between 5 to 10 mm you need to generate precipitation ones sequence as follows:

var precipitation = prDaily_lst.map(function (ele) {
  
  return ee.Algorithms.If(ee.Number.parse(ee.Image(ele).get('pMean')).gte(2)
                          .and(ee.Number.parse(ee.Image(ele).get('pMean')).lte(5)), 1, 0);
  
});

Complete code is here and, after running it, I got following result.

enter image description here

You can corroborate that code also works as expected by using precipitation_val variable.

3
  • You right it works. How can I set a range for rainfall threshold. For instance when I set a range between 5 to 10 mm returns error. Dec 16, 2021 at 4:14
  • The key is how to generate ones sequence by using that range. You can see my Editing Note where it can be watched how it can be done.
    – xunilk
    Dec 16, 2021 at 12:13
  • It works, appreciated. Dec 17, 2021 at 7:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.