Skip to content

Commit

Permalink
Merge pull request #79 from cogeotiff/BoundsAndStripmap
Browse files Browse the repository at this point in the history
allow stripmap dataset for sentinel1
  • Loading branch information
vincentsarago committed Aug 21, 2023
2 parents e75108a + 368f149 commit d767624
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Release Notes

## 0.10.1 (2023-08-21)

* calculate scene bounds from multipolygons for Sentinel-1
* allow `Stripmap` beam mode for sentinel-1 dataset

## 0.10.0 (2023-07-25)

* update rio-tiler requirement to `>=5.0,<7.0`
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ $ pip install git+https://github.com/cogeotiff/rio-tiler-pds.git
| [Sentinel 2][s2_l1c_jp2] | L1C | JPEG2000 | Sinergise / AWS | eu-central-1 | **Requester-pays** |
| [Sentinel 2][s2_l2a_jp2] | L2A | JPEG2000 | Sinergise / AWS | eu-central-1 | **Requester-pays** |
| [Sentinel 2][s2_l2a_cog] | L2A | COG | Digital Earth Africa / AWS | us-west-2 | Public |
| [Sentinel 1][s1_l1c_cog] | L1C | COG (Internal GCPS) | Sinergise / AWS | eu-central-1 | **Requester-pays** |
| [Sentinel 1][s1_l1c_cog] | L1C GRD (IW, EW, S1-6) | COG (Internal GCPS) | Sinergise / AWS | eu-central-1 | **Requester-pays** |
| [Landsat Collection 2][landsat_c2_cog] | L1,L2 | COG | USGS / AWS | us-west-2 | **Requester-pays** |
| [CBERS 4/4A][cbers_cog] | L2/L4 | COG | AMS Kepler / AWS | us-east-1 | **Requester-pays** |
| [MODIS (modis-pds)][modis_pds] | MCD43A4, MOD09GQ, MYD09GQ, MOD09GA, MYD09GA | GTiff (External Overviews) | - | us-west-2 | Public |
Expand Down
20 changes: 18 additions & 2 deletions rio_tiler_pds/sentinel/aws/sentinel1.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""AWS Sentinel 1 reader."""

import json
from typing import Dict, Type
from typing import Dict, Tuple, Type

import attr
from morecantile import TileMatrixSet
Expand All @@ -14,6 +14,22 @@
from rio_tiler_pds.utils import fetch


def get_bounds(geom: Dict) -> Tuple[float, float, float, float]:
"""Get Bounds from GeoJSON geometry and handle multi polygon crossing the antimeridian line.
ref: https://github.com/cogeotiff/rio-tiler-pds/issues/77
"""
if geom["type"] == "MultiPolygon":
bounds = [
featureBounds({"type": "Polygon", "coordinates": poly})
for poly in geom["coordinates"]
]
minx, miny, maxx, maxy = zip(*bounds)
return (max(minx), min(miny), min(maxx), max(maxy))

return featureBounds(geom)


@attr.s
class S1L1CReader(MultiBandReader):
"""AWS Public Dataset Sentinel 1 reader.
Expand Down Expand Up @@ -73,7 +89,7 @@ def __attrs_post_init__(self):
)

self.datageom = self.productInfo["footprint"]
self.bounds = featureBounds(self.datageom)
self.bounds = get_bounds(self.datageom)
self.crs = WGS84_CRS

