2

Working with Modis MOD13Q1 data and I am not sure how to correctly parse for pixel QA and DetailedQA.

// Call data 
var CRNP_Oban = ee.FeatureCollection("users/sijehasuk/CRNP_Oban2"),
    ndvi = ee.ImageCollection("MODIS/061/MOD13Q1");

// Explore the variable to view QA
print(ndvi);

// Create function with filter of quality pixels
var mask = function(im) {
  return im.updateMask(im.select("SummaryQA").eq(0));
};

Version VI SummaryQ includes bits 0-1 from the DetailedQA and I have masked Bit '0' (please, correct if done wrongly) ****Note: Bitmask for SummaryQA

/// Bits 0-1: VI quality (MODLAND QA Bits)
// 0: Good data, use with confidence
// 1: Marginal data, useful but look at detailed QA for more information
// 2: Pixel covered with snow/ice
// 3: Pixel is cloudy

// Apply filter to NDVI data
var ndvi = ee.ImageCollection(ndvi)
.filterDate('2000-01-01','2020-01-01')
.map(mask)
.select("NDVI")
.filterBounds(CRNP_Oban);

How do I include Bitmask 1 and apply other Bitmask for DetailedQA (see below) to ensure the best quality of pixel? See help2 Code and asset. While working on this in R, it was observed that the area had a lot of missing data issues. So it would be good to ease the QA a little so there is still some data left for analysis.

// VI quality indicators

// Bitmask for DetailedQA

// Bits 0-1: VI quality (MODLAND QA Bits)
// 0: VI produced with good quality
// 1: VI produced, but check other QA
// 2: Pixel produced, but most probably cloudy
// 3: Pixel not produced due to other reasons than clouds

// Bits 2-5: VI usefulness
// 0: Highest quality
// 1: Lower quality
// 2: Decreasing quality
// 4: Decreasing quality
// 8: Decreasing quality
// 9: Decreasing quality
// 10: Decreasing quality
// 12: Lowest quality
// 13: Quality so low that it is not useful
// 14: L1B data faulty
// 15: Not useful for any other reason/not processed

// Bits 6-7: Aerosol Quantity
// 0: Climatology
// 1: Low
// 2: Intermediate
// 3: High

// Bit 8: Adjacent cloud detected
// 0: No
// 1: Yes

// Bit 9: Atmosphere BRDF correction
// 0: No
// 1: Yes

// Bit 10: Mixed Clouds
// 0: No
// 1: Yes

// Bits 11-13: Land/water mask
// 0: Shallow ocean
// 1: Land (nothing else but land)
// 2: Ocean coastlines and lake shorelines
// 3: Shallow inland water
// 4: Ephemeral water
// 5: Deep inland water
// 6: Moderate or continental ocean
// 7: Deep ocean

// Bit 14: Possible snow/ice
// 0: No
// 1: Yes

// Bit 15: Possible shadow
// 0: No
// 1: Yes

See further description of the VI quality assessment. Further description of VI QA Source

2
  • Check this answer to decode QA bits: gis.stackexchange.com/questions/271322/… I don't have enough time right now for writing an answer, but it'll be useful
    – aldo_tapia
    Jan 20, 2023 at 17:11
  • As per the help center please do not include chit chat like thanks and any other statements of appreciation within your posts.
    – PolyGeo
    Jan 20, 2023 at 19:38

1 Answer 1

3

I'm unsure what values you wanted for each of the quality bits, so I wrote comments where you may want to adjust them.

var CRNP_Oban = ee.FeatureCollection("users/sijehasuk/CRNP_Oban2"),
    ndvi = ee.ImageCollection("MODIS/061/MOD13Q1");
    ndvi = ndvi.map(function(image){ return image.clip(CRNP_Oban)});

// Create function with filter of quality pixels
var mask = function(im) {
  return im.updateMask(im.select("SummaryQA").eq(0));
};

ndvi = ndvi.map(mask);
// Explore the variable to view QA
print(ndvi);

