Přeskočit obsah

12. Nasazení výpočetních procesů online (OGC, Actinia)

OGC

OGC poskytuje dvě specifikace, které se týkají publikování výpočetních procesů online, a to:

  • OGC Web Processing Service (WPS)
  • OGC API Processes

OGC WPS

OGC WPS patří do skupiny specifikací označovaných jako Open Web Services (OWS) jako je Web Map Service (WMS), Web Feature Sevice (WFS) či Web Coverage Service (WCS).

Existuje řada open source serverových implementací WPS:

Nejprve se na OGC WPS podíváme z pohledu klienta. Pro ukázku si zvolíme projekt Rain, v rámci něhož jsou poskytovány výpočetní nástroje určené pro srážková a půdní data. Tato implementace je založena na PyWPS.

Výpočetní nástroje můžete spustit např. pomocí zásuvného modulu QGIS WPS (ke stažení jako zip):

Ukázka Python klienta založeném na knihovně OWSLib:

import csv

from owslib.wps import WebProcessingService, monitorExecution
from owslib.wps import ComplexDataInput

# metadata
wps = WebProcessingService('https://rain1.fsv.cvut.cz/services/wps')
wps.getcapabilities()
print(wps.identification.type)

# list of processes
for process in wps.processes:
    print(' -', process.identifier, process.title)

# run selected process
processId = 'd-rain6h-timedist'
inputs = [
    ("input", ComplexDataInput('http://rain.fsv.cvut.cz/geodata/test.gml')),
    ("keycolumn", "HLGP_ID"),
    ("return_period", "N2"),
    ("return_period", "N5"),
    ("return_period", "N10"),
    ("type", "E"),
    ("type", "F")  
]

print(f"Running {processId}...")
execution = wps.execute(processId, inputs)
monitorExecution(execution)
outputFile = '/tmp/output.csv'
execution.getOutput(outputFile)

# print result
with open(outputFile) as fd:
    reader = csv.reader(fd)
    for line in reader:
        print(line)

Postupu zprovoznění vlastního WPS serveru založeném na PyWPS se věnuje materiál Jena GRASS GIS Workshop.

OGC API Processes

OGC API Processes patří do skupiny nově vznikajících specifikací OGC API. OGC API je založen na rozdíl od OGC OWS na REST API a značně tak zjednodušuje komunikaci mezi klientem a serverem.

Pro jazyk Python existuje refereční implementace OGC API pygeoapi. Tento balíček nabízí podporu i pro OGC API Processes.

Note

Tato část bude zpracována v akademickém roce 2024/2025.

Actinia

Actinia je škálovatelné REST (representational state transfer) API pro distribuovatelné procesy nad rastrovými daty využívající na pozadí GRASS GIS. Její zdrojový kód jest dostupný pod licencí GNU GPLv3+.

Databáze

Názvosloví Actinie rozlišuje tři druhy databází:

  • trvalá (persistent): určena ke čtení (většina uživatelských rolí ji ani upravovati nemůže) jako prostředí zpracování a zdroj dat, zůstává naživu i po dokončení procesů
  • dočasná (ephemeral): z důvodů bezpečnosti a výkonu procesy probíhají v ní, vytváří se pro všechna API volání, po ukončení procesů jestiť odstraněna; užívá trvalých databází jakožto prostředí zpracování pro přístup k datům
  • uživatelská (user-specific): trvalá databáze vytvořitelná danou uživatelskou skupinou; lokace může zakládati na lokacích v trvalé databázi, názvy mapsetů však musí býti unikátní; uživatelská skupina může míti přístup pouze k jedné uživatelské databázi, počet jejích lokací však není omezen

Role

Přístup do Actinie definují uživatelé (users), uživatelské role (user-roles) a uživatelské skupiny (user groups). Jeden uživatel má vždy specifickou uživatelskou roli a je součástí nanejvýš jedné uživatelské skupiny.

Uživatelské role se dělí do čtyř následujících:

  • superuživatel (superadmin): přístup ke všem API voláním a databázím; může vytvářet, upravovat a odstraňovat uživatele
  • administrátor (admin): přístup ke všem API voláním a k trvalým databázím povoleným mu superuživateli; může vytvářet, upravovat a odstraňovat uživatele nižších rolí
  • uživatel (user): limitovaný přístup k API voláním, může spouštět procesy v dočasných a uživatelských databázích a má přístup k trvalým databázím povoleným mu superuživateli; může vytvářet, upravovat a odstraňovat lokace a mapsety v uživatelských databázích
  • host (guest): velmi limitovaný přístup k API voláním a má přístup k trvalým databázím povoleným mu superuživateli; nemůže vytvářet, upravovat, ani odstraňovat lokace, mapsety, ani uživatele

Spuštění serveru

Jestiť možné Actinii instalovati a spustiti lokálně, v našem případě však opět využijeme izolace pomocí předpřipravených Docker obrazů. Kód pro sestavení Dockeru nalezneme v oficiálním repozitáři a k sestavení využijme nástroje docker compose:

git clone https://github.com/mundialis/actinia-core.git
cd actinia-core
sudo docker compose -f docker/docker-compose.yml up

Přesvědčme se, zda naše instance Actinie běží, dotazem na obsažené verze:

> curl http://localhost:8088/api/v3/version
{"api_version":"3.4.0","grass_version":{"build_date":"2024-02-22","build_off_t_size":"8","build_platform":"x86_64-pc-linux-musl","date":"2024","gdal":"3.6.4","geos":"3.11.2","libgis_date":"2024-02-22T19:48:21+00:00","libgis_revision":"8.3.2dev","proj":"9.2.1","revision":"6a52add","sqlite":"3.41.2","version":"8.3.2dev"},"plugin_versions":{},"plugins":"","python_version":"3.11.6 (main, Oct  4 2023, 06:22:18) [GCC 12.2.1 20220924]","running_since":"n/a","version":"4.13.0"}

Tip

Pokud se vám zdá výstup na jednom řádku býti nepřehledný (v příkladu dlouhého výstupu jest takové tvrzení neoddiskutovatelné), můžete jej "zpřelednit" za pomoci balíčku jazyka Python json.tool. Příkaz by tak byl curl http://localhost:8088/api/v3/version | python3 -m json.tool. V následujících příkladech se k tomuto kroku pro zpřehlednění budeme přikláněti.

Operace uvnitř Actinie

Vstupme do našeho Dockeru pomocí následujícího příkladu.

sudo docker exec -it docker_actinia_1 sh

Důležité

Základní Docker image neobsahuje jako přístupový bod bash. Musíme tedy využívati základního shellu sh.

Vypišme existující uživatele:

> actinia-user list
[b'actinia-gdi']
['actinia-gdi']

Přidejme nového uživatele následujícím příkazem. Učiníme tak příkazem actinia-user create. -u definuje uživatelské jméno, -w definuje heslo, -g definuje uživatelskou skupinu a -r definuje uživatelskou roli.

