3

How do you write the MSAVI formula in JavaScript function for Google Earth Engine?

I am trying to calculate the MSAVI as a function. The aim is to map the result over a Sentinel-2 composite and not a single image.

I tried the same thing for the OSAVI Index and it worked fine: OSAVI = (NIR-Red)/ (NIR+Red+0.16)

function addOSAVI(input) {
  var nir = input.select(['B8']);
  var red = input.select(['B4']);
  var osavi = nir.subtract(red).divide(nir.add(red).add(0.16)).rename('OSAVI');
return input.addBands(osavi);

}

I need a function in the same manner as the OSAVI function, but I have problem with implementing sqrt() and pow() correctly.

enter image description here

function addMSAVI(input) {
  var nir = input.select(['B8']);
  var red = input.select(['B4']);
  var msavi = (nir.add(1).multiply(2).subtract(sqrt(pow(nir.add(1).multiply(2),2)).subtract((nir.subtract(red)).multiply(2)))).divide(2).rename('MSAVI');
return input.addBands(msavi);

}

More information about MSAVI: http://wiki.landscapetoolbox.org/doku.php/remote_sensing_methods:modified_soil-adjusted_vegetation_index

5
  • 1
    have you read developers.google.com/earth-engine/image_math? Commented Mar 22, 2018 at 17:50
  • Yes I have of course, but I can't find anything helpful for using within a function. Are you refering to image.expression()?
    – loloj0
    Commented Mar 22, 2018 at 18:05
  • Use image.expression() with TOA or BOA reflectance values
    – aldo_tapia
    Commented Mar 22, 2018 at 18:36
  • I want to use the function on an a pre filtered sentinel-2 composite, so I can't use image.expression() as far as I know and I tried it. var msavi = s2_composite.expression('(2*NIR+1-sqrt(pow((2*NIR+1),2) - 8*(NIR-RED))/2)', {'NIR': input.select('B8'), 'RED': input.select('B4')}); is not working
    – loloj0
    Commented Mar 22, 2018 at 18:51
  • you should update the question showing what you've tried so far. Commented Mar 22, 2018 at 19:28

1 Answer 1

9

Both ways work just fine and give the same results: https://code.earthengine.google.com/3f766772035a8890b0caf231eb652a1f.

There is also a small mistake in the formula in your code - wrong bracket.

// compute composite for all images aquired in the last 3 days
var now = ee.Date(Date.now())
var composite = s2
  .filterDate(now.advance(-3, 'day'), now)
  .mosaic()
  .divide(10000)

Map.addLayer(composite, {bands: ['B8', 'B8', 'B4'], min: 0, max: 0.4}, 'composite')

// compute MSAVI2 using expression
var msavi2 = composite.expression(
  '(2 * NIR + 1 - sqrt(pow((2 * NIR + 1), 2) - 8 * (NIR - RED)) ) / 2', 
  {
    'NIR': composite.select('B8'), 
    'RED': composite.select('B4')
  }
);

Map.addLayer(msavi2, {min: -0.1, max: 0.5}, 'msavi2 (expression)')

// compute MSAVI2 using fluent API
msavi2 = composite.select('B8').multiply(2).add(1)
  .subtract(composite.select('B8').multiply(2).add(1).pow(2)
    .subtract(composite.select('B8').subtract(composite.select('B4')).multiply(8)).sqrt()
  ).divide(2)

Map.addLayer(msavi2, {min: -0.1, max: 0.5}, 'msavi2 (fluent)')
2
  • This was very helpful. Thank you!
    – Waleed93
    Commented Jul 11, 2020 at 9:52
  • I am facing problems with sqrt operator. Error: Image.parseExpression: Expression parse error at character 11: '(A/B) - 1.0)/(sqrt((A/B) +1.0 ))' ^. Please see the script below var addMSR = function(image) { var msr = image.expression( '(A/B) - 1.0)/(sqrt((A/B) +1.0 ))',{ 'A': image.select('B8'), 'B': image.select('B4') } ).rename('ZZMSR'); return image.addBands(msr); };
    – Lollo
    Commented Jul 23, 2020 at 14:18

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.