Files
SkySensePlusPlus/tools/pretraining_data_builder/rsi_download/download/search.py
esenke 01adcfdf60 init
2025-12-08 22:16:31 +08:00

79 lines
2.9 KiB
Python

from __future__ import annotations
from typing import List
import msgspec
import httpx
from rsi_download.exceptions import SearchException
from rsi_download.geo.geo_types import GeoJsonPolygon
ESA_SEARCH_URL = r"https://catalogue.dataspace.copernicus.eu/odata/v1/Products"
class ContentData(msgspec.Struct, rename="pascal"):
"""Odata search result start and end date"""
start: str
end: str
class Asset(msgspec.Struct, rename="pascal"):
"""Odata search Asset"""
type_: str = msgspec.field(name="Type")
id: str
download_link: str
s3_path: str
class SearchResult(msgspec.Struct, rename="pascal"):
"""Odata search Result"""
id: str
name: str
content_length: int
origin_date: str
s3_path: str
content_date: ContentData
geo_footprint: GeoJsonPolygon
assets: List[Asset]
class SearchContent(msgspec.Struct):
value: List[SearchResult]
next_link: str | None = msgspec.field(default=None, name="@odata.nextLink")
async def search_odata(
long: float,
lat: float,
cloud_coverage: float,
time_lt: str,
time_gt: str,
max_: int,
platform_name: str,
) -> SearchContent:
# filter voor zoeken op cloudCover, Productype en orbitDirection.
# lt = less then
# eq = equal to
# gt = greater then
# sentinel-2
if platform_name == "S2":
search_filter = f"OData.CSC.Intersects(area=geography'SRID=4326;POINT ({long:.4f} {lat:.4f})') and Attributes/OData.CSC.DoubleAttribute/any(att:att/Name eq 'cloudCover' and att/OData.CSC.DoubleAttribute/Value lt {cloud_coverage:.2f}) and Attributes/OData.CSC.StringAttribute/any(att:att/Name eq 'productType' and att/OData.CSC.StringAttribute/Value eq 'S2MSI2A') and ContentDate/Start gt {time_gt} and ContentDate/Start lt {time_lt}"
elif platform_name == "S1":
search_filter = f"OData.CSC.Intersects(area=geography'SRID=4326;POINT ({long:.4f} {lat:.4f})') and Attributes/OData.CSC.StringAttribute/any(att:att/Name eq 'productType' and att/OData.CSC.StringAttribute/Value eq 'IW_GRDH_1S') and ContentDate/Start gt {time_gt} and ContentDate/Start lt {time_lt}"
elif platform_name == "WV3":
search_filter = f"OData.CSC.Intersects(area=geography'SRID=4326;POINT ({long:.4f} {lat:.4f})') and Attributes/OData.CSC.StringAttribute/any(att:att/Name eq 'platformName' and att/OData.CSC.StringAttribute/Value eq 'WorldView-3') and ContentDate/Start gt {time_gt} and ContentDate/Start lt {time_lt}"
else:
raise ValueError(f"Invalid platform name: {platform_name}")
async with httpx.AsyncClient() as client:
r = await client.get(
url=f"{ESA_SEARCH_URL}?$filter={search_filter}&$top={max_}&$expand=Assets",
timeout=60,
)
if not r.status_code == 200:
raise SearchException(f"Error getting data: {r.text}")
return msgspec.json.decode(r.content, type=SearchContent)