Přeskočit obsah

08.2 STAC

STAC (SpatioTemporal Asset Catalog; https://stacspec.org/) jestiť standardem, jehož cílem je usnadniti vyhledávání produktů a dotazování se na ně. Jeho výhodou je značná jednoduchost a modulárnost umožňující snadné začlenění různých rozšíření.

Komponenty STAC

STAC se skládá ze tří komponent - item, catalog a collection. Každá z nich je použitelná i sama o sobě, zpravidla se však v praxi setkáváme s jejich kombinacemi.

Item

Základní prvek představující jeden produkt, např. jednu scénu Sentinel-2. Jedná se o GeoJSON obsahující metadata o daném produktu. Tato metadata představují klasická metadata formátu GeoJSON rozšířená o 3 povinná a další nepovinná metadata specifická pro STAC.

Specifikace STAC item. Zdroj: https://stacspec.org/en/tutorials/intro-to-stac/

Jeden item může odkazovat na více souborů (tzv. assets) - jedna scéna Sentinel-2 se skládá ze samostatných souborů pro jednotlivé kanály a dodatečných souborů.

Catalog

Strukturní prvky sloužící k propojení items a collections sloužící k navigaci skrze nabízené produkty. Jedná se o JSON soubor nazvaný catalog.json.

Specifikace STAC catalog. Zdroj: https://stacspec.org/en/tutorials/intro-to-stac/

Catalog může spojovaným itemům a kolekcím přidávat další metadata. Catalog může obsahovat i jiné catalogs, kterým se pak přezdívá sub-catalogs.

Catalog může být dvou typů:

  • ABSOLUTE_PUBLISHED: Používá absolutní cesty pro links a HREFs
  • RELATIVE_PUBLISHED: Používá relativní cesty pro links a absolutní cestu pro kořenový catalog
  • SELF_CONTAINED: Používá relativní cesty pro vše (ideální pro přenositelnost)

Collection

Skupina sdružující související items, např. collection Sentinel-2 by mohla sdružovat nabízené dlaždice jmenovaného satelitního systému. Collection může hromadně rozšiřovat jejich metadata.Jedná se o JSON soubor.

Specifikace STAC collection. Zdroj: https://stacspec.org/en/tutorials/intro-to-stac/

PySTAC

Jednou z možností, jak se STACem komunikovati, jestiť Python klient zvaný PySTAC. PySTAC je balíček programovacího jazyku Python pod Apache licencí umožňující nejen STAC prvky a systém vytvářeti, nýbrž se na něj také dotazovati.

Vývojář - Tvorba

V této sekci si ukážeme, jak vytvořit a sdílet STAC catalog s testovacími daty. Testovací data nalezneme v Repository/155FGIS/05/DTM.tif. Zkopírujme si je do pracovních adresářů (v materiálech používáme /tmp/stac_lesson)

Načtěme si data a získejme potřebná metadata:

import os
import datetime
import rasterio

from shapely.geometry import Polygon, mapping


img_dir = '/tmp/stac_lesson'
filename = 'DTM.tif'
img_path = os.path.join(img_dir, filename)


def get_geometry_metadata(raster: str):
    with rasterio.open(raster) as r:
        bounds = r.bounds
        bbox = (bounds.left, bounds.bottom, bounds.right, bounds.top)
        footprint = mapping(
            Polygon(
                [
                    [bounds.left, bounds.bottom],
                    [bounds.left, bounds.top],
                    [bounds.right, bounds.top],
                    [bounds.right, bounds.bottom],
                ]
            )
        )

    return bbox, footprint


bbox, geometry = get_geometry_metadata(img_path)
timestamp = datetime.datetime.now(tz=datetime.timezone.utc)
item_name = os.path.splitext(filename)[0]

Vytvořme si catalog a přesvědčme se, že je v pořádku a čitelný:

import pystac


catalog = pystac.Catalog(
  id='fgis-catalog',
  description='Tohle je testovaci catalog pro predmet 155FGIS.'
)

# vypis strukturu catalogu
print(f'catalog: \n{catalog.to_dict()}')

# catalog by mel byt prazdny
print(f'popis: {catalog.describe()}')
print(f'childrens: {catalog.get_children()}')
print(f'items: {catalog.get_items()}')

Vytvořme STAC Item, naplnme jej a vložme jej do catalogu:

import pystac

item = pystac.Item(
    id=item_name,
    geometry=geometry,
    bbox=bbox,
    datetime=timestamp,
)

print(f'item: {item.to_dict()}')

# vztahy mezi vytvorenymi catalog a item
print(f'parent: {item.get_parent()}')

catalog.add_item(item)

# vztahy mezi vytvorenymi catalog a item
print(f'parent: {item.get_parent()}')
print(f'popis: {catalog.describe()}')
print(f'childrens: {catalog.get_children()}')
print(f'items: {catalog.get_items()}')

# pridejme soubor
item.add_asset(
    key='file',
    asset=pystac.Asset(
        href=img_path,
        media_type=pystac.MediaType.GEOTIFF
    )
)

print(f'item: {item.to_dict()}')

# normalizujme HREF v links
catalog.normalize_hrefs(os.path.join(img_dir, 'stac'))

print(f'item po normalizaci HREFs: {item.to_dict()}')

# ulozme catalog (ulozi se v adresari stac uvnitr adresare s items)
catalog.save(catalog_type=pystac.CatalogType.SELF_CONTAINED)

# make_all_asset_hrefs_relative()

Nyní bude zapotřebí spustiti STAC. Tak učiníme tím, že se přesuneme do složky obsahující catalog.json (v našem případě /tmp/stac_lesson/stac) a spustíme python3 -m http.server. Náš lokální STAC nyní běží na serveru http://localhost:8000.

Uživatel - Komunikace a dotazy

STAC catalog můžeme prozkoumat v pohlížeči, ale pro systematičtější stahování a průzkum dat je zajisté lepší dělati vše automatizovaně. Napišme si tedy za tímto účelem Python skript.

import pystac


catalog = pystac.Catalog.from_file('http://localhost:8000/catalog.json')

print(f'Catalog - popis: {catalog.describe()}')
print(f'Catalog - id: {catalog.id}')

# projdeme si vsechny items a ulozme si je
for item in catalog.get_all_items():
    print(f'item: {item.id}')
    print(f'extensions: {item.stac_extensions}')
    # projdeme si jednotlive assets
    for asset_key in item.assets:
        print(f'asset: {asset_key}')
        print(f'asset - href: {item.assets[asset_key].href}')
        # cesta k assetu je lokalni u nas na pocitaci, jinak bychom produkt
        # stahovali pres requests