2 Working with EMIT L2A Reflectance and ECOSTRESS L2 LSTE Products
Summary
In the previous notebook, we found and downloaded concurrent EMIT L2A Reflectance and ECOSTRESS L2 Land Surface Temperature and Emissivity scenes over our region of interest. In this notebook, we will open and explore the datasets along with ECOSTRESS L3 Evapotranspiration to better understand the structure, then we will conduct some common preprocessing routines to make the data usable together, including: applying quality data, reprojecting, placing data on a common grid, and cropping.
Background
The ECOSTRESS instrument is a multispectral thermal imaging radiometer designed to answer three overarching science questions:
- How is the terrestrial biosphere responding to changes in water availability?
- How do changes in diurnal vegetation water stress the global carbon cycle?
- Can agricultural vulnerability be reduced through advanced monitoring of agricultural water consumptive use and improved drought estimation?
The ECOSTRESS mission is answering these questions by accurately measuring the temperature of plants. Plants regulate their temperature by releasing water through tiny pores on their leaves called stomata. If they have sufficient water they can maintain their temperature, but if there is insufficient water, their temperatures rise and this temperature rise can be measured with ECOSTRESS. The images acquired by ECOSTRESS are the most detailed temperature images of the surface ever acquired from space and can be used to measure the temperature of an individual farmers field. These temperature images, along with auxillary inputs, are used to produce one of the primary science outputs of ECOSTRESS: evapotranspiration, an indicator of plant health via the measure of evaporation and transpiration of water through a plant.
More details about ECOSTRESS and its associated products can be found on the ECOSTRESS website and ECOSTRESS product pages hosted by the Land Processes Distributed Active Archive Center (LP DAAC).
The EMIT instrument is an imaging spectrometer that measures light in visible and infrared wavelengths. These measurements display unique spectral signatures that correspond to the composition on the Earth’s surface. The EMIT mission focuses specifically on mapping the composition of minerals to better understand the effects of mineral dust throughout the Earth system and human populations now and in the future. In addition, the EMIT instrument can be used in other applications, such as mapping of greenhouse gases, snow properties, and water resources.
More details about EMIT and its associated products can be found on the EMIT website and EMIT product pages hosted by the LP DAAC.
References
- Leith, Alex. 2023. Hyperspectral Notebooks. Jupyter Notebook. Auspatious. https://github.com/auspatious/hyperspectral-notebooks/tree/main
Requirements
- NASA Earthdata Account
- No Python setup requirements if connected to the workshop cloud instance!
- Local Only Set up Python Environment - See setup_instructions.md in the /setup/
folder to set up a local compatible Python environment
- Downloaded necessary files. This is done at the end of the 01_Finding_Concurrent_Data notebook.
Learning Objectives
- How to open and work with EMIT L2A Reflectance and ECOSTRESS L2T LSTE data
- How to apply a quality mask to EMIT datasets
- How to reproject and regrid data
- How to crop EMIT and ECOSTRESS data
Tutorial Outline
2.1 Setup
2.2 Opening and Exploring EMIT Data
2.2.1 Applying Quality Masks to EMIT Data
2.2.2 Interactive Plots
2.2.3 Cropping EMIT Data
2.2.4 Writing Outputs
2.3 Opening and Exploring ECOSTRESS Data
2.3.1 Reprojecting and Regridding ECOSTRESS Data
2.3.2 Cropping ECOSTRESS Data
2.3.3 Writing Outputs
2.1 Setup
Import Python libraries.
# Import Packages
import warnings
# Some cells may generate warnings that we can ignore. Comment below lines to see.
'ignore')
warnings.filterwarnings(
import math
import earthaccess
import numpy as np
from osgeo import gdal
import rasterio as rio
import rioxarray as rxr
import hvplot.xarray
import hvplot.pandas
import holoviews as hv
import geopandas as gp
from modules.emit_tools import emit_xarray, spatial_subset, ortho_xr
Log into Earthdata using the login
function 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.
=True) earthaccess.login(persist
For the workshop, we will stream the data, but you can also use this notebook if you downloaded the data. Either method can be used to complete this notebook. If you downloaded the data in notebook 1, Finding Concurrent Data, you can comment out the cells in the streaming section, and run the cell in the downloading section. Functionally after those sections, there’s really no difference in the workflow, just how the data is accessed. For EMIT data, streaming is often less efficient if your internet connection is slow.
2.1.1 Streaming EMIT Data
First, read the data from the URLs we found in the previous notebook. Open the required_granules.txt
file and read the URLs into a list.
# List the files in the text file output from notebook 1.
= '../data/required_granules.txt'
file_list with open(file_list) as f:
= [line.rstrip('\n') for line in f]
urls urls
Next we need to start an fsspec https session, and use it to open the urls. This will allow us to access the data in the cloud like its part of our local file system. We’ll use this method to access the EMIT netCDF files, but a slightly different workflow for the ECOSTRESS data, which we will show later.
# Get Https Session using Earthdata Login Info
= earthaccess.get_fsspec_https_session()
fs
# Define Local Filepath
= fs.open(urls[1])
emit_fp = fs.open(urls[2]) emit_qa_fp
2.1.2 Downloading EMIT Data
If you’ve already downloaded the data using the workflow shown in Section 6 of the Finding Concurrent Data notebook, you can just set filepaths using the cell below.
Define a filepath for an EMIT L2A Reflectance file, EMIT L2A Mask file, and an ECOSTRESS L2T LSTE and ECOSTRESS L2T Mask file. The files selected in this example are from April 1, 2023, at around 20:37.
# emit_fp = "../data/EMIT_L2A_RFL_001_20230401T203751_2309114_002.nc"
# emit_qa_fp = "../data/EMIT_L2A_MASK_001_20230401T203751_2309114_002.nc"
# eco_fp = "../data/ECOv002_L2T_LSTE_26860_001_10SGD_20230401T203733_0710_01_LST.tif"
# # eco_et_fp = "../data/ECOv002_L3T_JET_26860_001_10SGD_20230401T203732_0700_01_ETdaily.tif" # concurrent scene generated for tutorial 5
# eco_et_fp = "../data/ECOv002_L3T_JET_30644_005_10SGD_20231201T201005_0711_01_ETdaily.tif" # newly available scene for ECOSTRESS ET
2.2 Opening and Exploring EMIT Reflectance Data
EMIT L2A Reflectance Data are distributed in a non-orthocorrected spatially raw NetCDF4 (.nc) format consisting of the data and its associated metadata. Inside the L2A Reflectance .nc
file there are 3 groups. Groups can be thought of as containers to organize the data.
- The root group that can be considered the main dataset contains the reflectance data described by the downtrack, crosstrack, and bands dimensions.
- The
sensor_band_parameters
group containing the wavelength center and the full-width half maximum (FWHM) of each band.
- The
location
group contains latitude and longitude values at the center of each pixel described by the crosstrack and downtrack dimensions, as well as a geometry lookup table (GLT) described by the ortho_x and ortho_y dimensions. The GLT is an orthorectified image (EPSG:4326) consisting of 2 layers containing downtrack and crosstrack indices. These index positions allow us to quickly project the raw data onto this geographic grid.
To work with the EMIT data, we will use the emit_tools
module. There are other ways to work with the data and a more thorough explanation of the emit_tools
in the EMIT-Data-Resources Repository.
Open the example EMIT scene using the emit_xarray
function. In this step we will use the ortho=True
argument to orthorectify the scene using the included GLT.
# Load the data to speed up future cells
= emit_xarray(emit_fp, ortho=True).load()
emit_ds emit_ds
We can plot the spectra of an individual pixel closest to a latitude and longitude we want using the sel
function from xarray
. Using the good_wavelengths
flag from the sensor_band_parameters
group, mask out bands where water absorption features were assigned a value of -0.01 reflectance. Typically data around 1320-1440 nm and 1770-1970 nm is noisy due to the moisture present in the atmosphere; therefore, these spectral regions offer little information about targets and can be excluded from calculations.
'reflectance'].data[:,:,emit_ds['good_wavelengths'].data==0] = np.nan emit_ds[
Now select a point and plot a spectra. In this example, we’ll first find the center of the scene and use those coordinates.
= emit_ds.latitude.values[int(len(emit_ds.latitude)/2)],emit_ds.longitude.values[int(len(emit_ds.longitude)/2)]
scene_center scene_center
= emit_ds.sel(latitude=scene_center[0],longitude=scene_center[1], method='nearest')
point ='reflectance',x='wavelengths', color='black').opts(
point.hvplot.line(y=f'Latitude = {point.latitude.values.round(3)}, Longitude = {point.longitude.values.round(3)}') title
We can also plot individual bands spatially by selecting a wavelength, then plotting.
First, mask the fill values with np.nan
so they appeear transparent, then select the band with a wavelength of 850 nm and plot it using ESRI imagery as a basemap to get a better understanding of where the scene was acquired.
# Mask Fill Values
'reflectance'].data[emit_ds['reflectance'].data == -9999] = np.nan emit_ds[
# Select Wavelength and Plot
= emit_ds.sel(wavelengths=850,method='nearest')
emit_layer ='viridis',geo=True, tiles='ESRI', crs='EPSG:4326', frame_width=720,frame_height=405, alpha=0.7, fontscale=2).opts(
emit_layer.hvplot.image(cmap=f"{emit_layer.wavelengths:.3f} {emit_layer.wavelengths.units}", xlabel='Longitude',ylabel='Latitude') title
2.2.1 Applying Quality Masks to EMIT Data
The EMIT L2A Mask file contains some bands that are direct masks (Cloud, Dilated, Cirrus, Water, Spacecraft), and some (AOD550 and H2O (g cm-2)) that contain information calculated during the L2A reflectance retrieval. These may be used as additional screening, depending on the application. The Aggregate Flag is the mask used during EMIT L2B Mineralogy calculations, which we will also use here, but not all users might want this particular mask.
Note: It is more memory efficient to apply the mask before orthorectifying.
= emit_xarray(emit_qa_fp, ortho=True)
emit_mask emit_mask
List the quality flags contained in the mask_bands
dimension.
emit_mask.mask_bands.data.tolist()
As mentioned, we will use the Aggregate Flag
. Select that band with the sel
function as we did for wavelengths before.
= emit_mask.sel(mask_bands='Aggregate Flag') emit_cloud_mask
Like we did with the reflectance data, set the data with a fill value (-9999) equal to np.nan
to improve the visualization.
== -9999] = np.nan emit_cloud_mask.mask.data[emit_cloud_mask.mask.data
Now we can visualize our aggregate quality mask. You may have noticed before that we added a lot of parameters to our plotting function. If we want to consistently apply the same formatting for multiple plots, we can add those arguments to a dictionary that we can unpack into hvplot
functions using **
.
Create two dictionaries with plotting options.
= dict(frame_height=405, frame_width=720, fontscale=2)
size_opts = dict(geo=True, crs='EPSG:4326', alpha=0.7, xlabel='Longitude',ylabel='Latitude') map_opts
='viridis', tiles='ESRI', **size_opts, **map_opts) emit_cloud_mask.hvplot.image(cmap
Values of 1 in the mask indicate areas to omit. Apply the mask to our EMIT Data by assigning values where the mask.data == 1
to np.nan
== 1] = np.nan emit_ds.reflectance.data[emit_cloud_mask.mask.data
We can confirm our masking worked with a spatial plot.
= emit_ds.sel(wavelengths=850, method='nearest').hvplot.image(cmap='viridis',tiles='ESRI',**size_opts, **map_opts)
emit_layer_filtered_plot emit_layer_filtered_plot
2.2.2 Interactive Spectral Plots
Combining the Spatial and Spectral information into a single visualization can be a powerful tool for exploring and inspecting imaging spectroscopy data. Using the streams module from Holoviews we can link a spatial map to a plot of spectra.
We could plot a single band image as we previously have, but using a multiband image, like an RGB may help infer what targets we’re examining. Build an RGB image following the steps below.
Select bands to represent red (650 nm), green (560 nm), and blue (470 nm) by finding the nearest to a wavelength chosen to represent that color.
= emit_ds.sel(wavelengths=[650, 560, 470], method='nearest') emit_rgb
We may need to adjust balance the brightness of the selected wavelengths to make a prettier map. This will not affect the data, just the visuals. To do this we will use the function below. We can change the bright
argument to increase or decrease the brightness of the scene as a whole. A value of 0.2 usually works pretty well.
def gamma_adjust(rgb_ds, bright=0.2, white_background=False):
= rgb_ds.reflectance.data
array = math.log(bright)/math.log(np.nanmean(array)) # Create exponent for gamma scaling - can be adjusted by changing 0.2
gamma = np.power(np.nan_to_num(array,nan=1),np.nan_to_num(gamma,nan=1)).clip(0,1) # Apply scaling and clip to 0-1 range
scaled if white_background == True:
= np.nan_to_num(scaled, nan = 1) # Assign NA's to 1 so they appear white in plots
scaled = scaled
rgb_ds.reflectance.data return rgb_ds
= gamma_adjust(emit_rgb,white_background=True) emit_rgb
Now that we have an RGB dataset, we can use that to create a spatial plot, and data selected by clicking on that ‘map’ can be inputs for a function to return values from the full dataset at that latitude and longitude location using the cell below. To visualize the spectral and spatial data side-by-side, we use the Point Draw tool from the holoviews library.
Define a limit to the quantity of points and spectra we will plot, a list of colors to cycle through, and an initial point. Then use the input from the Tap function to provide clicked x and y positions on the map and use these to retrieve spectra from the dataset at those coordinates.
Click in the RGB image to add spectra to the plot. You can also click and hold the mouse button then drag previously place points. To remove a point click and hold the mouse button down, then press the backspace key.
# Interactive Points Plotting
# Modified from https://github.com/auspatious/hyperspectral-notebooks/blob/main/03_EMIT_Interactive_Points.ipynb
= 10
POINT_LIMIT = hv.Cycle('Category20')
color_cycle
# Create RGB Map
map = emit_rgb.hvplot.rgb(fontscale=1.5, xlabel='Longitude',ylabel='Latitude',frame_width=480, frame_height=480)
# Set up a holoviews points array to enable plotting of the clicked points
= emit_ds.longitude.values[int(len(emit_ds.longitude) / 2)]
xmid = emit_ds.latitude.values[int(len(emit_ds.latitude) / 2)]
ymid
= ([xmid], [ymid], [0])
first_point = hv.Points(first_point, vdims='id')
points = hv.streams.PointDraw(
points_stream =points.columns(),
data=points,
source=True,
drag=POINT_LIMIT,
num_objects={'fill_color': color_cycle.values[1:POINT_LIMIT+1], 'line_color': 'gray'}
styles
)
= hv.streams.PointerXY(source=map, x=xmid, y=ymid)
posxy = hv.streams.Tap(source=map, x=xmid, y=ymid)
clickxy
# Function to build spectral plot of clicked location to show on hover stream plot
def click_spectra(data):
= []
coordinates if data is None or not any(len(d) for d in data.values()):
0][0], clicked_points[1][0])
coordinates.append(clicked_points[else:
= [c for c in zip(data['x'], data['y'])]
coordinates
= []
plots for i, coords in enumerate(coordinates):
= coords
x, y = emit_ds.sel(longitude=x, latitude=y, method="nearest")
data
plots.append(
data.hvplot.line(="reflectance",
y="wavelengths",
x=color_cycle,
color=f"{i}"
label
)
)"id"][i] = i
points_stream.data[return hv.Overlay(plots)
def hover_spectra(x,y):
return emit_ds.sel(longitude=x,latitude=y,method='nearest').hvplot.line(y='reflectance',x='wavelengths',
='black', frame_width=400)
color# Define the Dynamic Maps
= hv.DynamicMap(click_spectra, streams=[points_stream])
click_dmap = hv.DynamicMap(hover_spectra, streams=[posxy])
hover_dmap # Plot the Map and Dynamic Map side by side
*click_dmap + map * points).cols(2).opts(
hv.Layout(hover_dmap=['point_draw'], size=10, tools=['hover'], color='white', line_color='gray'),
hv.opts.Points(active_tools=False, show_title=False, fontscale=1.5, frame_height=480)
hv.opts.Overlay(show_legend )
We can take these selected points and the corresponding reflectance spectra and save them as a .csv
for later use.
Select 10 points by adding to the figure above. We will save these and use them in a to calculate Equivalent Water Thickness or Canopy water content in the next notebook.
Build a dictionary of the selected points and spectra, then export the spectra to a .csv file.
= points_stream.data
data = emit_ds.wavelengths.values
wavelengths
= [["id", "x", "y"] + [str(i) for i in wavelengths]]
rows
for p in zip(data['x'], data['y'], data['id']):
= p
x, y, i = emit_ds.sel(longitude=x, latitude=y, method="nearest").reflectance.values
spectra = [i, x, y] + list(spectra)
row rows.append(row)
We’ve preselected 10 points, but feel free to uncomment the cell below to use your own. This will overwrite the file containing the preselected points.
# with open('../data/emit_click_data.csv', 'w', newline='') as f:
# writer = csv.writer(f)
# writer.writerows(rows)
2.2.3 Cropping EMIT data to a Region of Interest
To crop our dataset to our ROI we first need to open a shapefile of the region. Open the included geojson
for Sedgwick Reserve and Plot it onto our EMIT 850nm reflectance spatial plot. To ensure the plotting of the shape and EMIT scene works, be sure to specify the CRS (this is done for the image in the map_opts
dictionary).
= gp.read_file("../data/dangermond_boundary.geojson")
shape shape
=850, method='nearest').hvplot.image(cmap='viridis',**size_opts,**map_opts,tiles='ESRI')*shape.hvplot(color='#d95f02',alpha=0.5, crs='EPSG:4326') emit_ds.sel(wavelengths
Now use the clip
function from rasterio
to crop the data to our ROI using our shape’s geometry
and crs
. The all_touched=True
argument will ensure all pixels touched by our polygon will be included.
= emit_ds.rio.clip(shape.geometry.values,shape.crs, all_touched=True) emit_cropped
Plot the cropped data.
=850,method='nearest').hvplot.image(cmap='viridis', tiles='ESRI', **size_opts, **map_opts) emit_cropped.sel(wavelengths
2.2.4 Write an output
Lastly for our EMIT dataset, we can write a smaller output that we can use in later notebooks, to calculate Canopy water content or other applications. We use the granule_id
from the dataset to keep a similar naming convention.
# Write Clipped Output
f'../data/{emit_cropped.granule_id}_dangermond.nc') emit_cropped.to_netcdf(
2.3. Working with ECOSTRESS L2T Land Surface Temperature and Emissivity
For this example we’re taking a look at the ECOSTRESS Level 2 Tiled Land Surface Temperature (ECO_L2T_LSTE) and Level 3 Tiled Evapotranspiration (ECO_L3T_JET) products. The Land Surface Temperature and Emissivity values are derived from five thermal infrared (TIR) bands using a physics-based Temperature and Emissivity Separation (TES) algorithm. The Level 3 Tiled Evapotranspiration product is estimated from a combination of Level 2 Tiled Land Surface Temperature products and other auxillary inputs. These tiled data products use 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.
The ECOSTRESS L3T Tiled Evapotranspiration (ECO_L3T_JET) product is now being delivered to the LP DAAC. Right now these are only being forward processed from around October 2023, but historical processing to cover dates will start within the next year. Since the time range used for this workshop isn’t available we have added a non-concurrent scene from our region of interest to the required_granules.txt
to showcase the ET dataset.
2.3.1 Streaming ECOSTRESS Tiled Data
To stream the ECOSTRESS data, which is formatted as a cloud-optimized geotiff (COG) we will use a different approach than for EMIT. We can use the rioxarray
library, which is built on GDAL to access the data, just using a URL as the filepath, but first we need to set some GDAL configuration options to make sure that our authentication credentials are being passed properly to NASA Earthdata.
Set the necessary GDAL configuration options.
# GDAL configurations used to successfully access LP DAAC Cloud Assets via vsicurl
'GDAL_HTTP_COOKIEFILE','~/cookies.txt')
gdal.SetConfigOption('GDAL_HTTP_COOKIEJAR', '~/cookies.txt')
gdal.SetConfigOption('GDAL_DISABLE_READDIR_ON_OPEN','EMPTY_DIR')
gdal.SetConfigOption('CPL_VSIL_CURL_ALLOWED_EXTENSIONS','TIF')
gdal.SetConfigOption('GDAL_HTTP_UNSAFESSL', 'YES') gdal.SetConfigOption(
Open the LSTE and ET files using open_rasterio
from the rioxarray
library. Since the files consist of only 1 layer, we can squeeze
it, removing the band
dimension.
= rxr.open_rasterio(urls[0]).squeeze('band', drop=True)
eco_lst_ds eco_lst_ds
# ECO ET Tile is URL 4
= rxr.open_rasterio(urls[4]).squeeze('band', drop=True)
eco_et_ds eco_et_ds
As mentioned the ECOSTRESS product we are using here is tiled and the coordinate reference system (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 the dataset first, and be sure to specify the CRS argument within the hvplot.image
function so the ESRI imagery RBG background tile aligns with our scene.
'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') eco_lst_ds.rio.reproject(
For the ET data, we can plot the data in the same way, and even generate a color map to better visualize the data.
Create a gradient color map for the ET data.
# Generating ECOSTRESS ET color ramp
= [
ET_colors "#f6e8c3",
"#d8b365",
"#99974a",
"#53792d",
"#6bdfd2",
"#1839c5"
]def interpolate_hex(hex1, hex2, ratio):
= [int(hex1[i:i+2], 16) for i in (1, 3, 5)]
rgb1 = [int(hex2[i:i+2], 16) for i in (1, 3, 5)]
rgb2 = [int(rgb1[i] + (rgb2[i] - rgb1[i]) * ratio) for i in range(3)]
rgb
return '#{:02x}{:02x}{:02x}'.format(*rgb)
= []
ET_gradient
for i in range(len(ET_colors) - 1):
for j in range(100):
= j / float(100)
ratio +1], ratio))
ET_gradient.append(interpolate_hex(ET_colors[i], ET_colors[i
-1]) ET_gradient.append(ET_colors[
Visualize the ET data using the color map (remember this is a different scene, so it will look slightly different).
'EPSG:4326').hvplot.image(x='x',y='y',**size_opts, clim = (eco_et_ds.quantile(0.02),eco_et_ds.quantile(0.98)), cmap=ET_gradient, tiles='ESRI', xlabel='Longitude',ylabel='Latitude',title='ECOSTRESS ET (mm/day)', crs='EPSG:4326') eco_et_ds.rio.reproject(
2.3.1 Reprojecting and Regridding ECOSTRESS Data
We will need to reproject manually to pair this scene with the EMIT data, but we will not need to mask ECOSTRESS, because cloud masking has already been done for the tiled LSTE product.
To give a reasonable 1:1 comparison, in addition to reprojecting we want the data on the same grid, so each pixel from the ECOSTRESS scene corresponds to a pixel in the EMIT scene. To do this, we can use the reproject_match
function from the rioxarray
library. This will reproject and regrid our ECOSTRESS data to match the EMIT CRS and grid using the spatial_ref
variable from each dataset. Since we’ve already cropped the EMIT scene, this will limit our ECOSTRESS scene to the extent of that cropped EMIT scene as well.
= eco_lst_ds.rio.reproject_match(emit_cropped)
eco_lst_ds_regrid = eco_et_ds.rio.reproject_match(emit_cropped) eco_et_ds_regrid
We can now visualize our reprojected, regridded ECOSTRESS LST and ET scenes.
=True, tiles='ESRI',cmap='inferno',**size_opts, xlabel='Longitude',ylabel='Latitude',title='Regridded ECOSTRESS LST (K)', crs='EPSG:4326') eco_lst_ds_regrid.hvplot.image(geo
=True, tiles='ESRI',cmap=ET_gradient,**size_opts, clim=(eco_et_ds_regrid.quantile(0.02), eco_et_ds_regrid.quantile(0.98)), xlabel='Longitude',ylabel='Latitude',title='Regridded ECOSTRESS ET (mm/day)', crs='EPSG:4326') eco_et_ds_regrid.hvplot.image(geo
2.3.2 Cropping ECOSTRESS Data
This has been cropped to the extent, but we can further mask data outside of our region of interest by using the clip
function like we did for EMIT data.
= eco_lst_ds_regrid.rio.clip(shape.geometry.values,shape.crs, all_touched=True)
eco_dangermond = eco_et_ds_regrid.rio.clip(shape.geometry.values,shape.crs, all_touched=True) eco_et_dangermond
=True,cmap='inferno',**size_opts, tiles='ESRI',alpha=0.7, title='Cropped ECOSTRESS LST (K)', xlabel='Longitude',ylabel='Latitude', crs='EPSG:4326') eco_dangermond.hvplot.image(geo
=True,cmap=ET_gradient,**size_opts, clim=(eco_et_dangermond.quantile(0.02), eco_et_dangermond.quantile(0.98)), tiles='ESRI',alpha=0.7, title='Cropped ECOSTRESS ET (mm/day)', xlabel='Longitude',ylabel='Latitude', crs='EPSG:4326') eco_et_dangermond.hvplot.image(geo
2.3.3 Writing Outputs
We now have a subset ECOSTRESS scene that is aligned with EMIT data that we can export for our use in later notebooks.
Save the ECOSTRESS LSTE scene.
# Uncomment to overwrite included sample
# eco_outname = f"../data/{eco_fp.split('/')[-1].split('.')[0]}_dangermond.tif"
# eco_dangermond.rio.to_raster(raster_path=eco_outname, driver='COG')
# eco_et_outname = f"../data/{eco_et_fp.split('/')[-1].split('.')[0]}_et_dangermond.tif"
# eco_et_dangermond.rio.to_raster(raster_path=eco_et_outname, driver='COG')
Contact Info:
Email: LPDAAC@usgs.gov
Voice: +1-866-573-3222
Organization: Land Processes Distributed Active Archive Center (LP DAAC)¹
Website: https://lpdaac.usgs.gov/
Date last modified: 05-20-2024
¹Work performed under USGS contract 140G0121D0001 for NASA contract NNG14HH33I.