0

Please find attached basic architecture for my data-extraction procedure of NDVI values per pixel, for all images taken in a certain ROI in given dates: Data extraction architecture

The code below represent the architecture on a small scale of date-range and applied only for SEN2 images (to be done later - the same for SEN3 images):

//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 ---------------------------------------///
sen2 = sen2.map(function(image){
  return image.set('simpleDateMillis', ee.Date(image.date().format('YYYY-MM-dd')).millis())
});
var listMillisSimple = ee.List(sen2.aggregate_array('simpleDateMillis'));
var uniqueDatesSimple = listMillisSimple.distinct();
var SEN2_day0 = uniqueDatesSimple.map(function(date){
  return ee.Date(date);
});

print("SEN2 day0:",SEN2_day0);

//------------------------------ AOI ------------------------------//

//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, image) {
  var ndvi_s2 = image
     .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, date);
  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)
}

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

//------ test run for SEN2_day0 list -----//
var allImagesInRange = sen2.filter(ee.Filter.inList("system:time_start", SEN2_day0))


write_to_drive_front(ee.FeatureCollection(allImagesInRange.map(feat_per_img)));

I hope it is not too messy. As of now - the problem is that I get empty feature collection that needs to be later passed to the function that writes it to CSV file. So I get an empty CSV file.

My main question is - why doesn't the FeatureCollection pass on properly so the Export.table.toDrive could write it to CSV?

Another question is why isn't the code extracting as many CSV files as the number of dates on the list? I have mapped the image collection so the procedure of calculating and extracting ndvi values should be on every image of the ImageCollection.

Any ideas?

  • 1
    You really should try to simplify your code as much as possible. At the very least, remove chunks of unused code. Then ask a single, focused, question. I'm having trouble following your date filtering logic - what you're trying to do there. But I'm guessing you're having problems with that. – Daniel Wiell Apr 27 at 11:55
  • Hello Daniel and thank you for your replay. I get what you are saying and will edit my question so it will be more focused, thank you for the feedback. Regarding date filtering - I will be more specific in my edited question. – Sahar Attia Apr 27 at 12:01
  • Do you want to export a CSV per date, each containing pixels from all your regions, or do you want a CSV per date and region? Can you, in words, describe which dates you want to include? Is that dates you have imagery for? – Daniel Wiell Apr 27 at 12:17
  • Why do you want to save the values as a csv and not as tif? So, what do you want to do with those csv's? – JonasV May 5 at 7:57
2
+50

SEN2_day0 contain ee.Date objects stripped of time, which you use as a filter for system:time_start, which are timestamp contain the time of day. So, both an issue about the type of values, and the time component. One option would be to have simpleDateMillis be ee.Date, have SEN2_day0 just be the uniqueDatesSimple, and filter on simpleDateMillis, instead of system:time_start.

var region = ee.FeatureCollection([ee.Feature(Map.getBounds(true))])

//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 ---------------------------------------///
sen2 = sen2.map(function(image){
  return image.set('simpleDateMillis', ee.Date(ee.Date(image.date().format('YYYY-MM-dd'))))
});
print(sen2.first().get('simpleDateMillis'))
var listMillisSimple = ee.List(sen2.aggregate_array('simpleDateMillis'));
var uniqueDatesSimple = listMillisSimple.distinct();
var SEN2_day0 = uniqueDatesSimple
print("SEN2 day0:",SEN2_day0);

//------------------------------ AOI ------------------------------//

//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, image) {
  var ndvi_s2 = image
     .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)
}

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

//------ test run for SEN2_day0 list -----//
var allImagesInRange = sen2.filter(ee.Filter.inList("simpleDateMillis", SEN2_day0))


write_to_drive_front(ee.FeatureCollection(allImagesInRange.map(feat_per_img)));

https://code.earthengine.google.com/499f1b25a3d77ffd2eaa16106b94ecb6

On the question on why you only get a single CSV file exported: You only call Export.table.toDrive() once. That will generate a single CSV file.

| improve this answer | |
  • 1
    Thank you again Daniel. I don't know if it is only on my computer but the CSV comes out empty. Only the header 'ndvi_s2'. Any idea why? – Sahar Attia Apr 30 at 7:14

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.