def _get_band_url(self, band: str) -> str:
Expand Down
4 changes: 2 additions & 2 deletions rio_tiler_pds/sentinel/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def s1_sceneid_parser(sceneid: str) -> Dict:
"""
if not re.match(
"^S1[AB]_(IW|EW)_[A-Z]{3}[FHM]_[0-9][SA][A-Z]{2}_[0-9]{8}T[0-9]{6}_[0-9]{8}T[0-9]{6}_[0-9A-Z]{6}_[0-9A-Z]{6}_[0-9A-Z]{4}$",
"^S1[AB]_(IW|EW|S[1-6])_[A-Z]{3}[FHM]_[0-9][SA][A-Z]{2}_[0-9]{8}T[0-9]{6}_[0-9]{8}T[0-9]{6}_[0-9A-Z]{6}_[0-9A-Z]{6}_[0-9A-Z]{4}$",
sceneid,
):
raise InvalidSentinelSceneId("Could not match {}".format(sceneid))
Expand All @@ -144,7 +144,7 @@ def s1_sceneid_parser(sceneid: str) -> Dict:
r"(?P<sensor>\w{1})"
r"(?P<satellite>[AB]{1})"
r"_"
r"(?P<beam>[A-Z]{2})"
r"(?P<beam>(IW)|(EW)|(S[1-6]))"
r"_"
r"(?P<product>[A-Z]{3})"
r"(?P<resolution>[FHM])"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"id" : "S1A_IW_GRDH_1SDV_20230726T183302_20230726T183327_049598_05F6CA_31E7",
"path" : "GRD/2023/7/26/IW/DV/S1A_IW_GRDH_1SDV_20230726T183302_20230726T183327_049598_05F6CA_31E7",
"missionId" : "S1A",
"productType" : "GRD",
"resolution" : "H",
"mode" : "IW",
"polarization" : "DV",
"startTime" : "2023-07-26T18:33:02",
"stopTime" : "2023-07-26T18:33:27",
"absoluteOrbitNumber" : 49598,
"missionDataTakeId" : 390858,
"productUniqueIdentifier" : "31E7",
"sciHubIngestion" : "2023-07-26T20:28:27.549Z",
"s3Ingestion" : "2023-07-26T22:35:57.571Z",
"sciHubId" : "ed042e78-376d-4614-a73e-83f79ea463b6",
"footprint" : {
"type" : "MultiPolygon",
"coordinates" : [ [ [ [ 180.0, 62.52138872791733 ], [ 179.94979152463551, 62.52658106629492 ], [ 179.46990657679865, 62.57485506167223 ], [ 178.9813798181196, 62.6221501683127 ], [ 178.738681118481, 62.644959850172626 ], [ 178.25266997765007, 62.689273025316226 ], [ 177.77391401557458, 62.73116163376606 ], [ 177.53029365830048, 62.751804324749735 ], [ 177.04869673747694, 62.791293247459784 ], [ 176.5508378718863, 62.83026664501019 ], [ 176.3037281203709, 62.848922159103715 ], [ 175.84591004046774, 62.88226850489882 ], [ 175.7832968544936, 62.70374482277905 ], [ 175.72211102575443, 62.52504447786457 ], [ 175.66527915232953, 62.34605015536937 ], [ 175.6053588236643, 62.16729040474062 ], [ 175.54817449400198, 61.98834960555291 ], [ 175.48844521186035, 61.80960524230824 ], [ 175.38292995222957, 61.49054362053522 ], [ 175.82589036146206, 61.4571792745189 ], [ 176.05957913992813, 61.43895767761053 ], [ 176.52612531192008, 61.40131515991415 ], [ 176.9915270239868, 61.362078698156 ], [ 177.22378541508246, 61.341864763256126 ], [ 177.68739115241843, 61.300249793064 ], [ 178.14974778134427, 61.257057591701475 ], [ 178.38044504519894, 61.2348723445106 ], [ 178.84085245503275, 61.1893278399659 ], [ 179.29991114903933, 61.14222431125801 ], [ 179.52892267707472, 61.11809024266489 ], [ 179.97829453382462, 61.06949078480844 ], [ 180.0, 61.115074335603865 ], [ 180.0, 62.52138872791733 ] ] ], [ [ [ -180.0, 62.52138872791733 ], [ -180.0, 61.115074335603865 ], [ -179.95528668344312, 61.208976568342585 ], [ -179.86990854106338, 61.386675758949224 ], [ -179.78377141580856, 61.564335906363944 ], [ -179.69686099291556, 61.7419564176713 ], [ -179.60916260861518, 61.91953667731231 ], [ -179.52066123106215, 62.09707606329313 ], [ -179.43134387930303, 62.27457416563086 ], [ -179.34123633603335, 62.451941133348306 ], [ -179.81084543337622, 62.50182719954094 ], [ -180.0, 62.52138872791733 ] ] ] ]
},
"filenameMap" : {
"support/s1-level-1-calibration.xsd" : "support/s1-level-1-calibration.xsd",
"annotation/s1a-iw-grd-vh-20230726t183302-20230726t183327-049598-05f6ca-002.xml" : "annotation/iw-vh.xml",
"S1A_IW_GRDH_1SDV_20230726T183302_20230726T183327_049598_05F6CA_31E7.SAFE-report-20230726T202509.pdf" : "report-20230726T202509.pdf",
"support/s1-product-preview.xsd" : "support/s1-product-preview.xsd",
"measurement/s1a-iw-grd-vv-20230726t183302-20230726t183327-049598-05f6ca-001.tiff" : "measurement/iw-vv.tiff",
"annotation/s1a-iw-grd-vv-20230726t183302-20230726t183327-049598-05f6ca-001.xml" : "annotation/iw-vv.xml",
"support/s1-level-1-noise.xsd" : "support/s1-level-1-noise.xsd",
"preview/quick-look.png" : "preview/quick-look.png",
"manifest.safe" : "manifest.safe",
"preview/icons/logo.png" : "preview/icons/logo.png",
"annotation/calibration/noise-s1a-iw-grd-vv-20230726t183302-20230726t183327-049598-05f6ca-001.xml" : "annotation/calibration/noise-iw-vv.xml",
"support/s1-map-overlay.xsd" : "support/s1-map-overlay.xsd",
"annotation/calibration/noise-s1a-iw-grd-vh-20230726t183302-20230726t183327-049598-05f6ca-002.xml" : "annotation/calibration/noise-iw-vh.xml",
"preview/map-overlay.kml" : "preview/map-overlay.kml",
"annotation/rfi/rfi-s1a-iw-grd-vh-20230726t183302-20230726t183327-049598-05f6ca-002.xml" : "annotation/rfi/rfi-iw-vh.xml",
"annotation/calibration/calibration-s1a-iw-grd-vv-20230726t183302-20230726t183327-049598-05f6ca-001.xml" : "annotation/calibration/calibration-iw-vv.xml",
"annotation/rfi/rfi-s1a-iw-grd-vv-20230726t183302-20230726t183327-049598-05f6ca-001.xml" : "annotation/rfi/rfi-iw-vv.xml",
"annotation/calibration/calibration-s1a-iw-grd-vh-20230726t183302-20230726t183327-049598-05f6ca-002.xml" : "annotation/calibration/calibration-iw-vh.xml",
"support/s1-object-types.xsd" : "support/s1-object-types.xsd",
"support/s1-level-1-quicklook.xsd" : "support/s1-level-1-quicklook.xsd",
"preview/product-preview.html" : "preview/product-preview.html",
"support/s1-level-1-rfi.xsd" : "support/s1-level-1-rfi.xsd",
"support/s1-level-1-measurement.xsd" : "support/s1-level-1-measurement.xsd",
"support/s1-level-1-product.xsd" : "support/s1-level-1-product.xsd",
"measurement/s1a-iw-grd-vh-20230726t183302-20230726t183327-049598-05f6ca-002.tiff" : "measurement/iw-vh.tiff"
},
"version" : 3
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"id" : "S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175",
"path" : "GRD/2023/8/9/S1/DV/S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175",
"missionId" : "S1A",
"productType" : "GRD",
"resolution" : "H",
"mode" : "S1",
"polarization" : "DV",
"startTime" : "2023-08-09T02:07:29",
"stopTime" : "2023-08-09T02:07:54",
"absoluteOrbitNumber" : 49792,
"missionDataTakeId" : 392422,
"productUniqueIdentifier" : "1175",
"sciHubIngestion" : "2023-08-09T08:16:36.948Z",
"s3Ingestion" : "2023-08-09T10:24:15.088Z",
"sciHubId" : "10e1fa60-fa51-4e9f-b56e-608608bfa60c",
"footprint" : {
"type" : "MultiPolygon",
"coordinates" : [ [ [ [ 55.858765023967315, -4.022203076791528 ], [ 55.15269410781527, -3.8687201770035715 ], [ 54.84048193722755, -5.343071773846793 ], [ 55.54787619756915, -5.497421358669248 ], [ 55.858765023967315, -4.022203076791528 ] ] ] ]
},
"filenameMap" : {
"support/s1-level-1-calibration.xsd" : "support/s1-level-1-calibration.xsd",
"measurement/s1a-s1-grd-vh-20230809t020729-20230809t020754-049792-05fce6-002.tiff" : "measurement/s1-vh.tiff",
"annotation/s1a-s1-grd-vh-20230809t020729-20230809t020754-049792-05fce6-002.xml" : "annotation/s1-vh.xml",
"annotation/s1a-s1-grd-vv-20230809t020729-20230809t020754-049792-05fce6-001.xml" : "annotation/s1-vv.xml",
"measurement/s1a-s1-grd-vv-20230809t020729-20230809t020754-049792-05fce6-001.tiff" : "measurement/s1-vv.tiff",
"support/s1-product-preview.xsd" : "support/s1-product-preview.xsd",
"annotation/calibration/calibration-s1a-s1-grd-vh-20230809t020729-20230809t020754-049792-05fce6-002.xml" : "annotation/calibration/calibration-s1-vh.xml",
"annotation/rfi/rfi-s1a-s1-grd-vv-20230809t020729-20230809t020754-049792-05fce6-001.xml" : "annotation/rfi/rfi-s1-vv.xml",
"annotation/calibration/calibration-s1a-s1-grd-vv-20230809t020729-20230809t020754-049792-05fce6-001.xml" : "annotation/calibration/calibration-s1-vv.xml",
"support/s1-level-1-noise.xsd" : "support/s1-level-1-noise.xsd",
"annotation/calibration/noise-s1a-s1-grd-vh-20230809t020729-20230809t020754-049792-05fce6-002.xml" : "annotation/calibration/noise-s1-vh.xml",
"preview/quick-look.png" : "preview/quick-look.png",
"manifest.safe" : "manifest.safe",
"preview/icons/logo.png" : "preview/icons/logo.png",
"support/s1-map-overlay.xsd" : "support/s1-map-overlay.xsd",
"preview/map-overlay.kml" : "preview/map-overlay.kml",
"preview/product-preview.html" : "preview/product-preview.html",
"support/s1-level-1-quicklook.xsd" : "support/s1-level-1-quicklook.xsd",
"support/s1-object-types.xsd" : "support/s1-object-types.xsd",
"support/s1-level-1-rfi.xsd" : "support/s1-level-1-rfi.xsd",
"annotation/rfi/rfi-s1a-s1-grd-vh-20230809t020729-20230809t020754-049792-05fce6-002.xml" : "annotation/rfi/rfi-s1-vh.xml",
"support/s1-level-1-measurement.xsd" : "support/s1-level-1-measurement.xsd",
"support/s1-level-1-product.xsd" : "support/s1-level-1-product.xsd",
"S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175.SAFE-report-20230809T081019.pdf" : "report-20230809T081019.pdf",
"annotation/calibration/noise-s1a-s1-grd-vv-20230809t020729-20230809t020754-049792-05fce6-001.xml" : "annotation/calibration/noise-s1-vv.xml"
},
"version" : 3
}
82 changes: 82 additions & 0 deletions tests/test_sentinel1.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,92 @@ def test_AWSPDS_S1L1CReader(rio, fetch):
"_day": "20",
},
),
(
"S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175",
{
"sensor": "1",
"satellite": "A",
"beam": "S1",
"product": "GRD",
"resolution": "H",
"processing_level": "1",
"product_class": "S",
"polarisation": "DV",
"startDateTime": "20230809T020729",
"stopDateTime": "20230809T020754",
"absolute_orbit": "049792",
"mission_task": "05FCE6",
"product_id": "1175",
"acquisitionYear": "2023",
"acquisitionMonth": "08",
"acquisitionDay": "09",
"scene": "S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175",
"date": "2023-08-09",
"_month": "8",
"_day": "9",
},
),
)


@pytest.mark.parametrize("sceneid,expected_content", SENTINEL1_SCENE_PARSER_TEST_CASES)
def test_s1_sceneid_parser(sceneid, expected_content):
"""Parse Sentinel-1 Sceneid."""
assert s1_sceneid_parser(sceneid) == expected_content


@patch("rio_tiler_pds.sentinel.aws.sentinel1.fetch")
def test_multipolygon_bounds(fetch):
"""test fetching bounds from a multi polygon."""
with open(
f"{SENTINEL_BUCKET}/GRD/2023/7/26/IW/DV/S1A_IW_GRDH_1SDV_20230726T183302_20230726T183327_049598_05F6CA_31E7/productInfo.json",
"r",
) as f:
SENTINEL_METADATA = json.loads(f.read())

fetch.return_value = SENTINEL_METADATA

with S1L1CReader(
"S1A_IW_GRDH_1SDV_20230726T183302_20230726T183327_049598_05F6CA_31E7"
) as sentinel:
assert (
sentinel.scene_params["scene"]
== "S1A_IW_GRDH_1SDV_20230726T183302_20230726T183327_049598_05F6CA_31E7"
)
assert sentinel.minzoom == 8
assert sentinel.maxzoom == 14
assert len(sentinel.bounds) == 4
assert sentinel.bounds[0] > sentinel.bounds[2]
assert sentinel.bands == ("vv", "vh")


@patch("rio_tiler_pds.sentinel.aws.sentinel1.fetch")
@patch("rio_tiler.io.rasterio.rasterio")
def test_stripmap_beam(rio, fetch):
"""test stripmap beam mode."""
rio.open = mock_rasterio_open

with open(
f"{SENTINEL_BUCKET}/GRD/2023/8/9/S1/DV/S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175/productInfo.json",
"r",
) as f:
SENTINEL_METADATA = json.loads(f.read())

fetch.return_value = SENTINEL_METADATA

with S1L1CReader(
"S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175"
) as sentinel:
assert (
sentinel.scene_params["scene"]
== "S1A_S1_GRDH_1SDV_20230809T020729_20230809T020754_049792_05FCE6_1175"
)
assert sentinel.minzoom == 8
assert sentinel.maxzoom == 14
assert len(sentinel.bounds) == 4
assert sentinel.bands == ("vv", "vh")

metadata = sentinel.info(bands="vh")
assert len(metadata.band_metadata) == 1
assert metadata.band_metadata[0][0] == "vh"
assert metadata.band_descriptions == [("vh", "")]

0 comments on commit d767624

Please sign in to comment.