> actinia-user create -u virginia -g user -w "woolf" -r user
Created user <virginia> in group <user>
user_id: virginia
user_role: user
user_group: user
permissions: {'accessible_datasets': {'nc_spm_08': ['PERMANENT', 'user1', 'landsat'], 'ECAD': ['PERMANENT'], 'latlong_wgs84': ['PERMANENT']}, 'accessible_modules': ['d.legend', 'd.rast', 'd.rast.multi', 'd.vect', 'exporter', 'g.findfile', 'g.gisenv', 'g.list', 'g.mapset', 'g.proj', 'g.region', 'g.remove', 'g.rename', 'g.version', 'i.atcorr', 'i.cluster', 'i.colors.enhance', 'i.gensig', 'i.group', 'i.landsat.toar', 'i.maxlik', 'i.pansharpen', 'i.segment', 'i.tasscap', 'i.vi', 'importer', 'r.blend', 'r.buffer', 'r.buffer.lowmem', 'r.carve', 'r.category', 'r.circle', 'r.clump', 'r.coin', 'r.colors', 'r.colors.out', 'r.composite', 'r.compress', 'r.contour', 'r.cost', 'r.covar', 'r.cross', 'r.describe', 'r.distance', 'r.drain', 'r.fill.dir', 'r.fillnulls', 'r.flow', 'r.grow', 'r.grow.distance', 'r.gwflow', 'r.his', 'r.horizon', 'r.info', 'r.kappa', 'r.lake', 'r.latlong', 'r.li.cwed', 'r.li.dominance', 'r.li.edgedensity', 'r.li.mpa', 'r.li.mps', 'r.li.padcv', 'r.li.padrange', 'r.li.padsd', 'r.li.patchdensity', 'r.li.patchnum', 'r.li.pielou', 'r.li.renyi', 'r.li.richness', 'r.li.shannon', 'r.li.shape', 'r.li.simpson', 'r.mapcalc', 'r.mask', 'r.mfilter', 'r.mode', 'r.neighbors', 'r.null', 'r.out.png', 'r.param.scale', 'r.patch', 'r.plane', 'r.profile', 'r.proj', 'r.quant', 'r.quantile', 'r.random', 'r.random.cells', 'r.random.surface', 'r.reclass', 'r.reclass.area', 'r.recode', 'r.region', 'r.regression.line', 'r.regression.multi', 'r.regression.series', 'r.relief', 'r.report', 'r.resamp.bspline', 'r.resamp.filter', 'r.resamp.interp', 'r.resamp.rst', 'r.resamp.stats', 'r.resample', 'r.rescale', 'r.rescale.eq', 'r.rgb', 'r.ros', 'r.series', 'r.series.accumulate', 'r.series.interp', 'r.shade', 'r.sim.sediment', 'r.sim.water', 'r.slope.aspect', 'r.solute.transport', 'r.spread', 'r.spreadpath', 'r.statistics', 'r.stats', 'r.stats.quantile', 'r.stats.zonal', 'r.stream.extract', 'r.sun', 'r.sunhours', 'r.sunmask', 'r.support', 'r.support.stats', 'r.surf.area', 'r.surf.contour', 'r.surf.fractal', 'r.surf.gauss', 'r.surf.idw', 'r.surf.random', 'r.terraflow', 'r.texture', 'r.thin', 'r.tile', 'r.tileset', 'r.timestamp', 'r.to.rast3', 'r.to.rast3elev', 'r.to.vect', 'r.topidx', 'r.topmodel', 'r.transect', 'r.univar', 'r.uslek', 'r.usler', 'r.viewshed', 'r.vol.dem', 'r.volume', 'r.walk', 'r.water.outlet', 'r.watershed', 'r.what', 'r.what.color', 't.create', 't.info', 't.list', 't.rast.accdetect', 't.rast.accumulate', 't.rast.aggr_func', 't.rast.aggregate', 't.rast.aggregate.ds', 't.rast.algebra', 't.rast.colors', 't.rast.extract', 't.rast.gapfill', 't.rast.list', 't.rast.mapcalc', 't.rast.sample', 't.rast.series', 't.rast.univar', 't.rast.what', 't.register', 't.remove', 't.unregister', 'v.buffer', 'v.clean', 'v.db.select', 'v.db.univar', 'v.db.update', 'v.dissolve', 'v.in.ascii', 'v.overlay', 'v.patch', 'v.random', 'v.rast.stats', 'v.select', 'v.what.rast', 'v.what.strds'], 'cell_limit': 1000000000, 'process_num_limit': 1000, 'process_time_limit': 600}
>
> actinia-user list
[b'actinia-gdi', b'virginia']
['actinia-gdi', 'virginia']

Přidejme uživateli virginia přístup k příkazu, ke kterému jej ve výchozím nastavení nemá, např. k r.import:

> actinia-user update_add -u virginia -m r.import
Updated user <virginia>
user_id: virginia
user_role: user
user_group: user
permissions: {'accessible_datasets': {'nc_spm_08': ['PERMANENT', 'user1', 'landsat'], 'ECAD': ['PERMANENT'], 'latlong_wgs84': ['PERMANENT']}, 'accessible_modules': ['d.legend', 'd.rast', 'd.rast.multi', 'd.vect', 'exporter', 'g.findfile', 'g.gisenv', 'g.list', 'g.mapset', 'g.proj', 'g.region', 'g.remove', 'g.rename', 'g.version', 'i.atcorr', 'i.cluster', 'i.colors.enhance', 'i.gensig', 'i.group', 'i.landsat.toar', 'i.maxlik', 'i.pansharpen', 'i.segment', 'i.tasscap', 'i.vi', 'importer', 'r.blend', 'r.buffer', 'r.buffer.lowmem', 'r.carve', 'r.category', 'r.circle', 'r.clump', 'r.coin', 'r.colors', 'r.colors.out', 'r.composite', 'r.compress', 'r.contour', 'r.cost', 'r.covar', 'r.cross', 'r.describe', 'r.distance', 'r.drain', 'r.fill.dir', 'r.fillnulls', 'r.flow', 'r.grow', 'r.grow.distance', 'r.gwflow', 'r.his', 'r.horizon', 'r.info', 'r.kappa', 'r.lake', 'r.latlong', 'r.li.cwed', 'r.li.dominance', 'r.li.edgedensity', 'r.li.mpa', 'r.li.mps', 'r.li.padcv', 'r.li.padrange', 'r.li.padsd', 'r.li.patchdensity', 'r.li.patchnum', 'r.li.pielou', 'r.li.renyi', 'r.li.richness', 'r.li.shannon', 'r.li.shape', 'r.li.simpson', 'r.mapcalc', 'r.mask', 'r.mfilter', 'r.mode', 'r.neighbors', 'r.null', 'r.out.png', 'r.param.scale', 'r.patch', 'r.plane', 'r.profile', 'r.proj', 'r.quant', 'r.quantile', 'r.random', 'r.random.cells', 'r.random.surface', 'r.reclass', 'r.reclass.area', 'r.recode', 'r.region', 'r.regression.line', 'r.regression.multi', 'r.regression.series', 'r.relief', 'r.report', 'r.resamp.bspline', 'r.resamp.filter', 'r.resamp.interp', 'r.resamp.rst', 'r.resamp.stats', 'r.resample', 'r.rescale', 'r.rescale.eq', 'r.rgb', 'r.ros', 'r.series', 'r.series.accumulate', 'r.series.interp', 'r.shade', 'r.sim.sediment', 'r.sim.water', 'r.slope.aspect', 'r.solute.transport', 'r.spread', 'r.spreadpath', 'r.statistics', 'r.stats', 'r.stats.quantile', 'r.stats.zonal', 'r.stream.extract', 'r.sun', 'r.sunhours', 'r.sunmask', 'r.support', 'r.support.stats', 'r.surf.area', 'r.surf.contour', 'r.surf.fractal', 'r.surf.gauss', 'r.surf.idw', 'r.surf.random', 'r.terraflow', 'r.texture', 'r.thin', 'r.tile', 'r.tileset', 'r.timestamp', 'r.to.rast3', 'r.to.rast3elev', 'r.to.vect', 'r.topidx', 'r.topmodel', 'r.transect', 'r.univar', 'r.uslek', 'r.usler', 'r.viewshed', 'r.vol.dem', 'r.volume', 'r.walk', 'r.water.outlet', 'r.watershed', 'r.what', 'r.what.color', 't.create', 't.info', 't.list', 't.rast.accdetect', 't.rast.accumulate', 't.rast.aggr_func', 't.rast.aggregate', 't.rast.aggregate.ds', 't.rast.algebra', 't.rast.colors', 't.rast.extract', 't.rast.gapfill', 't.rast.list', 't.rast.mapcalc', 't.rast.sample', 't.rast.series', 't.rast.univar', 't.rast.what', 't.register', 't.remove', 't.unregister', 'v.buffer', 'v.clean', 'v.db.select', 'v.db.univar', 'v.db.update', 'v.dissolve', 'v.in.ascii', 'v.overlay', 'v.patch', 'v.random', 'v.rast.stats', 'v.select', 'v.what.rast', 'v.what.strds', 'r.import'], 'cell_limit': 1000000000, 'process_num_limit': 1000, 'process_time_limit': 600}

