Exploring ECOSTRESS Tiled Data

Summary

This notebook will show how to access ECOsystem Spaceborne Thermal Radiometer Experiment on Space Station (ECOSTRESS) data hosted in the Earthdata Cloud programmatically using the earthaccess python library. It shows how to authenticate, search, review browse images, download, and stream (directly access) data. It also shows ways to review the tiled data for quality.

Learning Objectives

- How to search ECOSTRESS tiled data using `earthaccess`
- How to review browse images
- How to stream or download ECOSTRESS data
- How to quality filter ECOSTRESS data
- How to clip ECOSTRESS data to a Region of Interest (ROI)
- How to export the processed ECOSTRESS data

Requirements

Tutorial Outline

1. Setup
2. Searching for ECOSTRESS Tiled Data
3. Review the Browse Images
4. Select Bands
5. Accessing COG Bands
6. Quality Filtering
7. Cropping ECOSTRESS Data 
8. Writing Outputs
9. Automate

1. Setup

Import the required libraries.

# Import Packages
import warnings
# Some cells may generate warnings that we can ignore. Comment below lines to see.
warnings.filterwarnings('ignore')

import os, sys, shutil
import earthaccess
import numpy as np
import geopandas as gp
import pandas as pd

from osgeo import gdal
import rasterio as rio
import rioxarray as rxr
import xarray as xr
import hvplot.xarray
import hvplot.pandas

from zipfile import ZipFile 

Authentication

Log into Earthdata using the Auth and login functions from the earthaccess library. The persist=True argument will create a local .netrc file if it doesn’t exist, or add your login info to an existing .netrc file. If no Earthdata Login credentials are found in the .netrc you’ll be prompted for them.

auth = earthaccess.login(persist = True)
# are we authenticated?
print(auth.authenticated)
True

2. Searching for ECOSTRESS Tiled Data

