I'm trying to generate a daily LST time series over a region by selecting only the good quality pixels. The code I've written is attached below along with the dataset description. My aim is to select pixels that have "0: Good data quality" in "Bits 2-3: Data quality flag" under QC_Day and QC_Night bands. But I'm not sure whether the code actually filters the pixels based on my requirement.
My GEE code:
var Bhagirathi = ee.FeatureCollection("users/Vineeth_Russell/NRSC_Bhagirathi_shp");
//Terra and Aqua Day time LST Daily Global 1km
var day_terra = ee.ImageCollection("MODIS/006/MOD11A1")
.filter(ee.Filter.date('2000-03-05', '2010-01-01'))
.select('LST_Day_1km','QC_Day');
//Terra and Aqua Night time LST Daily Global 1km
var night_terra = ee.ImageCollection("MODIS/006/MOD11A1")
.filter(ee.Filter.date('2000-03-05', '2010-01-01'))
.select('LST_Night_1km','QC_Night');
//create mask to extract only highest quality day band data
var filterDay = function(image){
var qa = image.select('QC_Day');
var bitMask2 = 1 << 2;
var bitMask3 = 1 << 3;
var mask = qa.bitwiseAnd(bitMask2).eq(0).and(qa.bitwiseAnd(bitMask3).eq(0));
return image.updateMask(mask);
};
//create mask to extract only highest quality night band data
var filterNight = function(image){
var qa = image.select('QC_Night');
var bitMask2 = 1 << 2;
var bitMask3 = 1 << 3;
var mask = qa.bitwiseAnd(bitMask2).eq(0).and(qa.bitwiseAnd(bitMask3).eq(0));
return image.updateMask(mask);
};
//apply mask to image collection
var lst_d_terra = day_terra.map(filterDay);
var lst_n_terra = night_terra.map(filterNight);
//Scale to Kelvin and convert to Celsius, set image acquisition time (Terra Day-time)
lst_d_terra = lst_d_terra.map(function(img) {
return img.select('LST_Day_1km')
.multiply(0.02)
.subtract(273.15)
.copyProperties(img, ['system:time_start','system:time_end']);
});
//Scale to Kelvin and convert to Celsius, set image acquisition time (Terra Night-time)
lst_n_terra = lst_n_terra.map(function(img) {
return img.select('LST_Night_1km')
.multiply(0.02)
.subtract(273.15)
.copyProperties(img, ['system:time_start','system:time_end']);
});
//Charting Terra Day-time LST over Bhagirathi
print(Chart.image.series(lst_d_terra, Bhagirathi,ee.Reducer.mean(),1000).setOptions({
title: "Time Series of MODIS Terra Daily Day-time LST across Bhagirathi",
hAxis: {
title: "Time Period",
titleTextStyle: {italic: false, bold: true}
},
vAxis: {
title: "LST",
titleTextStyle: {italic: false, bold: true}
},
colors: ["Red"]
}));
//Charting Terra Night-time LST over Bhagirathi
print(Chart.image.series(lst_n_terra, Bhagirathi,ee.Reducer.mean(),1000).setOptions({
title: "Time Series of MODIS Terra Daily Night-time LST across Bhagirathi",
hAxis: {
title: "Time Period",
titleTextStyle: {italic: false, bold: true}
},
vAxis: {
title: "LST",
titleTextStyle: {italic: false, bold: true}
},
colors: ["Blue"]
}));
Dataset description:
https://developers.google.com/earth-engine/datasets/catalog/MODIS_006_MOD11A1?hl=en
How do I resolve this?
Best Answer
Your code seems to be doing what it should, however you are adding unnecessary bits. Your code
If you look at the QC bitmask,
all you really need is to check for a
"1"
inbit 2
. a value of2
, or3
has been reserved for future use, but at the moment is in the To Be Determined state. So you can ignore them.The line for
bitmask3
, and its correspondingbitwiseAnd()
is not necessary. However, it should not affect your result, a mask would have been applied if ever the data was not good data quality.The result that you are seeing in your charts should be correct.
In future, include your code in your question, so that it is easier for future people to search.