import geopandas
import json
import shapely
import shapely.geometry
from shapely.ops import transform
from shapely.geometry import Point
from shapely.geometry import Polygon
import geoviews as gv
from pystac_client import Client
import xarray
import rasterio as rio
import rioxarray
import os
'bokeh', 'matplotlib') gv.extension(
Create buffer around point location
= -84.0106
lon = 10.432
lat buffer = 0.001 # decimal degrees equal to ~222 meters
= Point(lon, lat).buffer(buffer) loc
type(loc)
shapely.geometry.polygon.Polygon
= gv.tile_sources.EsriImagery.opts(width=650, height=500)
base = gv.Polygons(loc).opts(line_color='yellow', line_width=10, color=None)
sample_loc * sample_loc base
Translate the shapely polygon to a GeoJSON Polygon Object, which is what the STAC API expects.
= json.loads(geopandas.GeoSeries([loc]).to_json())
roi roi
{'type': 'FeatureCollection',
'features': [{'id': '0',
'type': 'Feature',
'properties': {},
'geometry': {'type': 'Polygon',
'coordinates': [[[-84.00959999999999, 10.432],
[-84.00960481527332, 10.43190198285967],
[-84.00961921471959, 10.431804909677984],
[-84.00964305966427, 10.431709715322746],
[-84.00967612046749, 10.431617316567635],
[-84.00971807873565, 10.431528603263175],
[-84.00976853038769, 10.43144442976698],
[-84.00982698954664, 10.431365606715836],
[-84.0098928932188, 10.431292893218814],
[-84.00996560671584, 10.431226989546637],
[-84.01004442976698, 10.431168530387698],
[-84.01012860326317, 10.431118078735652],
[-84.01021731656763, 10.43107612046749],
[-84.01030971532275, 10.431043059664269],
[-84.01040490967799, 10.431019214719598],
[-84.01050198285967, 10.431004815273328],
[-84.0106, 10.431000000000001],
[-84.01069801714033, 10.431004815273328],
[-84.010795090322, 10.431019214719598],
[-84.01089028467725, 10.431043059664269],
[-84.01098268343236, 10.43107612046749],
[-84.01107139673682, 10.431118078735652],
[-84.01115557023302, 10.431168530387698],
[-84.01123439328416, 10.431226989546637],
[-84.01130710678119, 10.431292893218814],
[-84.01137301045335, 10.431365606715836],
[-84.0114314696123, 10.43144442976698],
[-84.01148192126435, 10.431528603263175],
[-84.0115238795325, 10.431617316567635],
[-84.01155694033572, 10.431709715322746],
[-84.0115807852804, 10.431804909677984],
[-84.01159518472667, 10.43190198285967],
[-84.0116, 10.432],
[-84.01159518472667, 10.43209801714033],
[-84.0115807852804, 10.432195090322017],
[-84.01155694033572, 10.432290284677254],
[-84.0115238795325, 10.432382683432365],
[-84.01148192126435, 10.432471396736826],
[-84.0114314696123, 10.43255557023302],
[-84.01137301045335, 10.432634393284165],
[-84.01130710678119, 10.432707106781187],
[-84.01123439328416, 10.432773010453364],
[-84.01115557023302, 10.432831469612303],
[-84.01107139673682, 10.432881921264348],
[-84.01098268343236, 10.432923879532511],
[-84.01089028467725, 10.432956940335732],
[-84.010795090322, 10.432980785280403],
[-84.01069801714033, 10.432995184726673],
[-84.0106, 10.433],
[-84.01050198285967, 10.432995184726673],
[-84.01040490967799, 10.432980785280403],
[-84.01030971532275, 10.432956940335732],
[-84.01021731656763, 10.432923879532511],
[-84.01012860326317, 10.432881921264348],
[-84.01004442976698, 10.432831469612303],
[-84.00996560671584, 10.432773010453364],
[-84.0098928932188, 10.432707106781187],
[-84.00982698954664, 10.432634393284165],
[-84.00976853038769, 10.43255557023302],
[-84.00971807873565, 10.432471396736826],
[-84.00967612046749, 10.432382683432365],
[-84.00964305966427, 10.432290284677254],
[-84.00961921471959, 10.432195090322017],
[-84.00960481527332, 10.43209801714033],
[-84.00959999999999, 10.432]]]},
'bbox': [-84.0116, 10.431000000000001, -84.00959999999999, 10.433]}],
'bbox': [-84.0116, 10.431000000000001, -84.00959999999999, 10.433]}
GeoJSON Polygon Object vertices are expected to be in counterclockwise order. The current object vertices are in clockwise order. Below we reverse the order of the vertices and assign them back to our roi
object.
'features'][0]['geometry']['coordinates'][0] = roi['features'][0]['geometry']['coordinates'][0][::-1] roi[
Find data using the STAC API
Specify the STAC API endpoint
= 'https://cmr.earthdata.nasa.gov/stac' STAC_URL
Connect to the LPCLOUD catalog using PySTAC Client
= Client.open(f'{STAC_URL}/LPCLOUD/') catalog
Submit a query for: - HLSL30 and HLSS30 - The roi
’s geometry - Dates between 05-01-2021 and 06-30-2022
= catalog.search(
search = ['HLSL30.v2.0', 'HLSS30.v2.0'],
collections = roi['features'][0]['geometry'],
intersects = '2021-05/2022-06'
datetime )
search.matched()
87
Get all the STAC Items/granules
= search.get_all_items() items
len(items)
87
Get the first STAC Item from the list and print off the available assets
0].assets items[
{'B07': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B07.tif>,
'B01': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B01.tif>,
'B04': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B04.tif>,
'B06': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B06.tif>,
'VZA': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.VZA.tif>,
'Fmask': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.Fmask.tif>,
'B02': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B02.tif>,
'SAA': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.SAA.tif>,
'B11': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B11.tif>,
'B03': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B03.tif>,
'VAA': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.VAA.tif>,
'B10': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B10.tif>,
'B05': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B05.tif>,
'B09': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B09.tif>,
'SZA': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.SZA.tif>,
'browse': <Asset href=https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.jpg>,
'metadata': <Asset href=https://cmr.earthdata.nasa.gov/search/concepts/G2144745416-LPCLOUD.xml>}
Grab the URL for the B04
asset
= items[0].assets['B04'].href
data_url data_url
'https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/HLSL30.020/HLS.L30.T16PHS.2021133T155359.v2.0/HLS.L30.T16PHS.2021133T155359.v2.0.B04.tif'
NOTE: The above returns the HTTPS URL. For direct S3 access of cloud assets the S3 URL is need. See the following resource on how to generate the S3 URL: https://nasa-openscapes.github.io/2021-Cloud-Hackathon/tutorials/02_Data_Discovery_CMR-STAC_API.html
Read in the URL using rioxarray
NOTE: The example below show how to access the asset via HTTPS. An example for performing direct S3 access can be found here: https://nasa-openscapes.github.io/2021-Cloud-Hackathon/tutorials/05_Data_Access_Direct_S3.html
First we need to set our gdal
configs. Make sure a .netrc file has been created in your home directory
= rio.Env(GDAL_DISABLE_READDIR_ON_OPEN='EMPTY',
rio_env =os.path.expanduser('~/cookies.txt'),
GDAL_HTTP_COOKIEFILE=os.path.expanduser('~/cookies.txt'))
GDAL_HTTP_COOKIEJAR__enter__() rio_env.
<rasterio.env.Env at 0x7f846be57f70>
= rioxarray.open_rasterio(data_url) da
da
<xarray.DataArray (band: 1, y: 3660, x: 3660)> [13395600 values with dtype=int16] Coordinates: * band (band) int64 1 * x (x) float64 8e+05 8e+05 8.001e+05 ... 9.097e+05 9.098e+05 * y (y) float64 1.2e+06 1.2e+06 1.2e+06 ... 1.09e+06 1.09e+06 spatial_ref int64 0 Attributes: _FillValue: -9999.0 scale_factor: 0.0001 add_offset: 0.0 long_name: Red
Drop the ‘band’ coordinate
'band', drop=True) da.squeeze(
<xarray.DataArray (y: 3660, x: 3660)> [13395600 values with dtype=int16] Coordinates: * x (x) float64 8e+05 8e+05 8.001e+05 ... 9.097e+05 9.098e+05 * y (y) float64 1.2e+06 1.2e+06 1.2e+06 ... 1.09e+06 1.09e+06 spatial_ref int64 0 Attributes: _FillValue: -9999.0 scale_factor: 0.0001 add_offset: 0.0 long_name: Red