In this example, we will use cloud-hosted ECOSTRESS Tiled data, but the same search process can be applied to other NASA Earth data collections from different providers. The ECOSTRESS tiled data product uses a modified version of the Military Grid Reference System (MGRS) which divides Universal Transverse Mercator (UTM) zones into square tiles that are 109.8 km by 109.8 km with a 70 meter (m) spatial resolution. This allows the end user to assume that each 70 m ECOSTRESS pixel will remain in the same location at each timestep observed in analysis (tiled data User Guide.

We will use the earthaccess search_data function to search for ECOSTRESS granules (tiles). By providing query parameters such as collection short name, version, collection ID, acquisition time, and spatial region of interest (ROI), you can filter results to only those granules that meet your criteria. In this tutorial, we’ll go straight into searching the data. For more details on additional search methods, check the earthaccess introduction tutorial.

Region of Interest (ROI)

In this exercise, you can specify your Region of Interest (ROI) in one of two ways: - Draw a bounding box or polygon in geojson.io and save it as a GeoJSON or Shapefile. Store the file in /data folder. - The polygon argument accepts a list of vertices in counter-clockwise order. - Provide a tuple with coordinates in the following order: (lower_left_lon, lower_left_lat, upper_right_lon, upper_right_lat) - bbox = (-156.08325817024362, 18.884416413037513, -154.7956649879457, 20.289321000519536) #### Temporal Period Pass a tuple containing the start and end datetime, each in ISO-8601 format: - YYYY-MM-DDTHH:mm:ss - YYYY-MM-DDTHH:mm - YYYY-MM-DD

gdf = gp.read_file('../../data/hawaii.geojson')

# Get the first geometry
poly = gdf.geometry.iloc[0]

# Extract exterior coordinates
exterior_coords = list(poly.exterior.coords)
exterior_coords
[(-156.08325817024362, 19.761648519502998),
 (-155.94536162626957, 19.055265378036196),
 (-155.68912658483336, 18.884416413037513),
 (-154.7956649879457, 19.49868320811794),
 (-155.15701319757088, 19.977862511765977),
 (-155.88944801467946, 20.289321000519536),
 (-156.08325817024362, 19.761648519502998)]
gdf.hvplot(tiles='ESRI', color='#d95f02',alpha=0.6, crs='EPSG:4326', frame_height=405, frame_width=720, fontscale=2)
bbox = tuple(list(gdf.total_bounds))

Now let’s proceed to search for the granules. We’ll use the collection short name (ECO_L2T_LSTE) and version (002) to query the ECOSTRESS Tiled LSTE product. You can find the collection information using Earthdata Search, the dataset landing page, or through a collection search of the Common Metadata Repository (CMR).

You can replace polygon=polygon_coords with bounding_box = bbox for bounding box OR with point = (-156.08325817024362, 18.884416413037513) for point query.

results = earthaccess.search_data(
    short_name='ECO_L2T_LSTE',
    version='002',
    provider='LPCLOUD',
    polygon=exterior_coords,            # Replace with `bounding_box = bbox` OR point = (-156.08325817024362, 18.884416413037513)
    temporal=('2023-05-01','2023-05-10'),
)
print(f'Granules found: {len(results)}')
Granules found: 42

We will look at the results from the first granule returned.

results[0]
results[0]['umm']
{'TemporalExtent': {'RangeDateTime': {'BeginningDateTime': '2023-05-03T19:05:17.740Z',
   'EndingDateTime': '2023-05-03T19:06:09.710Z'}},
 'OrbitCalculatedSpatialDomains': [{'BeginOrbitNumber': 27355,
   'EndOrbitNumber': 27355}],
 'GranuleUR': 'ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01',
 'AdditionalAttributes': [{'Name': 'identifier_product_doi',
   'Values': ['10.5067/ECOSTRESS/ECO_L2T_LSTE.002']},
  {'Name': 'identifier_product_doi_authority', 'Values': ['http://doi.org']}],
 'MeasuredParameters': [{'ParameterName': 'L2T_LSTE'}],
 'SpatialExtent': {'HorizontalSpatialDomain': {'Geometry': {'BoundingRectangles': [{'WestBoundingCoordinate': -157.091125,
      'EastBoundingCoordinate': -156.025345,
      'NorthBoundingCoordinate': 20.789488,
      'SouthBoundingCoordinate': 19.783957}]}}},
 'ProviderDates': [{'Date': '2023-06-15T22:49:27.567Z', 'Type': 'Insert'},
  {'Date': '2023-06-15T22:49:59.950Z', 'Type': 'Update'}],
 'CollectionReference': {'ShortName': 'ECO_L2T_LSTE', 'Version': '002'},
 'PGEVersionClass': {'PGEVersion': 'v1.6.2'},
 'RelatedUrls': [{'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.tif',
   'Type': 'GET DATA',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.tif'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.tif',
   'Type': 'GET DATA VIA DIRECT ACCESS',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.json',
   'Type': 'VIEW RELATED INFORMATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.json'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.json',
   'Type': 'VIEW RELATED INFORMATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.cmr.xml',
   'Type': 'VIEW RELATED INFORMATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.cmr.xml'},
  {'URL': 's3://lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.cmr.xml',
   'Type': 'VIEW RELATED INFORMATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/s3credentials',
   'Type': 'VIEW RELATED INFORMATION',
   'Description': 'api endpoint to retrieve temporary credentials valid for same-region direct s3 access'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.png',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.png'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01.png',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_water.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_cloud.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_view_zenith.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_height.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_QC.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_LST_err.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.jpeg'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.jpeg',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'},
  {'URL': 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'Download ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.jpeg.aux.xml'},
  {'URL': 's3://lp-prod-public/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01/ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01_EmisWB.jpeg.aux.xml',
   'Type': 'GET RELATED VISUALIZATION',
   'Description': 'This link provides direct download access via S3 to the granule'}],
 'DataGranule': {'DayNightFlag': 'Day',
  'Identifiers': [{'Identifier': 'ECOv002_L2T_LSTE_27355_010_04QGH_20230503T190517_0710_01',
    'IdentifierType': 'ProducerGranuleId'}],
  'ProductionDateTime': '2023-05-04T14:18:45.217Z',
  'ArchiveAndDistributionInformation': [{'Name': 'Not provided',
    'Size': 1.71441,
    'SizeUnit': 'MB'}]},
 'Platforms': [{'ShortName': 'ISS',
   'Instruments': [{'ShortName': 'ECOSTRESS',
     'ComposedOf': [{'ShortName': 'PHyTIR'}]}]}],
 'MetadataSpecification': {'URL': 'https://cdn.earthdata.nasa.gov/umm/granule/v1.6.6',
  'Name': 'UMM-G',
  'Version': '1.6.6'}}
# pd.json_normalize(results).keys()
results_df = pd.json_normalize(results)[['meta.native-id', 'umm.TemporalExtent.RangeDateTime.BeginningDateTime','umm.SpatialExtent.HorizontalSpatialDomain.Geometry.BoundingRectangles','umm.RelatedUrls', 'umm.DataGranule.DayNightFlag']]
results_df = results_df.rename(columns={'meta.native-id':'Granule', 'umm.TemporalExtent.RangeDateTime.BeginningDateTime':'Date','umm.SpatialExtent.HorizontalSpatialDomain.Geometry.BoundingRectangles':'bbox', 'umm.RelatedUrls':'URL', 'umm.DataGranule.DayNightFlag':'DayNightFlag'})

# Get browse image links and other data links
results_df['Browse'] = results_df['URL'].apply(
    lambda urls: [l['URL'] for l in urls if l['URL'].endswith('.png') and l['URL'].startswith('https')][0]
)
results_df['data_link'] = results_df['URL'].apply(
    lambda urls: [l['URL'] for l in urls if l['URL'].endswith('.tif') and l['URL'].startswith('https')]
)
# remove the URL column
results_df = results_df.drop(columns=['URL'])

results_df.iloc[0]
Granule         ECOv002_L2T_LSTE_27355_010_04QGH_20230503T1905...
Date                                     2023-05-03T19:05:17.740Z
bbox            [{'WestBoundingCoordinate': -157.091125, 'East...
DayNightFlag                                                  Day
Browse          https://data.lpdaac.earthdatacloud.nasa.gov/lp...
data_link       [https://data.lpdaac.earthdatacloud.nasa.gov/l...
Name: 0, dtype: object

3. Review the Browse Images

Before accessing the data layers, we can review the browse images provided as .png files. These previews allow us to visually assess data quality. For example, we can quickly filter out granules that only partially intersect the ROI or overly cloudy granules can be easily identified and excluded. While water and cloud pixels are removed in higher-level ECOSTRESS products, reviewing the browse images is still helpful for identifying any potential quality issues.

from ipyleaflet import Map, ImageOverlay, Rectangle, LayersControl
from ipywidgets import SelectMultiple, VBox, Button, Output
from IPython.display import display

# Output widget for map
out = Output()

# Create selection widget
granule_options = [(row["Granule"], idx) for idx, row in results_df.iterrows()]
granule_select = SelectMultiple(
    options=granule_options,
    value=[0],  # initially select first row
    description='Granules',
    rows=10,
    layout={'width': '400px'}
)

# Variable to store the selected DataFrame
selected_df = pd.DataFrame()

# Function to create map based on selection
def create_map(selected_indices):
    all_bounds = [results_df.iloc[idx]["bbox"][0] for idx in selected_indices]
    lats = [(b["SouthBoundingCoordinate"] + b["NorthBoundingCoordinate"])/2 for b in all_bounds]
    lons = [(b["WestBoundingCoordinate"] + b["EastBoundingCoordinate"])/2 for b in all_bounds]

    m = Map(center=[sum(lats)/len(lats), sum(lons)/len(lons)], zoom=7.5)

    for idx in selected_indices:
        row = results_df.iloc[idx]
        bbox = row["bbox"][0]
        west, east = bbox["WestBoundingCoordinate"], bbox["EastBoundingCoordinate"]
        south, north = bbox["SouthBoundingCoordinate"], bbox["NorthBoundingCoordinate"]

        overlay = ImageOverlay(
            url=row["Browse"],
            bounds=((south, west), (north, east)),
            opacity=0.7
        )
        m.add_layer(overlay)

        rect = Rectangle(bounds=((south, west), (north, east)), color='red', fill=False)
        m.add_layer(rect)

    m.add_control(LayersControl())
    return m

# Button to generate new dataframe from selected granules
button = Button(description="Create DataFrame from Selection")
def on_button_click(b):
    global selected_df
    selected_indices = list(granule_select.value)
    selected_df = results_df.iloc[selected_indices].copy()
    with out:
        out.clear_output(wait=True)
        print("New DataFrame with selected granules:")
        display(selected_df)

button.on_click(on_button_click)

# Update map when selection changes
def update_map(change):
    with out:
        out.clear_output(wait=True)
        display(create_map(list(granule_select.value)))
        display(button)

granule_select.observe(update_map, names='value')

# Display widgets
display(VBox([granule_select, out]))
update_map({'new': [0]})

In this example, data from rows 6, 8, and 9 are selected and stored in a new DataFrame called selected_df. These indices can also be used to filter the original DataFrame as needed.

selected_df = results_df.iloc[[6,8,9]]
selected_df
Granule Date bbox DayNightFlag Browse data_link
6 ECOv002_L2T_LSTE_27355_011_05QKC_20230503T1906... 2023-05-03T19:06:10.890Z [{'WestBoundingCoordinate': -155.881592, 'East... Day https://data.lpdaac.earthdatacloud.nasa.gov/lp... [https://data.lpdaac.earthdatacloud.nasa.gov/l...
8 ECOv002_L2T_LSTE_27355_011_04QHG_20230503T1906... 2023-05-03T19:06:10.890Z [{'WestBoundingCoordinate': -156.152756, 'East... Day https://data.lpdaac.earthdatacloud.nasa.gov/lp... [https://data.lpdaac.earthdatacloud.nasa.gov/l...
9 ECOv002_L2T_LSTE_27355_011_05QKB_20230503T1906... 2023-05-03T19:06:10.890Z [{'WestBoundingCoordinate': -155.864914, 'East... Day https://data.lpdaac.earthdatacloud.nasa.gov/lp... [https://data.lpdaac.earthdatacloud.nasa.gov/l...

4. Select Bands

From the filtered DataFrame, we will only select the LST, Quality, and Cloud bands for this example. Other bands can be selected in the same way if needed.

i = 1
selected_df.iloc[i]['data_link']
['https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_water.tif',
 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_cloud.tif',
 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_view_zenith.tif',
 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_height.tif',
 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_QC.tif',
 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_LST.tif',
 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_LST_err.tif',
 'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/ECO_L2T_LSTE.002/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01/ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01_EmisWB.tif']
selected_df['lst_link'] = selected_df['data_link'].apply(
    lambda links: [link for link in links if 'LST.tif' in link][0]
)
selected_df['quality_link'] = selected_df['data_link'].apply(
    lambda links: [link for link in links if 'QC' in link][0]
)
selected_df['cloud_link'] = selected_df['data_link'].apply(
    lambda links: [link for link in links if 'cloud' in link][0]
)
selected_df
Granule Date bbox DayNightFlag Browse data_link lst_link quality_link cloud_link
6 ECOv002_L2T_LSTE_27355_011_05QKC_20230503T1906... 2023-05-03T19:06:10.890Z [{'WestBoundingCoordinate': -155.881592, 'East... Day https://data.lpdaac.earthdatacloud.nasa.gov/lp... [https://data.lpdaac.earthdatacloud.nasa.gov/l... https://data.lpdaac.earthdatacloud.nasa.gov/lp... https://data.lpdaac.earthdatacloud.nasa.gov/lp... https://data.lpdaac.earthdatacloud.nasa.gov/lp...
8 ECOv002_L2T_LSTE_27355_011_04QHG_20230503T1906... 2023-05-03T19:06:10.890Z [{'WestBoundingCoordinate': -156.152756, 'East... Day https://data.lpdaac.earthdatacloud.nasa.gov/lp... [https://data.lpdaac.earthdatacloud.nasa.gov/l... https://data.lpdaac.earthdatacloud.nasa.gov/lp... https://data.lpdaac.earthdatacloud.nasa.gov/lp... https://data.lpdaac.earthdatacloud.nasa.gov/lp...
9 ECOv002_L2T_LSTE_27355_011_05QKB_20230503T1906... 2023-05-03T19:06:10.890Z [{'WestBoundingCoordinate': -155.864914, 'East... Day https://data.lpdaac.earthdatacloud.nasa.gov/lp... [https://data.lpdaac.earthdatacloud.nasa.gov/l... https://data.lpdaac.earthdatacloud.nasa.gov/lp... https://data.lpdaac.earthdatacloud.nasa.gov/lp... https://data.lpdaac.earthdatacloud.nasa.gov/lp...

5. Accessing COG Bands

ECOSTRESS data is stored in NASA’s Earthdata Cloud and can be accessed in different ways.

Downloading – This has been a supported option since the inception of NASA’s DAACs. Users can use the data link(s) to download files to their local working environment. This method works in both cloud and non-cloud environments. earthaccess.download(list(selected_df['lst_link']), local_path='../../data')

Streaming – Streaming enables on-the-fly reading of remote files (i.e., files not saved locally). However, the accessed data must fit into the workspace’s memory. Streaming works in both cloud and non-cloud environments. Streaming data stored in the cloud without downloading is called in-place access or direct S3 access, this is only available when working in a cloud environment deployed in AWS us-west-2.

The Python libraries used to access COG files in Earthdata Cloud leverage GDAL’s virtual file systems. Whether you are running this code in the Cloud or in a local workspace, GDAL configurations must be set in order to successfully access the ECOSTRESS COG files. Entering the context manager for multiple cells of the notebook allows us to more freely interact with the data. We’ll close the context manager (env.exit()) when we have all of the data loaded into memory.

rio_env = rio.Env(GDAL_DISABLE_READDIR_ON_OPEN='EMPTY_DIR',
                  GDAL_HTTP_COOKIEFILE=os.path.expanduser('~/cookies.txt'),
                  GDAL_HTTP_COOKIEJAR=os.path.expanduser('~/cookies.txt'),
                  GDAL_HTTP_MAX_RETRY=10,
                  GDAL_HTTP_RETRY_DELAY=0.5)
rio_env.__enter__()
<rasterio.env.Env at 0x7f8b837e2290>

Below, files are read into the workspace using open_rasterio from the rioxarray library. Since the files consists of only 1 layer, we can squeeze it, removing the band dimension.

granules = selected_df['Granule']
lst = selected_df['lst_link']
qa = selected_df['quality_link']
cld = selected_df['cloud_link']
granule_name = granules.iloc[i]
eco_lst_ds = rxr.open_rasterio(lst.iloc[i]).squeeze('band', drop=True)
eco_qa_ds = rxr.open_rasterio(qa.iloc[i]).squeeze('band', drop=True)
eco_cld_ds = rxr.open_rasterio(cld.iloc[i]).squeeze('band', drop=True)
eco_lst_ds
<xarray.DataArray (y: 1568, x: 1568)> Size: 10MB
[2458624 values with dtype=float32]
Coordinates:
  * x            (x) float64 13kB 8e+05 8.001e+05 ... 9.096e+05 9.097e+05
  * y            (y) float64 13kB 2.2e+06 2.2e+06 2.2e+06 ... 2.09e+06 2.09e+06
    spatial_ref  int64 8B 0
Attributes:
    AREA_OR_POINT:  Area
    _FillValue:     nan
    scale_factor:   1.0
    add_offset:     0.0

As mentioned, the ECOSTRESS product we are using here is tiled and the CRS is dependent on UTM zone. For this tile, we can look at the spatial_ref variable through the interactive object above to see details such as the well-known-text (WKT) representation of the CRS and other attributes.

Now let’s plot the data using hvplot. reproject function is applied only for the visualization. Make sure to specify the CRS argument within the hvplot.image function so the ESRI imagery RBG background tile aligns with our scene.

size_opts = dict(frame_height=405, frame_width=720, fontscale=2)

eco_lst_ds.rio.reproject('EPSG:4326').hvplot.image(x='x', y='y', **size_opts, 
                                                   cmap='inferno', tiles='ESRI', xlabel='Longitude', 
                                                   ylabel='Latitude', title='ECOSTRESS LST (K)', 
                                                   crs='EPSG:4326')*gdf.hvplot(color=None, line_color='Red',alpha=0.5, line_width=4, crs='EPSG:4326')

6. Quality Filtering

The quality values are 16 digits bit values with bits 0 and 1 being the mandatory QA flag that will be interpreted as:

    00 = Pixel produced, best quality
    01 = Pixel produced, nominal quality. Either one or more of the following conditions are met:  

            1. emissivity in both bands 4 and 5 < 0.95, i.e. possible cloud contamination  
            2. low transmissivity due to high water vapor loading (<0.4), check PWV values and error estimates  
            3. Pixel falls on missing scan line in bands 1&5, and filled using spatial neural net. Check error estimates  
            Recommend more detailed analysis of other QC information  
    10 = Pixel produced, but cloud detected  
    11 = Pixel not produced due to missing/bad data, user should check Data quality flag bits  

Important: There is a known data issue related to quality of ECOSTRESS Tile LSTE version 2 data:
All users of ECOSTRESS L2 v002 products (ECO_L2T_LSTE, ECO_L2_LSTE, ECO_L2G_LSTE) should be aware that the cloud mask information previously available in the Quality Control (QC) layer in v001, is not available in the v002 QC layer. Instead, users should be using the ‘cloud_mask’ layer in the L2 LSTE product, or the cloud information in the standard cloud mask products (ECO_L2_CLOUD, ECO_L2T_CLOUD, ECO_L2G_CLOUD) to assess if a pixel is clear or cloudy (see section 3 of the User Guide).

The detailed quality information is provided in Table 3-5 in ECOSTRESS Product Specification Document and product CMR page

Below, the unique quality values are extracted from the data, and only the values showing good quality are kept. To identify clear pixels, you must now apply an extra filtering step. In the cloud mask layer, value zero means absence of cloud, and one means presence of cloud. When processing, ensure you retain only pixels with a value of 0 in the cloud mask layer to exclude cloudy pixels.

quality_vals = np.unique(eco_qa_ds.values).tolist()
good_q = [q for q in quality_vals if np.binary_repr(q, width=16)[-2:] == '00']

The .where method is used to filter the data by quality, retaining only the LST values flagged as best quality and cloud-free.

eco_lst_mask = eco_lst_ds.where(eco_qa_ds.isin(good_q))
eco_lst_mask = eco_lst_mask.where(eco_cld_ds.isin([0]))
eco_lst_mask.rio.reproject('EPSG:4326').hvplot.image(x='x', y='y', **size_opts, 
                                                   cmap='inferno', tiles='ESRI', xlabel='Longitude', 
                                                   ylabel='Latitude', title='ECOSTRESS LST (K)', 
                                                   crs='EPSG:4326')

Other quality considerations:

  • Solar Array Obstruction: Some ECOSTRESS scenes may be affected by solar array obstructions from the International Space Station (ISS), potentially impacting data quality of obstructed pixels. The ‘FieldOfViewObstruction’ metadata field is included in all Version 2 products to indicate possible obstructions: Before October 24, 2024 (orbits prior to 35724): The field is present but was not populated and does not reliably identify affected scenes. On or after October 24, 2024 (starting with orbit 35724): The field is populated and generally accurate, except for late December 2024, when a temporary processing error may have caused false positives. A list of scenes confirmed to be affected by obstructions is available and is recommended for verifying historical data (before October 24, 2024) and scenes from late December 2024.

  • Geolocation: The ISS native pointing information is coarse relative to ECOSTRESS pixels, so ECOSTRESS geolocation is improved through image matching with a basemap. GeolocationAccuracyQA metadata in the L1B_GEO file shows the success of this geolocation improvement, using categorizations “best”, “good”, “suspect”, and “poor”. We recommend that users use only “best” and “good” scenes for evaluations where geolocation is important (e.g., comparison to field sites). For some scenes, this metadata is not reflected in the higher-level products (e.g., land surface temperature, evapotranspiration, etc.). While this metadata is always available in the geolocation product, to save users additional download, we have produced a summary text file that includes the geolocation quality flags for all scenes from launch to present.

  • Noisy Data: During the time period of May 15th 2025 through July 1st, 2025 ECOSTRESS data was noisier than expected. Cycling the payload resolved the issue, but researchers should use all levels of ECOSTRESS data acquired during this time period with caution.

More details available at https://cmr.earthdata.nasa.gov/search/concepts/C2076090826-LPCLOUD.html.

7. Cropping ECOSTRESS Data

The clip function from rasterio is used to mask out data outside of our ROI. Before clipping, the ROI must be reprojected to match the projection of the dataset.

polygon_reproj = gdf.to_crs(eco_lst_mask.rio.crs)
eco_lst_mask = eco_lst_mask.rio.clip(polygon_reproj.geometry.values, polygon_reproj.crs, all_touched=True)
eco_lst_mask.hvplot.image(
    geo=True,cmap='inferno',**size_opts, tiles='ESRI',alpha=0.8, 
    title='Cropped ECOSTRESS LST (K)', xlabel='Longitude',ylabel='Latitude')

8. Writing Outputs

We now have a ECOSTRESS tile that is clipped to our ROI with only good quality values. Now, we can save this file locally. The filed with only NA values will not be exported.

granule_name
'ECOv002_L2T_LSTE_27355_011_04QHG_20230503T190610_0710_01'
if eco_lst_mask.notnull().any():
    out_name = f"../../data/{granule_name}_clipped.tif"
    eco_lst_mask.rio.to_raster(raster_path=out_name, driver='COG')

9. Automate

for i in range(len(lst)):
    granule_name = granules.iloc[i]
    eco_lst_ds = rxr.open_rasterio(lst.iloc[i]).squeeze('band', drop=True)
    eco_qa_ds = rxr.open_rasterio(qa.iloc[i]).squeeze('band', drop=True)
    eco_cld_ds = rxr.open_rasterio(cld.iloc[i]).squeeze('band', drop=True)
    
    quality_vals = np.unique(eco_qa_ds.values).tolist()
    good_q = [q for q in quality_vals if np.binary_repr(q, width=16)[-2:] == '00']
    
    eco_lst_mask = eco_lst_ds.where(eco_qa_ds.isin(good_q))
    eco_lst_mask = eco_lst_mask.where(eco_cld_ds.isin([0]))
    eco_lst_mask = eco_lst_mask.rio.clip(polygon_reproj.geometry.values, polygon_reproj.crs, all_touched=True)
    if eco_lst_mask.notnull().any():
        out_name = f"../../data/{granule_name}_clipped.tif"
        eco_lst_mask.rio.to_raster(raster_path=out_name, driver='COG')
rio_env.__exit__()

Contact Info:

Email: LPDAAC@usgs.gov
Voice: +1-866-573-3222
Organization: Land Processes Distributed Active Archive Center (LP DAAC)¹
Website: https://www.earthdata.nasa.gov/centers/lp-daac

¹Work performed under USGS contract G15PD00467 for NASA contract NNG14HH33I.