Sentinel Level 2 search and download in SAFE format

I have a simple use case where I do a geometry based search, and I want to download all the resulting Level 2 products in the SAFE format:

geometry = Geometry('POLYGON((9.26923 0.57138,9.28358 0.56777,9.28358 0.54613,9.24769 0.54613,9.25128 0.56777,9.26564 0.56777,9.26923 0.57138))', CRS.WGS84)
search_bbox = gabon_geometry.bbox
search_time_interval = ("2020-02-20T00:00:00", "2020-04-20T23:59:59")
config = SHConfig()
config.instance_id = 'my_sentinel_hub_instance_id'
wfs_iterator = WebFeatureService(search_bbox, search_time_interval, data_source=DataSource.SENTINEL2_L2A, maxcc=0.5, config=config)

for tile_info in wfs_iterator:

This gets me one entry:
{'id': 'S2B_OPER_MSI_L2A_TL_MPS__20200322T121116_A015892_T32NNF_N02.14', 'date': '2020-03-22', 'time': '09:50:38', 'path': 's3://sentinel-s2-l2a/tiles/32/N/NF/2020/3/22/0', 'crs': 'EPSG:32632', 'mbr': '499980,-9780 609780,100020', 'cloudCoverPercentage': 26.59}

I then take that tile id, and try to get the download part in place:
tile_id = ‘S2B_OPER_MSI_L2A_TL_MPS__20200322T121116_A015892_T32NNF_N02.14’
tile_name, time, aws_index = AwsTile.tile_id_to_tile(tile_id)

Last line fails with TileMissingException

Is there a workaround to this - my use case is simple - search Level 2 products, and then download them in the SAFE format.

I’ve been looking at the actual code a bit, and it looks like AwsTile makes a call to opensearch to do that translation. Based on an answer here, looks like opensearch only works with level 1 data.

So now I am very confused - one can use WebFeatureService to search Level2 data, but you get back tile ids, and there is no way to translate that tile id to a tile name, so that you can then download the bundle?

If this is the case, perhaps the docs should be updated to reflect that everything there applies only for Level1 data.

A workaround could to be to use WebFeatureService to search Level2 data, get the tile metadata, look up the tile s3 path (eg. ‘s3://sentinel-s2-l2a/tiles/32/N/NF/2020/3/22/0’), open productInfo.json from there, and read the name property which is the actual sentinel product id. With that, one can download the product. It feels cumbersome though - is there any better alternative to this?


1 Like

I think your workaround is the way to go. It might ba a bit cumnbersome but nothing that a few lines of code would not fix it.

When designing sentinelhub-py the S2 L2A data were irrelevant (very few of them) so we did not focus to that. Since then things changed, obviously.

In terms of updating the documentation, you are kindly invited to do a pull request to improve these. sentinelhub-py is an open-source project so contributions by community are more than welcome.