eoio.readers.landsat.metadata package#

eoio.readers.landsat.metadata#

Landsat metadata readers and extractors for Collection 2 Level-1 data.

This module provides two main classes for working with Landsat metadata:

  1. LSL1ProdXMLReader: Low-level XML metadata reader - Reads Landsat Collection 2 Level-1 MTL XML files - Provides semantic accessors for temporal, radiometric, projection, and band metadata - Handles graceful degradation when optional sections are missing

  2. LSL1ProdJSONReader: Low-level JSON metadata reader - Reads Landsat Collection 2 Level-1 MTL JSON files - Provides semantic accessors for temporal, radiometric, projection, and band metadata - Handles graceful degradation when optional sections are missing

  3. LSMetadataExtractor: High-level metadata extractor - Transforms low-level metadata into structured datasets - Integrates with the xarray data model - Matches the Sentinel-2 reader architecture pattern

Example usage:

from eoio.readers.landsat.metadata import LSL1ProdXMLReader, LSMetadataExtractor from pathlib import Path

# Load and parse metadata mtl_file = Path(“LC08_L1TP_040033_20200306_20200822_02_T1_MTL.xml”) reader = LSL1ProdXMLReader(mtl_file)

# Access basic metadata print(reader.find_product_id()) print(reader.find_acquisition_datetime())

# Get radiometric calibration coefficients rescaling = reader.get_radiometric_rescaling() thermal_constants = reader.get_thermal_constants()

# Get bounds geometry bounds_polygon = reader.find_bounds()

class eoio.readers.landsat.metadata.LSL1ProdJSONReader(json_path: Path | str)[source]#

Bases: object

Landsat Collection-2 Level-1 JSON metadata reader.

Supports STAC item JSON (preferred) and MTL JSON (limited).

find_all_band_central_wavelengths() dict[str, float][source]#

Return a mapping of band name to central wavelength (nm).

Returns:

Dict of {band: wavelength_nm}.

find_all_band_gsds() dict[str, float][source]#

Return a mapping of band name to GSD (meters).

Returns:

Dict of {band: gsd_m}.

find_band_central_wavelength(band: str, default: float | None = None) float[source]#

Return the central wavelength (nm) for a specific band.

Parameters:
  • band – Band identifier (e.g., “B2”, “B10”).

  • default – Value to return if band is not found.

Returns:

Central wavelength in nm.

Raises:

KeyError – If band is missing and no default is provided.

find_epsg(default: int | None = None) int[source]#

Return the EPSG code of the projection from JSON metadata.

Parameters:

default – Value to return if EPSG not found.

Returns:

EPSG code as integer.

Raises:

ValueError – If EPSG is missing and no default is provided.

find_proj_shape(default=None)[source]#

Return STAC proj:shape if present.

Parameters:

default – Value to return if missing.

Returns:

Shape list [rows, cols] or default.

find_proj_transform(default=None)[source]#

Return STAC proj:transform if present.

Parameters:

default – Value to return if missing.

Returns:

Affine transform list or default.

class eoio.readers.landsat.metadata.LSL1ProdXMLReader(path: Path)[source]#

Bases: XMLReader

Landsat Collection-2 Level-1 product metadata reader.

This class provides semantic accessors for commonly used fields in the Landsat product metadata XML (MTL.xml). It builds on the generic XMLReader to return domain-appropriate Python objects.

find_acquisition_date() date[source]#

Return the acquisition date (DATE_ACQUIRED).

Returns:

Acquisition date as a datetime.date object.

find_acquisition_datetime() datetime[source]#

Return the scene center sensing time as a timezone-aware datetime (UTC).

Combines DATE_ACQUIRED (YYYY-MM-DD) and SCENE_CENTER_TIME (HH:MM:SS[.fffffff]Z).

Returns:

Acquisition datetime as a datetime.datetime object (UTC).

find_bounds()[source]#

Return the product footprint as a Shapely polygon in lon/lat order.

Uses PROJECTION_ATTRIBUTES corner lat/lon (PRODUCT) coordinates: UL, UR, LR, LL. The polygon is ordered UL -> UR -> LR -> LL -> UL and validated.

find_collection_category() str[source]#

Return the COLLECTION_CATEGORY (e.g., ‘T1’).

find_collection_number() str[source]#

Return the COLLECTION_NUMBER (e.g., ‘02’).

find_processing_level() str[source]#

Return the PROCESSING_LEVEL (e.g., ‘L1TP’).

find_product_id() str[source]#

Return the LANDSAT_PRODUCT_ID string.

find_projection_parameters() dict[source]#

Return Level-1 projection parameters (map projection, grid sizes, orientation, resampling option).

find_sensor_id() str[source]#

Return the SENSOR_ID (e.g., ‘OLI_TIRS’).

find_spacecraft_name() str[source]#

