Last active
February 10, 2021 06:49
-
-
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/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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