Skip to content

Instantly share code, notes, and snippets.

@kylebarron
Last active February 10, 2021 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kylebarron/e0ef94f8eec5a21887f4c217d0203937 to your computer and use it in GitHub Desktop.
Save kylebarron/e0ef94f8eec5a21887f4c217d0203937 to your computer and use it in GitHub Desktop.
Scratch work for creating STAC items for Sentinel-2 L2A 120m Mosaic (https://registry.opendata.aws/sentinel-s2-l2a-mosaic-120/)
{
"type": "Feature",
"stac_version": "1.0.0-beta.2",
"id": "sentinel-2-l2a-mosaic-120-2019-12-7-01K",
"properties": {
"start_datetime": "2019-12-07T00:00:00",
"end_datetime": "2019-12-17T00:00:00",
"platform": "sentinel-2",
"gsd": 120,
"datetime": null
},
"geometry": null,
"links": [],
"assets": {
"B02": {
"href": "s3://sentinel-s2-l2a-mosaic-120/2019/12/7/01K/B02.TIF",
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"title": "B02",
"eo:bands": [
{
"name": "B02",
"common_name": "blue",
"center_wavelength": 0.4966,
"full_width_half_max": 0.098
}
]
},
"B03": {
"href": "s3://sentinel-s2-l2a-mosaic-120/2019/12/7/01K/B03.TIF",
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"title": "B03",
"eo:bands": [
{
"name": "B03",
"common_name": "green",
"center_wavelength": 0.56,
"full_width_half_max": 0.045
}
]
},
"B04": {
"href": "s3://sentinel-s2-l2a-mosaic-120/2019/12/7/01K/B04.TIF",
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"title": "B04",
"eo:bands": [
{
"name": "B04",
"common_name": "red",
"center_wavelength": 0.6645,
"full_width_half_max": 0.038
}
]
},
"B08": {
"href": "s3://sentinel-s2-l2a-mosaic-120/2019/12/7/01K/B08.TIF",
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"title": "B08",
"eo:bands": [
{
"name": "B08",
"common_name": "nir",
"center_wavelength": 0.8351,
"full_width_half_max": 0.145
}
]
},
"B11": {
"href": "s3://sentinel-s2-l2a-mosaic-120/2019/12/7/01K/B11.TIF",
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"title": "B11",
"eo:bands": [
{
"name": "B11",
"common_name": "swir16",
"center_wavelength": 1.6137,
"full_width_half_max": 0.143
}
]
},
"B12": {
"href": "s3://sentinel-s2-l2a-mosaic-120/2019/12/7/01K/B12.TIF",
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"title": "B12",
"eo:bands": [
{
"name": "B12",
"common_name": "swir22",
"center_wavelength": 2.22024,
"full_width_half_max": 0.242
}
]
}
},
"stac_extensions": [
"eo"
],
"collection": "sentinel-2-l2a-mosaic-120"
}
from datetime import datetime, timedelta
import boto3
from pystac import Asset, Extensions, Item, MediaType
from pystac.extensions.eo import Band
s3 = boto3.client('s3')
BUCKET = 'sentinel-s2-l2a-mosaic-120'
BANDS = [{
"name": "B02",
"common_name": "blue",
"center_wavelength": 0.4966,
"full_width_half_max": 0.098
}, {
"name": "B03",
"common_name": "green",
"center_wavelength": 0.56,
"full_width_half_max": 0.045
}, {
"name": "B04",
"common_name": "red",
"center_wavelength": 0.6645,
"full_width_half_max": 0.038
}, {
"name": "B08",
"common_name": "nir",
"center_wavelength": 0.8351,
"full_width_half_max": 0.145
}, {
"name": "B11",
"common_name": "swir16",
"center_wavelength": 1.6137,
"full_width_half_max": 0.143
}, {
"name": "B12",
"common_name": "swir22",
"center_wavelength": 2.22024,
"full_width_half_max": 0.242
}]
def main():
date_prefixes = list(get_date_prefixes())
tiles = list(get_tiles(date_prefixes[0]))
for date_prefix in date_prefixes:
for tile in tiles:
# date_prefix and tile have an extra ending /
# e.g. '2019/12/7/' and '01K/'
construct_stac(date_prefix.rstrip('/'), tile.rstrip('/'))
def construct_stac(date_prefix, tile):
year, month, day = date_prefix.split('/')
year, month, day = int(year), int(month), int(day)
properties = get_properties(year, month, day)
geometry = get_geometry(tile)
bbox = get_bbox(geometry)
collection_id = 'sentinel-2-l2a-mosaic-120'
item_id = f'{collection_id}-{year}-{month}-{day}-{tile}'
item = Item(id=item_id,
geometry=geometry,
bbox=bbox,
datetime=None,
properties=properties,
collection=collection_id,
stac_extensions=[Extensions.EO])
for band_info in BANDS:
asset = create_asset(date_prefix, tile, band_info)
item.add_asset(asset.title, asset)
eo_band = Band.create(**band_info)
item.ext.eo.set_bands([eo_band], asset)
return item
def get_properties(year, month, day):
start_datetime = datetime(year, month, day)
end_datetime = start_datetime + timedelta(days=10)
return {
'start_datetime': start_datetime,
'end_datetime': end_datetime,
'platform': 'sentinel-2',
'gsd': 120,
}
def create_asset(date_prefix, tile, band_info):
band_name = band_info['name']
href = f's3://{BUCKET}/{date_prefix}/{tile}/{band_name}.TIF'
return Asset(href=href, title=band_name, media_type=MediaType.COG)
def get_geometry(tile):
# TODO: load tile geometry from shapefile
return None
def get_bbox(geometry):
# TODO: get bounding box from geometry
return None
def get_date_prefixes():
for year in [2019]:
for month in range(1, 13):
prefix = f'{year}/{month}/'
resp = s3.list_objects_v2(Bucket=BUCKET,
Delimiter='/',
Prefix=prefix)
for common_prefix in resp['CommonPrefixes']:
yield common_prefix['Prefix']
def get_tiles(prefix):
# Note this assumes all tiles exist for all dates
resp = s3.list_objects_v2(Bucket=BUCKET, Delimiter='/', Prefix=prefix)
for common_prefix in resp['CommonPrefixes']:
yield common_prefix['Prefix'][len(prefix):]
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment