Google Earth Engine – Calculating Daily GDD from ERA-5 Hourly Data

google-earth-enginegoogle-earth-engine-javascript-api

I have written a code for calculating GDD(Growing Degree Days) using the ERA-5 hourly 2m temperature data in Google Earth Engine. The code uses the max and min temperature of that day to calculate the average temperature which is then subtracted by the base temperature (which is a constant value). The code works fine for a single date data, however when I try to replicate it for a month, I either get a single value for all days or hourly values which is incorrect. I have to carry out this analysis day wise for an entire year, hence I cannot run the code for each day individually. I have tried many methods to replicate the code for a longer time period but none of them are giving me results.

To summarize following are the objectives I wish to achieve with my code:

  1. Replicate the GDD formula for each day in a month
  2. Extract GDD value and export in .csv format with the date and GDD value

How can I achieve these objectives?

// Create a geometry representing an export region.
    var StudyArea = ee.Geometry.Rectangle([76.134,28.7472,76.394, 28.486]);
    Map.addLayer(StudyArea)
    Map.centerObject(StudyArea)
    var roi = ee.Geometry.Rectangle([76.302,28.602,76.317,28.593]);
    Map.addLayer(roi)
    //////////Adding Data///////////////////////////////////////////////////////////
    var image = ee.ImageCollection("ECMWF/ERA5_LAND/HOURLY")
            .filter(ee.Filter.date('2021-01-01','2021-01-02'))
            //.filter(ee.Filter.eq('hour', 17))
            .filterBounds(StudyArea)
            .select('temperature_2m');
            
   ///////////////////////Calculation of GDD///////////////////////////////////////
   var cgdd = function(image){
          var min = image.min()
          var min1 = min.clip(StudyArea)
          Map.addLayer(min1)
          var max = image.max()
          var max1 = max.clip(StudyArea)
          Map.addLayer(max1)
          var a = ee.Image(2)
          var sum = max1.add(min1)
          var avg = sum.divide(a)
          var b = ee.Image(273)
         var celcius= avg.subtract(b)
         Map.addLayer(avg)
         Map.addLayer(celcius)
         var c = ee.Image(17.9)
         var gdd = celcius.subtract(c).rename('GDD');
  //Map.addLayer(gdd)
  return gdd;
  };

 // Test the function on a single image.
 var test = cgdd(image);
 Map.addLayer(test)
 print(test)

// Extracting the values for ROI
var extract = test.reduceRegions({
   collection: roi,
   reducer: ee.Reducer.mean(),
   scale: 10,
});
        
print(extract)   




    

Best Answer

You need to create a list with the dates and run a server-side mapping (run your calculation for every object in that list). I would than filter the collection taking the date that was passed to the function from the list and advancing it by one day: var image = ic.filterDate(date, ee.Date(date).advance(1, "day"))

Something like this:

  var dates = ee.List.sequence(1, 365).map(function(day){
    return ee.Date('2021-01-01').advance(day, "day")
  })
  print(dates)
  
  var ic =   ee.ImageCollection("ECMWF/ERA5_LAND/HOURLY")
            .filterBounds(StudyArea)
            .select('temperature_2m');
  var res = dates.map(function(date){
          var image = ic.filterDate(date, ee.Date(date).advance(1, "day"))
          var min = image.min()
          var min1 = min.clip(StudyArea)
          var max = image.max()
          var max1 = max.clip(StudyArea)
          var a = ee.Image(2)
          var sum = max1.add(min1)
          var avg = sum.divide(a)
          var b = ee.Image(273)
          var celcius= avg.subtract(b)
          var c = ee.Image(17.9)
          var gdd = celcius.subtract(c).rename('GDD');
          var gdd_reduced = gdd.reduceRegion({
               geometry: roi,
               reducer: ee.Reducer.mean(),
               scale: 10
              }).get("GDD")
        
        return ee.Feature(null).set(ee.Dictionary({"date": date, "GDD": gdd_reduced}))
        }).flatten()
  
  print("calculation result per day", res)
  Export.table.toDrive(ee.FeatureCollection(res))

The link to the edited script is here: https://code.earthengine.google.com/8e95d8eb6e71baca6c26e851744b393b

Alternatively, you could also create the list with starting and ending dates and map the function over that list.

Also, the scale of the data is >10km, no need for you to use 10m scale.

Related Question