STAC und openEO in der Praxis:
Integration in actinia
Carmen Tawalika - mundialis - FOSSGIS 2022
STAC
SpatioTemporal Asset Catalog - Gemeinsame Sprache zur Beschreibung raum- und zeitbezogener Daten
Ziele
- Daten können leichter indiziert werden
- Daten können leichter gefunden werden
- kein neuer Code nötig bei Veröffentlichung von neuem Datensatz / API
Konzepte
Item
Catalog
Collection
# STAC Item
* Einzelnes __raum-zeitliches Asset__
* GeoJSON mit Geometrie (bbox), Eigenschaften und Links. `datetime` ist erforderliche Eigenschaft
* Andere mögliche Felder: Thumbnail, Asset-Links (Download, Streaming), Relationship-Links, STAC Content Extensions
* Verbindung zu genau einer Collection
* Benötigt __Link zur übergeordneten Collection__
* __Baumblatt__
# STAC Catalog
* Hat ID, Beschreibung, stac_version und Links
* Bietet Strukturelemente zur __Gruppierung von Items und Collections__
* Aufteilung übermäßig großer Collections in Gruppen
* Gruppieren von Collections als Einstiegspunkt in eine STAC-Objekthierarchie (Wurzelknoten)
# STAC Collection
* __Catalog, der mehr erforderliche Metadaten enthält__ und eine Gruppe zusammengehöriger Objekte beschreibt
* Hat alle Felder eines Catalogs + Lizenz und Extent
* Kann sowohl übergeordnete Catalogs und Collections als auch untergeordnete Items, Catalogs und Collections haben. Muss keine haben
* __Verlinken idealerweise auf umfassendere Metadaten__ (ISO 19115, etc.), sofern verfügbar
# actinia-stac-plugin
![actinia-stac-plugin](resources/img/actinia-stac-plugin.jpeg)
- Über das Plugin wird actinia selbst zu einem STAC
- Vorhandene __Collections__ können geharvested werden,
- um als __Input Datensatz für actinia gelistet__ werden zu können
- um __in Prozessierungen verwendet__ werden zu können
- Bisher wurden zwei Ressourcen implementiert:
- `/instances`: Virtueller Raum, in dem Collections gespeichert werden können. Eine Instanz ist dabei immer eine STAC Instanz, von der geharvested wird
- `/collections`: Gehören immer zu einer Instanz.
Da zwei Instanzen die gleiche Collection enthalten können, wird eine interne ID zugeordnet:
`stac.{{ stac_instance_id }}.rastercube.{{ stac_collection_id }}`
# CREATE: POST `/instances`
$ cat stac.json
{
"stac_instance_id": "dlr"
}
curl -X POST -u $user:$pw -d @stac.json https://actinia-dev.mundialis.de/api/v3/stac/instances
{
"StacInstance": null,
"message": "The Instance has been added successfully"
}
# CREATE: POST `/collections`
$ cat stac.json
{
"stac_instance_id": "dlr",
"stac_url": "https://geoserver.dlr.loose.eox.at/ogc/stac/collections/S2_L2A_MSI_COG"
}
curl -X POST -u $user:$pw -d @stac.json https://actinia-dev.mundialis.de/api/v3/stac/collections
{
"StacCollection": {
"stac.dlr.rastercube.S2_L2A_MSI_COG": {
"href": "api/v3/stac/collections/stac.dlr.rastercube.S2_L2A_MSI_COG",
"root": "https://geoserver.dlr.loose.eox.at/ogc/stac/collections/S2_L2A_MSI_COG"
}
},
"message": "The STAC Collection has been added successfully"
}
# READ: GET `/instances`
curl -u $user:$pw https://actinia-dev.mundialis.de/api/v3/stac/instances
{
"defaultStac": {
"path": "stac.defaultStac.rastercube.< stac_collection_id >"
},
"dlr": {
"path": "stac.dlr.rastercube.< stac_collection_id >"
}
}
curl -u $user:$pw https://actinia-dev.mundialis.de/api/v3/stac/instances/dlr
{
"stac.dlr.rastercube.S2_L2A_MSI_COG": {
"href": "api/v3/stac/collections/stac.dlr.rastercube.S2_L2A_MSI_COG",
"root": "https://geoserver.dlr.loose.eox.at/ogc/stac/collections/S2_L2A_MSI_COG"
}
}
```
# READ: GET `/collections`
# curl -u $user:$pw https://actinia-dev.mundialis.de/api/v3/stac/collections/stac.dlr.rastercube.S2_L2A_MSI_COG
curl -u $user:$pw https://actinia-dev.mundialis.de/api/v3/stac/collections
{
"collections": [
{
"id": "stac.dlr.rastercube.S2_L2A_MSI_COG",
"title": "Sentinel-2 L2A MSI Products (Cloud-Optimized)",
"extent": {
"spatial": {"bbox": [[ 30.1918571065124, -16.3692458600817, 42.834039161154, -0.2636709443366629]]},
"temporal": {"interval": [["2020-01-01T07:33:35.000+00:00","2020-12-30T08:03:03.000+00:00"]]}
},
"links": [
{
"href": "https://geoserver.dlr.loose.eox.at/ogc/stac/collections/S2_L2A_MSI_COG?f=application/json",
"rel": "self",
"type": "application/json"
},
...
],
...
}
]
}
# DELETE `/instances`
$ curl -X DELETE -u $user:$pw https://actinia-dev.mundialis.de/api/v3/stac/instances/dlr
{
"message": "The instance --dlr-- was deleted with all the collections stored inside"
}
# DELETE `/collections`
$ curl -X DELETE -u $user:$pw \
https://actinia-dev.mundialis.de/api/v3/stac/collections/stac.dlr.rastercube.S2_L2A_MSI_COG
{}
# actinia STAC importer
Nutzung der gespeicherten Collections in Prozessketten
{
"list": [{
"id": "importer_1",
"module": "importer",
"inputs": [{
"import_descr": {
"source": "stac.defaultStac.rastercube.landsat-8-l1-c1",
"type": "stac",
"semantic_label": "B1",
"extent": {
"spatial": {
"bbox": [[30.192, -16.369, 42.834, -0.264]]
},
"temporal":{
"interval": [["2021-09-09", "2021-09-12"]]
}
},
"filter": {}
},
"param": "map",
"value": "example-red"
}
]
}],
"version": 1
}
$ curl -u $user:$pw -d @test -H 'Content-Type: application/json' \
https://actinia-dev.mundialis.de/api/v3/locations/nc_spm_08/processing_async_export
# actinia STAC exporter
Erzeugung eines STAC Items für eine Ergebnis-Rasterkarte, Instanz gleich Nutzername
{
"list": [
{
"module": "r.slope.aspect",
...
"outputs": [
{
"param": "slope",
"value": "elev_ned_30m_slope",
"metadata": {
"format": "STAC",
"type": "metadata",
"output_layer": "stac"
}
}
]
}
],
"version": "1"
}
# openEO API
![openeo.org](resources/img/openeo.org.jpeg)
* Offene API, um Clients mit großen Erdbeobachtungs-Cloud-Backends zu verbinden
* Jeder Client kann mit jedem Backend sprechen
* Backends werden vergleichbar
* Funktionalitäten:
* Listet verfügbare Erdbeobachtungsdaten und -prozesse in Cloud-Backends
* Ausführen von (verkettete) Prozesse auf Backends
* Herunterladen von (Zwischen-)Ergebnissen
* Verwaltung von Benutzerinhalten einschließlich der Rechnungsstellung
# openEO - wichtige Endpunkte
* Grundlegende Metadaten für alle Datensätze
* `GET /collections`
* Vollständige Metadaten für einen bestimmten Datensatz
* `GET /collections/{collection_id}`
* Unterstützte vordefinierte Prozesse
* `GET /processes`
* Einen neuen Batchjob erstellen
* `POST /jobs`
* Alle Batchjobs auflisten
* `GET /jobs`
* Starten der Verarbeitung eines Batchjob
* `POST /jobs/{job_id}/results`
* Herunterladen von Ergebnissen für einen abgeschlossenen Batchjob
* `GET /jobs/{job_id}/results`
# openEO + STAC Endpunkte
* Grundlegende Metadaten für alle Datensätze
* `GET /collections`
* Vollständige Metadaten für einen bestimmten Datensatz
* `GET /collections/{collection_id}`
-> Collection-Spezifikation kann eigenständig verwendet werden zur Beschreibung von
Datenaggregationen, keine Links zu Unterkatalogen und Objekten nötig
__STAC API Empfehlungen__
* Data Discovery wie in openEO (OGC Features)
* `GET /collections`
* `GET /collections/{collection_id}`
* STAC volle Implementierung, **nicht** in openEO
* `GET /collections/{collectionId}/items`
* `GET /collections/{collectionId}/items/{featureId}`
# openeo-grassgis-driver
![openeo-grassgis-driver auf GitHUb](resources/img/openeo-grassgis-driver-github.jpeg)
* Backend Implementierung der openEO API in Python
* GRASS GIS als Prozessier-Backend, kommuniziert per HTTP mit actinia
![openeo-webeditor](resources/img/openeo-stac.jpeg)
![openeo-collections1](resources/img/openeo-collection1.jpeg)
![openeo-collections2](resources/img/openeo-collection2.jpeg)
![openeo-process](resources/img/webeditor_pg.jpeg)
![openeo-process](resources/img/webeditor_job.jpeg)
# Vielen Dank! Fragen?