//Purpose: To calculate plant productivity indices

//////////
//Functions
/////////

function assignDate(img){
  var imgYear = img
  .set('yr',ee.Number(img.date().format('YYYY')))
  .set('month',ee.Number(img.date().format('MM')));
  return imgYear;
}

//////////
//Assets
/////////

//Buffered the start points of Breeding Bird Survey routes
//by 39.4 km and upload as an asset to Google Earth Engine
//Due to memory limitations, the buffers were 
//split into two separate, complementary feature classes
//and uploaded as different assets. The script was then
//run for each set

var bbs = ee.FeatureCollection("Path to first set of BBS start point buffers");
//var bbs = ee.FeatureCollection("Path to second set of BBS start point buffers"); //currently commented out

//MODIS Gross Primary Productivity 
var gpp = ee.ImageCollection("UMT/NTSG/v2/MODIS/GPP")
.select("GPP")
.map(assignDate)
.filter(ee.Filter.calendarRange(2001,2004,'year')); //filtering by year

//////////
//Settings
/////////

//Coordinate reference system and scale
var crs = gpp.first().projection();
var nScale = gpp.first().projection().nominalScale();

//////////
//Processing
/////////

//Resampling to 1 km
var gpp1km = ee.ImageCollection(gpp.map(function(img){
  
  //Doubling original resolution to match approach of 
  //Phillips et al. 2010
  var i1km = img.reduceResolution({
    reducer: ee.Reducer.sum().unweighted(),//unweighted to get total
    maxPixels: 16
  }).reproject(crs,null,nScale.multiply(4));
  
  return(i1km);
  
}));

//List to loop through years and months
var ySeq = ee.List.sequence(2001,2004);
var mSeq = ee.List.sequence(1,12);

//Calculating mean GPP pixel value for each year and month
var gppF = ee.ImageCollection(ySeq.map(function(y){
  return mSeq.map(function(m){
    //Filtering gpp collection by year
    var ndviT = gpp1km
      .filter(ee.Filter.eq('yr', ee.Number(y).format('%01d')))
      .filter(ee.Filter.eq('month', ee.Number(m).format('%02d')));
    //Calculating median GPP value
    var ndviT2 = ndviT.mean()
    .reproject(crs,null,nScale.multiply(4));
    //Setting year value to filter image 
    //collection later
    var ndviT3 = ndviT2
    .set('system:index',ee.Date.fromYMD(y,1,1).format('YYYY'))
    .set('yr',ee.Date.fromYMD(y,1,1).format('YYYY'))
    .rename("GPP");
    return(ndviT3);
  });
}).flatten());

//Calculating productivity measures
var dhi = ee.ImageCollection(ySeq.map(function(y){
    //Filtering gpp collection by year
    var ndviT = gppF
    .filter(ee.Filter.eq('yr', ee.Number(y).format('%01d')));
    //Calculating annual summary statistics
    var gppSum = ndviT.sum()
    .int32()
    .reproject(crs,null,nScale.multiply(4))
    .rename(ee.String('Sum'));
    var gppMin = ndviT.min()
    .int32()
    .reproject(crs,null,nScale.multiply(4))
    .rename(ee.String('Min'));
    var gppMean = ndviT.mean()
    .reproject(crs,null,nScale.multiply(4))
    .rename('Mean');
    var gppStDev = ndviT
    .reduce(ee.Reducer.stdDev())
    .reproject(crs,null,nScale.multiply(4))
    .rename('stdDev');
    var gppCoV = gppStDev
    .divide(gppMean)
    .multiply(ee.Image(100))
    .int32()
    .reproject(crs,null,nScale.multiply(4))
    .rename(ee.String('CoV'));
    var tCollection = ee.ImageCollection([gppSum,gppMin,gppCoV]);
    //Converting collection to an image
    var fImg = tCollection
    .toBands()
    .set('yr',ee.Date.fromYMD(y,1,1).format('YYYY'));
    return fImg;
  }).flatten());

//Isolating and taking mean of sum values  
var sumCol = dhi.map(function(img){
  var imgSel = img.select(0);
  return imgSel;
});

var sumMean = sumCol.mean().rename("sum");

//Isolating and taking mean of minimum values
var minCol = dhi.map(function(img){
  var imgSel = img.select(1);
  return imgSel;
});

var minMean = minCol.mean().rename("min");

//Isolating and taking mean of coefficient of variation values
var covCol = dhi.map(function(img){
  var imgSel = img.select(2);
  return imgSel;
});

var covMean = covCol.mean().rename("cov");

//Creating image with mean of sum, minimum, and seasonality (coefficient of varation)
//as bands
var dhiImg = ee.ImageCollection([sumMean,minMean,covMean]).toBands().rename(["sum","min","cov"]);

//Determining mean stats for each BBS buffer
var bbsDhi = dhiImg.reduceRegions({
  collection: bbs,
  reducer: ee.Reducer.mean().unweighted(),
  scale: nScale,
  crs: crs
});

//////////
//Exporting
//////////

Export.table.toDrive({
  collection: bbsDhi,
  description:'bbsDHI',
  folder: 'GEE',
  fileFormat: 'CSV'
});