3

I have here a FeatureCollection containing some productive forests of the company I work for.

The age in month for each forest site is important to me, since my study only looks for forests that are between 1 and 5 month of age.

With this age I calculated, at a desktop GIS software, the maximum date and the minimum date to filter the Landsat 8 images inside a period of the year (September to May).

So, with all these informations together as a FeatureCollection in my Assets, I have to define a function to be mapped to the whole FeatureCollection containing company's forests.

The function needs to get values from columns MIN_DATE and MAX_DATE to filter the Landsat images, apply cloud masking, calculate NDVI and return the feature to the collection with the mean of NDVI computed as a column.

I've already developed something here, but it keeps returning me some weird result.

The code:

/ Script to get historical NDVI for each productive area

// Import FeatureCollection 
var IPTalhoes = ee.FeatureCollection('users/ee_rootDir/toiFinal');

// Define function to map over collection 
function calcHistoricalNDVI(feature) {
  
  // Get initial and end date
  var dateIni = feature.get('MIN_DATE');
  var dateEnd = feature.get('MAX_DATE');
  
  // Import Landsat 8 ImageCollection
  var imgCollection = ee.ImageCollection("LANDSAT/LC08/C01/T1_TOA");
  
  // Filter imgCollection
  var imgFiltered = imgCollection
                    .filterDate(dateIni, dateEnd)
                    .filterBounds(feature)
                    .map(function updateCloudMask(image) {
                      var mask = ee.Algorithms.Landsat.simpleCloudScore(image);
                      var imgUpdated = image.updateMask(mask.select('cloud').lt(20));
                      return(imgUpdated);
                    });
                    
  // Calculate NDVI
  var imgNDVI = imgFiltered
                .map(function calcNDVI(image) {
                  return(image.expression(
                  '(b(4) - b(3)) / (b(4) + b(3))'
                  ).select(['B5'], ['NDVI']));
                });
  
  // NDVI mean inside a period 
  var NDVIMean = imgNDVI.mean();
  
  // Reducer statistics - mean by talhao
  var NDVIMean2 = NDVIMean.reduceRegion({
    reducer: ee.Reducer.mean(),
    geometry: feature.geometry(),
    scale: 30
    });
  
  // Turn dictionary with NDVI values to FeatureCollection
  var NDVIMean2Feat = feature.set('NDVI', NDVIMean2);
  
  // Return Feature as function result
  return(NDVIMean2Feat);
}

// Map main function over collection
var NDVITalhoes = IPTalhoes.map(calcHistoricalNDVI);

// Print results
print(NDVITalhoes);

The issue:

When I print the Feature Collection, what I see is that there is a column named 'NDVI' in FeatureCollection with an "Object" within, but when I open each feature in console, I can't find any property with this name, and indeed there are only 27 properties while there are 29 columns for the whole FeatureCollection.

Can anyone help me out?

1

What I like to do when debugging .map() calls or when developing, is to first do it with one element only since it is much easier to catch mistakes.

It's hard to debug without having access to your data or even some toy data, but here's a few pointers where it can go wrong:

The first thing (which might be the core issue) is the .filterBounds() call. It expects an ee.Geometry but gets a ee.Feature. So change it to this:

.filterBounds(feature.geometry())

Also since reduceRegion() returns a dict, you can give it straight to .set() without assigning it to something. The way you do it won't give you an error but changing it cleans up the output a bit:

var NDVIMean2Feat = feature.set(NDVIMean2);

If there's still no meaningful output, the only place it can go wrong is the filtering you do. If it is too restrictive, meaning a very short time-frame or a high threshold for cloud masking an empty Image Collection might be returned, if this happens you don't get any data back.

1
  • thanks for the answer. About the filterBounds() function, I thought it would work as it is, I've already used the feature without the .geometry() method and it did work out for me, but I'll try this solution anyway. About the .set() method, I had already edited my post with this new part, it follows like this now: var NDVIMean2Feat = feature.set('NDVI', NDVIMean2);. I don't know if it would work if I write the code as you recommended. I'll try this solution here and then I'll send you a feedback! Thanks a lot! Mar 2 at 10:45

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.