Source code for eodal.downloader.sentinel2.creodias
"""
REST-API based downloading of Sentinel-2 datasets from CREODIAS.
Make sure to have a valid CREODIAS account and provide your username and password
as environmental variables:
On a Linux system you can specify your credentials in the current Python environment
by:
.. code-block:: shell
export CREODIAS_USER = "<your-user-name>"
export CREODIAS_PASSWORD= "<your-password>"
Copyright (C) 2022 Lukas Valentin Graf
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import pandas as pd
import requests
from datetime import date
from shapely.geometry import Polygon
from typing import Optional
from eodal.utils.constants.sentinel2 import ProcessingLevels
from eodal.utils.exceptions import DataNotFoundError
CREODIAS_FINDER_URL = (
"https://finder.creodias.eu/resto/api/collections/Sentinel2/search.json?"
)
[docs]
def query_creodias(
start_date: date,
end_date: date,
max_records: int,
processing_level: ProcessingLevels,
bounding_box: Polygon,
cloud_cover_threshold: Optional[int] = 100,
) -> pd.DataFrame:
"""
queries the CREODIAS Finder API to obtain available
datasets for a given geographic region, date range and
Sentinel-2 processing level (L1C or L2A).
NO AUTHENTICATION is required for running this query.
:param start_date:
start date of the queried time period (inclusive)
:param end_date:
end date of the queried time period (inclusive)
:param max_records:
maximum number of items returned. NOTE that
CREODIAS might limit this number!
:param processing_level:
queried Sentinel-2 processing level
:param bounding_box:
polygon in geographic coordinates (WGS84) denoting
the queried region
:param cloud_cover_threshold:
cloudy pixel percentage threshold (0-100%) for filtering
mapper too cloudy for processing. All mapper with a cloud
cover lower than the threshold specified will be downloaded.
Per default all mapper are downloaded.
:returns:
results of the CREODIAS query (no downloaded data!)
as pandas DataFrame
"""
# convert dates to strings in the required format
start_date_str = start_date.strftime("%Y-%m-%d")
end_date_str = end_date.strftime("%Y-%m-%d")
# convert polygon to required format
coords = bounding_box.exterior.coords.xy
coord_str = ""
n_points = len(coords[0])
for n_point in range(n_points):
x = coords[0][n_point]
y = coords[1][n_point]
coord_str += f"{x}+{y}%2C"
# get rid of the last %2C
coord_str = coord_str[:-3]
# adopt the processing level
processing_level_creodias = processing_level.value.replace("-", "").upper()
# construct the REST query
query = CREODIAS_FINDER_URL + f"maxRecords={max_records}&"
query += f"startDate={start_date_str}T00%3A00%3A00Z&completionDate=" + \
f"{end_date_str}T23%3A59%3A59Z&"
query += f"cloudCover=%5B0%2C{cloud_cover_threshold}%5D&"
query += f"processingLevel={processing_level_creodias}&"
query += f"geometry=POLYGON(({coord_str}))&"
query += "sortParam=startDate&sortOrder=descending&status=all&dataset=ESA-DATASET"
# GET to CREODIAS Finder API
res = requests.get(query)
res.raise_for_status()
res_json = res.json()
# extract features (=available datasets)
features = res_json["features"]
datasets = pd.DataFrame(features)
# make sure datasets is not empty otherwise return
if datasets.empty:
raise DataNotFoundError("CREODIAS query returned empty set")
# get *.SAFE dataset names
datasets["dataset_name"] = datasets.properties.apply(
lambda x: x["productIdentifier"].split("/")[-1]
)
return datasets