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? 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
    Mar 22, 2018 at 18:05
  • Use image.expression() with TOA or BOA reflectance values
    – aldo_tapia
    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
    Mar 22, 2018 at 18:51
  • you should update the question showing what you've tried so far. 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
    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
    Jul 23, 2020 at 14:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.