Access Sentinel 2 Data from AWS¶
https://registry.opendata.aws/sentinel-2-l2a-cogs/
[1]:
import odc.ui
import yaml
from IPython.display import display
from odc.algo import to_rgba
from pystac_client import Client
from odc.stac import stac2ds, stac_load
[2]:
cfg = """---
"*":
warnings: ignore # Disable warnings about duplicate common names
sentinel-s2-l2a-cogs:
assets:
'*':
data_type: uint16
nodata: 0
unit: '1'
SCL:
data_type: uint8
nodata: 0
unit: '1'
visual:
data_type: uint8
nodata: 0
unit: '1'
aliases: # Alias -> Canonical Name
red: B04
green: B03
blue: B02
"""
cfg = yaml.load(cfg, Loader=yaml.SafeLoader)
catalog = Client.open("https://earth-search.aws.element84.com/v0")
Find STAC Items to Load¶
[3]:
km2deg = 1.0 / 111
x, y = (113.887, -25.843) # Center point of a query
r = 100 * km2deg
query = catalog.search(
collections=["sentinel-s2-l2a-cogs"],
datetime="2021-09-16",
limit=10,
bbox=(x - r, y - r, x + r, y + r),
)
items = list(query.get_items())
print(f"Found: {len(items):d} datasets")
Found: 9 datasets
Construct Dask Dataset¶
Note that even though there are 9 STAC Items on input, there is only one timeslice on output. This is because of groupy="solar_day"
. With that setting stac_load
will place all items that occured on the same day (as adjusted for the timezone) into one image plane.
[4]:
# Since we will plot it on a map we need to use `EPSG:3857` projection
crs = "epsg:3857"
zoom = 2 ** 5 # overview level 5
xx = stac_load(
items,
bands=("red", "green", "blue"),
crs=crs,
resolution=10 * zoom,
chunks={}, # <-- use Dask
groupby="solar_day",
stac_cfg=cfg,
)
display(xx)
<xarray.Dataset> Dimensions: (time: 1, y: 1098, x: 833) Coordinates: * time (time) datetime64[ns] 2021-09-16T02:34:44 * y (y) float64 -2.797e+06 -2.798e+06 ... -3.148e+06 -3.148e+06 * x (x) float64 1.255e+07 1.255e+07 ... 1.282e+07 1.282e+07 spatial_ref int32 3857 Data variables: red (time, y, x) uint16 dask.array<chunksize=(1, 1098, 833), meta=np.ndarray> green (time, y, x) uint16 dask.array<chunksize=(1, 1098, 833), meta=np.ndarray> blue (time, y, x) uint16 dask.array<chunksize=(1, 1098, 833), meta=np.ndarray> Attributes: crs: epsg:3857 grid_mapping: spatial_ref
xarray.Dataset
- time: 1
- y: 1098
- x: 833
- time(time)datetime64[ns]2021-09-16T02:34:44
- units :
- seconds since 1970-01-01 00:00:00
array(['2021-09-16T02:34:44.000000000'], dtype='datetime64[ns]')
- y(y)float64-2.797e+06 ... -3.148e+06
- units :
- metre
- resolution :
- -320.0
- crs :
- epsg:3857
array([-2797280., -2797600., -2797920., ..., -3147680., -3148000., -3148320.])
- x(x)float641.255e+07 1.255e+07 ... 1.282e+07
- units :
- metre
- resolution :
- 320.0
- crs :
- epsg:3857
array([12549280., 12549600., 12549920., ..., 12814880., 12815200., 12815520.])
- spatial_ref()int323857
- spatial_ref :
- PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"]]
- grid_mapping_name :
- ??
array(3857, dtype=int32)
- red(time, y, x)uint16dask.array<chunksize=(1, 1098, 833), meta=np.ndarray>
- nodata :
- 0
- units :
- 1
- crs :
- epsg:3857
- grid_mapping :
- spatial_ref
Array Chunk Bytes 1.74 MiB 1.74 MiB Shape (1, 1098, 833) (1, 1098, 833) Count 10 Tasks 1 Chunks Type uint16 numpy.ndarray - green(time, y, x)uint16dask.array<chunksize=(1, 1098, 833), meta=np.ndarray>
- nodata :
- 0
- units :
- 1
- crs :
- epsg:3857
- grid_mapping :
- spatial_ref
Array Chunk Bytes 1.74 MiB 1.74 MiB Shape (1, 1098, 833) (1, 1098, 833) Count 10 Tasks 1 Chunks Type uint16 numpy.ndarray - blue(time, y, x)uint16dask.array<chunksize=(1, 1098, 833), meta=np.ndarray>
- nodata :
- 0
- units :
- 1
- crs :
- epsg:3857
- grid_mapping :
- spatial_ref
Array Chunk Bytes 1.74 MiB 1.74 MiB Shape (1, 1098, 833) (1, 1098, 833) Count 10 Tasks 1 Chunks Type uint16 numpy.ndarray
- crs :
- epsg:3857
- grid_mapping :
- spatial_ref
Load data and convert to RGBA¶
[5]:
%%time
rgba = to_rgba(xx, clamp=(1, 3000))
_rgba = rgba.compute()
CPU times: user 2.43 s, sys: 1.96 s, total: 4.39 s
Wall time: 25.7 s
Display Image on a map¶
[6]:
dss = list(stac2ds(items, cfg))
_map = odc.ui.show_datasets(dss, style={"fillOpacity": 0.1}, scroll_wheel_zoom=True)
ovr = odc.ui.mk_image_overlay(_rgba)
_map.add_layer(ovr)
display(_map)