1

I'm trying to source average NDVI raster images from July of every year from 2008 through 2018 for the USA. I need to export this data to link with PHI offline. Exporting the images for the entire country isn't allowed so I need to break it up into 4 regions. This will result in 44 raster images exported from GEE. I'm having a really hard time automating this process since for loops are not allowed.

Below is an example I'm trying with just two regions and one date. My approach was to try and create a ee.List composed of two ee.Dictionaries then map the drawDateRegion function over that ee.List. It's not working. I think that some of the issue might be in the fact that I can't seem to reference elements of the dictionaries contained in the flatRegionsAndDates2 list.

I'm willing to try another approach if somebody has a suggestion. Essentially I need to clip and filter an ee.Image collection over all combinations of regions 1-4 and Julys 2008-2018.

//Getting MODIS Image Collection
var modis = ee.ImageCollection('MODIS/006/MOD13Q1');

//New program to get all regions and years 
//Import all 4 US regions as FeatureCollections 
//Importing region 
var region1 = ee.FeatureCollection("users/fossaal/us_region1_10km_buffer");
var region2 = ee.FeatureCollection("users/fossaal/us_region2_10km_buffer");
//var region3 = ee.FeatureCollection("users/fossaal/us_region3_10km_buffer");
//var region4 = ee.FeatureCollection("users/fossaal/us_region4_10km_buffer");

//Creating date ranges 
var startDate = ee.Date('2016-07-01');
var dateRange = ee.DateRange(startDate,startDate.advance(1,'month'));

//Create arrays
var allRegions = [region1,region2]
var allDates = [dateRange]
//Functions for mapping 
var arrayOfArrays = function(region){
  var regionDatePair = function(date){
    return {
      region:region,
      date:date
    }
  }
  return allDates.map(regionDatePair) 
}
var regionsAndDates = allRegions.map(arrayOfArrays)

print(regionsAndDates)

var flatRegionsAndDates = ee.List(regionsAndDates).flatten()

print(flatRegionsAndDates)

//Make elements of list into Dictionaries 
var toDict = function(a){
  return ee.Dictionary(a)
}

var flatRegionsAndDates2 = flatRegionsAndDates.map(toDict) 
print(flatRegionsAndDates2)


//Creating function to clip and filter 
var drawDateRegion = function(dateRegionObject){
  print(dateRegionObject)
  var dataset = modis.filter(ee.Filter.date(dateRegionObject.get('date')));
  //Reducing MODIS images to averages for all bands
  var redDataset = dataset.mean();      
  // Clip to to US borders.
  var clippedRedDataset = redDataset.clipToCollection(dateRegionObject.get('region'));
  // Select only NDVI band 
  var ndvi = clippedRedDataset.select('NDVI');
  return ndvi 
}

var output = flatRegionsAndDates2.map(drawDateRegion)
1

Exporting the images for the entire country isn't allowed so I need to break it up into 4 regions. This will result in 44 raster images exported from GEE. I'm having a really hard time automating this process since for loops are not allowed.

There's a slight misunderstanding here: for loops are "allowed". In fact, you must use a for loop here.

The basic explanation of Earth Engine's client-server model will tell you that you should avoid loops, but that is because any such loop is necessarily running on your computer, outside of Earth Engine, and so it can't directly use values from Earth Engine expressions (that haven't been computed yet) and may result in sending unnecessarily complex or repetitive requests to the server.

However, in this case, your goal is to export images. Every image export is always a separate request (and a separate task in the export task queue), so you have to write a loop which calls Export.image for each image you want.

So, there's no need to figure out how to structure this exclusively in terms of EE DateRanges and Lists and map — just write whatever JavaScript suits the problem. Here's a rough sketch of what it might look like (not tested):

var regions = [
    ee.FeatureCollection("users/fossaal/us_region1_10km_buffer"),
    ee.FeatureCollection("users/fossaal/us_region2_10km_buffer"),
    ee.FeatureCollection("users/fossaal/us_region3_10km_buffer"),
    ee.FeatureCollection("users/fossaal/us_region4_10km_buffer"),
];

regions.forEach(function (region) {
  for (var year = 2008; year <= 2018; year++) {
    var date = year + '-07-01';

    var image = modis.filter(ee.Filter.date(date))
      .mean();      
      .clipToCollection(region)
      .select('NDVI');
    Export.image.toDrive({
      image: image,
      // ... other export parameters ...
    });
  }
});
3
  • Thank you so much for this Kevin. I was making it more difficult than it needed to be. I'll post an update with the code I ended up using. – alanjfossa Feb 8 at 16:50
  • @alanjfossa Great to hear it's working! Such updates are best posted as answers, not edits to the question, though. (Yes, it's okay to answer your own question. And it doesn't mean you're rejecting my answer — different answers give different perspectives.) – Kevin Reid Feb 8 at 17:08
  • thanks I'll post in answers next time. That makes sense. – alanjfossa Feb 8 at 17:17
1

Below is the code I ended up using based on Kevin's suggestions.

var modis = ee.ImageCollection('MODIS/006/MOD13Q1');

//Creating an array of feature collections 
//One for each region
var regions = [
    ee.FeatureCollection("users/fossaal/us_region1_10km_buffer"),
    // ee.FeatureCollection("users/fossaal/us_region2_10km_buffer"),
    // ee.FeatureCollection("users/fossaal/us_region3_10km_buffer"),
    // ee.FeatureCollection("users/fossaal/us_region4_10km_buffer"),
];

//Use the forEach method to apply the innner function to all 4 regions
regions.forEach(
  function(region){ 
      for (var year = 2008; year <= 2018; year++) { //All years 08 through 18 
      var startDate = year + '-07-01'; //Start July 1st 
      var endDate = year + '-07-31'; //End July 31
      var image = modis.filter(ee.Filter.date(startDate,endDate)) //Filter by dates
      .mean() //Take the mean    
      .clipToCollection(region) //Clip to regions 
      .select('NDVI'); //Selection onlu NDVI band
      Export.image.toDrive({
        image: image,
        description:'region'+(regions.indexOf(region)+1).toString()+'_'+year
        folder: 'MODIS NDVI', // should match your Google Drive folder
        scale: 250, // this should match resolution of your satellite product
        region: region,
        crs: 'EPSG:4326', // can be whatever you want 4269 might be better for NA 
        maxPixels: 1e10}); // may need to boost to meet size
      }
  }
  )``` 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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