Protože výchozí Docker neobsahuje žádná data, naplňme jej. V našem případě stáhneme (wget) oficiální GRASS testovací lokaci ze Severní Karolíny, USA, a rozbalíme (unzip) ji do GRASS databáze (-d /actinia_core/grassdb).

wget https://grass.osgeo.org/sampledata/north_carolina/nc_spm_08_micro.zip
unzip nc_spm_08_micro.zip -d /actinia_core/grassdb/

Operace zvnějšku Actinie

Základní příkazy

Získejme dostupné lokace:

> curl -u virginia:woolf "http://localhost:8088/api/v3/locations"
{"locations":["nc_spm_08"],"status":"success"}

Zde můžeme viděti, že námi vytvořený uživatel nemá práva nahlížeti do nově vytvořené lokace. Se superuživatelskými přístupovými údaji již nalezneme i námi vytvořenou lokaci:

> curl -u actinia-gdi:actinia-gdi "http://localhost:8088/api/v3/locations"
{"locations":["nc_spm_08_micro","nc_spm_08"],"status":"success"}

Tip

Pokud nechcete vždy zadávat přístupové údaje, můžete si je v OS založeném na Unixu exportovat jako alias pomocí export AUTH='-u actinia-gdi:actinia-gdi' a následně jej používat jako ${AUTH}.

Získejme informace pro jednotlivé lokace:

> curl -u actinia-gdi:actinia-gdi http://localhost:8088/api/v3/locations/nc_spm_08_micro/info | python3 -m json.tool
{
    "accept_datetime": "2024-05-12 21:30:20.227838",
    "accept_timestamp": 1715549420.227836,
    "api_info": {
        "endpoint": "locationmanagementresourceuser",
        "method": "GET",
        "path": "/api/v3/locations/nc_spm_08_micro/info",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/info"
    },
    "datetime": "2024-05-12 21:30:20.494235",
    "http_code": 200,
    "message": "Processing successfully finished",
    "process_chain_list": [
        {
            "1": {
                "flags": "ug3",
                "module": "g.region"
            },
            "2": {
                "flags": "fw",
                "module": "g.proj"
            }
        }
    ],
    "process_log": [
        {
            "executable": "g.region",
            "id": "1",
            "parameter": [
                "-ug3"
            ],
            "return_code": 0,
            "run_time": 0.10036659240722656,
            "stderr": [
                ""
            ],
            "stdout": "projection=99\nzone=0\nn=1\ns=0\nw=0\ne=1\nt=1\nb=0\nnsres=1\nnsres3=1\newres=1\newres3=1\ntbres=1\nrows=1\nrows3=1\ncols=1\ncols3=1\ndepths=1\ncells=1\ncells3=1\n"
        },
        {
            "executable": "g.proj",
            "id": "2",
            "parameter": [
                "-fw"
            ],
            "return_code": 0,
            "run_time": 0.15045762062072754,
            "stderr": [
                ""
            ],
            "stdout": "PROJCRS[\"NAD83(HARN) / North Carolina\",BASEGEOGCRS[\"NAD83(HARN)\",DATUM[\"NAD83 (High Accuracy Reference Network)\",ELLIPSOID[\"GRS 1980\",6378137,298.257222101,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4152]],CONVERSION[\"SPCS83 North Carolina zone (meters)\",METHOD[\"Lambert Conic Conformal (2SP)\",ID[\"EPSG\",9802]],PARAMETER[\"Latitude of false origin\",33.75,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8821]],PARAMETER[\"Longitude of false origin\",-79,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8822]],PARAMETER[\"Latitude of 1st standard parallel\",36.1666666666667,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8823]],PARAMETER[\"Latitude of 2nd standard parallel\",34.3333333333333,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8824]],PARAMETER[\"Easting at false origin\",609601.22,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8826]],PARAMETER[\"Northing at false origin\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8827]]],CS[Cartesian,2],AXIS[\"easting (X)\",east,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"northing (Y)\",north,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Engineering survey, topographic mapping.\"],AREA[\"United States (USA) - North Carolina - counties of Alamance; Alexander; Alleghany; Anson; Ashe; Avery; Beaufort; Bertie; Bladen; Brunswick; Buncombe; Burke; Cabarrus; Caldwell; Camden; Carteret; Caswell; Catawba; Chatham; Cherokee; Chowan; Clay; Cleveland; Columbus; Craven; Cumberland; Currituck; Dare; Davidson; Davie; Duplin; Durham; Edgecombe; Forsyth; Franklin; Gaston; Gates; Graham; Granville; Greene; Guilford; Halifax; Harnett; Haywood; Henderson; Hertford; Hoke; Hyde; Iredell; Jackson; Johnston; Jones; Lee; Lenoir; Lincoln; Macon; Madison; Martin; McDowell; Mecklenburg; Mitchell; Montgomery; Moore; Nash; New Hanover; Northampton; Onslow; Orange; Pamlico; Pasquotank; Pender; Perquimans; Person; Pitt; Polk; Randolph; Richmond; Robeson; Rockingham; Rowan; Rutherford; Sampson; Scotland; Stanly; Stokes; Surry; Swain; Transylvania; Tyrrell; Union; Vance; Wake; Warren; Washington; Watauga; Wayne; Wilkes; Wilson; Yadkin; Yancey.\"],BBOX[33.83,-84.33,36.59,-75.38]],ID[\"EPSG\",3358]]\n"
        }
    ],
    "process_results": {
        "projection": "PROJCRS[\"NAD83(HARN) / North Carolina\",BASEGEOGCRS[\"NAD83(HARN)\",DATUM[\"NAD83 (High Accuracy Reference Network)\",ELLIPSOID[\"GRS 1980\",6378137,298.257222101,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4152]],CONVERSION[\"SPCS83 North Carolina zone (meters)\",METHOD[\"Lambert Conic Conformal (2SP)\",ID[\"EPSG\",9802]],PARAMETER[\"Latitude of false origin\",33.75,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8821]],PARAMETER[\"Longitude of false origin\",-79,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8822]],PARAMETER[\"Latitude of 1st standard parallel\",36.1666666666667,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8823]],PARAMETER[\"Latitude of 2nd standard parallel\",34.3333333333333,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8824]],PARAMETER[\"Easting at false origin\",609601.22,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8826]],PARAMETER[\"Northing at false origin\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8827]]],CS[Cartesian,2],AXIS[\"easting (X)\",east,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"northing (Y)\",north,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Engineering survey, topographic mapping.\"],AREA[\"United States (USA) - North Carolina - counties of Alamance; Alexander; Alleghany; Anson; Ashe; Avery; Beaufort; Bertie; Bladen; Brunswick; Buncombe; Burke; Cabarrus; Caldwell; Camden; Carteret; Caswell; Catawba; Chatham; Cherokee; Chowan; Clay; Cleveland; Columbus; Craven; Cumberland; Currituck; Dare; Davidson; Davie; Duplin; Durham; Edgecombe; Forsyth; Franklin; Gaston; Gates; Graham; Granville; Greene; Guilford; Halifax; Harnett; Haywood; Henderson; Hertford; Hoke; Hyde; Iredell; Jackson; Johnston; Jones; Lee; Lenoir; Lincoln; Macon; Madison; Martin; McDowell; Mecklenburg; Mitchell; Montgomery; Moore; Nash; New Hanover; Northampton; Onslow; Orange; Pamlico; Pasquotank; Pender; Perquimans; Person; Pitt; Polk; Randolph; Richmond; Robeson; Rockingham; Rowan; Rutherford; Sampson; Scotland; Stanly; Stokes; Surry; Swain; Transylvania; Tyrrell; Union; Vance; Wake; Warren; Washington; Watauga; Wayne; Wilkes; Wilson; Yadkin; Yancey.\"],BBOX[33.83,-84.33,36.59,-75.38]],ID[\"EPSG\",3358]]\n",
        "region": {
            "b": 0.0,
            "cells": 1,
            "cells3": 1,
            "cols": 1,
            "cols3": 1,
            "depths": 1,
            "e": 1.0,
            "ewres": 1.0,
            "ewres3": 1.0,
            "n": 1.0,
            "nsres": 1.0,
            "nsres3": 1.0,
            "projection": 99,
            "rows": 1,
            "rows3": 1,
            "s": 0.0,
            "t": 1.0,
            "tbres": 1.0,
            "w": 0.0,
            "zone": 0
        }
    },
    "progress": {
        "num_of_steps": 2,
        "step": 2
    },
    "queue": "local",
    "resource_id": "resource_id-9b688937-aa2a-450e-afb3-d016ca82abdc",
    "status": "finished",
    "time_delta": 0.2664210796356201,
    "timestamp": 1715549420.494222,
    "urls": {
        "resources": [],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-9b688937-aa2a-450e-afb3-d016ca82abdc"
    },
    "user_id": "actinia-gdi"
}

