1

a bit long - sorry for that.

I am looking for a way to export NDVI values for all the images in the ImageCollection. I must be using the wrong variable types because they don't pass well through the map function.

//Dates of Interest
var start = ee.Date("2018-04-01");
var finish = ee.Date("2018-05-01");

///--------------------- SENTINEL2 Collection ---------------------------------------///
var sen2 = ee.ImageCollection('COPERNICUS/S2_SR')
.filterDate(start, finish)
.filterBounds(region)
.map(function(image){
  return image
  .clipToCollection(region)
  .updateMask(image.select('QA60').not())
})

///--------------------- Unique list creation ---------------------------------------///
// MilliSec Extract function
function millisec(imgcol){
    var iter_func = function(image, newlist){
        var date = ee.Number.parse(image.date().millis());
        newlist = ee.List(newlist);
        return ee.List(newlist.add(date).sort())
    };
    return imgcol.iterate(iter_func, ee.List([]));
}

var ymd = millisec(sen2)
var allImagesInRange = sen2.filter(ee.Filter.inList("system:time_start", ymd))


//define all AOI
var field1 = ee.FeatureCollection(region.filterMetadata("system:index","equals","00000000000000000000"));

//-----------------------NDVI CALC-----------------------//

//Get the ndvi for the specific field and time
function get_ndvi_sen2(subRegion, id){
  var ndvi_s2 = ee.Image(id)
  .normalizedDifference(['B8', 'B4'])
  .rename('ndvi_s2');

  var ndvi_s2_Features = ee.FeatureCollection(ee.List(ndvi_s2
  .reduceRegion({
    reducer: ee.Reducer.toList(),
    geometry: subRegion,
    scale: 10
  })
  .get('ndvi_s2'))
  .map(function (ndvi_s2) {
    return ee.Feature(null, {ndvi_s2: ndvi_s2});
  })
  );
  return ndvi_s2_Features;
}

//------------------ CSV Export ---------------------//
var sen2_disc, sen2_selc = 'ndvi_s2';
var sen2_folder = 'GOOD/SEN2'

function write_to_drive(col, disc, selc, folder, field){
  print("Col: ",col, "Disc: ",disc, "Selc: ",selc, "Folder: ",folder, "Field: ",field);
  Export.table.toDrive({
  collection: col,
  fileNamePrefix: disc+' '+field,
  selectors: [selc],
  folder: folder+'/'+field
  })
}

var feat_per_img = function(sngl_img){
  return get_ndvi_sen2(field1, sngl_img.id())
}

function write_to_drive_front(feat){
  write_to_drive(feat, 'NDVI_Sen2', sen2_selc, sen2_folder, 'field1');
}

//------ Export all the NDVI values from the ImageCollection ----------//
write_to_drive_front(ee.FeatureCollection(allImagesInRange.map(feat_per_img)));

I had to make front and back functions for the write_to_drive because I didn't manage to understand the arguments that needed to be passed through the map functions.

My error while running the script is: FeatureCollection (Error) Actual value for parameter 'id' must be a constant.

Link to the original code, with the original region asset.

My main goal is to have a CSV file with the pixel-wise NDVI value for each image.

1 Answer 1

2

FeatureCollection (Error) Actual value for parameter 'id' must be a constant.

This error comes from

function get_ndvi_sen2(subRegion, id){
  var ndvi_s2 = ee.Image(id)
     .normalizedDifference(['B8', 'B4'])
     .rename('ndvi_s2');
  ...
}

which is mapped. You cannot load an image by a computed ID in Earth Engine — they must be string literals in your code (or computed client-side in JavaScript, but that's not necessary here).

What you should do instead is just pass the image object.

var feat_per_img = function(sngl_img){
  return get_ndvi_sen2(field1, sngl_img)  // sngl_img instead of sngl_img.id()
}

function get_ndvi_sen2(subRegion, image) {
  var ndvi_s2 = image
     .normalizedDifference(['B8', 'B4'])
     .rename('ndvi_s2');
  ...
}
4
  • Thank you Kevin. This resolved the issue, but the code does not produce a CSV file with the NDVI values per pixel. Any idea why is that? I get a CSV file with only the header for the column ('ndvi_s2'). When debugging the code and trying to print the variables passed to feat_per_img and get_ndvi_sen2 I get the error: Internal error: function argument not initialized. Any Idea? Apr 27, 2020 at 6:31
  • 1
    @SaharAttia Please post further problems separately, not as comments — often different people will be able to help better. I recommend that you work on simplifying your script to one that demonstrates the problem (no rows on output) without being as complex as your actual goal (for example, remove the NDVI calculation and keep the date selection, and see what you get then). Then it will be easier to study and easier to help with. If you still can't find the problem, post the simplified code as a new question — focus on the specific problem, not your final goal.
    – Kevin Reid
    Apr 27, 2020 at 14:51
  • 1
    The "not initialized" is probably because you cannot print() inside of a server-side .map() — you have to map and then print the result. This is one of the reasons why simplifying your code can help with solving a problem — it's easier to change it to understand how it behaves if you don't keep it in shape to solve the original scientific problem, and instead take it as a programming puzzle.
    – Kevin Reid
    Apr 27, 2020 at 14:52
  • Dear Kevin, thank you for your feedback. I will take it for further questions and problem solving on my end. Apr 28, 2020 at 6:24

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.