Quality control

Not all pixels in a MODIS image are not suitable for analysis of land areas. For example, pixel quality can be negatively affected by clouds or other atmospheric conditions. For that reason, each image needs to be pre-processed to remove the values that cannot be used.

Each MODIS file contains quality assurance (QA) information that can be used to identify the pixels to remove. The QA information is stored in a somewhat complicated bit-encoding format. This allows for very efficient storage, but it makes it much harder to use.

A single bit can represent two values — 0 (no) or 1 (yes); a combination of two bits can represent 22 = 4 values (00, 01, 10, and 11), and with three bits you can store 23 = 8 values. This video by USGS explains the QA encoding.

The table below shows State QA description (16-bit) for 500 m, 1 km and lower resolution MODIS surface reflectance products. For product specific QA attribute, follow the MODIS Surface Reflectance User’s Guide.

bit

variable

value

description

1-2

cloud state

00

clear

01

cloudy

10

mixed

11

not set, assumed clear

3

cloud shadow

1

yes

0

no

4-6

land/water flag

000

shallow ocean

001

land

010

ocean coastlines and lake shorelines

011

shallow inland water

100

ephemeral water

101

deep inland water

110

continental/moderate ocean

111

deep ocean

7-8

aerosol quantity

00

climatology

01

low

10

average

11

high

9-10

cirrus detected

00

none

01

small

10

average

11

high

11

cloud flag

1

cloud

0

no cloud

12

fire flag

1

fire

0

no fire

13

snow/ice flag

1

yes

0

no

14

is adjacent to cloud

1

yes

0

no

15

Salt pan

1

yes

0

no

16

Snow mask

1

yes

0

no

Note that in R, the first bit will be referred as “1”, whereas in many other languages (e.g. Python) it will follow the values as shown in table.

To interpret the pixel level QA values, we need to convert them from decimal to binary format. The luna package offers a function for this conversion and create a mask from the QA band. The user need to specify a matrix (“qabits”) with the start and end of the quality assessment (QA) bits considered, and specify a list (“reject”) with the values to be rejected (in the image) matching the rows in qabits. Following the table above, we will define the “reject” values to exclude pixels affected by cloud and cloud shadow.

from <- c(1,3,11,14)
to   <- c(2,3,11,14)
reject <- c("01,10", "1", "1", "1")
qa_bits <- cbind(from, to, reject)
qa_bits
##      from to   reject
## [1,] "1"  "2"  "01,10"
## [2,] "3"  "3"  "1"
## [3,] "11" "11" "1"
## [4,] "14" "14" "1"

Pixels with bits 1 and 2 with values “01” or “10” will be rejected. All other combinations (“00” and “11” in this case) are not rejected.

We use the downloaded MODIS file that, in a previouse step, we saved in the datadir directory.

library(terra)
datadir <- file.path(dirname(tempdir()), "_modis")
mf <- file.path(datadir, "MOD09A1.A2009361.h21v08.061.2021149144347.hdf")
r <- rast(mf)

Generate the quality mask. We will use band 12 sur_refl_state_500m that has the quality data.

qc <- r[[12]]
plot(qc, main = "Quality")

image0

The luna package has a modis_mask method to create a mask from the quality band and the parameters defined above.

library(luna)
##
## Attaching package: 'luna'
## The following object is masked from 'package:base':
##
##     version
quality_mask <- modis_mask(qc, 16, qa_bits)
plot(quality_mask, main="Quality mask")

image1

The plot shows the pixels we want to retain. Now that we have the quality mask, we can apply it to all the bands. It is always useful to visually check the result of the masking as many times pixels could be wrongly flagged as “poor” quality. Residual noises can be filtered in subsequent gap-filling and smoothing operations.

rmask <- mask(r, quality_mask)

And we can plot the results, here as a “false color composite” (NIR:Red:Green)

plotRGB(rmask, r = 2, g = 1, b = 4, main='False color composite', stretch="lin")

image2

Finally we save the result after cloud masking.