Získejme mapsety pro jednotlivé lokace:

> curl -u actinia-gdi:actinia-gdi http://localhost:8088/api/v3/locations/nc_spm_08_micro/mapsets
{
    "accept_datetime": "2024-05-12 21:25:10.199744",
    "accept_timestamp": 1715549110.1997433,
    "api_info": {
        "endpoint": "listmapsetsresource",
        "method": "GET",
        "path": "/api/v3/locations/nc_spm_08_micro/mapsets",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/mapsets"
    },
    "datetime": "2024-05-12 21:25:10.391824",
    "http_code": 200,
    "message": "Processing successfully finished",
    "process_chain_list": [
        {
            "1": {
                "flags": "l",
                "inputs": {
                    "separator": "newline"
                },
                "module": "g.mapsets"
            }
        }
    ],
    "process_log": [
        {
            "executable": "g.mapsets",
            "id": "1",
            "parameter": [
                "separator=newline",
                "-l"
            ],
            "return_code": 0,
            "run_time": 0.050249338150024414,
            "stderr": [
                "Available mapsets:",
                ""
            ],
            "stdout": "PERMANENT\nlandsat\nuser1\n"
        }
    ],
    "process_results": [
        "PERMANENT",
        "landsat",
        "user1"
    ],
    "progress": {
        "num_of_steps": 1,
        "step": 1
    },
    "queue": "local",
    "resource_id": "resource_id-8a1ace9b-bdd0-4fb8-b33c-05dbbfe4ac0e",
    "status": "finished",
    "time_delta": 0.1921064853668213,
    "timestamp": 1715549110.3918061,
    "urls": {
        "resources": [],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-8a1ace9b-bdd0-4fb8-b33c-05dbbfe4ac0e"
    },
    "user_id": "actinia-gdi"
}

Úkol

Získejte informace pro jednotlivé mapsety.

Získejme rastrové mapy pro jednotlivé mapsety:

> curl -u actinia-gdi:actinia-gdi http://localhost:8088/api/v3/locations/nc_spm_08_micro/mapsets/landsat/raster_layers | python3 -m json.tool
{
    "accept_datetime": "2024-05-12 21:26:01.074106",
    "accept_timestamp": 1715549161.0741048,
    "api_info": {
        "endpoint": "rasterlayersresource",
        "method": "GET",
        "path": "/api/v3/locations/nc_spm_08_micro/mapsets/landsat/raster_layers",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/mapsets/landsat/raster_layers"
    },
    "datetime": "2024-05-12 21:26:01.211045",
    "http_code": 200,
    "message": "Processing successfully finished",
    "process_chain_list": [
        {
            "1": {
                "inputs": {
                    "mapset": "landsat",
                    "type": "raster"
                },
                "module": "g.list"
            }
        }
    ],
    "process_log": [
        {
            "executable": "g.list",
            "id": "1",
            "parameter": [
                "mapset=landsat",
                "type=raster"
            ],
            "return_code": 0,
            "run_time": 0.10033631324768066,
            "stderr": [
                ""
            ],
            "stdout": "lsat5_1987_10\nlsat5_1987_20\nlsat5_1987_30\n"
        }
    ],
    "process_results": [
        "lsat5_1987_10",
        "lsat5_1987_20",
        "lsat5_1987_30"
    ],
    "progress": {
        "num_of_steps": 1,
        "step": 1
    },
    "queue": "local",
    "resource_id": "resource_id-b687c8bb-5eb3-444f-b458-2e746db301f8",
    "status": "finished",
    "time_delta": 0.13695788383483887,
    "timestamp": 1715549161.2110324,
    "urls": {
        "resources": [],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-b687c8bb-5eb3-444f-b458-2e746db301f8"
    },
    "user_id": "actinia-gdi"
}

Tip

Všechny STRDS bychom pak vypsali záměněním raster_layers za strds. V případě STRDS se můžeme dotázati i na rastrové mapy obsažené v STRDS (.../strs/my_strds/raster_layers).

Získejme informace o jednotlivých rastrech:

