I'm trying to mask each modis image using the QA layer. As far as I understand, the part .select("QA").eq(0) should remove all pixels with no ideal quality for all bands. However, when I make a plot with Map.addLayer(ls7.first()) it seems like there is no pixel in any part of the world with the best quality.

It seems strange, is something wrong with my code? When I use .select("StateQA").eq(0) it seems that only some sparse pixels (most of them in the sea) are ok. Any suggestions?

This is my code:

//select collection

var ls7SR = ee.ImageCollection('MODIS/006/MOD09A1');

// calculate normalized burn ration

var ls4_7_Indices = function(lsImage){
  var nbr = lsImage.normalizedDifference(['sur_refl_b02', 'sur_refl_b07']).toFloat();
  nbr = nbr.updateMask(lsImage.select("QA").eq(0));
  return nbr.copyProperties(lsImage, ['system:time_start']);

// Map functions across modis Collection

var ls7 = ls7SR.map(ls4_7_Indices)


1 Answer 1


You have to do some bitwise operations when using these types of bands. If you look at the image collection in the catalog, you'll find this under Bitmask for QA:

Bits 0-1: MODLAND QA bits

0: Corrected product produced at ideal quality - all bands
1: Corrected product produced at less than ideal quality - some or all bands
2: Corrected product not produced due to cloud effects - all bands
3: Corrected product not produced for other reasons - some or all bands, may be fill value (11) [Note that a value of (11) overrides a value of (01)]

This means that you have to look at the value of bit 0 to 1 from the QA band. When this value is 0, all bands have ideal quality. I have a little utility function I use to help with this. See bitwiseExtract() here below.

var bitwiseExtract = function(value, fromBit, toBit) {
  if (toBit === undefined)
    toBit = fromBit
  var maskSize = ee.Number(1).add(toBit).subtract(fromBit)
  var mask = ee.Number(1).leftShift(maskSize).subtract(1)
  return value.rightShift(fromBit).bitwiseAnd(mask)

var ls7SR = ee.ImageCollection('MODIS/006/MOD09A1')

var ls4_7_Indices = function(lsImage) {
  var nbr = lsImage.normalizedDifference(['sur_refl_b02', 'sur_refl_b07']).toFloat()
  var modlandQa = bitwiseExtract(lsImage.select("QA"), 0, 1)
  nbr = nbr.updateMask(modlandQa.eq(0))
  return nbr.copyProperties(lsImage, ['system:time_start'])

var ls7 = ls7SR.map(ls4_7_Indices)


  • Thank DAniel. It seems to work, but the truth is that I didn't undertand how the function works. Can you explain it a little bite?
    – jose maria
    Mar 8, 2021 at 17:05
  • 1
    The function takes three arguments: A value (like the QA band here, or an ee.Number), the first bit to use and the last bit to use (e.g. 0 and 1 for MODLAND QA bits, or 2 and 5 for band 1 data quality). The function look at the value as a binary number. As an example, 2470774279 is 10010011010001010000011000000111 in binary. In your case, you look at bits 0 and 1, that's the first two bits. These bits can be 00, 01, 10, or 11. That's the same as 0, 1, 2, 3 in decimal. In the example number here, you have 11 (start reading from the right), which is 3 (Corrected product not produced for other). Mar 8, 2021 at 19:29
  • Thanks Daniel. Now I understand how it works. So, for instance, if I was intererested in best quality for band n1 (bits 2-5), i need to put: bitwiseExtract(lsImage.select("QA"), 2, 5) , and then inside the function "ls4_7_Indices" nbr = nbr.updateMask(modlandQa.eq(4)) right? just to know how to manipulate the function in the future.
    – jose maria
    Mar 9, 2021 at 9:02
  • or eq(0) becasue it is looking only bits 2 to 5?
    – jose maria
    Mar 9, 2021 at 9:08

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.