From a4aa179ea5daaccfe52db87fefc6472b2dc490a0 Mon Sep 17 00:00:00 2001 From: Gregory Halverson Date: Tue, 17 Jun 2025 15:41:57 -0700 Subject: [PATCH] working on quality mask --- EMITL2ARFL/granule.py | 12 +++++++ EMITL2ARFL/quality_mask.py | 31 ++++++++++++++++ ...MIT L2A Reflectance with earthaccess.ipynb | 36 ++++++++++++------- 3 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 EMITL2ARFL/quality_mask.py diff --git a/EMITL2ARFL/granule.py b/EMITL2ARFL/granule.py index 13ad108..a6e3e13 100644 --- a/EMITL2ARFL/granule.py +++ b/EMITL2ARFL/granule.py @@ -4,6 +4,7 @@ from rasters import Raster, RasterGeometry from .emit_ortho_raster import emit_ortho_raster +from .quality_mask import quality_mask class EMITL2ARFL: def __init__(self, directory: str): @@ -32,6 +33,17 @@ def mask_filename(self) -> str: def uncertainty_filename(self) -> str: return glob(join(self.directory_absolute, "*_RFLUNCERT_*.nc"))[0] + def quality_mask(self, geometry: RasterGeometry) -> Raster: + raster = quality_mask( + filepath=self.mask_filename, + quality_bands=[0, 1, 2, 3, 4] + ) + + if geometry is not None: + raster = raster.to_geometry(geometry) + + return raster + def reflectance(self, geometry: RasterGeometry) -> Raster: raster = emit_ortho_raster( filepath=self.reflectance_filename, diff --git a/EMITL2ARFL/quality_mask.py b/EMITL2ARFL/quality_mask.py new file mode 100644 index 0000000..0c13504 --- /dev/null +++ b/EMITL2ARFL/quality_mask.py @@ -0,0 +1,31 @@ +import numpy as np +import xarray as xr + +def quality_mask(filepath, quality_bands): + """ + This function builds a single layer mask to apply based on the bands selected from an EMIT L2A Mask file. + + Parameters: + filepath: an EMIT L2A Mask netCDF file. + quality_bands: a list of bands (quality flags only) from the mask file that should be used in creation of mask. + + Returns: + qmask: a numpy array that can be used with the emit_xarray function to apply a quality mask. + """ + # Open Dataset + mask_ds = xr.open_dataset(filepath, engine="h5netcdf") + # Open Sensor band Group + mask_parameters_ds = xr.open_dataset( + filepath, engine="h5netcdf", group="sensor_band_parameters" + ) + # Print Flags used + flags_used = mask_parameters_ds["mask_bands"].data[quality_bands] + print(f"Flags used: {flags_used}") + # Check for data bands and build mask + if any(x in quality_bands for x in [5, 6]): + err_str = f"Selected flags include a data band (5 or 6) not just flag bands" + raise AttributeError(err_str) + else: + qmask = np.sum(mask_ds["mask"][:, :, quality_bands].values, axis=-1) + qmask[qmask > 1] = 1 + return qmask \ No newline at end of file diff --git a/Searching EMIT L2A Reflectance with earthaccess.ipynb b/Searching EMIT L2A Reflectance with earthaccess.ipynb index 10a09a6..e8d64e8 100644 --- a/Searching EMIT L2A Reflectance with earthaccess.ipynb +++ b/Searching EMIT L2A Reflectance with earthaccess.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -39,7 +39,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -55,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -77,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -121,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -148,7 +148,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -211,7 +211,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -233,7 +233,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -253,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -273,7 +273,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -293,7 +293,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -313,7 +313,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -332,6 +332,16 @@ "granule.reflectance(geometry=geometry)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "emit_mask = emit_xarray(granule.mask_filename, ortho=True)\n", + "emit_mask" + ] + }, { "cell_type": "code", "execution_count": null,