Return the spacecraft name (e.g., ‘LANDSAT_8’).

find_wrs_path() int[source]#

Return the WRS_PATH as integer if possible.

find_wrs_row() int[source]#

Return the WRS_ROW as integer if possible.

get_radiometric_rescaling() dict[source]#

Extract all radiometric rescaling parameters for bands B1..B11.

Returns a dict mapping band name (‘B1’..’B11’) to: - radiance_mult, radiance_add (all bands) - reflectance_mult, reflectance_add (B1..B9 only)

get_thermal_constants() dict[source]#

Extract thermal constants (K1, K2) for thermal bands B10, B11. Returns dict: {“B10”: {“k1”: …, “k2”: …}, “B11”: {“k1”: …, “k2”: …}}

metadata_paths: dict[str, str] = {'cloud_cover': './/IMAGE_ATTRIBUTES/CLOUD_COVER', 'cloud_cover_land': './/IMAGE_ATTRIBUTES/CLOUD_COVER_LAND', 'collection_category': './/PRODUCT_CONTENTS/COLLECTION_CATEGORY', 'collection_number': './/PRODUCT_CONTENTS/COLLECTION_NUMBER', 'corner_ll_lat_product': './/PROJECTION_ATTRIBUTES/CORNER_LL_LAT_PRODUCT', 'corner_ll_lon_product': './/PROJECTION_ATTRIBUTES/CORNER_LL_LON_PRODUCT', 'corner_lr_lat_product': './/PROJECTION_ATTRIBUTES/CORNER_LR_LAT_PRODUCT', 'corner_lr_lon_product': './/PROJECTION_ATTRIBUTES/CORNER_LR_LON_PRODUCT', 'corner_ul_lat_product': './/PROJECTION_ATTRIBUTES/CORNER_UL_LAT_PRODUCT', 'corner_ul_lon_product': './/PROJECTION_ATTRIBUTES/CORNER_UL_LON_PRODUCT', 'corner_ur_lat_product': './/PROJECTION_ATTRIBUTES/CORNER_UR_LAT_PRODUCT', 'corner_ur_lon_product': './/PROJECTION_ATTRIBUTES/CORNER_UR_LON_PRODUCT', 'date_acquired': './/IMAGE_ATTRIBUTES/DATE_ACQUIRED', 'date_product_generated': './/LEVEL1_PROCESSING_RECORD/DATE_PRODUCT_GENERATED', 'datum': './/PROJECTION_ATTRIBUTES/DATUM', 'earth_sun_distance': './/IMAGE_ATTRIBUTES/EARTH_SUN_DISTANCE', 'ellipsoid': './/PROJECTION_ATTRIBUTES/ELLIPSOID', 'grid_cell_size_panchromatic': './/PROJECTION_ATTRIBUTES/GRID_CELL_SIZE_PANCHROMATIC', 'grid_cell_size_reflective': './/PROJECTION_ATTRIBUTES/GRID_CELL_SIZE_REFLECTIVE', 'grid_cell_size_thermal': './/PROJECTION_ATTRIBUTES/GRID_CELL_SIZE_THERMAL', 'image_quality_oli': './/IMAGE_ATTRIBUTES/IMAGE_QUALITY_OLI', 'image_quality_tirs': './/IMAGE_ATTRIBUTES/IMAGE_QUALITY_TIRS', 'k1_constant_band_10': './/LEVEL1_THERMAL_CONSTANTS/K1_CONSTANT_BAND_10', 'k1_constant_band_11': './/LEVEL1_THERMAL_CONSTANTS/K1_CONSTANT_BAND_11', 'k2_constant_band_10': './/LEVEL1_THERMAL_CONSTANTS/K2_CONSTANT_BAND_10', 'k2_constant_band_11': './/LEVEL1_THERMAL_CONSTANTS/K2_CONSTANT_BAND_11', 'landsat_product_id': './/PRODUCT_CONTENTS/LANDSAT_PRODUCT_ID', 'map_projection': './/PROJECTION_ATTRIBUTES/MAP_PROJECTION', 'orientation': './/PROJECTION_ATTRIBUTES/ORIENTATION', 'output_format': './/PRODUCT_CONTENTS/OUTPUT_FORMAT', 'processing_level': './/PRODUCT_CONTENTS/PROCESSING_LEVEL', 'processing_software_version': './/LEVEL1_PROCESSING_RECORD/PROCESSING_SOFTWARE_VERSION', 'proj_params_datum': './/LEVEL1_PROJECTION_PARAMETERS/DATUM', 'proj_params_ellipsoid': './/LEVEL1_PROJECTION_PARAMETERS/ELLIPSOID', 'proj_params_grid_cell_size_panchromatic': './/LEVEL1_PROJECTION_PARAMETERS/GRID_CELL_SIZE_PANCHROMATIC', 'proj_params_grid_cell_size_reflective': './/LEVEL1_PROJECTION_PARAMETERS/GRID_CELL_SIZE_REFLECTIVE', 'proj_params_grid_cell_size_thermal': './/LEVEL1_PROJECTION_PARAMETERS/GRID_CELL_SIZE_THERMAL', 'proj_params_map_projection': './/LEVEL1_PROJECTION_PARAMETERS/MAP_PROJECTION', 'proj_params_orientation': './/LEVEL1_PROJECTION_PARAMETERS/ORIENTATION', 'proj_params_resampling_option': './/LEVEL1_PROJECTION_PARAMETERS/RESAMPLING_OPTION', 'proj_params_utm_zone': './/LEVEL1_PROJECTION_PARAMETERS/UTM_ZONE', 'radiance_add_band_1': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_1', 'radiance_add_band_10': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_10', 'radiance_add_band_11': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_11', 'radiance_add_band_2': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_2', 'radiance_add_band_3': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_3', 'radiance_add_band_4': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_4', 'radiance_add_band_5': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_5', 'radiance_add_band_6': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_6', 'radiance_add_band_7': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_7', 'radiance_add_band_8': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_8', 'radiance_add_band_9': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_ADD_BAND_9', 'radiance_mult_band_1': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_1', 'radiance_mult_band_10': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_10', 'radiance_mult_band_11': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_11', 'radiance_mult_band_2': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_2', 'radiance_mult_band_3': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_3', 'radiance_mult_band_4': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_4', 'radiance_mult_band_5': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_5', 'radiance_mult_band_6': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_6', 'radiance_mult_band_7': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_7', 'radiance_mult_band_8': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_8', 'radiance_mult_band_9': './/LEVEL1_RADIOMETRIC_RESCALING/RADIANCE_MULT_BAND_9', 'reflectance_add_band_1': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_1', 'reflectance_add_band_2': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_2', 'reflectance_add_band_3': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_3', 'reflectance_add_band_4': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_4', 'reflectance_add_band_5': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_5', 'reflectance_add_band_6': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_6', 'reflectance_add_band_7': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_7', 'reflectance_add_band_8': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_8', 'reflectance_add_band_9': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_ADD_BAND_9', 'reflectance_mult_band_1': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_1', 'reflectance_mult_band_2': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_2', 'reflectance_mult_band_3': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_3', 'reflectance_mult_band_4': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_4', 'reflectance_mult_band_5': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_5', 'reflectance_mult_band_6': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_6', 'reflectance_mult_band_7': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_7', 'reflectance_mult_band_8': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_8', 'reflectance_mult_band_9': './/LEVEL1_RADIOMETRIC_RESCALING/REFLECTANCE_MULT_BAND_9', 'scene_center_time': './/IMAGE_ATTRIBUTES/SCENE_CENTER_TIME', 'sensor_id': './/IMAGE_ATTRIBUTES/SENSOR_ID', 'spacecraft_id': './/IMAGE_ATTRIBUTES/SPACECRAFT_ID', 'sun_azimuth': './/IMAGE_ATTRIBUTES/SUN_AZIMUTH', 'sun_elevation': './/IMAGE_ATTRIBUTES/SUN_ELEVATION', 'utm_zone': './/PROJECTION_ATTRIBUTES/UTM_ZONE', 'wrs_path': './/IMAGE_ATTRIBUTES/WRS_PATH', 'wrs_row': './/IMAGE_ATTRIBUTES/WRS_ROW'}#

Mapping from metadata keys to XPath expressions. Intended to be overridden by subclasses.

class eoio.readers.landsat.metadata.LSMetadataExtractor(reader)[source]#

Bases: BaseMetadataExtractor

High-level metadata extractor for Landsat 8/9 products.

This class extracts metadata from Landsat MTL XML file via LSProdXMLReader and exposes structured dictionaries suitable for downstream use.

get_angle_metadata() dict[source]#

Return metadata for angle variables (solar/observer angles).

Returns:

Dictionary of angle variable metadata.

get_aux_metadata() dict[source]#

Return metadata for auxiliary data variables.

Returns:

Dictionary of auxiliary data variable metadata.

get_basic_metadata() dict[source]#

Return high-level, product-wide metadata shared across variables.

Returns:

Dictionary of basic product metadata.

get_product_metadata() dict[source]#

Return detailed product-level metadata (acquisition, quality, calibration).

Returns:

Dictionary of detailed product metadata.

get_variable_basic_metadata(var: str) dict[source]#

Return basic descriptive metadata for a dataset variable (band).

Parameters:

var – Variable name for which metadata should be extracted.

Returns:

Dictionary containing basic variable metadata.

get_variable_product_metadata(var: str) dict[source]#

Return detailed metadata for a specific Landsat band variable: spectral characteristics, radiometric calibration coefficients, and thermal constants (for B10/B11).

Submodules#