// This function sets the starting position for the bit and the number of
// positions necessary.
var GetQABits = function(image, bitStart, numBits){
    var bitmapped = image.select('DetailedQA').rightShift(bitStart).mod(Math.pow(2, numBits));
    return bitmapped;
};

var MaskToBestBits = function(image){
  var detailqa = image.select('DetailedQA');
  var VIQual = GetQABits(detailqa, 0, 2);
  var VIUse = GetQABits(detailqa, 2, 4);
  var VIaer = GetQABits(detailqa, 6, 2);
  var Viadjcl = GetQABits(detailqa, 8, 1);
  var atmbrdf = GetQABits(detailqa, 9, 1);
  var mxdcl = GetQABits(detailqa,  10, 1);
  var lnwt = GetQABits(detailqa, 11, 3);
  var snowice = GetQABits(detailqa, 14, 1);
  var shadow = GetQABits(detailqa, 15, 1);
  // update the image mask to select the indicator values you.
  // the values in the following updateMasks are GUESSES based on what you posted
  // with regard to the indicator. For example, VI Quality has 2 values, 0
  // or 1, that are good, so used less than 2 ("lt(2)") to get either.
  return image.addBands(detailqa)
    .updateMask(VIQual.lt(2)) //Suggested, but not sure what you want here
    // .updateMask(VIUse.lt(8)) //Suggested, but not sure what you want here
    // .updateMask(VIaer.lt(3)) //Suggested, but not sure what you want here
    // .updateMask(Viadjcl.eq(1)) //Suggested, but not sure what you want here
    // .updateMask(atmbrdf.lt(1)) //Suggested, but not sure what you want here
    // .updateMask(mxdcl.eq(0)) //Suggested, but not sure what you want here
    // .updateMask(lnwt.eq(1)) //Suggested, but not sure what you want here
    // .updateMask(snowice.eq(0)) //Suggested, but not sure what you want here
    // .updateMask(shadow.eq(0)); //Suggested, but not sure what you want here
};

var newndvi = ee.ImageCollection(ndvi)
.filterDate('2000-01-01','2020-01-01')
.map(MaskToBestBits)
.select("NDVI")
.filterBounds(CRNP_Oban)
.map(function(im) { return im.clip(CRNP_Oban)});

print('newndvi', newndvi);


Map.addLayer(newndvi, null, 'newndvi');
Map.addLayer(ndvi, null, 'ndvi')
Map.setCenter(8.53, 5.56, 9);
Map.addLayer(CRNP_Oban, null, 'CRNP Oban')

8
  • I have updated my question with more information. As shown in the Modis document (image above), the detailedQA is in binary. Does that not apply when masking? Also, I guess I have to remove my initial mask var mask = function(im) { return im.updateMask(im.select("SummaryQA").eq(0));}; ?
    – Geo_CJ
    Jan 20, 2023 at 23:04
  • I have removed the initial mask. The code works fine. Very much appreciated.
    – Geo_CJ
    Jan 20, 2023 at 23:36
  • How can you select two undateMask values in between other values? For example, I have 0, 1, 2, 3 etc and I want to select 1 and 2 in the update mask section .updateMask(Viadjcl.eq(1)).
    – Geo_CJ
    Feb 3, 2023 at 17:03
  • Your options are to use the logical operators, such as eq (equals), lt (less than), lte (less than or equal to), etc. I'm not 100% sure you can have one than one value. But since you want 1 and 2, and they're both less than 3, you can try updateMask(VIQual.lt(3)). The logic works. It's up to how the collection and GEE works on whether or not they allow more than one value. (I can't see a reason they can't). Worth a try. If that doesn't work, you should make a different post to ask if a mask (updateMask) of more than 1 value can be used with the QA bits for MOD13Q1 or something similar.
    – John Polo
    Feb 3, 2023 at 18:48
  • 0 is climatology, 1 is low, and 2 is intermediate but I'm not sure what climatology means. I've tried to read up on it but can't see anything substantial. I don't think it's worth asking another question. I'll just assume climatology is the best quality. Thank you.
    – Geo_CJ
    Feb 3, 2023 at 20:33

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.