1

I'm working toward estimating leaf area index using vegetation indices derived from Sentinel-2 data. I would like to complete atmospheric corrections for all available TOA imagery within specific areas (as defined by polygons); however, when I attempt to use the methodology described here: Image.constant: Parameter 'value' is required. Error in Google Earth Engine, I get this error

Error in map(ID=20150711T165456_20150711T165450_T15SWR):
Image.constant: Parameter 'value' is required.

I'm not familiar with javascript and am sure I'm missing something here.

Any ideas?

My code is below.

var insts = ee.FeatureCollection('users/wpeay26/laiMeasured');

var startdate = '2015-06-01';
var enddate   = '2021-08-31';

/**
 * Function to mask clouds using the Sentinel-2 QA band
 * @param {ee.Image} image Sentinel-2 image
 * @return {ee.Image} cloud masked Sentinel-2 image
 */

function maskS2clouds(image) {
  var date = image.date().millis()
  var qa = image.select('QA60');

  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000).set('system:time_start', date);
}

// EVI
var evi = function(image) {
  var evi = image.expression(
    '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', 
    {'NIR': image.select('B8'),
    'RED': image.select('B4'),
    'BLUE': image.select('B2')});
  return image.addBands(evi.rename('evi').float());
};

// NDMI
var ndmi  = function(image) {
  var ndmi = image.normalizedDifference(['B8', 'B11']).rename('ndmi');
  return image.addBands(ndmi);
};

// NDVI
var ndvi = function(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
  return image.addBands(ndvi);
};

// SR
var sr = function(image) {
  var sr = image.expression(
    'NIR / RED',
    {'NIR': image.select('B8'),
    'RED': image.select('B4')});
  return image.addBands(sr.rename('sr').float());
};

// Load Sentinel-2 TOA reflectance data.
var s2Col = ee.ImageCollection('COPERNICUS/S2')
              .filterDate(startdate, enddate)
              .filterBounds(insts)
              .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10))
              .map(maskS2clouds)
              .map(evi)
              .map(ndmi)
              .map(ndvi)
              .map(sr);

var colorComp = {bands: ['B4', 'B3', 'B2'], min: 0, max: 0.3};
Map.addLayer(s2Col.first(), colorComp, 'TOA');
Map.centerObject(insts);
Map.addLayer(insts, {color: 'red'}, 'insts');

// Import the SIAC atmospheric correction module
var siac = require('users/marcyinfeng/utils:SIAC');

// Apply SIAC and retrieve bottom of atmosphere (BOA) reflectance
var s2Boa = s2Col.map(function(image){
    return siac.get_sur(image);
}) 

print(s2Boa)

// var s2BoaFilt = s2Boa
//   .filterMetadata('B2', 'not_equals', null)
//   .filterMetadata('B4', 'not_equals', null)
//   .filterMetadata('B8', 'not_equals', null)
//   .filterMetadata('B8A', 'not_equals', null)
//   .filterMetadata('B11', 'not_equals', null)
//   .filterMetadata('evi', 'not_equals', null)
//   .filterMetadata('ndmi', 'not_equals', null)
//   .filterMetadata('ndvi', 'not_equals', null)
//   .filterMetadata('sr', 'not_equals', null);

var getMeans = function(image) {
  return ee.Image(image).reduceRegions({
    collection: insts, 
    reducer: ee.Reducer.mean(), 
    scale: 10
  }).map(function(f) {return f.set("date", image.date().format("YYYY-MM-dd")
                                    )});
};

var s2BoaMerged = s2Boa.map(getMeans).flatten();

Export.table.toDrive({
    collection: s2BoaMerged,
    selectors: (['date', 'INST', 'TRT', 'B2', 'B4', 'B8', 'B8A', 'B11', 'evi', 'ndmi', 'ndvi', 'sr']),
    description: 'mrtSentDat2A',
    folder:  'GEE',
    fileNamePrefix: 'sentDat2A',
    fileFormat: 'CSV'
})
2
  • Just curious. Why are you computing vegetation indices before atmospheric correction?
    – aldo_tapia
    Commented Dec 14, 2021 at 18:40
  • @aldo_tapia I initially used the above script to download the sent2 TOA data. I just started adding things in without much attention to order to see if I could figure out the atmospheric corrections. The corrections should come before the vi computations. Thanks for pointing that out.
    – wpeay26
    Commented Dec 15, 2021 at 19:11

1 Answer 1

0

The error comes from maskS2clouds function. Since you are not familiar with JS I recommend you to use Fito Principe's functions (check github repo). Instead of:

function maskS2clouds(image) {
  var date = image.date().millis()
  var qa = image.select('QA60');

  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000).set('system:time_start', date);
}

Use:

var cloud_masks = require('users/fitoprincipe/geetools:cloud_masks');
var maskS2clouds = cloud_masks.sentinel2();

Although, you will need to add the factor scale for getting reflectance values in 0 - 1 range for computing vegetation indices:

var cloud_masks = require('users/fitoprincipe/geetools:cloud_masks');
var maskS2clouds = cloud_masks.sentinel2();

var scale_factor = function(image){
  image.divide(10000);
}

var s2Col = ee.ImageCollection('COPERNICUS/S2')
              .filterDate(startdate, enddate)
              .filterBounds(insts)
              .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10))
              .map(maskS2clouds)
              .map(scale_factor)

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.