> curl -u actinia-gdi:actinia-gdi http://localhost:8088/api/v3/locations/nc_spm_08_micro/mapsets/landsat/raster_layers/lsat5_1987_10 | python3 -m json.tool
{
    "accept_datetime": "2024-05-12 21:36:03.677277",
    "accept_timestamp": 1715549763.6772761,
    "api_info": {
        "endpoint": "rasterlayerresource",
        "method": "GET",
        "path": "/api/v3/locations/nc_spm_08_micro/mapsets/landsat/raster_layers/lsat5_1987_10",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/mapsets/landsat/raster_layers/lsat5_1987_10"
    },
    "datetime": "2024-05-12 21:36:03.824291",
    "http_code": 200,
    "message": "Processing successfully finished",
    "process_chain_list": [
        {
            "1": {
                "flags": "gre",
                "inputs": {
                    "map": "lsat5_1987_10@landsat"
                },
                "module": "r.info"
            }
        }
    ],
    "process_log": [
        {
            "executable": "r.info",
            "id": "1",
            "mapset_size": 433,
            "parameter": [
                "map=lsat5_1987_10@landsat",
                "-gre"
            ],
            "return_code": 0,
            "run_time": 0.10037541389465332,
            "stderr": [
                ""
            ],
            "stdout": "north=228513\nsouth=214975.5\neast=645012\nwest=629992.5\nnsres=28.5\newres=28.5\nrows=475\ncols=527\ncells=250325\ndatatype=CELL\nncats=254\nmin=45\nmax=254\nmap=lsat5_1987_10\nmaptype=raster\nmapset=landsat\nlocation=nc_spm_08_micro\ndatabase=/actinia_core/workspace/temp_db/gisdbase_ccf8e05b15744a10b8d0b8a6ec3aaaea\ndate=\"Wed May  9 11:37:57 2007\"\ncreator=\"neteler\"\ntitle=\"LANDSAT-TM5 Band 1 Visible (0.45-0.52um) 30m\"\ntimestamp=\"14 Oct 1987\"\nunits=\"none\"\nvdatum=\"none\"\nsemantic_label=\"none\"\nsource1=\"Global Land Cover Facility (GLCF)\"\nsource2=\"\"\ndescription=\"generated by r.in.gdal\"\ncomments=\"r.in.gdal input=\"p016r035_5t19871014_z17_nn10_nc_spm_wake.tif\" outpu\\t=\"lsat5_1987_10\"IMAGE_ID=P016R35_5T871014,PATH=16,ROW=35,DATE=10/14/87,PLATFORM=LANDSAT5i.landsat.rgb \"b=lsat5_1987_10\" \"g=lsat5_1987_20\" \"r=lsat5_1987_30\"\"\n"
        }
    ],
    "process_results": {
        "cells": "250325",
        "cols": "527",
        "comments": "\"r.in.gdal input=\"p016r035_5t19871014_z17_nn10_nc_spm_wake.tif\" outpu\\t=\"lsat5_1987_10\"IMAGE_ID=P016R35_5T871014,PATH=16,ROW=35,DATE=10/14/87,PLATFORM=LANDSAT5i.landsat.rgb \"b=lsat5_1987_10\" \"g=lsat5_1987_20\" \"r=lsat5_1987_30\"\"",
        "creator": "\"neteler\"",
        "database": "/actinia_core/workspace/temp_db/gisdbase_ccf8e05b15744a10b8d0b8a6ec3aaaea",
        "datatype": "CELL",
        "date": "\"Wed May  9 11:37:57 2007\"",
        "description": "\"generated by r.in.gdal\"",
        "east": "645012",
        "ewres": "28.5",
        "location": "nc_spm_08_micro",
        "map": "lsat5_1987_10",
        "mapset": "landsat",
        "maptype": "raster",
        "max": "254",
        "min": "45",
        "ncats": "254",
        "north": "228513",
        "nsres": "28.5",
        "rows": "475",
        "semantic_label": "\"none\"",
        "source1": "\"Global Land Cover Facility (GLCF)\"",
        "source2": "\"\"",
        "south": "214975.5",
        "timestamp": "\"14 Oct 1987\"",
        "title": "\"LANDSAT-TM5 Band 1 Visible (0.45-0.52um) 30m\"",
        "units": "\"none\"",
        "vdatum": "\"none\"",
        "west": "629992.5"
    },
    "progress": {
        "num_of_steps": 1,
        "step": 1
    },
    "queue": "local",
    "resource_id": "resource_id-9c802416-ccc4-4c56-8470-209adad3e19f",
    "status": "finished",
    "time_delta": 0.14703702926635742,
    "timestamp": 1715549763.8242767,
    "urls": {
        "resources": [],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-9c802416-ccc4-4c56-8470-209adad3e19f"
    },
    "user_id": "actinia-gdi"
}

Vlastní procesy

Základy

Ve většině případů využívá uživatel Actinie k vykonání vlastních procesů, resp. řetězících se procesů (process chains) na serveru s instalací GRASS GIS a dostupnými daty. Takový proces probíhá v dočasné databázi a může data nejen zpracovávati, ale může také obsahovati jejich import a export. Proces jestiť JSON souborem obsahujícím svou verzi a seznam GRASS GIS modulů a jejich parametrů (vstupů a výstupů). Každý modul je pak sám definován ve formátu JSON. Příkladem modulu může býti následující proces počítající míru sklonitosti:

{
  "module": "r.slope.aspect",
  "id": "r.slope.aspect_0",
  "flags":"a",
  "inputs":[
     {"param": "elevation", "value": "elevation"}
   ],
  "outputs":[
     {"param": "slope", "value": "slope"}
   ]
}

Tip

V příkazové řádce GRASS GIS existuje zkratka ve formě přepínače --json. Výše uvedený proces tak lze vygenerovati zavoláním příkazu r.slope.aspect -a elev=elevation slope=slope --json.

Proces pro Actinii využívající tento modul pak vypadá následovně (seznam modulů má tentokráte délku 1):

{
  "id": "model",
  "description": "Script generated by wxGUI Graphical Modeler.",
  "version": "1",
  "list": [
    {
      "module": "r.slope.aspect",
      "id": "r.slope.aspect_0",
      "flags": "a",
      "inputs": [
        {"param": "elevation", "value": "elevation"}
      ],
      "outputs": [
        {"param": "slope", "value": "slope"}
      ]
    }
  ]
}

Tip

Rozhodneme-li se řetěziti více modulů za sebou, bude manuální práce s tím spojená ubíjející. Přepínač --json nám sice práci usnadní, přesto však zůstane část formátování na uživateli. Pro složitější posloupnosti doporučujeme používat v GRASS GIS modelář (g.gui.gmodeler). Pokud máte v modeláři hotový vlastní model, export do JSON formátu Actinie za vás provede záložka Script editor, přepnete-li si Script type na actinia.

