What is Masking?
In processing EO data, masking is a very common operation to mark certain pixel locations as null values. For more discussion, see the RasterFrames masking page.
MODIS Land Surface Temperature
This page demonstrates the masking procedure for MODIS Land Surface Temperature (LST) data. The product is organized to provide daytime and nighttime bands, with separate quality information for each.
Masking is described on the dataset page. You can find the referenced user guide here.
There are several related factors to consider when choosing which data to mask. In this exercise we will mask away all data except the "good quality" data.
According to the information on the site, this translates to masking out all values except where bits 0 and 1 have the value 00
. We will try an alternative strategy as well.
Using Earth OnDemand, let's query some MODIS LST data. First, let's use Earth OnDemand to check how to query for this data set.
from earthai.init import * from pyspark.sql.functions import col, lit collections = earth_ondemand.collections() collections[collections.description.str.contains("Temperature")]
In the above DataFrame we see that the collection we want has an id of mod11a1
. Let's see which asset names correspond to daytime temperature and the daytime QA.
earth_ondemand.item_assets('mod11a1').sort_values('asset_name')
Now that we know the appropriate collection id and asset names, let's perform our query for a small bounding box around Tallinn, Estonia.
catalog = spark.read.earth_ondemand_catalog(geo=[24.57, 59.58, 25.37, 59.10], start_datetime='20190901', end_datetime='20191101', collections='mod11a1', max_cloud_cover=25, ) print(catalog.columns)
asset_names = ['LSTD', 'QCD'] df = spark.read.raster(catalog, catalog_col_names=asset_names)
masked = df.withColumn('mask', rf_local_greater( rf_local_extract_bits('QCD', 0, 2), 0)) \ .withColumn('lstd_masked', rf_mask_by_value('LSTD', 'mask', 1))
Inspect tiles where there are many cloudy pixels.
masked.select('LSTD', 'QCD', 'lstd_masked')
We observe the purple regions of the QCD
band are the areas of highest quality pixels that are retained after masking.
Alternative Mask
The QA bands for the LST product enable some more sophisticated selection based on the quality conditions and estimated errors. We will examine another mask based on discarding cells that meet the following conditions:
-
Mandatory QA flag is 10 or 11; Not produced due to cloud or other reason
-
LST error flag is 10 or 11; average error greater than 2K
This uses the rf_mask_by_bits
to both extract the bits and apply the mask according to a blacklisted values.
df.withColumn('lstd_masked', rf_mask_by_bits('LSTD', 'QCD', 0, 2, [2, 3])) \ .withColumn('lstd_masked', rf_mask_by_bits('lstd_masked', 'QCD', 6, 2, [2, 3])) \ .select('LSTD', 'QCD', 'lstd_masked')
We can see much more data is retained using this more permissive method.
Comments
0 comments
Please sign in to leave a comment.