Náš vytvořený proces uložme do souboru (/tmp/slope.json) a pošleme (-X POST) jej (-d @/tmp/slope.json) na server s běžící Actinií. Uživatel musí specifikovati typ souboru (hlavičku skrze -H "Content-Type: application/json") a způsob zpracování (poslední část adresy specifikuje asynchronní zpracování, http://.../processing_async).

> curl -u actinia-gdi:actinia-gdi -H "Content-Type: application/json" -X POST "http://localhost:8088/api/v3/locations/nc_spm_08_micro/processing_async" -d @/tmp/slope.json | python3 -m json.tool
{
    "accept_datetime": "2024-05-13 10:49:31.804987",
    "accept_timestamp": 1715597371.8049831,
    "api_info": {
        "endpoint": "asyncephemeralresource",
        "method": "POST",
        "path": "/api/v3/locations/nc_spm_08_micro/processing_async",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/processing_async"
    },
    "datetime": "2024-05-13 10:49:31.807186",
    "http_code": 200,
    "message": "Resource accepted",
    "process_chain_list": [],
    "process_results": {},
    "queue": "local",
    "resource_id": "resource_id-867dcd1f-916a-4d2d-ab2b-51010c4907e5",
    "status": "accepted",
    "time_delta": 0.0022125244140625,
    "timestamp": 1715597371.807184,
    "urls": {
        "resources": [],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-867dcd1f-916a-4d2d-ab2b-51010c4907e5"
    },
    "user_id": "actinia-gdi"
}

Navrácený JSON řetězec znamená, že dotaz proběhl v pořádku a běží v pozadí na serveru. Jeho výsledky můžeme kontrolovati na adrese označené jako urls/status. V případě úspěšného dotazu by měl obsah dané adresy vypadati následujícím způsobem:

> curl -u actinia-gdi:actinia-gdi http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-867dcd1f-916a-4d2d-ab2b-51010c4907e5 | python3 -m json.tool
{
    "accept_datetime": "2024-05-13 10:49:31.804987",
    "accept_timestamp": 1715597371.8049831,
    "api_info": {
        "endpoint": "asyncephemeralresource",
        "method": "POST",
        "path": "/api/v3/locations/nc_spm_08_micro/processing_async",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/processing_async"
    },
    "datetime": "2024-05-13 10:49:32.104395",
    "http_code": 200,
    "message": "Processing successfully finished",
    "process_chain_list": [
        {
            "description": "Script generated by wxGUI Graphical Modeler.",
            "id": "model",
            "list": [
                {
                    "flags": "a",
                    "id": "r.slope.aspect_0",
                    "inputs": [
                        {
                            "param": "elevation",
                            "value": "elevation"
                        }
                    ],
                    "module": "r.slope.aspect",
                    "outputs": [
                        {
                            "param": "slope",
                            "value": "slope"
                        }
                    ]
                }
            ],
            "version": "1"
        }
    ],
    "process_log": [
        {
            "executable": "r.slope.aspect",
            "id": "r.slope.aspect_0",
            "mapset_size": 1237,
            "parameter": [
                "elevation=elevation",
                "slope=slope",
                "-a"
            ],
            "return_code": 0,
            "run_time": 0.10031437873840332,
            "stderr": [
                "0..100",
                "Slope raster map <slope> complete",
                ""
            ],
            "stdout": ""
        }
    ],
    "process_results": {},
    "progress": {
        "num_of_steps": 1,
        "step": 1
    },
    "queue": "local",
    "resource_id": "resource_id-867dcd1f-916a-4d2d-ab2b-51010c4907e5",
    "status": "finished",
    "time_delta": 0.29947686195373535,
    "timestamp": 1715597372.104314,
    "urls": {
        "resources": [],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-867dcd1f-916a-4d2d-ab2b-51010c4907e5"
    },
    "user_id": "actinia-gdi"
}

Import dat definujeme následujícím způsobem (import_descr) skrze online úložiště. V následujícím případě využijeme online uloženého rastru k nastavení výpočetního regionu. Definujme též export (export).

{
  "list": [
    {
      "module": "g.region",
      "id": "g_region_1",
      "inputs": [
        {
          "import_descr": {
            "source": "https://grass.osgeo.org/sampledata/north_carolina/ortho2010_t792_subset_20cm.tif",
            "type": "raster"
          },
          "param": "raster",
          "value": "ortho2010_t792_subset_20cm"
        }
      ],
      "flags": "p"
    },
    {
      "module": "r.slope.aspect",
      "id": "r.slope.aspect_0",
      "flags":"a",
      "inputs":[
         {"param": "elevation", "value": "elevation"}
       ],
      "outputs":[
         {
           "export": {
             "format": "GTiff",
             "type": "raster"
           },
           "param": "slope",
           "value": "slope"
         }
       ]
    }
  ],
  "version": "1"
}

Tip

Pokud chcete získati odkaz na data, která proces vrací, zavolejte processing_async_export namísto processing_async_export. Odkaz pak naleznete v sekci urls -> resources.

Zpracování standardního výstupu modulu

Mnohokráte potřebujeme pracovati s modulem, jehož výstup jest ve formě textu. Actinia dovede standardní výstup (stdout) modulů zpracovávat. Pro zpracování musíme zadati identifikátor proměnné (id), formát (format) a oddělovač (delimiter). K dispozici jsou v Actinii tři formáty:

  • kv: klíče a hodnoty
  • list: seznam hodnot
  • table: seznam seznamů, možno si jej představiti jako 2D pole či "tabulku"

V následujícím příkladu bychom zpracovali a zapsali standardní výstup tří modulů třemi různými způsoby:

 {
     "version": 1,
     "list": [
         {
             "id": "1",
             "module": "g.region",
             "inputs": [
                 {"param": "raster",
                  "value": "elevation@PERMANENT"},
                 {"param": "res",
                  "value": "5000"}
             ],
             "stdout": {"id": "region", "format": "kv", "delimiter": "="},
             "flags": "g"
         },
         {
             "id": "2",
             "module": "r.out.ascii",
             "inputs": [{"param": "input",
                         "value": "elevation@PERMANENT"},
                        {"param": "precision", "value": "0"}],
             "stdout": {"id": "elevation", "format": "table", "delimiter": " "},
             "flags": "h"
         },
         {
             "id": "3",
             "module": "g.list",
             "inputs": [{"param": "type",
                         "value": "raster"}],
             "stdout": {"id": "map_list", "format": "list", "delimiter": "\n"}
         }
    ]
}

Námi zachycené standardní výstupy v různých formátech jsou zapsány v sekci process_results.

{
    "accept_datetime": "2024-05-13 21:44:46.812599",
    "accept_timestamp": 1715636686.812598,
    "api_info": {
        "endpoint": "asyncephemeralresource",
        "method": "POST",
        "path": "/api/v3/locations/nc_spm_08_micro/processing_async",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/processing_async"
    },
    "datetime": "2024-05-13 21:44:47.385133",
    "http_code": 200,
    "message": "Processing successfully finished",
    "process_chain_list": [
        {
            "list": [
                {
                    "flags": "g",
                    "id": "1",
                    "inputs": [
                        {
                            "param": "raster",
                            "value": "elevation@PERMANENT"
                        },
                        {
                            "param": "res",
                            "value": "5000"
                        }
                    ],
                    "module": "g.region",
                    "stdout": {
                        "delimiter": "=",
                        "format": "kv",
                        "id": "region"
                    }
                },
                {
                    "flags": "h",
                    "id": "2",
                    "inputs": [
                        {
                            "param": "input",
                            "value": "elevation@PERMANENT"
                        },
                        {
                            "param": "precision",
                            "value": "0"
                        }
                    ],
                    "module": "r.out.ascii",
                    "stdout": {
                        "delimiter": " ",
                        "format": "table",
                        "id": "elevation"
                    }
                },
                {
                    "id": "3",
                    "inputs": [
                        {
                            "param": "type",
                            "value": "raster"
                        }
                    ],
                    "module": "g.list",
                    "stdout": {
                        "delimiter": "\n",
                        "format": "list",
                        "id": "map_list"
                    }
                }
            ],
            "version": 1
        }
    ],
    "process_log": [
        {
            "executable": "g.region",
            "id": "1",
            "mapset_size": 409,
            "parameter": [
                "raster=elevation@PERMANENT",
                "res=5000",
                "-g"
            ],
            "return_code": 0,
            "run_time": 0.10029292106628418,
            "stderr": [
                ""
            ],
            "stdout": "projection=99\nzone=0\nn=228500\ns=215000\nw=630000\ne=645000\nnsres=4500\newres=5000\nrows=3\ncols=3\ncells=9\n"
        },
        {
            "executable": "r.out.ascii",
            "id": "2",
            "mapset_size": 409,
            "parameter": [
                "input=elevation@PERMANENT",
                "precision=0",
                "-h"
            ],
            "return_code": 0,
            "run_time": 0.10027599334716797,
            "stderr": [
                "0..33..66.."
            ],
            "stdout": "147 138 100 \n125 114 76 \n125 121 96 \n"
        },
        {
            "executable": "g.list",
            "id": "3",
            "mapset_size": 409,
            "parameter": [
                "type=raster"
            ],
            "return_code": 0,
            "run_time": 0.10037517547607422,
            "stderr": [
                ""
            ],
            "stdout": "aspect\nbasin_50K\nelevation\nlanduse96_28m\nlsat7_2002_10\nslope\n"
        }
    ],
    "process_results": {
        "elevation": [
            [
                "147",
                "138",
                "100"
            ],
            [
                "125",
                "114",
                "76"
            ],
            [
                "125",
                "121",
                "96"
            ]
        ],
        "map_list": [
            "aspect",
            "basin_50K",
            "elevation",
            "landuse96_28m",
            "lsat7_2002_10",
            "slope"
        ],
        "region": {
            "cells": "9",
            "cols": "3",
            "e": "645000",
            "ewres": "5000",
            "n": "228500",
            "nsres": "4500",
            "projection": "99",
            "rows": "3",
            "s": "215000",
            "w": "630000",
            "zone": "0"
        }
    },
    "progress": {
        "num_of_steps": 3,
        "step": 3
    },
    "queue": "local",
    "resource_id": "resource_id-aba1a45e-853c-4410-b280-fa9bed478242",
    "status": "finished",
    "time_delta": 0.5725667476654053,
    "timestamp": 1715636687.3850846,
    "urls": {
        "resources": [],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-aba1a45e-853c-4410-b280-fa9bed478242"
    },
    "user_id": "actinia-gdi"
}
Výpočet NDVI na datech Sentinel-2

Importery mají v Actinii mnoho rozšíření pro data DPZ. Jedním takovým skrytým trikem jestiť možnost stahovat a importovat data Sentinel-2. V tomto příkladu jich využijeme k výpočtu normalizovaného vegetační diferencovaného indexu (NDVI) na jedné satelitní dlaždici.

Na pozadí se importerů pro Sentinel-2 používají dva přídavné moduly GRASS GIS, i.sentinel.download a i.sentinel.import. Nejdříve jest tedy zapotřebí je do naší instance Actinie doinstalovati.

sudo docker exec docker_actinia_1 grass /actinia_core/grassdb/nc_spm_08_micro/PERMANENT/ --exec g.extension i.sentinel.download
sudo docker exec docker_actinia_1 grass /actinia_core/grassdb/nc_spm_08_micro/PERMANENT/ --exec g.extension i.sentinel.import

Výpočet NDVI proveďme vykonáním následujících kroků:

  1. Importujme osmý a čtvrtý kanál dlaždice Sentinel-2
  2. Nastavme výpočetní region
  3. Vypočítejme NDVI
  4. Exportujme NDVI

Odpovídající JSON soubor může vypadat jako následující:

{
 "list": [{"id": "importer_1",
          "module": "importer",
          "inputs": [{"import_descr": {"source": "S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632",
                                       "type": "sentinel2",
                                       "sentinel_band": "B04"},
                      "param": "map",
                      "value": "B04"},
                     {"import_descr": {"source": "S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632",
                                       "type": "sentinel2",
                                       "sentinel_band": "B08"},
                      "param": "map",
                      "value": "B08"}]},
         {"id": "g_region_1",
          "module": "g.region",
          "inputs": [{"param": "raster",
                      "value": "B04"}],
          "flags": "g"},
         {"id": "rmapcalc_1",
          "module": "r.mapcalc",
          "inputs": [{"param": "expression",
                      "value": "NDVI = float(B08 - B04)/(B08 + B04)"}]},
         {"id": "exporter_1",
          "module": "exporter",
          "outputs": [{"export": {"type": "raster", "format": "GTiff"},
                       "param": "map",
                       "value": "NDVI"}]}
         ],
 "version": "1"
}

Nenastala-li chyba, výstup by měl vypadati jako následující:

{
    "accept_datetime": "2024-05-13 22:30:01.428755",
    "accept_timestamp": 1715639401.4287548,
    "api_info": {
        "endpoint": "asyncephemeralresource",
        "method": "POST",
        "path": "/api/v3/locations/nc_spm_08_micro/processing_async",
        "request_url": "http://localhost:8088/api/v3/locations/nc_spm_08_micro/processing_async_export"
    },
    "datetime": "2024-05-13 22:35:58.409945",
    "http_code": 200,
    "message": "Processing successfully finished",
    "process_chain_list": [
        {
            "list": [
                {
                    "id": "importer_1",
                    "inputs": [
                        {
                            "import_descr": {
                                "sentinel_band": "B04",
                                "source": "S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632",
                                "type": "sentinel2"
                            },
                            "param": "map",
                            "value": "B04"
                        },
                        {
                            "import_descr": {
                                "sentinel_band": "B08",
                                "source": "S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632",
                                "type": "sentinel2"
                            },
                            "param": "map",
                            "value": "B08"
                        }
                    ],
                    "module": "importer"
                },
                {
                    "flags": "g",
                    "id": "g_region_1",
                    "inputs": [
                        {
                            "param": "raster",
                            "value": "B04"
                        }
                    ],
                    "module": "g.region"
                },
                {
                    "id": "rmapcalc_1",
                    "inputs": [
                        {
                            "param": "expression",
                            "value": "NDVI = float(B08 - B04)/(B08 + B04)"
                        }
                    ],
                    "module": "r.mapcalc"
                },
                {
                    "flags": "g",
                    "id": "r_univar_sentinel2",
                    "inputs": [
                        {
                            "param": "map",
                            "value": "NDVI"
                        }
                    ],
                    "module": "r.univar"
                },
                {
                    "id": "exporter_1",
                    "module": "exporter",
                    "outputs": [
                        {
                            "export": {
                                "format": "GTiff",
                                "type": "raster"
                            },
                            "param": "map",
                            "value": "NDVI"
                        }
                    ]
                }
            ],
            "version": "1"
        }
    ],
    "process_log": [
        {
            "executable": "i.sentinel.download",
            "id": "i_sentinel_download_S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632",
            "mapset_size": 375,
            "parameter": [
                "datasource=GCS",
                "query=identifier=S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632",
                "output=/actinia_core/workspace/temp_db/gisdbase_0109c0ce91b44265bb458010514684c0/.tmp/temp_file_1"
            ],
            "return_code": 0,
            "run_time": 17.66672992706299,
            "stderr": [
                "Downloading data into </actinia_core/workspace/temp_db/gisdbase_0109c0ce91b44265bb458010514684c0/.tmp/temp_file_1>...",
                "Downloading S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632...",
                "\r  0%|          | 0/84 [00:00<?, ?it/s]\r  2%|\u258f         | 2/84 [00:00<00:04, 19.11it/s]\r  5%|\u258d         | 4/84 [00:00<00:09,  8.11it/s]\r  8%|\u258a         | 7/84 [00:00<00:06, 12.55it/s]\r 12%|\u2588\u258f        | 10/84 [00:00<00:04, 15.67it/s]\r 14%|\u2588\u258d        | 12/84 [00:02<00:20,  3.60it/s]\r 17%|\u2588\u258b        | 14/84 [00:04<00:38,  1.83it/s]\r 18%|\u2588\u258a        | 15/84 [00:06<00:47,  1.44it/s]\r 19%|\u2588\u2589        | 16/84 [00:07<00:58,  1.17it/s]\r 20%|\u2588\u2588        | 17/84 [00:08<00:55,  1.21it/s]\r 23%|\u2588\u2588\u258e       | 19/84 [00:08<00:37,  1.73it/s]\r 24%|\u2588\u2588\u258d       | 20/84 [00:09<00:34,  1.85it/s]\r 25%|\u2588\u2588\u258c       | 21/84 [00:09<00:35,  1.76it/s]\r 26%|\u2588\u2588\u258c       | 22/84 [00:10<00:33,  1.86it/s]\r 27%|\u2588\u2588\u258b       | 23/84 [00:10<00:31,  1.95it/s]\r 29%|\u2588\u2588\u258a       | 24/84 [00:11<00:29,  2.01it/s]\r 30%|\u2588\u2588\u2589       | 25/84 [00:11<00:28,  2.07it/s]\r 31%|\u2588\u2588\u2588       | 26/84 [00:11<00:27,  2.12it/s]\r 32%|\u2588\u2588\u2588\u258f      | 27/84 [00:12<00:27,  2.10it/s]\r 33%|\u2588\u2588\u2588\u258e      | 28/84 [00:12<00:26,  2.15it/s]\r 36%|\u2588\u2588\u2588\u258c      | 30/84 [00:13<00:20,  2.64it/s]\r 37%|\u2588\u2588\u2588\u258b      | 31/84 [00:13<00:19,  2.77it/s]\r 39%|\u2588\u2588\u2588\u2589      | 33/84 [00:13<00:12,  4.17it/s]\r 42%|\u2588\u2588\u2588\u2588\u258f     | 35/84 [00:14<00:08,  5.51it/s]\r 44%|\u2588\u2588\u2588\u2588\u258d     | 37/84 [00:14<00:06,  6.82it/s]\r 46%|\u2588\u2588\u2588\u2588\u258b     | 39/84 [00:14<00:05,  7.84it/s]\r 49%|\u2588\u2588\u2588\u2588\u2589     | 41/84 [00:14<00:04,  8.86it/s]\r 51%|\u2588\u2588\u2588\u2588\u2588     | 43/84 [00:14<00:04,  9.59it/s]\r 54%|\u2588\u2588\u2588\u2588\u2588\u258e    | 45/84 [00:14<00:03, 10.67it/s]\r 56%|\u2588\u2588\u2588\u2588\u2588\u258c    | 47/84 [00:14<00:03, 11.44it/s]\r 60%|\u2588\u2588\u2588\u2588\u2588\u2589    | 50/84 [00:15<00:02, 14.32it/s]\r 63%|\u2588\u2588\u2588\u2588\u2588\u2588\u258e   | 53/84 [00:15<00:01, 16.65it/s]\r 67%|\u2588\u2588\u2588\u2588\u2588\u2588\u258b   | 56/84 [00:15<00:01, 18.16it/s]\r 70%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588   | 59/84 [00:15<00:01, 19.71it/s]\r 74%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258d  | 62/84 [00:15<00:01, 20.93it/s]\r 77%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258b  | 65/84 [00:15<00:00, 22.09it/s]\r 81%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588  | 68/84 [00:15<00:00, 22.94it/s]\r 85%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258d | 71/84 [00:16<00:00, 22.71it/s]\r 88%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258a | 74/84 [00:16<00:00, 23.05it/s]\r 92%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258f| 77/84 [00:16<00:00, 23.40it/s]\r 95%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258c| 80/84 [00:16<00:00, 22.51it/s]\r 99%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2589| 83/84 [00:16<00:00, 21.85it/s]\r100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 84/84 [00:16<00:00,  5.06it/s]",
                "Downloaded to /actinia_core/workspace/temp_db/gisdbase_0109c0ce91b44265bb458010514684c0/.tmp/temp_file_1/S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632.SAFE",
                ""
            ],
            "stdout": ""
        },
        {
            "executable": "i.sentinel.import",
            "id": "i_sentinel_import_S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632",
            "mapset_size": 377029998,
            "parameter": [
                "input=/actinia_core/workspace/temp_db/gisdbase_0109c0ce91b44265bb458010514684c0/.tmp/temp_file_1",
                "pattern=(B04_10m|B08_10m)",
                "-r"
            ],
            "return_code": 0,
            "run_time": 309.34225726127625,
            "stderr": [
                "Processing <T18SUE_20220420T154941_B04_10m>...",
                "Importing raster map <T18SUE_20220420T154941_B04_10m>...",
                "0..3..6..9..12..15..18..21..24..27..30..33..36..39..42..45..48..51..54..57..60..63..66..69..72..75..78..81..84..87..90..93..96..99..100",
                "Estimated target resolution for input band <T18SUE_20220420T154941_B04_10m>: 9.618686330457596",
                "Using given resolution for input band <T18SUE_20220420T154941_B04_10m>: 10.0",
                "Reprojecting <T18SUE_20220420T154941_B04_10m>...",
                "Rounding to integer after reprojection",
                "Processing <T18SUE_20220420T154941_B08_10m>...",
                "Importing raster map <T18SUE_20220420T154941_B08_10m>...",
                "0..3..6..9..12..15..18..21..24..27..30..33..36..39..42..45..48..51..54..57..60..63..66..69..72..75..78..81..84..87..90..93..96..99..100",
                "Estimated target resolution for input band <T18SUE_20220420T154941_B08_10m>: 9.618686330457596",
                "Using given resolution for input band <T18SUE_20220420T154941_B08_10m>: 10.0",
                "Reprojecting <T18SUE_20220420T154941_B08_10m>...",
                "Rounding to integer after reprojection",
                "Writing metadata to maps...",
                ""
            ],
            "stdout": ""
        },
        {
            "executable": "g.rename",
            "id": "rename_S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632_B04",
            "mapset_size": 377029998,
            "parameter": [
                "raster=T18SUE_20220420T154941_B04_10m,B04"
            ],
            "return_code": 0,
            "run_time": 0.10027694702148438,
            "stderr": [
                "Rename raster <T18SUE_20220420T154941_B04_10m> to <B04>",
                ""
            ],
            "stdout": ""
        },
        {
            "executable": "g.rename",
            "id": "rename_S2A_MSIL2A_20220420T154941_N0400_R054_T18SUE_20220421T000632_B08",
            "mapset_size": 377029998,
            "parameter": [
                "raster=T18SUE_20220420T154941_B08_10m,B08"
            ],
            "return_code": 0,
            "run_time": 0.10035204887390137,
            "stderr": [
                "Rename raster <T18SUE_20220420T154941_B08_10m> to <B08>",
                ""
            ],
            "stdout": ""
        },
        {
            "executable": "g.region",
            "id": "g_region_1",
            "mapset_size": 377030038,
            "parameter": [
                "raster=B04",
                "-g"
            ],
            "return_code": 0,
            "run_time": 0.10033679008483887,
            "stderr": [
                ""
            ],
            "stdout": "projection=99\nzone=0\nn=269280\ns=155130\nw=769610\ne=883770\nnsres=10\newres=10\nrows=11415\ncols=11416\ncells=130313640\n"
        },
        {
            "executable": "r.mapcalc",
            "id": "rmapcalc_1",
            "mapset_size": 808310460,
            "parameter": [
                "expression=NDVI = float(B08 - B04)/(B08 + B04)"
            ],
            "return_code": 0,
            "run_time": 22.48184609413147,
            "stderr": [
                ""
            ],
            "stdout": ""
        },
        {
            "executable": "r.univar",
            "id": "r_univar_sentinel2",
            "mapset_size": 808310460,
            "parameter": [
                "map=NDVI",
                "-g"
            ],
            "return_code": 0,
            "run_time": 6.721964359283447,
            "stderr": [
                ""
            ],
            "stdout": "n=120547065\nnull_cells=9766575\ncells=130313640\nmin=-0.468370884656906\nmax=0.720661163330078\nrange=1.18903204798698\nmean=0.25310113195823\nmean_of_abs=0.283006503246459\nstddev=0.219731453415328\nvariance=0.0482819116200123\ncoeff_var=86.8156739226241\nsum=30510598.6057423\n"
        }
    ],
    "process_results": {},
    "progress": {
        "num_of_steps": 7,
        "step": 7
    },
    "queue": "local",
    "resource_id": "resource_id-8d34c407-ca3b-41d4-a9aa-33e371acb889",
    "status": "finished",
    "time_delta": 356.98121070861816,
    "timestamp": 1715639758.4099405,
    "urls": {
        "resources": ["http://localhost:8088/api/v3/resources/allen/resource_id-5b6815ae-dcfd-4b11-842f-3eb1dbef3988/NDVI.tif"],
        "status": "http://localhost:8088/api/v3/resources/actinia-gdi/resource_id-8d34c407-ca3b-41d4-a9aa-33e371acb889"
    },
    "user_id": "actinia-gdi"
}

Úkol

Bylo řečeno, že na pozadí importerů pro Sentinel-2 se používají i.sentinel.download a i.sentinel.import. Vyzkoušejte si tvorbu procesu, ve kterém nepoužijete importerů, ale právě zmiňovaných přídavných modulů. Výstup z našeho příkladu vám prozradí, co se děje na pozadí importerů.